fix opt/logic bug

This commit is contained in:
gb 2023-09-09 18:09:20 +08:00
parent 06b4caf64b
commit 852e508edb
18 changed files with 1204 additions and 2744 deletions

View File

@ -18,11 +18,6 @@ static void copy_simple_type(TC* dst, T& src)
{
*dst = src;
}
template<class T, class TC>
static void copy_string(TC* dst, T& src)
{
strcpy(*dst, src.c_str());
}
template<class T, class TC>
static bool refine_data_to_range(gb_json* jsn, void* value, void(*cp)(TC*, T&))
@ -33,21 +28,37 @@ static bool refine_data_to_range(gb_json* jsn, void* value, void(*cp)(TC*, T&))
jsn->get_value("range", range);
if (range)
{
T v;
if (range->get_value("min", v))
T vl, vu, s;
if (range->get_value("min", vl))
{
if (*(TC*)value < v)
if (*(TC*)value < vl)
{
cp((TC*)value, v);
cp((TC*)value, vl);
refined = true;
}
else if (range->get_value("max", v))
else if (range->get_value("max", vu))
{
if (*(TC*)value > v)
if (*(TC*)value > vu)
{
cp((TC*)value, v);
cp((TC*)value, vu);
refined = true;
}
else if (range->get_value("step", s))
{
T cur(*(TC*)value);
vl = cur - vl;
vl /= s;
if (!IS_DOUBLE_EQUAL(vl, (int)vl))
{
vl += .5f;
vl = (int)vl * s;
if (vl > vu)
vl = vu;
cp((TC*)value, vl);
refined = true;
}
}
}
}
else
@ -57,9 +68,9 @@ static bool refine_data_to_range(gb_json* jsn, void* value, void(*cp)(TC*, T&))
while (val)
{
if (val->value(v))
if (val->value(vl))
{
if (*(TC*)value == v)
if (*(TC*)value == vl)
{
found = true;
val->release();
@ -71,10 +82,85 @@ static bool refine_data_to_range(gb_json* jsn, void* value, void(*cp)(TC*, T&))
}
if (!found)
{
if (jsn->get_value("default", v))
if (jsn->get_value("default", vl))
{
refined = true;
cp((TC*)value, v);
cp((TC*)value, vl);
}
}
}
range->release();
}
return refined;
}
static bool refine_string_data(gb_json* jsn, void* value)
{
bool refined = false;
gb_json* range = nullptr;
std::string v((char*)value);
jsn->get_value("range", range);
if (range)
{
std::string vl(""), vu(""), s("");
if (range->get_value("min", vl))
{
if (v < vl)
{
strcpy((char*)value, vl.c_str());
refined = true;
}
else if (range->get_value("max", vu))
{
if (v > vu)
{
strcpy((char*)value, vu.c_str());
refined = true;
}
//else if (range->get_value("step", s))
//{
// T cur(*(TC*)value);
//
// vl = cur - vl;
// vl /= s;
// if (!IS_DOUBLE_EQUAL(vl, (int)vl))
// {
// vl += .5f;
// vl = (int)vl * s;
// if (vl > vu)
// vl = vu;
// cp((TC*)value, vl);
// refined = true;
// }
//}
}
}
else
{
gb_json* val = range->first_child();
bool found = false;
while (val)
{
if (val->value(vl))
{
if (v == vl)
{
found = true;
val->release();
break;
}
}
val->release();
val = range->next_child();
}
if (!found)
{
if (jsn->get_value("default", vl))
{
refined = true;
strcpy((char*)value, vl.c_str());
}
}
}
@ -540,7 +626,7 @@ bool device_option::parse_simple_logic_expression(gb_json* root, const char* exp
for (auto& v : opers)
{
tag = strstr(expr, v);
if (!tag)
if (tag)
break;
}
@ -710,7 +796,10 @@ bool device_option::calc_simple_logic_expression(const char* expr, void* param)
{
gb_json* child = nullptr;
obj->now_->get_value(obj->compare_[expr].name.c_str(), child);
if(obj->now_)
obj->now_->get_value(obj->compare_[expr].name.c_str(), child);
else
obj->origin_->get_value(obj->compare_[expr].name.c_str(), child);
if (child)
{
bool bv = false;
@ -737,7 +826,7 @@ bool device_option::calc_simple_logic_expression(const char* expr, void* param)
child->get_value("cur", sv);
}
val = &sv[0];
ret = obj->compare_[expr].compare(child, val, &obj->compare_[expr].val1[0], &obj->compare_[expr].val2[0]);
ret = obj->compare_[expr].compare(child, val, &obj->compare_[expr].val1[0], &obj->compare_[expr].val2[0]) ^ obj->compare_[expr].not_op;
child->release();
}
@ -832,6 +921,7 @@ gb_json* device_option::copy_opt(gb_json* from)
if (src && dst)
{
dst->clear(src->is_array());
dst->key() = src->key();
to->get_value("type", val);
if (val == JSON_SANE_TYPE_BOOL)
{
@ -929,8 +1019,9 @@ bool device_option::to_now(bool init)
if (!origin_)
return false;
gb_json* from = nullptr, * to = nullptr, * tmp = new gb_json();
gb_json* from = nullptr, * to = nullptr, * tmp = now_; // new gb_json();
now_ = new gb_json();
from = origin_->first_child();
while (from)
{
@ -943,22 +1034,58 @@ bool device_option::to_now(bool init)
from->release();
if (to)
{
tmp->set_value(name.c_str(), to);
// copy cur value ...
if (tmp)
{
gb_json* now = nullptr;
tmp->get_value(to->key().c_str(), now);
if (now)
{
std::string type("");
now->get_value("type", type);
if (type == JSON_SANE_TYPE_BOOL)
{
bool v = false;
now->get_value("cur", v);
to->set_value("cur", v);
}
else if (type == JSON_SANE_TYPE_INT)
{
int v = 0;
now->get_value("cur", v);
to->set_value("cur", v);
}
else if (type == JSON_SANE_TYPE_FIXED)
{
double v = .0f;
now->get_value("cur", v);
to->set_value("cur", v);
}
else if (type == JSON_SANE_TYPE_STRING)
{
std::string v("");
now->get_value("cur", v);
to->set_value("cur", v.c_str());
}
now->release();
}
}
now_->set_value(name.c_str(), to);
to->release();
from = origin_->next_child();
}
else
{
tmp->release();
tmp = nullptr;
now_->release();
now_ = nullptr;
break;
}
}
if (now_)
now_->release();
now_ = tmp;
if (tmp)
tmp->release();
return now_ != nullptr;
}
@ -1040,7 +1167,7 @@ bool device_option::refine_data(const char* name, void* value)
}
else if (type == JSON_SANE_TYPE_STRING)
{
refined = refine_data_to_range<std::string, char*>(child, value, copy_string<std::string, char*>);
refined = refine_string_data(child, value);
}
child->release();

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
//#include <vld.h>
#include "usb_manager.h"
#include "../../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include "jsonconfig.h"
#include "../3rdparty/nick/StopWatch.h"
#include "hg_ipc.h"
#include "common_setting.h"
@ -70,6 +69,7 @@ typedef HGResult(__stdcall* SDKHGVersion_Postlog_)(HGVersionMgr mgr, const HGCha
const HGChar* devType, const HGChar* devFW, HGBool isLock);
typedef HGResult(__stdcall* SDKHGVersion_Free_)(HGVersionMgr mgr);
class gb_json;
class hg_scanner
{
HGVersionMgr HGVersion_mgr_;
@ -122,7 +122,7 @@ class hg_scanner
bool check_paper_and_resolution(int res, int paper);
bool check_resolution_and_quality(int res, const char* quality);
int restore(const char* name);
bool get_default_value(void* buf, json* jsn);
bool get_default_value(void* buf, gb_json* jsn);
bool is_to_file(void);
void thread_handle_image_process(void);
@ -133,7 +133,7 @@ class hg_scanner
void reset_custom_area_range(int paper);
float reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u); // return cur value
int set_color_change(void);
bool jsn_reorganize(); // 固件版本不同 初始化json要做出相对应的删除
bool jsn_reorganize(); // 固件版本不同 初始化gb_json要做出相对应的删除
public:
@ -293,9 +293,8 @@ protected:
bool async_io_;
bool cb_mem_;
bool test_1_paper_; // 是否为单张扫描模式
std::vector<std::string> jsn_children_;
std::vector<string> erase_depend_; //需要删除父依赖项
json setting_jsn_;
gb_json *setting_jsn_;
IMGPRCFIXPARAM image_prc_param_;
int erase_bkg_range_; // 背景移除像素范围
@ -400,11 +399,9 @@ protected:
uint32_t fetching_id_; // for sane read image ext info. added on 2023-01-13
void change_setting_language(bool init);
void erase_option(const char* name);
void init_settings(const char* json_setting_text);
int init_settings(int pid);
void change_string_2_lang_id(const char* name, const char* key);
std::string get_setting_item_string(const char* name, const char* key);
int on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作
int try_third_app_handle_start(bool& handled);
@ -458,8 +455,8 @@ public:
int get_pid(void);
int get_vid(void);
int close(bool force);
int set_setting(const char* name, void* data, long* len);
int get_setting(const char* name, char* json_txt_buf, int* len, int* id);
int set_setting(const char* name, void* data, bool to_default);
int get_setting(const char* name, char* buf, int* len, int type);
int hgpaper_to_devspaper(Paper_Map papermap[], int len, int& paper, bool* exact, TwSS* type);
int image_configuration(SCANCONF &ic);
std::string name(void);

View File

@ -3,6 +3,7 @@
#include "../../sdk/hginclude/utils.h"
#include <lang/app_language.h>
#include "filetools.h"
#include "../../sdk/json/gb_json.h"
#if defined(WIN32) || defined(_WIN64)
#include "scanner_manager.h"
@ -1575,19 +1576,7 @@ int hg_scanner_239::device_io_control(unsigned long code, void* data, unsigned*
{
int ret = SCANNER_ERR_OUT_OF_RANGE;
if (HG_CONTROL_CODE_OPTION_ENABLE == code)
{
OPTEN* opten = (OPTEN*)data;
ret = SCANNER_ERR_OK;
if (opten->name == SANE_STD_OPT_NAME_ANTI_SKEW && !opten->enabled) // for BUG-20 modified by Gongbing on 2022-03-12
{
bool enable = true;
long l = sizeof(enable);
setting_automatic_skew(&enable, &l);
}
}
else if (IO_CTRL_CODE_TEST_SINGLE == code)
if (IO_CTRL_CODE_TEST_SINGLE == code)
{
test_1_paper_ = true;
ret = start();
@ -1692,12 +1681,15 @@ int hg_scanner_239::set_clear_history_num(void)
ret = read_control_device_files(json_path, str);
std::string str2;
json js = json::parse(str);
if (js.contains("TotalScanned"))
gb_json* jsn = new gb_json();
jsn->attach_text(&str[0]);
if (jsn->get_value("TotalScanned", len))
{
js["TotalScanned"] = 0;
str2 = js.dump();
jsn->set_value("TotalScanned", 0);
str2 = jsn->to_string();
}
jsn->release();
if (ret == SCANNER_ERR_OK)
{

View File

@ -1138,19 +1138,7 @@ int hg_scanner_302::device_io_control(unsigned long code, void* data, unsigned*
{
int ret = SCANNER_ERR_OUT_OF_RANGE;
if (HG_CONTROL_CODE_OPTION_ENABLE == code)
{
OPTEN* opten = (OPTEN*)data;
ret = SCANNER_ERR_OK;
if (opten->name == SANE_STD_OPT_NAME_ANTI_SKEW && !opten->enabled) // for BUG-20 modified by Gongbing on 2022-03-12
{
bool enable = true;
long l = sizeof(enable);
setting_automatic_skew(&enable, &l);
}
}
else if (IO_CTRL_CODE_TEST_SINGLE == code)
if (IO_CTRL_CODE_TEST_SINGLE == code)
{
test_1_paper_ = true;
ret = start();

View File

@ -166,6 +166,13 @@ hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1), user_(""), pwd_(""), cf_name(""
}
hg_scanner_mgr::~hg_scanner_mgr()
{
{
std::lock_guard<std::mutex> lock(mutex_dev_);
for (auto& v : online_devices_)
libusb_unref_device(v.dev);
online_devices_.clear();
}
usb_manager::clear();
}
@ -814,11 +821,18 @@ scanner_err hg_scanner_mgr::hg_scanner_close(scanner_handle h, bool force)
return SCANNER_ERR_OK;
}
scanner_err hg_scanner_mgr::hg_scanner_get_parameter(scanner_handle h, const char* name, char* data, long* len, SANE_Int* id)
scanner_err hg_scanner_mgr::hg_scanner_get_parameter(scanner_handle h, const char* name, char* data, long* len, int type)
{
if (!len)
return SCANNER_ERR_INVALID_PARAMETER;
if (!h)
{
*len = 0;
return SCANNER_ERR_OK;
}
// global options ...
if (!IS_PTR_NUMBER(name))
{
@ -942,13 +956,13 @@ scanner_err hg_scanner_mgr::hg_scanner_get_parameter(scanner_handle h, const cha
}
int l = *len,
err = SCAN_PTR(h)->get_setting(name, data, &l, id);
err = SCAN_PTR(h)->get_setting(name, data, &l, type);
*len = l;
return (scanner_err)err;
}
scanner_err hg_scanner_mgr::hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, long* len)
scanner_err hg_scanner_mgr::hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, bool to_default)
{
if (!IS_PTR_NUMBER(name))
{
@ -1008,20 +1022,26 @@ scanner_err hg_scanner_mgr::hg_scanner_set_parameter(scanner_handle h, const cha
{
if (user_ == ADMIN_NAME && pwd_ == ADMIN_PWD)
{
int* len = nullptr;
return (scanner_err)SCAN_PTR(h)->device_io_control(IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT, data, (unsigned*)len);
}
return SCANNER_ERR_ACCESS_DENIED;
}
else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_GAMMA, name) == 0)
{
int* len = nullptr;
return (scanner_err)SCAN_PTR(h)->device_io_control(IO_CTRL_CODE_SET_CUSTOM_GAMMA, data, (unsigned int*)len);
}
else if (strcmp(SANE_STD_OPT_NAME_TRANSFORM_IMAGE_FORMAT, name) == 0)
{
int* len = nullptr;
return (scanner_err)SCAN_PTR(h)->device_io_control(IO_CTRL_CODE_CONVERT_IMAGE_FORMAT, data, (unsigned int*)len);
}
else if (strcmp(SANE_STD_OPT_NAME_FREE_BUFFER, name) == 0)
{
void* ptr = data ? *(void**)data : nullptr;
int* len = nullptr;
scanner_err ret = (scanner_err)SCAN_PTR(h)->device_io_control(IO_CTRL_CODE_FREE_MEMORY, ptr, (unsigned int*)len);
if (data)
@ -1031,7 +1051,7 @@ scanner_err hg_scanner_mgr::hg_scanner_set_parameter(scanner_handle h, const cha
}
}
return (scanner_err)SCAN_PTR(h)->set_setting(name, data, len);
return (scanner_err)SCAN_PTR(h)->set_setting(name, data, to_default);
}
scanner_err hg_scanner_mgr::hg_scanner_start(scanner_handle h, void* async_event, int num)
{

View File

@ -125,8 +125,8 @@ public:
scanner_err hg_scanner_enum(ScannerInfo* scanner_list, long* count, bool local_only);
scanner_err hg_scanner_open(scanner_handle* h, const char* name, bool shared, const char* user, const char* pwd, const char* check, char* rsc);
scanner_err hg_scanner_close(scanner_handle h, bool force);
scanner_err hg_scanner_get_parameter(scanner_handle h, const char* name, char* data, long* len, SANE_Int* id);
scanner_err hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, long* len);
scanner_err hg_scanner_get_parameter(scanner_handle h, const char* name, char* data, long* len, int type);
scanner_err hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, bool to_default);
scanner_err hg_scanner_start(scanner_handle h, void* async_event, int num);
scanner_err hg_scanner_stop(scanner_handle h);
scanner_err hg_scanner_get_img_info(scanner_handle h, SANE_Parameters* bmi, long len);

View File

@ -63,6 +63,39 @@ namespace string_util
ptr++;
}
}
enum
{
TRIM_LEFT = 1,
TRIM_RIGHT,
TRIM_BOTH,
};
void trim(std::string& str, int type = TRIM_BOTH)
{
int pos = 0;
if (type & TRIM_LEFT)
{
for (; pos < str.length(); ++pos)
{
if (str[pos] != ' ')
break;
}
if (pos)
str.erase(0, pos);
}
if (type & TRIM_RIGHT)
{
pos = str.length() - 1;
for (; pos >= 0; --pos)
{
if (str[pos] != ' ')
break;
}
str.erase(pos + 1);
}
}
};
@ -171,7 +204,7 @@ bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const
first = nullptr;
}
if (e->parse(sub.c_str(), &over))
if (e->parse(sub.c_str(), &over, leaf, leaf_param))
{
e->set_not(not_v);
ele.push_back(e);
@ -196,6 +229,7 @@ bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const
{
simple_logic* e = new simple_logic();
e->expr_ = std::string(first, ptr - first);
string_util::trim(e->expr_);
e->oper_ = LOGIC_OPER_LEAF;
ele.push_back(e);
first = nullptr;
@ -231,6 +265,7 @@ bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const
{
simple_logic* e = new simple_logic();
e->expr_ = std::string(first, ptr - first);
string_util::trim(e->expr_);
e->oper_ = LOGIC_OPER_LEAF;
ele.push_back(e);
first = nullptr;
@ -264,6 +299,7 @@ bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const
{
simple_logic* e = new simple_logic();
e->expr_ = std::string(first, ptr - first);
string_util::trim(e->expr_);
e->oper_ = LOGIC_OPER_LEAF;
ele.push_back(e);
first = nullptr;
@ -311,7 +347,11 @@ bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const
simple_logic* e = new simple_logic();
int over = 0;
if (e->parse(first, &over))
{
ele.push_back(e);
if (e->oper_ == LOGIC_OPER_LEAF && leaf)
leaf(e->expr_.c_str(), leaf_param);
}
else
{
good = false;

View File

@ -166,14 +166,14 @@ extern "C"
return hg_scanner_mgr::instance()->hg_scanner_close(h, force);
}
scanner_err hg_scanner_get_parameter(scanner_handle h, const char* name, char* data, long* len, SANE_Int* id)
scanner_err hg_scanner_get_option(scanner_handle h, const char* name, char* data, long* len, int type)
{
return hg_scanner_mgr::instance()->hg_scanner_get_parameter(h, name, data, len, id);
return hg_scanner_mgr::instance()->hg_scanner_get_parameter(h, name, data, len, type);
}
scanner_err hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, long* len)
scanner_err hg_scanner_set_option(scanner_handle h, const char* name, void* data, bool to_default)
{
return hg_scanner_mgr::instance()->hg_scanner_set_parameter(h, name, data, len);
return hg_scanner_mgr::instance()->hg_scanner_set_parameter(h, name, data, to_default);
}
scanner_err hg_scanner_start(scanner_handle h, void* async_event, int num)

View File

@ -47,7 +47,7 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
}
SANE_Status inner_sane_control_option(SANE_Handle handle, const void* option, SANE_Action action, void* value, SANE_Int* info)
{
return hg_sane_middleware::instance()->set_option(handle, option, action, value, info);
return hg_sane_middleware::instance()->control_option(handle, option, action, value, info);
}
SANE_Status inner_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params)
{
@ -110,7 +110,7 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
}
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);
return hg_sane_middleware::instance()->ex_io_control(h, code, data, len);
}
SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len)
{

File diff suppressed because it is too large Load Diff

View File

@ -1,197 +1,65 @@
#pragma once
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include "sane/sane_ex.h"
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include <vector>
#include <algorithm>
#include <string>
#include <map>
#include <stdio.h>
#if defined(WIN32) || defined(_WIN64)
#define bzero(b, s) memset(b, 0, s)
#else
#include <iconv.h>
#endif
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include "sane/sane_ex.h"
#define ENABLE_SLAVE_OPTION_CONTROL
#define ALIGN_INT(n) ((((n) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
#ifdef OEM_HANWANG
#define hg_sane_middleware hw_sane_middleware
#elif defined(OEM_LISICHENG)
#define hg_sane_middleware lsc_sane_middleware
#endif
class gb_json;
class sane_std_opts;
typedef struct _device_option
{
// std::string dev_name;
int option_no;
int fixed_no; // 固定ID
std::string opt_name;
SANE_Option_Descriptor* desc;
}DEVOPT;
typedef struct _cur_val
{
std::string name;
std::string type;
std::string val; /*参数全部字符串化*/
bool operator==(const std::string& n)
{
return name == n;
}
}CURVAL;
typedef struct _master_option
{
std::string name;
SANE_Value_Type type;
std::string limit_l;
std::string limit_r;
bool(*compare_val)(const char* cur_val, const char* limit_l, const char* limit_r); // ==, !=, >, >=, <, <=, [l, r], ![l, r]
}MASTEROP;
typedef struct _slave_option
{
std::string name;
bool enable_now;
std::vector<MASTEROP> master;
bool (*is_enable)(scanner_handle hdev, const std::vector<MASTEROP>& master
, std::vector<CURVAL>& curvals/*参数全部字符串化*/); // logic 'and', 'or' opertions
}SLAVEOP;
typedef struct _opt_status
{
std::string name;
bool enable;
bool operator==(const std::string& opt)
{
return name == opt;
}
}OPTENABLE;
typedef struct _dev_inst
{
scanner_handle dev;
std::string name;
sane_std_opts* std_opt;
std::vector<DEVOPT> opts;
std::vector<CURVAL> cur_vals;
std::vector<SLAVEOP> slaves;
std::vector<std::string> masters;
std::map<sane_option_id, int> fixed_id;
bool operator==(const char* n)
{
return strcmp(name.c_str(), n) == 0;
}
bool operator==(scanner_handle h)
{
return dev == h;
}
_dev_inst()
{
dev = nullptr;
name = "";
std_opt = nullptr;
}
}DEVINST, * LPDEVINST;
class device_opts;
class hg_sane_middleware
{
// std::vector<DEVOPT> opts_;
SANE_Option_Descriptor* opt_0_;
bool init_ok_;
typedef struct _dev_inst
{
scanner_handle dev;
std::string name;
device_opts* opts;
//typedef struct _openning_scanner_option
//{
// std::string dev_name;
// scanner_handle handle;
// int scan_count;
//
// //struct _openning_scanner_option()
// //{
// // dev_name = "";
// // handle = NULL;
// // option_no = 0;
// // desc = NULL;
// //}
// bool operator==(const char* name)
// {
// return strcmp(dev_name.c_str(), name) == 0;
// }
// bool operator==(scanner_handle h)
// {
// return handle == h;
// }
//}OPENDEV;
//std::vector<OPENDEV> openning_;
bool operator==(scanner_handle h)
{
return dev == h;
}
_dev_inst()
{
dev = nullptr;
name = "";
opts = nullptr;
}
}DEVINST, * LPDEVINST;
bool init_ok_;
std::vector<LPDEVINST> openning_;
device_opts* offline_; // options can be controled when scanner was offline
static hg_sane_middleware *inst_;
static const SANE_Device** dev_list_;
static void language_changed(int cp, void* param);
static const SANE_Device** to_sane_device(ScannerInfo* hgscanner, int count); // 将驱动层传回的设备列表数据转换为标准SANE协议的设备列表
static void free_sane_device(SANE_Device** dev); // 释放由to_sane_device返回的指针
static void device_pnp(int sig); // 热插拔事件监控
static SANE_Fixed double_2_sane_fixed(double v);
static double sane_fixed_2_double(SANE_Fixed v);
static void set_value_to_var(void* val, size_t bytes, void* param);
static void set_value_to_new(void* val, size_t bytes, void* param);
static scanner_handle sane_handle_to_scanner(SANE_Handle h);
static void free_device_instance(LPDEVINST inst);
void reload_options(scanner_handle dev = nullptr);
void set_status_by_depends(scanner_handle hdev, SLAVEOP& so, std::vector<CURVAL>& vals, SANE_Option_Descriptor* desc);
SANE_Status open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc);
SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, gb_json* jsn);
std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr, SANE_Int* id = nullptr);
SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = nullptr, SANE_Int* fix_id = nullptr);
LPDEVINST find_openning_device(SANE_Handle h, bool rmv = false);
LPDEVINST find_openning_device(const char* name, bool rmv = false);
bool reload_options(LPDEVINST inst);
void reload_current_value(scanner_handle handle, std::vector<std::string>* changed = NULL);
bool get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type = NULL);
void* get_default_value(scanner_handle handle, const void* option, int* bytes = nullptr, bool log = false, bool* can_auto = nullptr); // caller should call local_utility::free_memory to free the returned value
/// <summary>
/// 关联项处理
// 添加对多依赖项的支持 - 2022-03-10
//std::vector<CURVAL> cur_vals_;
bool refresh_current_value(LPDEVINST dev, const char* name, gb_json* jsn); // return whether changed old value
bool refresh_current_value(LPDEVINST dev, const char* name, const char* val);
static bool compare_val_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_between(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_between(const char* cur_val, const char* limit_l, const char* limit_r);
static bool is_enable_and(scanner_handle hdev, const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
static bool is_enable_or(scanner_handle hdev, const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
//std::vector<SLAVEOP> slave_options_;
//std::vector<std::string> master_options_;
bool parse_master_option(const char* depend_str, MASTEROP& mo);
bool parse_depends(scanner_handle h, gb_json* jsn, SLAVEOP& so, std::vector<std::string>& master);
bool is_associatived(const SLAVEOP& slave, const char* master_name);
bool set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size = NULL);
int something_after_do(LPDEVINST dev, const char* master_name, const char* cur_val);
OPTEN* get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave);
void free_control_enable_data(OPTEN* opt);
void on_SCANNER_ERR_CONFIGURATION_CHANGED(LPDEVINST dev);
std::vector<LPDEVINST> openning_;
std::vector<LPDEVINST>::iterator find_openning_device_in_que(scanner_handle h);
std::vector<LPDEVINST>::iterator find_openning_device_in_que(const char* name);
/// 关联项处理结束
static void free_device_inst(LPDEVINST dev, bool del = true);
scanner_handle find_openning_device(SANE_Handle h, bool rmv = false, LPDEVINST* dev = NULL);
scanner_err read_value(scanner_handle h, const char* name, SANE_Value_Type type, size_t len, void* value, bool to_default);
scanner_err write_value(scanner_handle h, const char* name, SANE_Value_Type type, void* value, bool to_default, LPDEVINST optinst, SANE_Int* affect);
SANE_Status get_current_value(LPDEVINST inst, const void* opt, void* value, bool default_val);
SANE_Status set_value(LPDEVINST inst, const void* opt, void* value, SANE_Int* affect, bool to_default);
SANE_Status get_option_fixed_id(LPDEVINST inst, const void* opt, void* value);
protected:
hg_sane_middleware(void);
@ -205,25 +73,9 @@ public:
};
static void set_app_callback(void* cb, void* param = nullptr, int type = APP_CALLBACK_AUTH);
static void get_version(SANE_Int* ver);
static hg_sane_middleware* instance(void);
static void set_callback(sane_callback cb, void* param);
static void clear(void);
static std::string option_value_2_string(SANE_Value_Type type, void* val);
static std::string string_value_from_json(gb_json* jsn, bool curval);
static scanner_handle sane_handle_to_scanner(SANE_Handle h);
static SANE_Handle scanner_handle_to_sane(scanner_handle h);
static SANE_Option_Descriptor* allocate_descriptor(const char* name, const char* title, const char* desc);
static void free_descriptor(SANE_Option_Descriptor* desc);
static SANE_Option_Descriptor* string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<std::string>& values);
static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, bool double_val, double* lower, double* upper, double* step); // NO constraint if lower or upper were NULL
static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<int>& values); // NO constraint if values was empty
static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<double>& values); // NO constraint if values was empty
static std::string get_string_in_json(gb_json* jsn, const char* key, bool* has = nullptr);
// methods ...
public:
@ -234,15 +86,11 @@ public:
SANE_Status start(SANE_Handle h, void* async_event);
SANE_Status read(SANE_Handle h, void* buf, int* bytes);
SANE_Status stop(SANE_Handle h);
SANE_Option_Descriptor* get_option_descriptor(SANE_Handle h, const void* option);
SANE_Status set_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do);
bool get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type = nullptr); // SANE_type
void* get_cur_value(SANE_Handle handle, void* option, SANE_Value_Type* type = nullptr); // caller should call local_utility::free_memory to free the returned value, SANE_type
void* get_def_value(SANE_Handle handle, void* option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value, SANE_type
SANE_Status control_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do);
// extension ...
SANE_Status io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);
SANE_Status ex_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);
public:
bool is_ready(void);

View File

@ -409,3 +409,9 @@ scanner_err sane_std_opts::set_value(scanner_handle h, int opt, void* buf)
return statu;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -64,3 +64,6 @@ public:
scanner_err get_value(scanner_handle h, int opt, void* buf); // call this ONLY when is_known_option returnning true
scanner_err set_value(scanner_handle h, int opt, void* buf); // call this ONLY when is_known_option returnning true
};

View File

@ -176,19 +176,13 @@ enum hg_control_code
{
HG_CONTROL_CODE_OPTION_ENABLE = IO_CTRL_CODE_LAST + 1, // 配置项使能状态改变. data - OPTEN*, len - unused, be NULL
};
typedef struct _opt_val
{
char name[MAX_OPT_NAME_LEN]; // 配置项名称
void* data; // 配置项数据
}OPTVAL;
typedef struct _opt_enabled // 配置项使能状态改变
{
char name[MAX_OPT_NAME_LEN]; // 配置项名称
int enabled; // 0 - 禁止1 - 可用
int master_count; // 该配置项的依赖项数目
OPTVAL master[1]; // 该配置项的依赖项当前值
}OPTEN;
enum option_value
{
OPT_VAL_CURRENT = 0,
OPT_VAL_DEFAULT,
OPT_VAL_JSON,
};
//
// 可变参数数据使用JSON格式配置utf-8编码
//
@ -237,6 +231,7 @@ typedef struct _opt_enabled // 配置项使能状态改变
/// </summary>
typedef void* scanner_handle;
#define PARAM_ALL (const char*)1
#ifdef __cplusplus
extern "C"{
@ -315,25 +310,27 @@ extern "C"{
// Return: 错误代码E_OK or E_HASDATAYET
scanner_err hg_scanner_close(scanner_handle h, bool force);
// Function: 获取设备的配置参数说明及当前的设置
// Function: 获取设备的属性
//
// Parameter: h - hg_open_scanner打开的设备句柄
//
// name - 参数名称如果为“null”在len中返回参数总数量
// name - 参数名称如果为“null”在len中返回参数总数量;
// (char*)1 则返回所有属性的JSON文本;
// 正常属性名称则返回当前值或者默认值
//
// json_data - JSON格式的参数数据参考可变参数数据,
// data - 返回的数据,空间由调用者分配
//
// len - [in] 'data' 大小; [out]data中返回的数据大小
// 当'data'为NULL或者空间小于所需最小长度时返回所需要的内存长度
// 如果“param_no==0”,则返回最大可配置的参数号
// 如果“name==null”,则返回最大可配置的参数号
// 该参数必须非空如果为NULL则会返回 EPARAMETERINVAL 的错误
//
// id - to receive the option ID if 'name' is the name of the option
// type - 获取的值类型0 - 当前值1 - 默认值;……
//
// Return: 错误代码E_OK or E_INSUFFICIENTMEM or E_PARAMETERINVAL or E_DEVICENOTFOUND or E_OUTOFRANGE
//
// NOTE: 'data'空间由用户分配,如果空间太小(包含传入NULL)会在len中返回所需要的最小空间字节数并返回 EINSUFFICIENTMEM
scanner_err hg_scanner_get_parameter(scanner_handle h, const char* name, char* json_data, long* len, SANE_Int* id = nullptr);
scanner_err hg_scanner_get_option(scanner_handle h, const char* name, char* data, long* len, int type = OPT_VAL_CURRENT);
// Function: 设置设备的配置参数
//
@ -344,16 +341,16 @@ extern "C"{
// data - 参数数据如果为“NULL”执行恢复到默认值动作。所有类型的参数按照该功能号的实际类型指针处理
// bool: (bool*)data
// int: (int*)data
// float: (float*)data
// float: (double*)data
// string: (char*)data
//
// len - [in] - 'data' 大小, [out] - exact data size in 'data' if E_NOTEXACT returned
//
// to_default - false: to set value in 'data'; true: to set value to default value
//
// Return: 错误代码E_OK or E_NOTEXACT or E_ACCESSDENIED or E_NEEDRELOADPARAM
//
// NOTE: 如果传入的参数不精确则由驱动选择合适的参数设置并写入到data中返回 E_NOTEXACT 的错误码。用户需要根据该参数更新UI
// 以共享方式打开的设备,没有设置权限,会返回 E_ACCESSDENIED 错误。
scanner_err hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, long* len);
scanner_err hg_scanner_set_option(scanner_handle h, const char* name, void* data, bool to_default);
// Function: 启动设备工作
//

View File

@ -101,6 +101,8 @@ gb_json::gb_json(const char* key, double val) : ref_(1), type_(VAL_TYPE_FLOAT),
}
gb_json::gb_json(const char* key, const char* val) : ref_(1), type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val ? val : ""), cur_child_(-1)
{}
gb_json::gb_json(const char* key, const std::string& val) : ref_(1), type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val), cur_child_(-1)
{}
gb_json::~gb_json()
{
clear();

View File

@ -41,12 +41,13 @@ class gb_json
public:
gb_json(char* json_txt = 0);
protected:
gb_json(const char* key, bool val);
gb_json(const char* key, int val);
gb_json(const char* key, double val);
gb_json(const char* key, const char* val);
gb_json(const char* key, const std::string& val);
protected:
~gb_json();
public:

View File

@ -2723,10 +2723,24 @@ COM_API_IMPLEMENT(scanner, void, free_buffer(void* buf, int len))
}
COM_API_IMPLEMENT(scanner, int, get_fixed_ids(bool(* cb)(uint32_t id, void* param), void* param))
{
for (auto& v : sane_ids_)
//for (auto& v : sane_ids_)
//{
// if (!cb(v.first, param))
// break;
//}
SANE_Int cnt = 0;
sane_helper_->invoke_sane_control_option(handle_, 0, SANE_ACTION_GET_VALUE, &cnt, nullptr);
for (int i = 1; i < cnt; ++i)
{
if (!cb(v.first, param))
break;
SANE_Int fixid = -1;
if (sane_helper_->invoke_sane_control_option(handle_, i, (SANE_Action)SANE_ACTION_GET_FIX_ID, &fixid, nullptr) == SANE_STATUS_GOOD)
{
if (!cb(fixid, param))
break;
}
}
return 0;