code_device/hgsane/sane_hg_mdw.cpp

2699 lines
73 KiB
C++
Raw Permalink Normal View History

2022-05-03 03:56:07 +00:00
#include "sane_hg_mdw.h"
#include "json.h"
#include <stdarg.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mutex>
2022-10-14 01:00:57 +00:00
#include <thread>
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
#include <windows.h>
#include <direct.h>
#define pthread_t DWORD
#define pthread_self GetCurrentThreadId
#define MKDIR(a, b) mkdir(a)
#else
#define MKDIR(a, b) mkdir(a, b)
#include <pthread.h>
#endif
#include "../../sdk/include/sane/sane_option_definitions.h"
#include "sane_option.h"
2023-01-19 07:43:59 +00:00
#include <lang/app_language.h>
2022-05-03 03:56:07 +00:00
#ifndef SIGUSR1
#define SIGUSR1 10
#endif
// copy to /usr/lib/x86_64-linux-gnu/sane
// export SANE_DEBUG_DLL=5
#ifndef iconv_t
#define iconv_t void*
#endif
static std::string g_sane_path("");
static std::string g_sane_name(GET_BACKEND_NAME);
2022-05-03 03:56:07 +00:00
namespace local_utility
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-07-18 02:54:41 +00:00
#define RETURN_MATCH_ERROR(err, from, to) \
if(err == from) \
return to;
SANE_Status scanner_err_2_sane_statu(int hgerr)
2022-05-03 03:56:07 +00:00
{
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_OK, SANE_STATUS_GOOD);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_INVALID_PARAMETER, SANE_STATUS_INVAL);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_INSUFFICIENT_MEMORY, SANE_STATUS_NO_MEM);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_ACCESS_DENIED, SANE_STATUS_ACCESS_DENIED);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_IO_PENDING, SANE_STATUS_GOOD);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_NOT_EXACT, SANE_STATUS_GOOD);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_CONFIGURATION_CHANGED, SANE_STATUS_GOOD);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_RELOAD_IMAGE_PARAM, SANE_STATUS_GOOD);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_RELOAD_OPT_PARAM, SANE_STATUS_GOOD);
2022-08-02 10:20:34 +00:00
//RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_NOT_OPEN, SANE_STATUS_NO_DOCS);
//RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_NOT_START, SANE_STATUS_NO_DOCS);
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_NO_DATA, SANE_STATUS_EOF);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_IO, SANE_STATUS_IO_ERROR);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_OUT_OF_RANGE, SANE_STATUS_INVAL);
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_IO, SANE_STATUS_IO_ERROR);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_TIMEOUT, SANE_STATUS_IO_ERROR);
// RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_NOT_FOUND, SANE_STATUS_NO_DOCS);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_NOT_SUPPORT, SANE_STATUS_UNSUPPORTED);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_BUSY, SANE_STATUS_DEVICE_BUSY);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_COVER_OPENNED, SANE_STATUS_COVER_OPEN);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_NO_PAPER, SANE_STATUS_NO_DOCS);
RETURN_MATCH_ERROR(hgerr, SCANNER_ERR_DEVICE_PAPER_JAMMED, SANE_STATUS_JAMMED);
2022-05-03 03:56:07 +00:00
return (SANE_Status)hgerr;
}
2022-06-15 03:05:36 +00:00
int sane_statu_2_scanner_err(int statu)
{
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_OK);
RETURN_MATCH_ERROR(statu, SANE_STATUS_INVAL, SCANNER_ERR_INVALID_PARAMETER);
RETURN_MATCH_ERROR(statu, SANE_STATUS_NO_MEM, SCANNER_ERR_INSUFFICIENT_MEMORY);
RETURN_MATCH_ERROR(statu, SANE_STATUS_ACCESS_DENIED, SCANNER_ERR_ACCESS_DENIED);
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_IO_PENDING);
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_NOT_EXACT);
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_CONFIGURATION_CHANGED);
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_RELOAD_IMAGE_PARAM);
RETURN_MATCH_ERROR(statu, SANE_STATUS_GOOD, SCANNER_ERR_RELOAD_OPT_PARAM);
2022-08-02 10:20:34 +00:00
//RETURN_MATCH_ERROR(statu, SANE_STATUS_NO_DOCS, SCANNER_ERR_NOT_OPEN);
//RETURN_MATCH_ERROR(statu, SANE_STATUS_NO_DOCS, SCANNER_ERR_NOT_START);
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(statu, SANE_STATUS_EOF, SCANNER_ERR_NO_DATA);
RETURN_MATCH_ERROR(statu, SANE_STATUS_IO_ERROR, SCANNER_ERR_IO);
RETURN_MATCH_ERROR(statu, SANE_STATUS_INVAL, SCANNER_ERR_OUT_OF_RANGE);
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(statu, SANE_STATUS_IO_ERROR, SCANNER_ERR_IO);
RETURN_MATCH_ERROR(statu, SANE_STATUS_IO_ERROR, SCANNER_ERR_TIMEOUT);
2022-08-02 10:20:34 +00:00
//RETURN_MATCH_ERROR(statu, SANE_STATUS_NO_DOCS, SCANNER_ERR_DEVICE_NOT_FOUND);
2022-07-18 02:54:41 +00:00
RETURN_MATCH_ERROR(statu, SANE_STATUS_UNSUPPORTED, SCANNER_ERR_DEVICE_NOT_SUPPORT);
RETURN_MATCH_ERROR(statu, SANE_STATUS_DEVICE_BUSY, SCANNER_ERR_DEVICE_BUSY);
RETURN_MATCH_ERROR(statu, SANE_STATUS_COVER_OPEN, SCANNER_ERR_DEVICE_COVER_OPENNED);
RETURN_MATCH_ERROR(statu, SANE_STATUS_NO_DOCS, SCANNER_ERR_DEVICE_NO_PAPER);
RETURN_MATCH_ERROR(statu, SANE_STATUS_JAMMED, SCANNER_ERR_DEVICE_PAPER_JAMMED);
2022-06-15 03:05:36 +00:00
return statu;
}
2022-05-03 03:56:07 +00:00
void* acquire_memory(size_t bytes, const char* info)
{
//if (!info)
// info = "";
//hg_sane_middleware::log(strlen(info) + 80, "allocate memory with %u bytes from %s\n", bytes, info);
void* buf = malloc(bytes);
if (buf)
memset(buf, 0, bytes);
return buf;
2022-05-03 03:56:07 +00:00
}
void free_memory(void* m)
{
if (m)
free(m);
}
2022-05-03 03:56:07 +00:00
2022-05-03 03:56:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// json parser ...
2022-05-03 03:56:07 +00:00
bool is_space(char ch)
{
return ch == ' ' || ch == '\t';
}
bool is_digital(char ch)
{
return ch >= '0' && ch <= '9';
}
bool is_hex_num(char ch)
{
if (is_digital(ch))
return true;
return (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
}
bool to_num(char ch, int& v, bool hex)
{
if (is_digital(ch))
{
v = ch - '0';
return true;
}
if (hex)
{
if (ch >= 'a' && ch <= 'f')
{
v = ch - 'a' + 10;
}
else if (ch >= 'A' && ch <= 'F')
{
v = ch - 'A' + 10;
}
else
{
hex = false;
}
}
return hex;
}
bool skip_space(const char*& str)
{
const char* bgn = str;
while (is_space(*str))
str++;
return str > bgn;
}
// 暂不支持科学计数<E8AEA1><E695B0>?1.2e+10
2022-05-03 03:56:07 +00:00
bool get_number(const char*& str, double& val)
{
const char* bgn = str;
double val_race = 10.0f,
val_sign = 1.0f,
digit_race = 1.0f,
digit_race_race = 1.0f;
val = .0f;
if (*str == '-')
{
str++;
val_sign = -1.0f;
}
if (*str == '.')
{
str++;
digit_race = digit_race_race = .1f;
val_race = 1.0f;
}
bgn = str;
while (*str && is_digital(*str))
{
int v = 0;
val *= val_race;
to_num(*str++, v, false);
val += v * digit_race;
digit_race *= digit_race_race;
}
if (*str == '.')
{
if (digit_race_race < 1.0f)
return false;
digit_race = digit_race_race = .1f;
val_race = 1.0f;
while (*str && is_digital(*str))
{
int v = 0;
val *= val_race;
to_num(*str++, v, false);
val += v * digit_race;
digit_race *= digit_race_race;
}
}
return str > bgn;
}
bool get_limit(const char*& str, std::string& l, std::string& r)
{
// set l = "a", r = "b" in text "[a, b]"
bool ret = *str == '[';
if (ret)
{
str++;
skip_space(str);
l = str;
size_t pos = l.find("]");
if (pos == -1)
return false;
l.erase(pos);
pos = l.find(",");
if (pos == -1)
return false;
r = l.substr(pos + 1);
l.erase(pos);
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// fixed id map
2023-06-15 02:10:17 +00:00
static void init_fixed_id(const char* name, int id, std::map<sane_option_id, int>& mapid, int* fixid = nullptr)
{
2023-05-23 03:19:37 +00:00
#define TRY_MATCH(n) \
if(strcmp(SANE_STD_OPT_NAME_##n, name) == 0) \
{ \
mapid[SANE_OPT_ID_##n] = id; \
2023-06-15 02:10:17 +00:00
if(fixid) \
*fixid = SANE_OPT_ID_##n; \
return; \
}
TRY_MATCH(IS_MULTI_OUT);
TRY_MATCH(MULTI_OUT_TYPE);
TRY_MATCH(COLOR_MODE);
TRY_MATCH(FILTER);
TRY_MATCH(RID_MULTIOUT_RED);
TRY_MATCH(RID_ANSWER_SHEET_RED);
TRY_MATCH(ERASE_BACKGROUND);
TRY_MATCH(BKG_COLOR_RANGE);
TRY_MATCH(SHARPEN);
TRY_MATCH(RID_MORR);
TRY_MATCH(RID_GRID);
TRY_MATCH(ERROR_EXTENSION);
TRY_MATCH(NOISE_OPTIMIZE);
TRY_MATCH(NOISE_SIZE);
TRY_MATCH(PAPER);
TRY_MATCH(CUSTOM_AREA);
TRY_MATCH(CUSTOM_AREA_LEFT);
TRY_MATCH(CUSTOM_AREA_RIGHT);
TRY_MATCH(CUSTOM_AREA_TOP);
TRY_MATCH(CUSTOM_AREA_BOTTOM);
TRY_MATCH(SIZE_CHECK);
TRY_MATCH(PAGE);
TRY_MATCH(DISCARD_BLANK_SENS);
TRY_MATCH(RESOLUTION);
TRY_MATCH(IMAGE_QUALITY);
TRY_MATCH(EXCHANGE);
TRY_MATCH(SPLIT);
TRY_MATCH(ANTI_SKEW);
TRY_MATCH(IS_CUSTOM_GAMMA);
TRY_MATCH(BRIGHTNESS);
TRY_MATCH(CONTRAST);
TRY_MATCH(GAMMA);
TRY_MATCH(ERASE_BLACK_FRAME);
TRY_MATCH(DARK_SAMPLE);
TRY_MATCH(THRESHOLD);
TRY_MATCH(ANTI_NOISE_LEVEL);
TRY_MATCH(MARGIN);
TRY_MATCH(FILL_BKG_MODE);
TRY_MATCH(IS_ANTI_PERMEATE);
TRY_MATCH(ANTI_PERMEATE_LEVEL);
TRY_MATCH(RID_HOLE);
TRY_MATCH(SEARCH_HOLE_RANGE);
TRY_MATCH(IS_FILL_COLOR);
TRY_MATCH(IS_ULTROSONIC_CHECK);
TRY_MATCH(IS_CHECK_STAPLE);
TRY_MATCH(SCAN_MODE);
TRY_MATCH(SCAN_COUNT);
TRY_MATCH(TEXT_DIRECTION);
TRY_MATCH(IS_ROTATE_BKG_180);
TRY_MATCH(IS_CHECK_DOG_EAR);
TRY_MATCH(DOG_EAR_SIZE);
TRY_MATCH(IS_CHECK_ASKEW);
TRY_MATCH(ASKEW_RANGE);
TRY_MATCH(BINARY_THRESHOLD);
TRY_MATCH(IS_PHOTO_MODE);
TRY_MATCH(DOUBLE_FEED_HANDLE);
TRY_MATCH(WAIT_TO_SCAN);
TRY_MATCH(FEED_STRENGTH);
TRY_MATCH(TIME_TO_SLEEP);
TRY_MATCH(IS_AUTO_FEED_STRENGTH);
TRY_MATCH(FEED_STRENGTH_VALUE);
TRY_MATCH(REVERSE_01);
TRY_MATCH(RID_HOLE_L);
TRY_MATCH(SEARCH_HOLE_RANGE_L);
TRY_MATCH(RID_HOLE_R);
TRY_MATCH(SEARCH_HOLE_RANGE_R);
TRY_MATCH(RID_HOLE_T);
TRY_MATCH(SEARCH_HOLE_RANGE_T);
TRY_MATCH(RID_HOLE_B);
TRY_MATCH(SEARCH_HOLE_RANGE_B);
TRY_MATCH(FOLD_TYPE);
TRY_MATCH(COLOR_CORRECTION);
2023-06-15 02:10:17 +00:00
TRY_MATCH(LANGUAGE);
2023-08-16 06:11:59 +00:00
TRY_MATCH(INITIAL_BOOT_TIME);
2023-08-16 07:31:29 +00:00
TRY_MATCH(DISCARDBLANK);
2023-11-02 07:32:22 +00:00
TRY_MATCH(LENS_DIRTY);
2023-08-16 07:31:29 +00:00
//TRY_MATCH(HISTORY_COUNT);
//TRY_MATCH(DRIVER_VERSION);
//TRY_MATCH(MANUFACTURER);
//TRY_MATCH(COPYRIGHT);
//TRY_MATCH(CO_URL);
//TRY_MATCH(CO_TEL);
//TRY_MATCH(CO_ADDR);
//TRY_MATCH(CO_GPS);
//TRY_MATCH(HELP);
//TRY_MATCH(VID);
//TRY_MATCH(PID);
//TRY_MATCH(DEV_NAME);
//TRY_MATCH(DEV_FAMILY);
//TRY_MATCH(LOGIN);
//TRY_MATCH(LOGOUT);
//TRY_MATCH(ROLLER_COUNT);
//TRY_MATCH(DRIVER_LOG);
//TRY_MATCH(DEVICE_LOG);
}
2023-05-17 01:42:46 +00:00
static std::string un_json_option_name(int id, int *len)
{
2023-05-17 01:42:46 +00:00
int tmp = sizeof(int);
if (!len)
len = &tmp;
#define FIX_ID_TO_NAME(fid, l) \
if(id == SANE_OPT_ID_##fid) \
{ \
*len = l; \
return SANE_STD_OPT_NAME_##fid; \
}
FIX_ID_TO_NAME(HISTORY_COUNT, sizeof(int));
FIX_ID_TO_NAME(DRIVER_VERSION, 255);
FIX_ID_TO_NAME(MANUFACTURER, 255);
FIX_ID_TO_NAME(COPYRIGHT, 255);
FIX_ID_TO_NAME(CO_URL, 255);
FIX_ID_TO_NAME(CO_TEL, 255);
FIX_ID_TO_NAME(CO_ADDR, 255);
FIX_ID_TO_NAME(CO_GPS, 255);
FIX_ID_TO_NAME(VID, sizeof(int));
FIX_ID_TO_NAME(PID, sizeof(int));
FIX_ID_TO_NAME(DEV_NAME, 255);
FIX_ID_TO_NAME(DEV_FAMILY, 255);
FIX_ID_TO_NAME(ROLLER_COUNT, sizeof(int));
FIX_ID_TO_NAME(HELP, sizeof(int));
FIX_ID_TO_NAME(LOGIN, 255);
FIX_ID_TO_NAME(LOGOUT, 255);
FIX_ID_TO_NAME(DRIVER_LOG, 255);
FIX_ID_TO_NAME(DEVICE_LOG, 255);
2023-06-17 05:29:18 +00:00
FIX_ID_TO_NAME(MOTOR_VER, 255);
2023-08-16 06:11:59 +00:00
FIX_ID_TO_NAME(INITIAL_BOOT_TIME, 255);
2023-05-17 01:42:46 +00:00
FIX_ID_TO_NAME(DEVICE_SERIAL_NO, 255);
FIX_ID_TO_NAME(FIRMWARE_VERSION, 255);
FIX_ID_TO_NAME(DEVICE_IP_ADDR, 255);
FIX_ID_TO_NAME(DEVICE_MAC_ADDR, 255);
2023-06-13 04:28:20 +00:00
FIX_ID_TO_NAME(ROLLER_LIFE, sizeof(SANE_Int));
2023-05-16 03:44:48 +00:00
2023-05-29 07:51:01 +00:00
FIX_ID_TO_NAME(CUSTOM_GAMMA, sizeof(SANE_Gamma));
FIX_ID_TO_NAME(TRANSFORM_IMAGE_FORMAT, sizeof(SANE_ImageFormatConvert));
FIX_ID_TO_NAME(FREE_BUFFER, sizeof(void*));
2023-06-15 02:10:17 +00:00
//FIX_ID_TO_NAME(LANGUAGE, 128);
2023-05-29 07:51:01 +00:00
return "";
}
2022-05-03 03:56:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static sane_callback cb_ui_ = NULL;
static void* cb_ui_parm_ = NULL;
static SANE_Auth_Callback cb_auth_ = NULL;
static std::mutex cb_lock_;
2022-05-03 03:56:07 +00:00
static std::string sane_event(SANE_Event ev)
{
RETURN_IF(ev, SANE_EVENT_NONE);
RETURN_IF(ev, SANE_EVENT_SUPPORT_ASYNC_IO);
RETURN_IF(ev, SANE_EVENT_IS_MEMORY_ENOUGH);
RETURN_IF(ev, SANE_EVENT_NEED_AUTH);
RETURN_IF(ev, SANE_EVENT_DEVICE_ARRIVED);
RETURN_IF(ev, SANE_EVENT_DEVICE_LEFT);
RETURN_IF(ev, SANE_EVENT_STATUS);
RETURN_IF(ev, SANE_EVENT_ERROR);
RETURN_IF(ev, SANE_EVENT_WORKING);
RETURN_IF(ev, SANE_EVENT_IMAGE_OK);
RETURN_IF(ev, SANE_EVENT_SCAN_FINISHED);
RETURN_IF(ev, SANE_EVENT_ABOUT_INFORMATION);
RETURN_IF(ev, SANE_EVENT_SCANNER_CLOSED);
char unk[20];
sprintf(unk, "%d", ev);
return unk;
}
int ui_cb(scanner_handle dev, int code, void* data, unsigned int* len, void* unused)
{
2022-11-18 08:05:39 +00:00
sane_callback cb_ui = NULL;
void* cb_ui_parm = NULL;
SANE_Auth_Callback cb_auth = NULL;
{
std::lock_guard<std::mutex> lck(cb_lock_);
cb_ui = cb_ui_;
cb_ui_parm = cb_ui_parm_;
cb_auth_ = cb_auth;
}
2022-05-03 03:56:07 +00:00
if (SANE_EVENT_SUPPORT_ASYNC_IO == code)
return cb_ui_ ? SCANNER_ERR_OK : SCANNER_ERR_DEVICE_NOT_SUPPORT;
2022-05-03 03:56:07 +00:00
SANE_Handle h = hg_sane_middleware::scanner_handle_to_sane(dev);
// VLOG_MINI_1(LOG_LEVEL_ALL, "sane callback invoked of event %s\n", sane_event((SANE_Event)code).c_str());
2022-05-03 03:56:07 +00:00
2022-11-18 08:05:39 +00:00
if (cb_ui)
2022-05-03 03:56:07 +00:00
{
2022-11-18 08:05:39 +00:00
return cb_ui(h, code, data, len, cb_ui_parm);
2022-05-03 03:56:07 +00:00
}
2022-11-18 08:05:39 +00:00
else if (cb_auth && code == SANE_EVENT_NEED_AUTH)
2022-05-03 03:56:07 +00:00
{
SANEAUTH* auth = (SANEAUTH*)data;
2022-11-18 08:05:39 +00:00
cb_auth(auth->resource, auth->name, auth->pwd);
2022-05-03 03:56:07 +00:00
}
return 0;
}
void get_version(SANE_Int* version_code)
{
if (version_code)
*version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD); // leading-char '1' is used for avoid compiler considering '0118' as an octal number :)
}
void set_callback(sane_callback cb, void* param)
{
std::lock_guard<std::mutex> lck(cb_lock_);
cb_ui_ = cb;
cb_ui_parm_ = param;
}
2022-05-03 03:56:07 +00:00
void stop_work(void)
{
std::lock_guard<std::mutex> lck(cb_lock_);
2022-05-03 03:56:07 +00:00
cb_ui_ = NULL;
cb_ui_parm_ = NULL;
cb_auth_ = NULL;
}
static void trans_language_if_was_word_id(std::string& val)
{
size_t pos = val.find(".");
if (pos != std::string::npos)
{
bool num = true;
for (size_t i = pos + 1; i < val.length(); ++i)
{
if (val[i] != '0')
{
num = false;
break;
}
}
if (num && std::to_string(atoi(val.c_str())) == val.substr(0, pos))
{
val = lang_load_string(atoi(val.c_str()), nullptr);
}
}
}
2022-05-03 03:56:07 +00:00
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
hg_sane_middleware* hg_sane_middleware::inst_ = NULL;
const SANE_Device** hg_sane_middleware::dev_list_ = NULL;
hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false)
2022-05-03 03:56:07 +00:00
{
char sane_ver[40] = { 0 };
2023-01-19 07:43:59 +00:00
init_ok_ = true;
sprintf(sane_ver, "%u.%u.%u", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD);
2022-05-03 03:56:07 +00:00
signal(SIGUSR1, &hg_sane_middleware::device_pnp);
hg_scanner_set_sane_info(g_sane_name.c_str(), sane_ver);
2023-08-11 09:53:56 +00:00
hg_scanner_initialize(local_utility::ui_cb, NULL);
register_language_changed_notify(&hg_sane_middleware::language_changed, true);
2022-07-19 01:40:30 +00:00
#if !defined(WIN32) && !defined(_WIN64)
char path[512] = { 0 };
size_t pos = 0;
g_sane_path = get_file_path((std::string(GET_BACKEND_NAME) + ".so").c_str(), path);
pos = g_sane_path.rfind('/');
if (pos++ != std::string::npos)
g_sane_path.erase(pos);
#endif
2022-05-03 03:56:07 +00:00
}
hg_sane_middleware::~hg_sane_middleware()
{
2023-01-19 07:43:59 +00:00
register_language_changed_notify(&hg_sane_middleware::language_changed, false);
for (size_t i = 0; i < openning_.size(); ++i)
2022-05-03 03:56:07 +00:00
{
hg_scanner_close(openning_[i]->dev, true);
hg_sane_middleware::free_device_inst(openning_[i]);
2022-05-03 03:56:07 +00:00
}
hg_scanner_uninitialize();
if (opt_0_)
local_utility::free_memory(opt_0_);
2022-05-03 03:56:07 +00:00
}
2023-01-19 07:43:59 +00:00
void hg_sane_middleware::language_changed(int cp, void* param)
{
hg_sane_middleware::instance()->reload_options();
//for (auto& v : hg_sane_middleware::instance()->openning_)
//{
// hg_sane_middleware::free_device_inst(v, false);
//
// long count = 0;
// hg_scanner_get_parameter(v->dev, nullptr, NULL, &count);
// for (long ind = 1; ind < count; ++ind)
// hg_sane_middleware::instance()->get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind);
//}
2023-01-19 07:43:59 +00:00
}
const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, int count)
2022-05-03 03:56:07 +00:00
{
// 将多级指针安排在一个连续的内存空间存放
SANE_Device** ret = NULL, * dev = NULL;
SANE_String val = NULL;
unsigned long bytes = (count + 1) * (sizeof(SANE_Device) + sizeof(SANE_Device*)), total = 0;
// calculate space ...
for (int i = 0; i < count; ++i)
{
bytes += ALIGN_INT(strlen(hgscanner[i].name) + 1);
bytes += ALIGN_INT(strlen(hgscanner[i].vendor) + 1);
bytes += ALIGN_INT(strlen(hgscanner[i].model) + 1);
bytes += ALIGN_INT(strlen(hgscanner[i].type) + 1);
}
bytes = ALIGN_INT(bytes + 16);
dev = (SANE_Device*)local_utility::acquire_memory(bytes, "hg_sane_middleware::to_sane_device");
total = bytes;
if (!dev)
return NULL;
memset(dev, 0, bytes);
ret = (SANE_Device**)dev;
dev = (SANE_Device*)((SANE_Device**)dev + count + 1);
val = (SANE_String)(dev + count);
#define COPY_DEVICE_MEMBER(m) \
dev->m = val; \
strcpy(val, hgscanner[i].m); \
bytes = ALIGN_INT(strlen(val) + 1); \
val += bytes;
for (int i = 0; i < count; ++i, ++dev)
{
ret[i] = dev;
COPY_DEVICE_MEMBER(name);
COPY_DEVICE_MEMBER(vendor);
COPY_DEVICE_MEMBER(model);
COPY_DEVICE_MEMBER(type);
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u / %u\n", val - (char*)ret, total);
2022-05-03 03:56:07 +00:00
return (const SANE_Device**)ret;
}
void hg_sane_middleware::free_sane_device(SANE_Device** dev)
{
char* mem = (char*)dev;
if (mem)
{
free(mem);
}
}
void hg_sane_middleware::device_pnp(int sig)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Device list changed (%d)...", sig);
2022-05-03 03:56:07 +00:00
}
SANE_Fixed hg_sane_middleware::double_2_sane_fixed(double v)
{
return SANE_FIX(v);
}
double hg_sane_middleware::sane_fixed_2_double(SANE_Fixed v)
{
return SANE_UNFIX(v);
}
void hg_sane_middleware::set_value_to_var(void* val, size_t bytes, void* param)
{
memcpy(param, val, bytes);
}
void hg_sane_middleware::set_value_to_new(void* val, size_t bytes, void* param)
{
void** addr = (void**)param;
*addr = local_utility::acquire_memory(bytes, "set_value_to_new");
memcpy(*addr, val, bytes);
}
2022-05-03 03:56:07 +00:00
std::string hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void* val)
{
std::string ret("unknown");
char buf[40];
switch (type)
{
case SANE_TYPE_BOOL:
ret = *(SANE_Bool*)val ? "true" : "false";
break;
case SANE_TYPE_INT:
sprintf(buf, "%d", *(SANE_Word*)val);
2022-05-03 03:56:07 +00:00
ret = buf;
break;
case SANE_TYPE_FIXED:
sprintf(buf, "%f", hg_sane_middleware::sane_fixed_2_double(*(SANE_Word*)val));
2022-05-03 03:56:07 +00:00
ret = buf;
break;
case SANE_TYPE_STRING:
ret = (char*)val;
break;
case SANE_TYPE_BUTTON:
ret = "Button";
break;
case SANE_TYPE_GROUP:
ret = "Group";
break;
default:
break;
}
return ret;
}
scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h)
{
if (!h)
return nullptr;
2022-05-03 03:56:07 +00:00
int bits = sizeof(h) / 2 * 8;
uint64_t v = (uint64_t)h;
2022-05-03 03:56:07 +00:00
v ^= v >> bits;
return (scanner_handle)(v);
}
SANE_Handle hg_sane_middleware::scanner_handle_to_sane(scanner_handle h)
{
if (!h)
return nullptr;
2022-05-03 03:56:07 +00:00
int bits = sizeof(h) / 2 * 8;
uint64_t v = (uint64_t)h;
2022-05-03 03:56:07 +00:00
v ^= v >> bits;
return (SANE_Handle)(v);
}
SANE_Option_Descriptor* hg_sane_middleware::allocate_descriptor(const char* name, const char* title, const char* desc)
{
SANE_Option_Descriptor* opdesc = (SANE_Option_Descriptor*)local_utility::acquire_memory(sizeof(SANE_Option_Descriptor), "SANE_Option_Descriptor");
memset(opdesc, 0, sizeof(SANE_Option_Descriptor));
opdesc->name = (char*)local_utility::acquire_memory(strlen(name) + 1, "SANE_Option_Descriptor::name");
strcpy((char*)opdesc->name, name);
opdesc->title = (char*)local_utility::acquire_memory(strlen(title) + 1, "SANE_Option_Descriptor::title");
strcpy((char*)opdesc->title, title);
opdesc->desc = (char*)local_utility::acquire_memory(strlen(desc) + 1, "SANE_Option_Descriptor::desc");
strcpy((char*)opdesc->desc, desc);
return opdesc;
}
void hg_sane_middleware::free_descriptor(SANE_Option_Descriptor* desc)
{
if (desc)
{
if (desc->name)
local_utility::free_memory((void*)desc->name);
desc->name = nullptr;
if (desc->title)
local_utility::free_memory((void*)desc->title);
desc->title = nullptr;
if (desc->desc)
local_utility::free_memory((void*)desc->desc);
desc->desc = nullptr;
if (desc->constraint.range)
local_utility::free_memory((void*)desc->constraint.range);
desc->constraint.range = nullptr;
local_utility::free_memory(desc);
}
}
2022-05-03 03:56:07 +00:00
SANE_Option_Descriptor* hg_sane_middleware::string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<std::string>& values)
{
int bytes = (values.size() + 1) * sizeof(SANE_String);
SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
2022-05-03 03:56:07 +00:00
for (size_t i = 0; i < values.size(); ++i)
bytes += ALIGN_INT(values[i].length() + 1);
sod->type = SANE_TYPE_STRING;
sod->unit = SANE_UNIT_NONE;
sod->size = values.size();
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
2022-05-03 03:56:07 +00:00
if (values.size())
{
SANE_String* buf = (SANE_String*)local_utility::acquire_memory(bytes, "string_list");
char* str = (char*)buf + (values.size() + 1) * sizeof(SANE_String);
2022-05-03 03:56:07 +00:00
sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
sod->constraint.string_list = buf;
2022-05-03 03:56:07 +00:00
for (size_t i = 0; i < values.size(); ++i)
{
buf[i] = str;
2022-05-03 03:56:07 +00:00
strcpy(str, values[i].c_str());
str += ALIGN_INT(values[i].length() + 1);
}
}
return sod;
}
SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
2022-12-31 07:44:47 +00:00
, bool double_val, double* lower, double* upper, double* step)
2022-05-03 03:56:07 +00:00
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
2022-05-03 03:56:07 +00:00
sod->type = double_val ? SANE_TYPE_FIXED : SANE_TYPE_INT;
sod->unit = SANE_UNIT_NONE;
sod->size = sizeof(SANE_Word);
2022-07-18 02:54:41 +00:00
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT
| SANE_CAP_AUTOMATIC;
2022-05-03 03:56:07 +00:00
if (lower || upper)
{
sod->size = sizeof(SANE_Range);
sod->constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range* range = (SANE_Range*)local_utility::acquire_memory(sizeof(SANE_Range), "constraint.range");
2022-05-03 03:56:07 +00:00
if (lower)
{
if (double_val)
range->min = hg_sane_middleware::double_2_sane_fixed(*lower);
2022-05-03 03:56:07 +00:00
else
range->min = (SANE_Word)*lower;
2022-05-03 03:56:07 +00:00
}
if (upper)
{
if (double_val)
range->max = hg_sane_middleware::double_2_sane_fixed(*upper);
2022-05-03 03:56:07 +00:00
else
range->max = (SANE_Word)*upper;
2022-05-03 03:56:07 +00:00
}
range->quant = 0;
2022-12-31 07:44:47 +00:00
if (step)
{
if(double_val)
range->quant = hg_sane_middleware::double_2_sane_fixed(*step);
2022-12-31 07:44:47 +00:00
else
range->quant = (SANE_Word)(*step);
2022-12-31 07:44:47 +00:00
}
2022-05-03 03:56:07 +00:00
sod->constraint.range = range;
2022-05-03 03:56:07 +00:00
}
return sod;
}
SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<int>& values)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
2022-05-03 03:56:07 +00:00
sod->type = SANE_TYPE_INT;
sod->unit = SANE_UNIT_NONE;
sod->size = sizeof(SANE_Word);
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
2022-05-03 03:56:07 +00:00
if (values.size())
{
sod->constraint.word_list = (SANE_Word*)local_utility::acquire_memory(sizeof(SANE_Word) * (values.size() + 1), "word_list");
SANE_Word* val = (SANE_Word*)sod->constraint.word_list;
2022-05-03 03:56:07 +00:00
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
*val++ = values.size();
for (size_t i = 0; i < values.size(); ++i)
val[i] = values[i];
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
2022-05-03 03:56:07 +00:00
return sod;
}
SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<double>& values)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
2022-05-03 03:56:07 +00:00
sod->type = SANE_TYPE_FIXED;
sod->unit = SANE_UNIT_NONE;
sod->size = sizeof(SANE_Word);
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
2022-05-03 03:56:07 +00:00
if (values.size())
{
sod->constraint.word_list = (SANE_Word*)local_utility::acquire_memory(sizeof(SANE_Word) * (values.size() + 1), "word_list");
SANE_Word* val = (SANE_Word*)sod->constraint.word_list;
2022-05-03 03:56:07 +00:00
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
*val++ = values.size();
for (size_t i = 0; i < values.size(); ++i)
val[i] = hg_sane_middleware::double_2_sane_fixed(values[i]);
}
return sod;
}
std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key)
{
std::string str("");
int id = -1;
if (jsn->get_value(key, id) && id != -1)
{
str = lang_load_string(id, &id);
}
else
jsn->get_value(key, str);
return std::move(str);
}
std::string hg_sane_middleware::sane_path(void)
{
return g_sane_path;
}
hg_sane_middleware* hg_sane_middleware::instance(void)
{
if (!hg_sane_middleware::inst_)
hg_sane_middleware::inst_ = new hg_sane_middleware();
return hg_sane_middleware::inst_;
}
void hg_sane_middleware::set_callback(sane_callback cb, void* param)
{
local_utility::set_callback(cb, param);
}
void hg_sane_middleware::clear(void)
{
local_utility::stop_work();
if (hg_sane_middleware::inst_)
{
delete hg_sane_middleware::inst_;
hg_sane_middleware::inst_ = NULL;
}
}
void hg_sane_middleware::reload_options(scanner_handle dev)
{
for (auto& v : openning_)
{
if (dev && dev != v->dev)
continue;
std::vector<DEVOPT> opts(std::move(v->opts));
long count = 0;
hg_sane_middleware::free_device_inst(v, false);
hg_scanner_get_parameter(v->dev, nullptr, NULL, &count);
for (long ind = 1; ind < count; ++ind)
{
get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind);
int n = v->opts.size() - 1;
if (n >= 0)
{
for (int i = 0; i < opts.size(); ++i)
{
if (v->opts[n].opt_name == opts[i].opt_name)
{
local_utility::free_memory((void*)opts[i].desc->name);
local_utility::free_memory((void*)opts[i].desc->title);
local_utility::free_memory((void*)opts[i].desc->desc);
local_utility::free_memory((void*)opts[i].desc->constraint.range);
*opts[i].desc = *v->opts[n].desc;
v->opts[n].desc->name = v->opts[n].desc->title = v->opts[n].desc->desc = nullptr;
v->opts[n].desc->constraint.range = nullptr;
hg_sane_middleware::free_descriptor(v->opts[n].desc);
v->opts[n].desc = opts[i].desc;
opts.erase(opts.begin() + i);
break;
}
}
}
}
// do depend logic opertion ...
for (auto& d : v->slaves)
{
SANE_Option_Descriptor* desc = get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), &d.name[0]);
set_status_by_depends(v->dev, d, v->cur_vals, desc);
}
}
}
void hg_sane_middleware::set_status_by_depends(scanner_handle hdev, SLAVEOP& so, std::vector<CURVAL>& vals, SANE_Option_Descriptor* desc)
{
if (so.master.size())
{
so.enable_now = so.is_enable(hdev, so.master, vals);
if (so.enable_now)
desc->cap &= ~SANE_CAP_INACTIVE;
else
desc->cap |= SANE_CAP_INACTIVE;
}
}
2022-05-03 03:56:07 +00:00
SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc)
{
scanner_handle h = NULL;
scanner_err err = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
if (handle == NULL)
return SANE_STATUS_INVAL;
err = hg_scanner_open(&h, devicename, false, NULL, NULL, NULL, rsc);
if (err == SCANNER_ERR_OK)
2022-05-03 03:56:07 +00:00
{
LPDEVINST inst = new DEVINST;
2022-05-03 03:56:07 +00:00
inst->name = devicename;
inst->dev = h;
openning_.push_back(inst);
2022-05-03 03:56:07 +00:00
*handle = hg_sane_middleware::scanner_handle_to_sane(h);
if (!local_utility::cb_ui_)
{
long count = 0;
hg_scanner_get_parameter(h, 0, NULL, &count);
inst->std_opt = new sane_std_opts(count);
}
2022-05-03 03:56:07 +00:00
return SANE_STATUS_GOOD;
}
else if (err == SCANNER_ERR_ACCESS_DENIED)
2022-05-03 03:56:07 +00:00
{
return SANE_STATUS_ACCESS_DENIED;
}
else
return (SANE_Status)err; // SANE_STATUS_UNSUPPORTED;
2022-05-03 03:56:07 +00:00
}
SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, json* jsn)
2022-05-03 03:56:07 +00:00
{
std::string title(hg_sane_middleware::get_string_in_json(jsn, "title")),
desc(hg_sane_middleware::get_string_in_json(jsn, "desc")),
val("");
2022-05-03 03:56:07 +00:00
std::vector<std::string> constraints;
2022-12-31 07:44:47 +00:00
double lower = .0f, upper = .0f, step = .0f;
2022-05-03 03:56:07 +00:00
bool db_val = false;
2023-08-11 09:53:56 +00:00
int opt_val_size = 0;
2022-05-03 03:56:07 +00:00
if (!jsn->get_value("type", val))
return NULL;
SANE_Option_Descriptor* ret = NULL;
if (val == "string")
{
json* range = NULL;
std::vector<std::string> constraints;
jsn->get_value("range", range);
if (range)
{
if (range->first_child(val))
{
2023-08-11 09:53:56 +00:00
local_utility::trans_language_if_was_word_id(val);
constraints.push_back(val);
opt_val_size = val.length();
while (range->next_child(val))
{
local_utility::trans_language_if_was_word_id(val);
constraints.push_back(val);
2023-08-11 09:53:56 +00:00
if (opt_val_size < val.length())
opt_val_size = val.length();
2022-05-03 03:56:07 +00:00
}
}
delete range;
}
ret = hg_sane_middleware::string_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, constraints);
}
else if (val == "int" || val == "float")
{
json* range = NULL;
jsn->get_value("range", range);
if (range)
{
if (val == "int")
{
int l = 0;
if (range->get_value("min", l))
{
2022-12-31 07:44:47 +00:00
int u = 0, s = 1;
2022-05-03 03:56:07 +00:00
range->get_value("max", u);
2022-12-31 07:44:47 +00:00
range->get_value("step", s);
2022-05-03 03:56:07 +00:00
lower = l;
upper = u;
2022-12-31 07:44:47 +00:00
step = s;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s range: [%d, +%d, %d]\n", name.c_str(), l, s, u);
2022-05-03 03:56:07 +00:00
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, false, &lower, &upper, &step);
2022-05-03 03:56:07 +00:00
}
else
{
std::vector<int> constraints;
if (range->first_child(val))
{
constraints.push_back(atoi(val.c_str()));
while (range->next_child(val))
{
constraints.push_back(atoi(val.c_str()));
}
}
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, constraints);
}
}
else
{
if (range->get_value("min", lower))
{
range->get_value("max", upper);
2022-12-31 07:44:47 +00:00
step = (upper - lower) / 10.0f;
range->get_value("step", step);
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s range: (%f, +%f, %f)\n", name.c_str(), lower, step, upper);
2022-05-03 03:56:07 +00:00
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, true, &lower, &upper, &step);
2022-05-03 03:56:07 +00:00
}
else
{
std::vector<double> constraints;
if (range->first_child(val))
{
constraints.push_back(atof(val.c_str()));
while (range->next_child(val))
{
constraints.push_back(atof(val.c_str()));
}
}
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, constraints);
}
}
delete range;
}
else
{
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, false, NULL, NULL, NULL);
2022-05-03 03:56:07 +00:00
}
}
else if (val == "bool")
{
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, false, NULL, NULL, NULL);
2022-05-03 03:56:07 +00:00
ret->type = SANE_TYPE_BOOL;
}
else if (val == "button")
{
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, false, NULL, NULL, NULL);
2022-05-03 03:56:07 +00:00
ret->type = SANE_TYPE_BUTTON;
}
else if (val == "group")
{
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
2022-12-31 07:44:47 +00:00
, false, NULL, NULL, NULL);
2022-05-03 03:56:07 +00:00
ret->type = SANE_TYPE_GROUP;
}
// fill the 'size' field, for SANE_ACTION_GET action ...
if (ret)
{
int bytes = 0;
bool bv = false;
2022-05-03 03:56:07 +00:00
jsn->get_value("size", bytes);
2023-08-11 09:53:56 +00:00
if (bytes < opt_val_size)
{
opt_val_size = ALIGN_INT(opt_val_size + 4);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Resize size of '%s' from %d to %d\n", name.c_str(), bytes, opt_val_size);
bytes = opt_val_size;
}
2022-05-03 03:56:07 +00:00
ret->size = bytes;
if (jsn->get_value("auto", bv) && !bv)
ret->cap &= ~SANE_CAP_AUTOMATIC;
if (jsn->get_value("readonly", bv) && bv)
SET_CAP_READONLY(ret->cap)
2022-05-03 03:56:07 +00:00
val = "";
jsn->get_value("cat", val);
2022-05-03 03:56:07 +00:00
if (val == "advanced")
{
ret->cap |= SANE_CAP_ADVANCED;
}
if (strcmp(ret->name, SANE_STD_OPT_NAME_RESOLUTION) == 0)
2022-05-03 03:56:07 +00:00
{
ret->unit = SANE_UNIT_DPI;
}
else if (strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) == 0)
2022-05-06 05:37:14 +00:00
ret->unit = SANE_UNIT_MM;
2022-05-03 03:56:07 +00:00
//bool enabled = true;
//if (jsn->get_value("enable", enabled) && !enabled)
// ret->cap |= SANE_CAP_INACTIVE;
// 关联<E585B3><E88194>?
2022-05-03 03:56:07 +00:00
json* depend = NULL;
SLAVEOP so;
if (jsn->get_value("depend_or", depend))
{
so.is_enable = &hg_sane_middleware::is_enable_or;
}
else if (jsn->get_value("depend_and", depend))
{
so.is_enable = &hg_sane_middleware::is_enable_and;
}
if (depend)
{
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(h);
if (it != openning_.end() && parse_depends(h, depend, so, (*it)->masters))
2022-05-03 03:56:07 +00:00
{
so.enable_now = (ret->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE;
so.name = name;
2022-05-03 03:56:07 +00:00
// initializing status ... move to set_status_by_depends (2023-06-21)
//if (so.master.size())
//{
// //std::string master(get_option_json(h, (void *)so.master[0].name.c_str()));
// //json* m = new json();
// //if (m->attach_text(&master[0]))
// //{
// // bool integer = false, str = false;
//
// // master = "";
// // m->get_value("type", master);
// // integer = master == "int";
// // str = master == "string";
// // master = "";
// // m->get_value_as_string("cur", master, integer);
// // local_utility::trans_language_if_was_word_id(val);
// so.enable_now = so.is_enable(h, so.master, (*it)->cur_vals);
// if (!so.enable_now)
// ret->cap |= SANE_CAP_INACTIVE;
// //}
// //delete m;
//}
(*it)->slaves.push_back(so);
2022-05-03 03:56:07 +00:00
}
delete depend;
}
}
return ret;
}
void hg_sane_middleware::free_device_inst(LPDEVINST dev, bool del)
{
for (auto& v : dev->opts)
hg_sane_middleware::free_descriptor(v.desc);
if (del)
{
if (dev->std_opt)
delete dev->std_opt;
delete dev;
}
else
{
if (dev->std_opt)
dev->std_opt->clear();
dev->opts.clear();
dev->cur_vals.clear();
dev->slaves.clear();
dev->masters.clear();
}
}
scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv, LPDEVINST* dev)
2022-05-03 03:56:07 +00:00
{
scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
2022-05-03 03:56:07 +00:00
if (it == openning_.end())
handle = NULL;
else
{
if (dev)
*dev = *it;
if (rmv)
{
if (!dev)
hg_sane_middleware::free_device_inst(*it);
2022-05-03 03:56:07 +00:00
openning_.erase(it);
}
2022-05-03 03:56:07 +00:00
}
return handle;
}
std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt, std::string* key, SANE_Int* id)
2022-05-03 03:56:07 +00:00
{
char* json_txt = NULL;
long length = 0;
scanner_err err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length);
2022-05-03 03:56:07 +00:00
std::string ret("");
if (err == SCANNER_ERR_INSUFFICIENT_MEMORY)
2022-05-03 03:56:07 +00:00
{
json_txt = (char*)local_utility::acquire_memory(ALIGN_INT(length + 4), "hg_sane_middleware::get_option_json");
bzero(json_txt, length + 4);
err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length, id);
if (err == SCANNER_ERR_OK)
2022-05-03 03:56:07 +00:00
{
const char* head = json_txt;
local_utility::skip_space(head);
if (*head == '\"')
{
head++;
while (*head != '\"' && *head)
ret.append(1, *head++);
if (*head)
{
head++;
local_utility::skip_space(head);
if (*head == ':')
{
head++;
local_utility::skip_space(head);
}
}
}
if (key)
*key = ret;
ret = head;
2022-05-03 03:56:07 +00:00
}
free(json_txt);
}
return ret;
}
2023-06-15 02:10:17 +00:00
SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id, SANE_Int* fix_id)
2022-05-03 03:56:07 +00:00
{
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (it != openning_.end())
{
if (IS_PTR_NUMBER(option))
{
2023-06-15 02:10:17 +00:00
if ((SANE_Int)(long long)option >= SANE_OPT_ID_BASE)
{
2023-06-15 02:10:17 +00:00
for (const auto& v : (*it)->opts)
{
if (v.fixed_no == (SANE_Int)(long long)option)
{
if (id)
*id = v.option_no;
if (fix_id)
*fix_id = v.fixed_no;
return v.desc;
}
}
}
else
{
for (const auto& v : (*it)->opts)
{
if (v.option_no == (SANE_Int)(long long)option)
{
if (id)
*id = v.option_no;
if (fix_id)
*fix_id = v.fixed_no;
return v.desc;
}
}
}
}
else
{
for (const auto& v : (*it)->opts)
{
if (v.opt_name == (const char*)option)
{
if (id)
*id = v.option_no;
2023-06-15 02:10:17 +00:00
if (fix_id)
*fix_id = v.fixed_no;
return v.desc;
}
}
}
2022-05-03 03:56:07 +00:00
}
return NULL;
}
void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector<std::string>* changed)
2022-06-15 03:05:36 +00:00
{
long count = 0;
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
2022-06-15 03:05:36 +00:00
if (changed)
changed->clear();
hg_scanner_get_parameter(handle, 0, NULL, &count);
for (int i = 1; i < count; ++i)
{
std::string key(""),
val(get_option_json(handle, (void *)i, &key));
2022-06-15 03:05:36 +00:00
json* jsn = new json();
if (jsn->attach_text(&val[0]) &&
jsn->get_value("type", val))
{
if (refresh_current_value(*it, key.c_str(), jsn))
changed->push_back(key);
2022-06-15 03:05:36 +00:00
}
delete jsn;
}
}
bool hg_sane_middleware::get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type)
2022-05-03 03:56:07 +00:00
{
if (IS_PTR_NUMBER(option))
{
2023-05-17 01:42:46 +00:00
int id = (int)(uint64_t)option,
l = 0;
std::string name(local_utility::un_json_option_name(id, &l));
if(!name.empty())
{
2023-05-29 07:51:01 +00:00
char *buf = new char[l + 4];
long len = l;
bool ret = false;
2023-05-17 01:42:46 +00:00
memcpy(buf, value, l);
2023-05-29 07:51:01 +00:00
buf[l] = 0;
if (hg_scanner_get_parameter(handle, name.c_str(), buf, &len) == SCANNER_ERR_OK)
{
setv(buf, len, value);
2023-05-29 07:51:01 +00:00
ret = true;
}
2023-05-29 07:51:01 +00:00
delete[] buf;
2023-05-29 07:51:01 +00:00
return ret;
}
}
std::string name(""),
val(get_option_json(handle, (void *)option, &name));
2022-06-15 03:05:36 +00:00
json* jsn = new json();
2022-05-03 03:56:07 +00:00
int estimate = 20;
bool ret = false;
if (jsn->attach_text(&val[0]) &&
jsn->get_value("type", val))
{
SANE_Value_Type t = SANE_TYPE_STRING;
ret = true;
if (val == "int")
2022-05-03 03:56:07 +00:00
{
int v = 0;
jsn->get_value("cur", v);
// *((SANE_Int*)value) = v;
setv(&v, sizeof(v), value);
2022-05-03 03:56:07 +00:00
t = SANE_TYPE_INT;
}
else if (val == "bool")
{
bool bv = false;
SANE_Bool v = SANE_FALSE;
jsn->get_value("cur", bv);
// *(SANE_Bool*)value = v;
v = bv;
setv(&v, sizeof(v), value);
2022-05-03 03:56:07 +00:00
t = SANE_TYPE_BOOL;
}
else if (val == "float")
{
double dv = .0f;
SANE_Fixed v = 0;
jsn->get_value("cur", dv);
v = hg_sane_middleware::double_2_sane_fixed(dv);
setv(&v, sizeof(v), value);
2022-05-03 03:56:07 +00:00
t = SANE_TYPE_FIXED;
}
else
{
int size = 0;
jsn->get_value("size", size);
val = hg_sane_middleware::get_string_in_json(jsn, "cur");
if (size <= val.length())
size = val.length() + 1;
//strcpy((char*)value, val.c_str());
setv(&val[0], size, value);
2022-05-03 03:56:07 +00:00
estimate += val.length();
}
if (type)
*type = t;
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
refresh_current_value(*it, name.c_str(), jsn);
2022-05-03 03:56:07 +00:00
val = hg_sane_middleware::get_string_in_json(jsn, "title");
2022-05-03 03:56:07 +00:00
if (setv == &hg_sane_middleware::set_value_to_new)
value = *(void**)value;
VLOG_MINI_3(LOG_LEVEL_ALL, "<--Get option(%d - %s) value: %s\n", option, val.c_str(), hg_sane_middleware::option_value_2_string(t, value).c_str());
2022-05-03 03:56:07 +00:00
}
delete jsn;
return ret;
}
void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* option, int* bytes, bool log, bool* can_auto)
{
std::string val(get_option_json(handle, (void *)option));
2022-06-15 03:05:36 +00:00
void* data = nullptr;
json* jsn = new json();
if (jsn->attach_text(&val[0]) &&
jsn->get_value("type", val))
{
if (can_auto)
{
bool yes = false;
*can_auto = true;
if (jsn->get_value("auto", yes))
*can_auto = yes;
}
std::string title(hg_sane_middleware::get_string_in_json(jsn, "title"));
if (val == "bool")
{
bool v = false;
jsn->get_value("default", v);
data = local_utility::acquire_memory(sizeof(SANE_Bool), "");
memcpy(data, &v, sizeof(v));
if (bytes)
*bytes = sizeof(SANE_Bool);
2022-11-10 03:09:16 +00:00
if (log)
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) default value is: %s\n", option, title.c_str(), v ? "true" : "false");
}
}
else if (val == "int")
{
int v = 0;
jsn->get_value("default", v);
data = local_utility::acquire_memory(sizeof(v), "");
memcpy(data, &v, sizeof(v));
if (bytes)
*bytes = sizeof(v);
2022-11-10 03:09:16 +00:00
if (log)
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) default value is: %d\n", option, title.c_str(), v);
}
}
else if (val == "float")
{
double v = .0f;
jsn->get_value("default", v);
SANE_Fixed sd = hg_sane_middleware::double_2_sane_fixed(v);
data = local_utility::acquire_memory(sizeof(sd), "");
if (bytes)
*bytes = sizeof(sd);
memcpy(data, &sd, sizeof(sd));
2022-11-10 03:09:16 +00:00
if (log)
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) default value is: %f\n", option, title.c_str(), v);
}
}
else if (val == "string")
{
int size = 0;
jsn->get_value("size", size);
val = hg_sane_middleware::get_string_in_json(jsn, "default");
2022-07-18 02:54:41 +00:00
if (size < (int)val.length())
size = val.length();
data = local_utility::acquire_memory(size + 4, "");
strcpy((char*)data, val.c_str());
if (bytes)
2023-06-15 02:10:17 +00:00
*bytes = val.length() + 1;
2022-11-10 03:09:16 +00:00
if (log)
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) default value is: %s\n", option, title.c_str(), (char*)data);
}
}
else
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) is '%s' and no value action.\n", option, title.c_str(), val.c_str());
}
}
delete jsn;
2022-05-03 03:56:07 +00:00
if (!data)
2022-05-03 03:56:07 +00:00
{
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (it != openning_.end() && (*it)->std_opt)
{
SANE_Int id = -1;
find_stored_descriptor(handle, option, &id);
data = (*it)->std_opt->get_default_value(handle, id);
}
2022-05-03 03:56:07 +00:00
}
2022-06-15 03:05:36 +00:00
return data;
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SANE_Bool local_only)
{
if (!device_list)
return SANE_STATUS_INVAL;
ScannerInfo * dev = NULL;
2022-05-03 03:56:07 +00:00
long count = 0;
scanner_err hgerr = hg_scanner_enum(dev, &count, local_only);
2022-05-03 03:56:07 +00:00
SANE_Status ret = SANE_STATUS_GOOD;
if (hgerr == SCANNER_ERR_INSUFFICIENT_MEMORY)
2022-05-03 03:56:07 +00:00
{
count += 4; // 为两次hg_scanner_enum间隙可能新增的设备预留空<E79599><E7A9BA>?
dev = (ScannerInfo*)local_utility::acquire_memory(sizeof(ScannerInfo) * count, "hg_sane_middleware::get_devices");
2022-05-03 03:56:07 +00:00
hgerr = hg_scanner_enum(dev, &count, local_only);
if (hgerr != SCANNER_ERR_OK)
2022-05-03 03:56:07 +00:00
{
local_utility::free_memory(dev);
2022-05-03 03:56:07 +00:00
dev = NULL;
}
}
if (hgerr == SCANNER_ERR_OK)
2022-05-03 03:56:07 +00:00
{
*device_list = hg_sane_middleware::to_sane_device(dev, count);
if (dev)
local_utility::free_memory(dev);
2022-05-03 03:56:07 +00:00
}
else
ret = local_utility::scanner_err_2_sane_statu(hgerr);
2022-05-03 03:56:07 +00:00
if (hg_sane_middleware::dev_list_)
local_utility::free_memory(hg_sane_middleware::dev_list_);
2022-05-03 03:56:07 +00:00
hg_sane_middleware::dev_list_ = *device_list;
return ret;
}
SANE_Status hg_sane_middleware::open_device(SANE_String_Const devicename, SANE_Handle* handle)
{
char rsc[128];
SANE_Status ret = SANE_STATUS_GOOD;
bzero(rsc, sizeof(rsc));
ret = open(devicename, handle, NULL, NULL, NULL, rsc);
if (ret == SANE_STATUS_ACCESS_DENIED && rsc[0])
{
SANEAUTH auth;
bzero(&auth, sizeof(auth));
auth.resource = rsc;
if (local_utility::ui_cb(NULL, SANE_EVENT_NEED_AUTH, (void*)&auth, NULL, NULL))
{
return SANE_STATUS_CANCELLED;
}
ret = open(devicename, handle, auth.name, auth.pwd, auth.method, rsc);
}
if (ret == SANE_STATUS_GOOD)
{
// for depend item maybe later, we move the depend-logic-operation out of 'from_json'. to ensure the status, we get all options actively and do depend-logic operation after all options got - 2023-06-21
reload_options(hg_sane_middleware::sane_handle_to_scanner(*handle));
}
2022-05-03 03:56:07 +00:00
return ret;
}
SANE_Status hg_sane_middleware::close_device(SANE_Handle h)
{
scanner_handle hs = find_openning_device(h, true);
SANE_Status err = SANE_STATUS_GOOD;
if (hs)
err = local_utility::scanner_err_2_sane_statu(hg_scanner_close(hs, true));
2022-05-03 03:56:07 +00:00
return err;
}
SANE_Status hg_sane_middleware::get_image_parameters(SANE_Handle handle, SANE_Parameters* params)
{
scanner_handle h = find_openning_device(handle);
scanner_err err = SCANNER_ERR_NOT_START;
2022-05-03 03:56:07 +00:00
if (!params)
return SANE_STATUS_INVAL;
err = hg_scanner_get_img_info(h, params, sizeof(*params));
return local_utility::scanner_err_2_sane_statu(err);
2022-05-03 03:56:07 +00:00
}
2023-10-07 04:41:50 +00:00
SANE_Status hg_sane_middleware::get_image_parameters_ex(SANE_Handle handle, SANE_Image* params)
{
scanner_handle h = find_openning_device(handle);
scanner_err err = SCANNER_ERR_NOT_START;
if (!params)
return SANE_STATUS_INVAL;
err = hg_scanner_get_img_info(h, (SANE_Parameters*)params, sizeof(*params));
return local_utility::scanner_err_2_sane_statu(err);
}
2022-05-03 03:56:07 +00:00
SANE_Status hg_sane_middleware::start(SANE_Handle h, void* async_event)
{
LPDEVINST dev;
scanner_handle hs = find_openning_device(h);
scanner_err err = SCANNER_ERR_INVALID_PARAMETER;
2022-05-03 03:56:07 +00:00
2023-12-07 07:06:48 +00:00
LOG_INFO(LOG_LEVEL_ALL, "sane_start ...\n");
2022-05-03 03:56:07 +00:00
if(hs)
err = hg_scanner_start(hs, async_event, -1);
2022-05-03 03:56:07 +00:00
return local_utility::scanner_err_2_sane_statu(err);
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware::read(SANE_Handle h, void* buf, int* bytes)
{
scanner_handle hs = find_openning_device(h);
scanner_err err = SCANNER_ERR_INVALID_PARAMETER;
2022-05-03 03:56:07 +00:00
long r = bytes ? *bytes : 0;
if (bytes && hs)
{
err = hg_scanner_read_img_data(hs, (unsigned char*)buf, &r);
*bytes = r;
}
return local_utility::scanner_err_2_sane_statu(err);
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware::stop(SANE_Handle h)
{
2023-10-23 03:26:35 +00:00
LOG_INFO(LOG_LEVEL_ALL, "sane_cancel\n");
2022-05-03 03:56:07 +00:00
scanner_handle hs = find_openning_device(h);
if(hs)
hg_scanner_stop(hs);
return SANE_STATUS_GOOD;
}
SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, const void* option)
2022-05-03 03:56:07 +00:00
{
SANE_Option_Descriptor* ret = nullptr;
scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
SANE_Int id = -1;
2022-05-03 03:56:07 +00:00
if (!handle || it == openning_.end())
return nullptr;
else if (option == 0)
{
if (!opt_0_)
{
opt_0_ = (SANE_Option_Descriptor*)local_utility::acquire_memory(sizeof(SANE_Option_Descriptor), "");
opt_0_->cap = SANE_CAP_SOFT_DETECT;
opt_0_->name = "option-count";
opt_0_->title = "";
opt_0_->desc = "Number of options";
opt_0_->type = SANE_TYPE_INT;
opt_0_->size = sizeof(SANE_TYPE_INT);
}
LOG_INFO(LOG_LEVEL_DEBUG_INFO, "get_option_descriptor(0)\n");
return opt_0_;
}
ret = find_stored_descriptor(handle, option, &id);
2022-05-03 03:56:07 +00:00
if (!ret)
{
std::string key(""),
json_txt(get_option_json(handle, (void*)option, &key, &id));
2022-05-03 03:56:07 +00:00
if (json_txt.length())
{
json* jsn = new json();
if (jsn->attach_text(&json_txt[0]))
{
ret = from_json(handle, key, jsn);
2022-05-03 03:56:07 +00:00
if (ret)
{
DEVOPT devopt;
devopt.option_no = id;
2023-06-15 02:10:17 +00:00
devopt.fixed_no = 0;
2022-05-03 03:56:07 +00:00
devopt.desc = ret;
2023-06-15 02:10:17 +00:00
if (jsn->get_value("fix-id", devopt.fixed_no))
(*it)->fixed_id[(sane_option_id)devopt.fixed_no] = id;
else
local_utility::init_fixed_id(key.c_str(), id, (*it)->fixed_id, &devopt.fixed_no);
devopt.opt_name = std::move(key);
(*it)->opts.push_back(std::move(devopt));
2022-05-03 03:56:07 +00:00
if ((*it)->std_opt)
(*it)->std_opt->init_known_opt(id, ret);
refresh_current_value(*it, ret->name, jsn);
2022-05-03 03:56:07 +00:00
}
}
delete jsn;
}
if(!ret && (*it)->std_opt)
ret = (*it)->std_opt->get_option(id);
2022-05-03 03:56:07 +00:00
}
return ret;
}
SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do)
2022-05-03 03:56:07 +00:00
{
2023-07-31 02:46:33 +00:00
if ((IS_PTR_NUMBER(option) && (int)(long)option == SANE_OPT_ID_DRIVER_LOG) ||
(!IS_PTR_NUMBER(option) && strcmp((const char*)option, SANE_STD_OPT_NAME_DRIVER_LOG) == 0))
{
// omit value of 'h' ...
long id = SANE_OPT_ID_DRIVER_LOG,
l = 0;
std::string name(local_utility::un_json_option_name(id, (int*)&l));
if (action == SANE_ACTION_GET_VALUE)
return local_utility::scanner_err_2_sane_statu(hg_scanner_get_parameter(h, SANE_STD_OPT_NAME_DRIVER_LOG, (char*)value, &l));
else if (action == SANE_ACTION_SET_VALUE)
return local_utility::scanner_err_2_sane_statu(hg_scanner_set_parameter(h, SANE_STD_OPT_NAME_DRIVER_LOG, (char*)value, &l));
else
return SANE_STATUS_INVAL;
}
LPDEVINST dev = nullptr;
2022-05-03 03:56:07 +00:00
scanner_handle handle = find_openning_device(h, false, &dev);
if (!handle || (action == SANE_ACTION_GET_VALUE && !value))
return SANE_STATUS_INVAL;
if (hg_scanner_get_status(handle, 0) == SCANNER_ERR_DEVICE_NOT_FOUND)
return local_utility::scanner_err_2_sane_statu(SCANNER_ERR_DEVICE_NOT_FOUND);
2022-05-03 03:56:07 +00:00
if (action == SANE_ACTION_GET_VALUE)
{
if (after_do)
*after_do = 0;
SANE_Status ret = SANE_STATUS_IO_ERROR;
if (option == 0)
{
long count = 0;
hg_scanner_get_parameter(handle, (const char*)option, NULL, &count);
2022-05-03 03:56:07 +00:00
*((SANE_Int*)value) = count;
ret = SANE_STATUS_GOOD;
VLOG_MINI_1(LOG_LEVEL_WARNING, "get option count = %d.\n", count);
2022-05-03 03:56:07 +00:00
}
else
{
SANE_Int id = -1;
SANE_Option_Descriptor* desc = find_stored_descriptor(handle, option);
if (desc &&
(desc->type == SANE_TYPE_BUTTON || desc->type == SANE_TYPE_GROUP))
return SANE_STATUS_UNSUPPORTED;
if (dev->std_opt && dev->std_opt->is_known_option(id))
{
dev->std_opt->get_value(h, id, value);
ret = SANE_STATUS_GOOD;
}
else if(get_current_value(handle, option, &hg_sane_middleware::set_value_to_var, value))
2022-05-03 03:56:07 +00:00
ret = SANE_STATUS_GOOD;
}
return ret;
}
else if (action == SANE_ACTION_GET_DEFAULT_VALUE)
{
SANE_Option_Descriptor* desc = find_stored_descriptor(handle, option);
if (desc &&
(desc->type == SANE_TYPE_BUTTON || desc->type == SANE_TYPE_GROUP))
return SANE_STATUS_UNSUPPORTED;
int len = 0;
void* val = get_default_value(handle, option, &len);
if (!val)
return SANE_STATUS_UNSUPPORTED;
memcpy(value, val, len);
local_utility::free_memory(val);
return SANE_STATUS_GOOD;
}
2023-06-15 02:10:17 +00:00
else if (action == SANE_ACTION_GET_FIX_ID)
{
SANE_Int id = 0;
find_stored_descriptor(handle, option, nullptr, &id);
if (id > SANE_OPT_ID_BASE)
{
*(SANE_Int*)value = id;
return SANE_STATUS_GOOD;
}
else
return SANE_STATUS_UNSUPPORTED;
}
else if(action == SANE_ACTION_SET_AUTO || action == SANE_ACTION_SET_VALUE)
2022-05-03 03:56:07 +00:00
{
SANE_Int id = -1;
SANE_Option_Descriptor* desc = find_stored_descriptor(handle, option, &id);
bool release_value = false;
scanner_err err = SCANNER_ERR_OK;
SANE_Status status = SANE_STATUS_GOOD;
2023-06-15 02:10:17 +00:00
std::string prev(""), v(""), desc_name(""), desc_title("");
SANE_Value_Type sane_type = SANE_TYPE_BUTTON;
if (desc)
{
desc_name = desc->name;
desc_title = desc->title;
sane_type = desc->type;
}
2022-05-03 03:56:07 +00:00
if (action == SANE_ACTION_SET_AUTO && desc && desc->type != SANE_TYPE_BUTTON && desc->type != SANE_TYPE_GROUP) // we assume the driver can set the option properbly, and no work to do
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title);
int len = 0;
bool can_auto = true;
void* val = get_default_value(handle, option, &len, false, &can_auto);
if (!val || !can_auto)
{
if(val)
local_utility::free_memory(val);
2023-06-15 02:10:17 +00:00
return SANE_STATUS_UNSUPPORTED;
}
2023-06-15 02:10:17 +00:00
if (value)
{
memcpy(value, val, len);
local_utility::free_memory(val);
}
else
{
value = val;
release_value = true;
}
}
if (dev->std_opt && dev->std_opt->is_known_option(id, &desc))
2022-05-03 03:56:07 +00:00
{
SANE_Option_Descriptor* known = dev->std_opt->get_option(id);
unsigned char* cont = (unsigned char*)value;
prev = hg_sane_middleware::option_value_2_string(known->type, value);
VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "$First 4-bytes of origin value for option %d is: %02X%02X%02X%02X\n", option, cont[0], cont[1], cont[2], cont[3]);
err = dev->std_opt->set_value(handle, id, value);
v = hg_sane_middleware::option_value_2_string(known->type, value);
2022-05-03 03:56:07 +00:00
}
else
2022-05-03 03:56:07 +00:00
{
if (!desc)
{
if (IS_PTR_NUMBER(option))
{
2023-05-17 01:42:46 +00:00
int id = (int)(uint64_t)option,
l = 0;
std::string name(local_utility::un_json_option_name(id, &l));
if (!name.empty())
return local_utility::scanner_err_2_sane_statu(hg_scanner_set_parameter(handle, name.c_str(), value, 0));
}
VLOG_MINI_1(LOG_LEVEL_FATAL, "Option descriptor %d not found.\n", option);
return SANE_STATUS_UNSUPPORTED;
}
else if (!value && desc->type != SANE_TYPE_BUTTON)
{
//if (action == SANE_ACTION_SET_AUTO) // we assume the driver can set the option properbly, and no work to do
//{
// VLOG_MINI_2(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title);
//
// value = get_default_value(handle, option);
// if (!value)
// return SANE_STATUS_GOOD;
// release_value = true;
//}
//else
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title);
return SANE_STATUS_INVAL;
}
}
2022-05-03 03:56:07 +00:00
void* pass = value;
double dv = .0f;
bool bv = false;
long size = desc->size;
2022-05-03 03:56:07 +00:00
prev = hg_sane_middleware::option_value_2_string(desc->type, value);
if (desc->type == SANE_TYPE_BOOL)
{
bv = *((SANE_Bool*)value) == SANE_TRUE;
pass = &bv;
size = sizeof(bv);
}
else if (desc->type == SANE_TYPE_FIXED)
{
dv = hg_sane_middleware::sane_fixed_2_double(*((SANE_Fixed*)value));
pass = &dv;
size = sizeof(dv);
}
2022-05-03 03:56:07 +00:00
2023-06-15 02:10:17 +00:00
err = hg_scanner_set_parameter(handle, (const char*)option, pass, &size); // NOTE: change language will lead 'desc' reallocated !!!
2022-05-03 03:56:07 +00:00
2023-06-15 02:10:17 +00:00
if (sane_type == SANE_TYPE_BOOL)
{
*((SANE_Bool*)value) = bv ? SANE_TRUE : SANE_FALSE;
}
2023-06-15 02:10:17 +00:00
else if (sane_type == SANE_TYPE_FIXED)
{
*((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(dv);
}
2023-06-15 02:10:17 +00:00
v = hg_sane_middleware::option_value_2_string(sane_type, value);
2022-05-03 03:56:07 +00:00
}
if (prev == v)
{
2023-06-15 02:10:17 +00:00
VLOG_MINI_3(LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc_title.c_str(), v.c_str());
2022-05-03 03:56:07 +00:00
}
else
{
2023-06-15 02:10:17 +00:00
VLOG_4(LOG_LEVEL_ALL, 512, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc_title.c_str(), prev.c_str(), v.c_str());
2022-05-03 03:56:07 +00:00
}
if (err == SCANNER_ERR_OK)
2022-05-03 03:56:07 +00:00
{
2023-06-15 02:10:17 +00:00
err = (scanner_err)something_after_do(dev, desc_name.c_str(), v.c_str());
2022-05-03 03:56:07 +00:00
}
else if (err == SCANNER_ERR_NOT_EXACT)
2022-05-03 03:56:07 +00:00
{
2023-06-15 02:10:17 +00:00
err = (scanner_err)(something_after_do(dev, desc_name.c_str(), v.c_str()) | SANE_INFO_INEXACT);
2022-05-03 03:56:07 +00:00
}
else if (err == SCANNER_ERR_CONFIGURATION_CHANGED)
2022-05-03 03:56:07 +00:00
{
2023-06-15 02:10:17 +00:00
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects other options value, RELOAD ...\n", desc_title.c_str());
//on_SCANNER_ERR_CONFIGURATION_CHANGED(dev);
2023-06-19 03:16:57 +00:00
if(dev->fixed_id.count(SANE_OPT_ID_LANGUAGE) == 0 || dev->fixed_id[SANE_OPT_ID_LANGUAGE] != id) // language reload by callback already
reload_options(handle);
err = (scanner_err)SANE_INFO_RELOAD_OPTIONS;
2022-05-03 03:56:07 +00:00
}
else if(err == SCANNER_ERR_RELOAD_IMAGE_PARAM)
{
2023-06-15 02:10:17 +00:00
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter, APP should re-get ...\n", desc_title.c_str());
err = (scanner_err)SANE_INFO_RELOAD_PARAMS;
}
else if(err == SCANNER_ERR_RELOAD_OPT_PARAM)
{
2023-06-15 02:10:17 +00:00
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter and options, APP should re-get image info and reload options...\n", desc_title.c_str());
//on_SCANNER_ERR_CONFIGURATION_CHANGED(dev);
2023-06-19 03:16:57 +00:00
if (dev->fixed_id.count(SANE_OPT_ID_LANGUAGE) == 0 || dev->fixed_id[SANE_OPT_ID_LANGUAGE] != id) // language reload by callback already
reload_options(handle);
err = (scanner_err)(SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS);
}
else if (err == SCANNER_ERR_ACCESS_DENIED)
2022-10-13 07:34:01 +00:00
{
2022-05-03 03:56:07 +00:00
status = SANE_STATUS_ACCESS_DENIED;
2022-10-13 07:34:01 +00:00
err = (scanner_err)0;
}
2022-05-03 03:56:07 +00:00
else
2022-10-13 07:34:01 +00:00
{
2023-06-14 07:06:02 +00:00
status = local_utility::scanner_err_2_sane_statu(err);
2022-10-13 07:34:01 +00:00
err = (scanner_err)0;
}
2022-05-03 03:56:07 +00:00
if (after_do)
*after_do = err;
if (release_value)
local_utility::free_memory(value);
2022-05-03 03:56:07 +00:00
return status;
}
return SANE_STATUS_INVAL;
2022-05-03 03:56:07 +00:00
}
bool hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type)
2022-06-15 03:05:36 +00:00
{
scanner_handle h = find_openning_device(handle);
if (!h)
return false;
return get_current_value(h, option, &hg_sane_middleware::set_value_to_var, value, type);
2022-06-15 03:05:36 +00:00
}
void* hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, SANE_Value_Type* type)
{
scanner_handle h = find_openning_device(handle);
void* buf = nullptr;
if (!h)
return NULL;
get_current_value(h, option, &hg_sane_middleware::set_value_to_new, &buf, type);
return buf;
}
void* hg_sane_middleware::get_def_value(SANE_Handle handle, void* option, int* bytes, bool log)
2022-06-15 03:05:36 +00:00
{
scanner_handle h = find_openning_device(handle);
if (!h)
return NULL;
2022-11-10 03:09:16 +00:00
return get_default_value(h, option, bytes, log);
2022-06-15 03:05:36 +00:00
}
2022-05-03 03:56:07 +00:00
SANE_Status hg_sane_middleware::io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len)
{
LPDEVINST dev;
scanner_handle handle = find_openning_device(h, false, &dev);
int ret = SANE_STATUS_GOOD;
2022-05-03 03:56:07 +00:00
// commented at 2022-03-23 for getting app about info before open any device
//
//if (!handle)
// return SANE_STATUS_INVAL;
ret = hg_scanner_control(handle, code, data, len);
if (ret == SCANNER_ERR_CONFIGURATION_CHANGED)
2022-05-03 03:56:07 +00:00
{
int nc = code;
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc);
on_SCANNER_ERR_CONFIGURATION_CHANGED(dev);
2022-05-03 03:56:07 +00:00
}
return local_utility::scanner_err_2_sane_statu(ret);
2022-05-03 03:56:07 +00:00
}
2023-01-19 07:43:59 +00:00
bool hg_sane_middleware::is_ready(void)
{
return init_ok_;
}
2022-05-03 03:56:07 +00:00
/// <summary>
/// 关联项处<E9A1B9><E5A484>?
2022-05-03 03:56:07 +00:00
bool hg_sane_middleware::compare_val_equal(const char* cur_val, const char* limit_l, const char* limit_r)
{
return strcmp(cur_val, limit_l) == 0;
}
bool hg_sane_middleware::compare_val_not_equal(const char* cur_val, const char* limit_l, const char* limit_r)
{
return !hg_sane_middleware::compare_val_equal(cur_val, limit_l, limit_r);
}
bool hg_sane_middleware::compare_val_great(const char* cur_val, const char* limit_l, const char* limit_r)
{
return atof(cur_val) > atof(limit_l);
}
bool hg_sane_middleware::compare_val_not_less(const char* cur_val, const char* limit_l, const char* limit_r)
{
return !hg_sane_middleware::compare_val_less(cur_val, limit_l, limit_r);
}
bool hg_sane_middleware::compare_val_less(const char* cur_val, const char* limit_l, const char* limit_r)
{
return atof(cur_val) < atof(limit_l);
}
bool hg_sane_middleware::compare_val_not_great(const char* cur_val, const char* limit_l, const char* limit_r)
{
return !hg_sane_middleware::compare_val_great(cur_val, limit_l, limit_r);
}
bool hg_sane_middleware::compare_val_between(const char* cur_val, const char* limit_l, const char* limit_r)
{
return atof(limit_l) < atof(cur_val) && atof(cur_val) < atof(limit_r);
}
bool hg_sane_middleware::compare_val_not_between(const char* cur_val, const char* limit_l, const char* limit_r)
{
return !hg_sane_middleware::compare_val_between(cur_val, limit_l, limit_r);
}
bool hg_sane_middleware::is_enable_and(scanner_handle hdev, const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals)
2022-05-03 03:56:07 +00:00
{
// NOTE: logical operator '&&' should get all master's value to check, here we only consider ONE master !!!!
bool enabled = true;
for (size_t i = 0; enabled && i < master.size(); ++i)
{
std::vector<CURVAL>::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name);
2022-05-03 03:56:07 +00:00
if (it == curvals.end())
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str());
2022-05-03 03:56:07 +00:00
continue;
}
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->find_stored_descriptor(hdev, master[i].name.c_str());
if (desc && (desc->cap & SANE_CAP_INACTIVE))
enabled = false;
else
enabled &= master[i].compare_val(it->val.c_str(), master[i].limit_l.c_str(), master[i].limit_r.c_str());
2022-05-03 03:56:07 +00:00
}
return enabled;
}
bool hg_sane_middleware::is_enable_or(scanner_handle hdev, const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals)
2022-05-03 03:56:07 +00:00
{
bool enabled = false;
for (size_t i = 0; !enabled && i < master.size(); ++i)
{
std::vector<CURVAL>::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name);
2022-05-03 03:56:07 +00:00
if (it == curvals.end())
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str());
2022-05-03 03:56:07 +00:00
continue;
}
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->find_stored_descriptor(hdev, master[i].name.c_str());
if (desc && (desc->cap & SANE_CAP_INACTIVE))
enabled = false;
else
enabled |= master[i].compare_val(it->val.c_str(), master[i].limit_l.c_str(), master[i].limit_r.c_str());
2022-05-03 03:56:07 +00:00
}
return enabled;
}
bool hg_sane_middleware::parse_master_option(const char* depend_str, MASTEROP& mo)
{
bool ret = true;
double num = .0f;
std::string v("");
2022-05-03 03:56:07 +00:00
mo.compare_val = &hg_sane_middleware::compare_val_equal;
mo.limit_l = mo.limit_r = "";
local_utility::skip_space(depend_str);
while ((*depend_str >= 'a' && *depend_str <= 'z') || *depend_str == '-')
v.push_back(*depend_str++);
if (!v.empty())
mo.name = v;
2022-05-03 03:56:07 +00:00
if (ret)
{
local_utility::skip_space(depend_str);
if (*depend_str == '=')
{
depend_str++;
if (*depend_str == '=')
{
depend_str++;
if (*depend_str == '[')
{
ret = local_utility::get_limit(depend_str, mo.limit_l, mo.limit_r);
mo.compare_val = &hg_sane_middleware::compare_val_between;
}
else
{
mo.compare_val = &hg_sane_middleware::compare_val_equal;
mo.limit_l = depend_str;
}
}
else
{
ret = false;
}
}
else if (*depend_str == '>')
{
depend_str++;
if (*depend_str == '=')
{
depend_str++;
mo.compare_val = &hg_sane_middleware::compare_val_not_less;
}
else
{
mo.compare_val = &hg_sane_middleware::compare_val_great;
}
mo.limit_l = depend_str;
}
else if (*depend_str == '<')
{
depend_str++;
if (*depend_str == '=')
{
depend_str++;
mo.compare_val = &hg_sane_middleware::compare_val_not_great;
}
else
{
mo.compare_val = &hg_sane_middleware::compare_val_less;
}
mo.limit_l = depend_str;
}
else if (*depend_str == '!')
{
depend_str++;
if (*depend_str == '=')
{
depend_str++;
if (*depend_str == '[')
{
ret = local_utility::get_limit(depend_str, mo.limit_l, mo.limit_r);
mo.compare_val = &hg_sane_middleware::compare_val_not_between;
}
else
{
mo.compare_val = &hg_sane_middleware::compare_val_not_equal;
mo.limit_l = depend_str;
}
}
else
{
ret = false;
}
}
else
{
ret = false;
}
}
return ret;
}
bool hg_sane_middleware::parse_depends(scanner_handle h, json* jsn, SLAVEOP& so, std::vector<std::string>& master)
2022-05-03 03:56:07 +00:00
{
std::string val(""), mn("");
2022-05-03 03:56:07 +00:00
bool ret = jsn->first_child(val);
while(ret)
{
MASTEROP mo;
ret = parse_master_option(val.c_str(), mo);
if (!ret)
break;
if (mo.name.empty())
mo.name = mn;
else
mn = mo.name;
SANE_Option_Descriptor* m = find_stored_descriptor(h, mo.name.c_str());
if (m && m->type == SANE_TYPE_STRING)
mo.limit_l = from_default_language(mo.limit_l.c_str(), nullptr);
2022-05-03 03:56:07 +00:00
so.master.push_back(mo);
if (std::find(master.begin(), master.end(), mo.name) == master.end())
2022-05-03 03:56:07 +00:00
{
master.push_back(mo.name);
std::sort(master.begin(), master.end());
2022-05-03 03:56:07 +00:00
}
ret = jsn->next_child(val);
}
return so.master.size() > 0;
}
bool hg_sane_middleware::is_associatived(const SLAVEOP& slave, const char* master_name)
2022-05-03 03:56:07 +00:00
{
bool result = false;
for (const auto& v: slave.master)
2022-05-03 03:56:07 +00:00
{
if (v.name == master_name)
2022-05-03 03:56:07 +00:00
{
result = true;
break;
}
}
return result;
}
bool hg_sane_middleware::set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size)
2022-05-03 03:56:07 +00:00
{
SANE_Option_Descriptor* opt = find_stored_descriptor(h, option);
2022-05-03 03:56:07 +00:00
bool ret = false;
if (opt)
{
if(size)
*size = opt->size;
ret = true;
if (enable)
opt->cap &= ~SANE_CAP_INACTIVE;
else
opt->cap |= SANE_CAP_INACTIVE;
}
return ret;
}
int hg_sane_middleware::something_after_do(LPDEVINST dev, const char* master_name, const char* cur_val)
2022-05-03 03:56:07 +00:00
{
int after = 0;
OPTENABLE oe;
std::vector<OPTENABLE> changed_options;
refresh_current_value(dev, master_name, cur_val);
if (std::find(dev->masters.begin(), dev->masters.end(), master_name) == dev->masters.end())
2022-05-03 03:56:07 +00:00
{
return after;
}
oe.name = master_name;
2022-05-03 03:56:07 +00:00
oe.enable = true;
changed_options.push_back(oe);
for (size_t i = 0; i < changed_options.size(); ++i)
{
for (size_t slave = 0; slave < dev->slaves.size(); ++slave)
2022-05-03 03:56:07 +00:00
{
if (dev->slaves[slave].name == changed_options[i].name ||
!is_associatived(dev->slaves[slave], changed_options[i].name.c_str()))
2022-05-03 03:56:07 +00:00
continue;
bool enable = changed_options[i].enable;
int bytes = 0;
2022-09-15 14:26:51 +00:00
// if (enable)
enable = dev->slaves[slave].is_enable(dev->dev, dev->slaves[slave].master, dev->cur_vals);
if (enable == dev->slaves[slave].enable_now)
2022-05-03 03:56:07 +00:00
continue;
dev->slaves[slave].enable_now = enable;
if (!set_stored_option_enabled(dev->dev, dev->slaves[slave].name.c_str(), enable, &bytes))
2022-05-03 03:56:07 +00:00
continue;
OPTEN* op = get_control_enalbe_data(dev, dev->slaves[slave]);
hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL);
2022-05-03 03:56:07 +00:00
free_control_enable_data(op);
if (std::find(changed_options.begin(), changed_options.end(), dev->slaves[slave].name) != changed_options.end())
2022-05-03 03:56:07 +00:00
continue;
oe.name = dev->slaves[slave].name;
oe.enable = dev->slaves[slave].enable_now;
2022-05-03 03:56:07 +00:00
changed_options.push_back(oe);
}
}
if (changed_options.size() > 1)
after = SANE_INFO_RELOAD_OPTIONS;
return after;
}
bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, json* jsn)
2022-05-03 03:56:07 +00:00
{
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it == dev->cur_vals.end())
2022-05-03 03:56:07 +00:00
{
CURVAL cv;
jsn->get_value("type", cv.type);
cv.name = name;
2022-05-03 03:56:07 +00:00
jsn->get_value_as_string("cur", cv.val, cv.type == "int");
if (cv.type == "string")
local_utility::trans_language_if_was_word_id(cv.val);
dev->cur_vals.push_back(cv);
2022-05-03 03:56:07 +00:00
return false;
}
else
{
std::string old(it->val);
jsn->get_value_as_string("cur", it->val, it->type == "int");
if (it->type == "string")
local_utility::trans_language_if_was_word_id(it->val);
2022-05-03 03:56:07 +00:00
return old != it->val;
}
}
bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, const char* val)
2022-05-03 03:56:07 +00:00
{
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it != dev->cur_vals.end())
2022-05-03 03:56:07 +00:00
{
bool ret = strcmp(it->val.c_str(), val) == 0;
it->val = val;
return ret;
}
return false;
}
OPTEN* hg_sane_middleware::get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave)
2022-05-03 03:56:07 +00:00
{
std::vector<std::string> master;
2022-05-03 03:56:07 +00:00
OPTEN* opt = NULL;
size_t size = sizeof(OPTEN);
for (size_t i = 0; i < slave.master.size(); ++i)
{
if (std::find(master.begin(), master.end(), slave.master[i].name) == master.end())
master.push_back(slave.master[i].name);
2022-05-03 03:56:07 +00:00
}
size += master.size() * sizeof(OPTVAL);
opt = (OPTEN*)malloc(size);
bzero(opt, size);
opt->enabled = slave.enable_now;
2023-08-11 06:06:12 +00:00
strcpy(opt->name, slave.name.c_str());
2022-05-03 03:56:07 +00:00
opt->master_count = 0;
for (size_t i = 0; i < master.size(); ++i)
{
std::vector<CURVAL>::iterator m = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), master[i]);
if (m == dev->cur_vals.end())
2022-05-03 03:56:07 +00:00
continue;
2023-08-11 06:06:12 +00:00
strcpy(opt->master[opt->master_count].name, master[i].c_str());
2022-05-03 03:56:07 +00:00
if (m->type == "string")
{
opt->master[opt->master_count].data = malloc(m->val.length() + 4);
strcpy((char*)opt->master[opt->master_count].data, m->val.c_str());
}
else
{
opt->master[opt->master_count].data = malloc(sizeof(double));
if (m->type == "bool")
*((bool*)opt->master[opt->master_count].data) = (m->val == "true");
else if (m->type == "int")
*((int*)opt->master[opt->master_count].data) = atoi(m->val.c_str());
else
*((double*)opt->master[opt->master_count].data) = atof(m->val.c_str());
}
2023-08-11 06:06:12 +00:00
opt->master_count++;
2022-05-03 03:56:07 +00:00
}
return opt;
}
void hg_sane_middleware::free_control_enable_data(OPTEN* opt)
{
if (opt)
{
for (int i = 0; i < opt->master_count; ++i)
{
if (opt->master[i].data)
free(opt->master[i].data);
}
free(opt);
}
}
void hg_sane_middleware::on_SCANNER_ERR_CONFIGURATION_CHANGED(LPDEVINST dev)
2022-05-03 03:56:07 +00:00
{
std::vector<std::string> changed;
reload_current_value(dev->dev, &changed);
2022-05-03 03:56:07 +00:00
if (changed.size())
{
for (size_t i = 0; i < changed.size(); ++i)
{
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), changed[i]);
if (it != dev->cur_vals.end())
something_after_do(dev, it->name.c_str(), it->val.c_str());
2022-05-03 03:56:07 +00:00
}
}
}
std::vector<LPDEVINST>::iterator hg_sane_middleware::find_openning_device_in_que(scanner_handle h)
{
for (size_t i = 0; i < openning_.size(); ++i)
{
if (openning_[i]->dev == h)
return openning_.begin() + i;
}
return openning_.end();
}
std::vector<LPDEVINST>::iterator hg_sane_middleware::find_openning_device_in_que(const char* name)
{
for (size_t i = 0; i < openning_.size(); ++i)
{
if (openning_[i]->name == name)
return openning_.begin() + i;
}
return openning_.end();
}
2022-05-03 03:56:07 +00:00
/// </summary>
/// <summary>
/// 导出接口
/// </summary>
extern "C" { // avoid compiler exporting name in C++ style !!!
2023-06-03 08:22:00 +00:00
const char* inner_sane_err_desc(SANE_Status err)
{
return hg_scanner_err_description(local_utility::sane_statu_2_scanner_err(err));
}
2022-05-03 03:56:07 +00:00
SANE_Status inner_sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize)
{
local_utility::cb_auth_ = authorize;
2023-01-19 07:43:59 +00:00
if (!hg_sane_middleware::instance()->is_ready())
return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST;
2022-05-03 03:56:07 +00:00
local_utility::get_version(version_code);
2022-10-14 01:00:57 +00:00
std::this_thread::sleep_for(std::chrono::milliseconds(500));
2022-05-03 03:56:07 +00:00
return SANE_STATUS_GOOD;
}
void inner_sane_exit(void)
{
hg_sane_middleware::clear();
}
SANE_Status inner_sane_get_devices(const SANE_Device*** device_list, SANE_Bool local_only)
{
SANE_Status code = hg_sane_middleware::instance()->get_devices(device_list, local_only);
return code;
}
SANE_Status inner_sane_open(SANE_String_Const devicename, SANE_Handle* handle)
{
return hg_sane_middleware::instance()->open_device(devicename, handle);
}
void inner_sane_close(SANE_Handle handle)
{
hg_sane_middleware::instance()->close_device(handle);
}
const SANE_Option_Descriptor*
inner_sane_get_option_descriptor(SANE_Handle handle, const void* option)
2022-05-03 03:56:07 +00:00
{
return hg_sane_middleware::instance()->get_option_descriptor(handle, option);
}
SANE_Status inner_sane_control_option(SANE_Handle handle, const void* option, SANE_Action action, void* value, SANE_Int* info)
2022-05-03 03:56:07 +00:00
{
return hg_sane_middleware::instance()->set_option(handle, option, action, value, info);
}
SANE_Status inner_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params)
{
return hg_sane_middleware::instance()->get_image_parameters(handle, params);
}
SANE_Status inner_sane_start(SANE_Handle handle)
{
return hg_sane_middleware::instance()->start(handle, NULL);
}
SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length)
{
if (!length)
length = &max_length;
else
*length = max_length;
return hg_sane_middleware::instance()->read(handle, data, length);
}
void inner_sane_cancel(SANE_Handle handle)
{
hg_sane_middleware::instance()->stop(handle);
}
SANE_Status inner_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)
{
LOG_INFO(LOG_LEVEL_ALL, "sane_set_io_mode\n");
2022-05-03 03:56:07 +00:00
return non_blocking ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD;
}
SANE_Status inner_sane_get_select_fd(SANE_Handle handle, SANE_Int* fd)
{
return SANE_STATUS_UNSUPPORTED;
}
SANE_String_Const inner_sane_strstatus(SANE_Status status)
{
2023-06-03 08:22:00 +00:00
// return hg_scanner_err_name(status);
return inner_sane_err_desc(status);
2022-05-03 03:56:07 +00:00
}
SANE_Status inner_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param)
{
local_utility::set_callback(cb, param);
2023-01-19 07:43:59 +00:00
if (!hg_sane_middleware::instance()->is_ready())
return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST;
2022-05-03 03:56:07 +00:00
local_utility::get_version(version_code);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
2022-05-03 03:56:07 +00:00
return SANE_STATUS_GOOD;
}
SANE_Status inner_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len)
{
return hg_sane_middleware::instance()->io_control(h, code, data, len);
}
SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len)
{
return SANE_STATUS_UNSUPPORTED;
}
2023-08-23 02:22:31 +00:00
SANE_Status inner_sane_ex_get_driver_version(SANE_Int* hh, SANE_Int* hl, SANE_Int* lh, SANE_Int* ll)
{
unsigned long long v = hg_scanner_get_version();
2023-08-23 02:22:31 +00:00
if (hh)
*hh = (v >> 24) & 0x0ff;
2023-08-23 02:22:31 +00:00
if (hl)
*hl = (v >> 16) & 0x0ff;
2023-08-23 02:22:31 +00:00
if (lh)
*lh = (v >> 8) & 0x0ff;
2023-08-23 02:22:31 +00:00
if (ll)
*ll = (v >> 0) & 0x0ff;
2023-08-23 02:22:31 +00:00
return SANE_STATUS_GOOD;
}
2023-10-07 04:41:50 +00:00
SANE_Status inner_sane_get_parameters_ex(SANE_Handle h, SANE_Image* info)
{
return hg_sane_middleware::instance()->get_image_parameters_ex(h, info);
}
2022-05-03 03:56:07 +00:00
void sanei_debug_msg(int level, int max_level, const char* be, const char* fmt, va_list ap)
{
}
}
#if defined(WIN32) || defined(_WIN64)
HMODULE g_my_inst = NULL;
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
g_my_inst = inst;
if (g_sane_path.empty())
{
char path[MAX_PATH] = { 0 };
GetModuleFileNameA(inst, path, _countof(path) - 1);
if (strrchr(path, '\\'))
{
g_sane_name = strrchr(path, '\\') + 1;
strrchr(path, '\\')[1] = 0;
g_sane_path = path;
if (g_sane_name.rfind('.') != std::string::npos)
g_sane_name.erase(g_sane_name.rfind('.'));
}
}
}
2022-06-15 03:05:36 +00:00
else if (reason == DLL_PROCESS_DETACH)
{
inner_sane_exit();
}
return TRUE;
}
#endif