diff --git a/hgdriver/hgdev/device_opt.cpp b/hgdriver/hgdev/device_opt.cpp index 121f1c1..efa8908 100644 --- a/hgdriver/hgdev/device_opt.cpp +++ b/hgdriver/hgdev/device_opt.cpp @@ -18,11 +18,6 @@ static void copy_simple_type(TC* dst, T& src) { *dst = src; } -template -static void copy_string(TC* dst, T& src) -{ - strcpy(*dst, src.c_str()); -} template 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(child, value, copy_string); + refined = refine_string_data(child, value); } child->release(); diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index 7cd16c3..b4eb9ea 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -5,6 +5,8 @@ #include "sane/sane_option_definitions.h" #include "scanner_setting.h" #include "scanner_manager.h" +#include "../../sdk/json/gb_json.h" +#include #if defined(WIN32) || defined(_WIN64) #include @@ -164,6 +166,7 @@ hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, usb_io* io, i , firmware_sup_wait_paper_(false),firmware_sup_pick_strength_(false),firmware_sup_log_export_(false),firmware_sup_color_corr_(false),firmware_sup_wake_device_(false) , firmware_sup_double_img(false),firmware_sup_devs_lock_(false),firmware_sup_dpi_300(false),firmware_sup_dpi_600(false),firmware_sup_auto_speed_(false),firmware_sup_morr_(false) , firmware_sup_color_fill_(false),firmware_sup_history_cnt(false), have_max_size(false), is_discardblank(false) + , setting_jsn_(new gb_json()) { #if !defined(_WIN32) && !defined(_WIN64) &&defined(x86_64) isx86_Advan_ = false; @@ -276,6 +279,7 @@ hg_scanner::~hg_scanner() name_ += lang_load_string(ID_STATU_DESC_SCANNER_ERR_DEVICE_IS_CLOSE, nullptr); notify_ui_working_status(name_.c_str(), SANE_EVENT_SCANNER_CLOSED); utils::to_log(LOG_LEVEL_DEBUG, "%s(%p) destroyed.\n", name_.c_str(), this); + setting_jsn_->release(); } std::string hg_scanner::temporary_file(char* tail, char* head) @@ -546,8 +550,8 @@ int hg_scanner::set_server_blacklist_lock() string fv = get_firmware_version(); if (fv.empty() || sn.empty()) return -1; - strcpy(snbuffer, sn.c_str()); - strcpy(fvbuffer, fv.c_str()); + ::strcpy(snbuffer, sn.c_str()); + ::strcpy(fvbuffer, fv.c_str()); sprintf(pidbuffer, "%0x", pid_); //优先从机器设备上进行校验 int ret = HGVersion_Islock_(HGVersion_mgr_, snbuffer, &islock); @@ -701,6 +705,8 @@ void hg_scanner::init_setting_func_map(void) } std::string hg_scanner::setting_name_from(const char* n_or_id, int* id) { + std::string name(""); + if (IS_PTR_NUMBER(n_or_id)) { if (id) @@ -725,114 +731,118 @@ std::string hg_scanner::setting_name_from(const char* n_or_id, int* id) if ((unsigned long)n_or_id == SANE_OPT_ID_DRIVER_LOG) return SANE_STD_OPT_NAME_GET_DEVS_L0G; - if ((unsigned long)n_or_id < jsn_children_.size()) - return jsn_children_[(unsigned long)n_or_id]; - else - return ""; + int sn = (int)(long long)n_or_id; + gb_json* child = setting_jsn_->child(sn); + if (child) + { + name = child->key(); + child->release(); + } } - else if (id) + else { - *id = std::distance(jsn_children_.begin(), std::find(jsn_children_.begin(), jsn_children_.end(), n_or_id)); + name = n_or_id; + if (id) + { + gb_json* child = nullptr; + setting_jsn_->get_value(name.c_str(), child); + if (child) + { + *id = setting_jsn_->index(child); + child->release(); + } + else + { + *id = -1; + } + } } - return n_or_id; + return std::move(name); } void hg_scanner::get_range(const char* name, std::vector& range, std::string& def_val, bool& is_range/*range or list*/) { std::string type(""); + gb_json *child = nullptr, *rng = nullptr; range.clear(); - if (setting_jsn_.at(name).contains("range")) + setting_jsn_->get_value(name, child); + if (!child) + return; + + child->get_value("range", rng); + if (rng) { - setting_jsn_.at(name).at("type").get_to(type); - is_range = !setting_jsn_.at(name).at("range").is_array(); + child->get_value("type", type); + is_range = !rng->is_array(); if (is_range) { if (type == "int") { int l = 0, u = 0; - setting_jsn_.at(name).at("range").at("min").get_to(l); - setting_jsn_.at(name).at("range").at("max").get_to(u); - - char str[20]; - sprintf(str, "%d", l); - range.push_back(str); - sprintf(str, "%d", u); - range.push_back(str); + + rng->get_value("min", l); + rng->get_value("max", u); + range.push_back(std::to_string(l)); + range.push_back(std::to_string(u)); } else { double l = .0f, u = .0f; - setting_jsn_.at(name).at("range").at("min").get_to(l); - setting_jsn_.at(name).at("range").at("max").get_to(u); - - char str[40]; - sprintf(str, "%f", l); - range.push_back(str); - sprintf(str, "%f", u); - range.push_back(str); + rng->get_value("min", l); + rng->get_value("max", u); + range.push_back(std::to_string(l)); + range.push_back(std::to_string(u)); } } else { - char str[40]; - for (int i = 0; i < setting_jsn_.at(name).at("range").size(); ++i) + gb_json* value = rng->first_child(); + while (value) { if (type == "int") { int v = 0; - setting_jsn_.at(name).at("range").at(i).get_to(v); - sprintf(str, "%d", v); - range.push_back(str); + value->value(v); + range.push_back(std::to_string(v)); } - else if(type == "float") + else if (type == "float") { double v = 0; - setting_jsn_.at(name).at("range").at(i).get_to(v); - sprintf(str, "%f", v); - range.push_back(str); + value->value(v); + range.push_back(std::to_string(v)); } else { std::string v(""); - if (setting_jsn_.at(name).at("range").at(i).is_number()) - { - int id = 0; - setting_jsn_.at(name).at("range").at(i).get_to(id); - v = lang_load_string(id, nullptr); - } - else - setting_jsn_.at(name).at("range").at(i).get_to(v); + value->value(v); range.push_back(v); } + value->release(); + value = rng->next_child(); } } + rng->release(); } - if (setting_jsn_.at(name).contains("default")) + if (type == "int") { - if (type == "int") - { - int v = 0; - char sn[20] = { 0 }; - setting_jsn_.at(name).at("default").get_to(v); - sprintf(sn, "%d", v); - def_val = sn; - } - else if (type == "float") - { - double v = 0; - char sn[20] = { 0 }; - setting_jsn_.at(name).at("default").get_to(v); - sprintf(sn, "%f", v); - def_val = sn; - } - else if (type == "string") - { - def_val = get_setting_item_string(name, "default"); - } + int v = 0; + if(child->get_value("default", v)) + def_val = std::to_string(v); } - //utils::to_log(LOG_LEVEL_DEBUG, "setting %d has %d range(s) and default value is '%s'\n", setting_no, range.size(), def_val.c_str()); + else if (type == "float") + { + double v = 0; + if (child->get_value("default", v)) + def_val = std::to_string(v); + } + else if (type == "string") + { + if (child->get_value("default", type)) + def_val = std::move(type); + } + child->release(); } bool hg_scanner::check_range(const char* name, bool& val) { @@ -974,97 +984,108 @@ int hg_scanner::restore(const char* name) { std::string val(""); int ret = SCANNER_ERR_OK; + gb_json* child = nullptr; - if (!setting_jsn_.at(name).contains("default")) + if (!setting_jsn_->get_value("name", child) || !child) return SCANNER_ERR_DEVICE_NOT_SUPPORT; - setting_jsn_.at(name).at("type").get_to(val); + child->get_value("type", val); if (val == "string") { - val = get_setting_item_string(name, "default"); - - char* buf = NULL; - long size = 0; - - setting_jsn_.at(name).at("size").get_to(size); - buf = (char*)malloc(size + 4); - if (buf) + if (child->get_value("default", val)) { - bzero(buf, size + 4); - strcpy(buf, val.c_str()); - ret = set_setting(name, buf, &size); - free(buf); + char* buf = NULL; + int l = 0; + + child->get_value("size", l); + buf = (char*)malloc(l + 4); + if (buf) + { + long size = l; + memset(buf, 0, l + 4); + ::strcpy(buf, val.c_str()); + ret = set_setting(name, buf, &size); + free(buf); + } + else + ret = SCANNER_ERR_INSUFFICIENT_MEMORY; } else - return SCANNER_ERR_INSUFFICIENT_MEMORY; + ret = SCANNER_ERR_DEVICE_NOT_SUPPORT; } else if (val == "int") { int v = 0; long size = sizeof(v); - setting_jsn_.at(name).at("default").get_to(v); - ret = set_setting(name, (char*)&v, &size); + if (child->get_value("default", val)) + ret = set_setting(name, (char*)&v, &size); + else + ret = SCANNER_ERR_DEVICE_NOT_SUPPORT; } else if (val == "float") { double v = .0f; long size = sizeof(v); - setting_jsn_.at(name).at("default").get_to(v); - ret = set_setting(name, (char*)&v, &size); + if (child->get_value("default", val)) + ret = set_setting(name, (char*)&v, &size); + else + ret = SCANNER_ERR_DEVICE_NOT_SUPPORT; } else if (val == "bool") { bool v = false; long size = sizeof(v); - setting_jsn_.at(name).at("default").get_to(v); - ret = set_setting(name, (char*)&v, &size); + if (child->get_value("default", val)) + ret = set_setting(name, (char*)&v, &size); + else + ret = SCANNER_ERR_DEVICE_NOT_SUPPORT; } + child->release(); return ret; } -bool hg_scanner::get_default_value(void* buf, json* jsn) +bool hg_scanner::get_default_value(void* buf, gb_json* jsn) { std::string type(""); + bool ret = true; - if (!jsn->contains("default")) - return false; - - jsn->at("type").get_to(type); + jsn->get_value("type", type); if (type == "bool") { bool v = false; - jsn->at("default").get_to(v); - *((SANE_Bool*)buf) = v; + if (jsn->get_value("default", v)) + *((SANE_Bool*)buf) = v; + else + ret = false; } else if (type == "int") { int v = 0; - jsn->at("default").get_to(v); - *((SANE_Int*)buf) = v; + if (jsn->get_value("default", v)) + *((SANE_Int*)buf) = v; + else + ret = false; } else if (type == "float") { double v = 0; - jsn->at("default").get_to(v); - *((SANE_Fixed*)buf) = SANE_FIX(v); + if (jsn->get_value("default", v)) + *((SANE_Fixed*)buf) = SANE_FIX(v); + else + ret = false; } else if (type == "string") { type = ""; - if (jsn->at("default").is_number()) - { - int n = 0; - jsn->at("default").get_to(n); - type = lang_load_string(n, nullptr); - } + if (jsn->get_value("default", type)) + ::strcpy((char*)buf, type.c_str()); else - jsn->at("default").get_to(type); - strcpy((char*)buf, type.c_str()); + ret = false; } else - return false; + ret = false; - return true; + return ret; } bool hg_scanner::is_to_file(void) { @@ -1333,62 +1354,65 @@ void hg_scanner::reset_custom_area_range(int paper) } float hg_scanner::reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u) { - custom_area_br_y_; - if (setting_jsn_.contains(name)) + gb_json* child = nullptr, * rng = nullptr; + + setting_jsn_->get_value(name, child); + if (!child) + return value_l; + + double v = .0f, tmp = .0f; + + child->get_value("cur", v); + tmp = v; + if (v < value_l) + v = value_l; + else if (v > value_u) + v = value_u; + if (!IS_DOUBLE_EQUAL(tmp, v)) + child->set_value("cur", v); + value_l = v; + + child->get_value("default", v); + tmp = v; + if (v < range_l) + v = range_l; + else if (v > range_u) + v = range_u; + if (!IS_DOUBLE_EQUAL(tmp, v)) + child->set_value("default", v); + + if (var < range_l) + var = range_l; + else if (var > range_u) + var = range_u; + + child->get_value("range", rng); + if (rng) { - float v = .0f, tmp = .0f; - - setting_jsn_.at(name).at("cur").get_to(v); - tmp = v; - if (v < value_l) - v = value_l; - else if (v > value_u) - v = value_u; - if (!IS_DOUBLE_EQUAL(tmp, v)) - setting_jsn_.at(name).at("cur") = v; - value_l = v; - - setting_jsn_.at(name).at("default").get_to(v); - tmp = v; - if (v < range_l) - v = range_l; - else if (v > range_u) - v = range_u; - if (!IS_DOUBLE_EQUAL(tmp, v)) - setting_jsn_.at(name).at("default") = v; - - if (var < range_l) - var = range_l; - else if (var > range_u) - var = range_u; - - if (setting_jsn_.at(name).contains("range")) + double lower = range_l, upper = range_u; + if (rng->get_value("min", lower)) { - float lower = range_l, upper = range_u; - if (setting_jsn_.at(name).at("range").contains("min")) - { - setting_jsn_.at(name).at("range").at("min").get_to(lower); - tmp = lower; - if (lower < range_l) - lower = range_l; - else if (lower > range_u) - lower = range_u; - if (!IS_DOUBLE_EQUAL(lower, tmp)) - setting_jsn_.at(name).at("range").at("min") = lower; - } - if (setting_jsn_.at(name).at("range").contains("max")) - { - setting_jsn_.at(name).at("range").at("max").get_to(upper); - tmp = upper; - if (upper < lower) - upper = lower; - else if (upper > range_u) - upper = range_u; - if (!IS_DOUBLE_EQUAL(upper, tmp)) - setting_jsn_.at(name).at("range").at("max") = upper; - } + tmp = lower; + if (lower < range_l) + lower = range_l; + else if (lower > range_u) + lower = range_u; + if (!IS_DOUBLE_EQUAL(lower, tmp)) + rng->set_value("min", lower); } + if (rng->get_value("max", upper)) + { + tmp = upper; + if (upper < lower) + upper = lower; + else if (upper > range_u) + upper = range_u; + if (!IS_DOUBLE_EQUAL(upper, tmp)) + rng->set_value("max", upper); + } + rng->release(); } + child->release(); return value_l; } @@ -1403,21 +1427,38 @@ int hg_scanner::set_color_change(void) } bool hg_scanner::jsn_reorganize() { - string str; - int len = setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").size(); int max_papers[] = { PAPER_MAX_SIZE, PAPER_MAX_SIZE_CLIP, PAPER_TRIGEMINY }; - for (auto& v : max_papers) + gb_json* paper = nullptr, * range = nullptr; + + setting_jsn_->get_value(SANE_STD_OPT_NAME_PAPER, paper); + if (paper) { - std::string paper(paper_string(v)); - for (int i = 0; i < len; i++) + paper->get_value("range", range); + if (range) { - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").at(i).get_to(str); - if (str.compare(paper) == 0) + gb_json* value = range->first_child(); + while (!have_max_size && value) { - have_max_size = true; - break; + std::string v(""); + if (value->value(v)) + { + for (auto& pp : max_papers) + { + if (v == paper_string(pp)) + { + have_max_size = true; + break; + } + } + } + value->release(); + value = range->next_child(); } + if (value) + value->release(); + range->release(); } + paper->release(); } if (!firmware_sup_wait_paper_ && pid_ == 0x239) @@ -1498,10 +1539,14 @@ int hg_scanner::setting_restore(void* data, long* len) notify_setting_result_ = false; for (auto& v : setting_map_) { - if (setting_jsn_.contains(v.first.c_str())) + gb_json* child = nullptr; + setting_jsn_->get_value(v.first.c_str(), child); + if (child) { std::string t(""); - setting_jsn_.at(v.first.c_str()).at("type").get_to(t); + + child->get_value("type", t); + child->release(); if (t != "group" && t != "button") restore(v.first.c_str()); } @@ -1526,7 +1571,7 @@ static int GetModuleName(void* addr, char* name, int maxLen) return -1; if (maxLen < strlen(dir) + 1) return -1; - strcpy(name, dir); + ::strcpy(name, dir); } else { @@ -1535,7 +1580,7 @@ static int GetModuleName(void* addr, char* name, int maxLen) return -1; if (maxLen < strlen(dlinfo.dli_fname) + 1) return -1; - strcpy(name, dlinfo.dli_fname); + ::strcpy(name, dlinfo.dli_fname); } #else HMODULE hModule = NULL; @@ -1546,7 +1591,7 @@ static int GetModuleName(void* addr, char* name, int maxLen) DWORD len = GetModuleFileNameA(hModule, moduleName, MAX_PATH); if (0 == len || maxLen < strlen(moduleName) + 1) return -1; - strcpy(name, moduleName); + ::strcpy(name, moduleName); #endif return 0; } @@ -1658,7 +1703,7 @@ int hg_scanner::setting_color_mode(void* data, long* len) utils::to_log(LOG_LEVEL_DEBUG, "Change color mode from %s to %s = %s color is =%s\n", color_mode_string(old).c_str(), (char*)data, hg_scanner_err_name(ret),str.c_str()); if(ret == SCANNER_ERR_NOT_EXACT) - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); return SCANNER_ERR_RELOAD_OPT_PARAM; // ret; } @@ -1715,7 +1760,7 @@ int hg_scanner::setting_rid_color(void* data, long* len) if (!exact) { ret = SCANNER_ERR_NOT_EXACT; - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); } return ret; @@ -1795,7 +1840,7 @@ int hg_scanner::setting_paper(void* data, long* len) if (!check_paper_and_resolution(resolution_, val)) { image_prc_param_.bits.paper = old; - strcpy((char*)data, paper_string(old).c_str()); + ::strcpy((char*)data, paper_string(old).c_str()); return SCANNER_ERR_DEVICE_NOT_SUPPORT; } @@ -1824,7 +1869,7 @@ int hg_scanner::setting_paper(void* data, long* len) utils::to_log(LOG_LEVEL_DEBUG, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret)); if(ret == SCANNER_ERR_NOT_EXACT) - strcpy((char*)data, paper.c_str()); + ::strcpy((char*)data, paper.c_str()); if(old != image_prc_param_.bits.paper) reset_custom_area_range(image_prc_param_.bits.paper); @@ -1838,9 +1883,18 @@ int hg_scanner::setting_paper(void* data, long* len) break; } } - if (setting_jsn_.at(SANE_STD_OPT_NAME_RESOLUTION).at("range").count("max")) + gb_json* child = nullptr, * range = nullptr; + setting_jsn_->get_value(SANE_STD_OPT_NAME_RESOLUTION, child); + if (child) { - setting_jsn_.at(SANE_STD_OPT_NAME_RESOLUTION).at("range").at("max") = max_dpi; + child->get_value("range", range); + if (range) + { + if (!range->is_array()) + range->set_value("max", max_dpi); + range->release(); + } + child->release(); } #endif @@ -1871,7 +1925,7 @@ int hg_scanner::setting_page(void* data, long* len) utils::to_log(LOG_LEVEL_DEBUG, "Change page from %s to %s = %s\n", page_string(image_prc_param_.bits.page).c_str(), (char*)data, hg_scanner_err_name(ret)); image_prc_param_.bits.page = match_best_page(val, NULL); if (!exact) - strcpy((char*)data, val.c_str()); + ::strcpy((char*)data, val.c_str()); return ret; } @@ -1914,7 +1968,7 @@ int hg_scanner::setting_resolution(void* data, long* len) if (resolution_ == 600 && old < 300) { char buf[128] = { 0 }; - strcpy(buf, OPTION_VALUE_HZ_HZYX); + ::strcpy(buf, OPTION_VALUE_HZ_HZYX); resolution_ = old; invoke_setting_xxx(&hg_scanner::setting_img_quality, buf); resolution_ = 600; @@ -1945,57 +1999,77 @@ int hg_scanner::setting_resolution(void* data, long* len) #ifdef DYN_JSON_BETWEEN_PAPER_AND_DPI int max_papers[] = { PAPER_MAX_SIZE, PAPER_MAX_SIZE_CLIP, PAPER_TRIGEMINY }; //std::string now(setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").dump()); + gb_json* paper = nullptr, * range = nullptr; - if (resolution_ >= 500) + setting_jsn_->get_value(SANE_STD_OPT_NAME_PAPER, paper); + if (paper) + paper->get_value("range", range); + if (range) { - // erase max papers ... - for (auto& v : max_papers) + gb_json* value = range->first_child(); + std::string item(""); + + if (resolution_ >= 500) { - std::string str(paper_string(v)); - int id = lang_get_string_id(str.c_str(), false); - if (id == -1) - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").erase(str.c_str()); - else + // erase max papers ... + while (value) { - for (int i = 0; i < setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").size(); ++i) + if (value->value(item)) { - int val = 0; - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").at(i).get_to(val); - if (val == id) + bool rm = false; + for (auto& v : max_papers) { - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").erase(i); - break; + std::string str(paper_string(v)); + if (str == item) + { + rm = true; + range->remove(value); + break; + } + } + if (rm) + { + value->release(); + value = range->first_child(); + continue; } } + value->release(); + value = range->next_child(); } } - } - else - { - for (auto& v : max_papers) + else { - std::string str(paper_string(v)); - int id = lang_get_string_id(str.c_str(), false), val = 0; - bool add = true; - for (int i = 0; i < setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").size(); ++i) + // restore max papers ... + for (auto& v : max_papers) { - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").at(i).get_to(val); - if (val == id) + std::string str(paper_string(v)); + bool add = true; + + value = range->first_child(); + while (value) { - add = false; - break; + if (value->value(item)) + { + if (item == str) + { + add = false; + value->release(); + break; + } + } + value->release(); + value = range->next_child(); } - } - if (add) - { - if(id == -1) - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").push_back(str); - else - setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").push_back(id); + if (add) + *range += str.c_str(); } } + range->release(); } // std::string last(setting_jsn_.at(SANE_STD_OPT_NAME_PAPER).at("range").dump()); + if (paper) + paper->release(); #endif return SCANNER_ERR_RELOAD_OPT_PARAM; // ret; @@ -2090,7 +2164,7 @@ int hg_scanner::setting_sharpen(void* data, long* len) image_prc_param_.bits.sharpen = match_best_sharpen(str, NULL); if (!exact) { - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); ret = SCANNER_ERR_NOT_EXACT; } utils::to_log(LOG_LEVEL_DEBUG, "%d\n", ret); @@ -2157,7 +2231,7 @@ int hg_scanner::setting_filling_background(void* data, long* len) image_prc_param_.bits.fill_background = match_best_fill_background(str, NULL); if (!exact) { - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); ret = SCANNER_ERR_NOT_EXACT; } @@ -2179,7 +2253,7 @@ int hg_scanner::setting_is_permeate_lv(void* data, long* len) if (!exact) { - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); ret = SCANNER_ERR_NOT_EXACT; } utils::to_log(LOG_LEVEL_DEBUG, "%d\n", ret); @@ -2232,7 +2306,7 @@ int hg_scanner::setting_go_on_when_double_checked(void* data, long* len) std::string val((char*)data); if (!firmware_sup_double_img && val.compare(lang_load_string(ID_OPTION_VALUE_SZTPCL_DQTXBTZSM, nullptr))) { - strcpy((char*)data, lang_load_string(ID_OPTION_VALUE_SZTPCL_SCTXBTZSM, nullptr)); + ::strcpy((char*)data, lang_load_string(ID_OPTION_VALUE_SZTPCL_SCTXBTZSM, nullptr)); return SCANNER_ERR_DEVICE_NOT_SUPPORT; } @@ -2246,7 +2320,7 @@ int hg_scanner::setting_go_on_when_double_checked(void* data, long* len) return SCANNER_ERR_OK; else { - strcpy((char*)data, val.c_str()); + ::strcpy((char*)data, val.c_str()); return SCANNER_ERR_NOT_EXACT; } @@ -2273,7 +2347,14 @@ int hg_scanner::setting_scan_mode(void* data, long* len) } else { - setting_jsn_.at(SANE_STD_OPT_NAME_SCAN_COUNT).at("cur").get_to(scan_count_); + gb_json* child = nullptr; + + setting_jsn_->get_value(SANE_STD_OPT_NAME_SCAN_COUNT, child); + if (child) + { + child->get_value("cur", scan_count_); + child->release(); + } } utils::to_log(LOG_LEVEL_DEBUG, "set scanning pages to %d\n", scan_count_); @@ -2308,7 +2389,7 @@ int hg_scanner::setting_text_direction(void* data, long* len) image_prc_param_.bits.text_direction = match_best_text_direction(str, NULL); if (!exact) - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO && ImagePrc_pHandle_) { hg_imgproc::init_auto_txt_hanld(ImagePrc_pHandle_); @@ -2436,7 +2517,7 @@ int hg_scanner::setting_img_quality(void* data, long* len) /*if (!check_resolution_and_quality(resolution_, is_img_quality(is_quality_).c_str())) { is_quality_ = old; - strcpy((char*)data, is_img_quality(is_quality_).c_str()); + ::strcpy((char*)data, is_img_quality(is_quality_).c_str()); return SCANNER_ERR_DEVICE_NOT_SUPPORT; }*/ @@ -2674,13 +2755,13 @@ int hg_scanner::setting_get_dev_pid(void* data, long* len) } int hg_scanner::setting_get_dev_family(void* data, long* len) { - strcpy((char*)data, family_.c_str()); + ::strcpy((char*)data, family_.c_str()); return SCANNER_ERR_OK; } int hg_scanner::setting_get_dev_name(void* data, long* len) { - strcpy((char*)data, name_.c_str()); + ::strcpy((char*)data, name_.c_str()); return SCANNER_ERR_OK; } @@ -2690,7 +2771,7 @@ int hg_scanner::setting_get_dev_sn(void* data, long* len) { return SCANNER_ERR_NO_DATA; } - strcpy((char*)data, get_serial_num().c_str()); + ::strcpy((char*)data, get_serial_num().c_str()); return SCANNER_ERR_OK; } int hg_scanner::setting_get_dev_fmver(void* data, long* len) @@ -2699,7 +2780,7 @@ int hg_scanner::setting_get_dev_fmver(void* data, long* len) { return SCANNER_ERR_NO_DATA; } - strcpy((char*)data, get_firmware_version().c_str()); + ::strcpy((char*)data, get_firmware_version().c_str()); return SCANNER_ERR_OK; } int hg_scanner::setting_get_dev_ip(void* data, long* len) @@ -2708,7 +2789,7 @@ int hg_scanner::setting_get_dev_ip(void* data, long* len) { return SCANNER_ERR_NO_DATA; } - strcpy((char*)data, get_ip().c_str()); + ::strcpy((char*)data, get_ip().c_str()); return SCANNER_ERR_OK; } int hg_scanner::setting_get_roller_count(void* data, long* len) @@ -2740,7 +2821,7 @@ int hg_scanner::setting_get_devs_log(void* data, long* len) string str; int ret = get_device_log(str); if(ret == SCANNER_ERR_OK) - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); return ret; } int hg_scanner::setting_set_language(void* data, long* len) @@ -2767,13 +2848,20 @@ int hg_scanner::setting_set_language(void* data, long* len) if (id == -1) { err = SCANNER_ERR_INVALID_PARAMETER; - strcpy((char*)data, now.c_str()); + ::strcpy((char*)data, now.c_str()); } else if(cur != id) { int lid = lang_get_string_id((char*)data, false); + gb_json* child = nullptr; + err = SCANNER_ERR_CONFIGURATION_CHANGED; - setting_jsn_.at(SANE_STD_OPT_NAME_LANGUAGE).at("cur") = lid; + setting_jsn_->get_value(SANE_STD_OPT_NAME_LANGUAGE, child); + if (child) + { + child->set_value("cur", lid); + child->release(); + } lang_set_code_page(id); on_language_changed(); } @@ -2787,7 +2875,7 @@ int hg_scanner::setting_get_motor_ver(void* data, long* len) int ret = get_motor_board_ver(str); if (ret == SCANNER_ERR_OK) { - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); } return ret; } @@ -2797,7 +2885,7 @@ int hg_scanner::setting_get_initial_boot_time(void* data, long* len) int ret = get_devs_time(str); if (ret == SCANNER_ERR_OK) { - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); } return ret; } @@ -2963,191 +3051,10 @@ SANE_Image_Statu hg_scanner::last_usb_image_statu(int err) return statu; } -void hg_scanner::change_setting_language(bool init) -{ - for (size_t i = 1; i < jsn_children_.size(); ++i) - { - std::string v(jsn_children_[i]); - - if (!setting_jsn_.contains(v.c_str())) - continue; - - std::string val(""); - - change_string_2_lang_id(v.c_str(), "title"); - change_string_2_lang_id(v.c_str(), "desc"); - - setting_jsn_.at(v.c_str()).at("type").get_to(val); - string depend; - string depend_temp; - bool is_depend = false; - - if (setting_jsn_.at(v.c_str()).contains("depend_or")) - { - int depend_size = setting_jsn_.at(v.c_str()).at("depend_or").size(); - int y = 0; - while (y < depend_size) - { - setting_jsn_.at(v.c_str()).at("depend_or").at(y).get_to(depend); - for (size_t k = 0; k < erase_depend_.size(); k++) - { - if (depend.find(erase_depend_[k]) != string::npos) - { - setting_jsn_.at(v.c_str()).at("depend_or").erase(y); - depend_temp = depend; - y--; - break; - } - else if (!depend_temp.empty() && !(depend[0] <= 'z' && depend[0] >= 'a')) - { - setting_jsn_.at(v.c_str()).at("depend_or").erase(y); - y--; - break; - } - } - depend_size = setting_jsn_.at(v.c_str()).at("depend_or").size(); - y++; - } - } - else if (setting_jsn_.at(v.c_str()).contains("depend_and")) - { - int depend_size = setting_jsn_.at(v.c_str()).at("depend_and").size(); - int y = 0; - while (y < depend_size) - { - setting_jsn_.at(v.c_str()).at("depend_and").at(y).get_to(depend); - for (size_t k = 0; k < erase_depend_.size(); k++) - { - if (depend.find(erase_depend_[k]) != string::npos) - { - setting_jsn_.at(v.c_str()).at("depend_and").erase(y); - depend_temp = depend; - y--; - break; - } - else if (!depend_temp.empty() && !(depend[0] <= 'z' && depend[0] >= 'a')) - { - setting_jsn_.at(v.c_str()).at("depend_and").erase(y); - y--; - break; - } - } - depend_size = setting_jsn_.at(v.c_str()).at("depend_and").size(); - y++; - } - } - - - //if (v.compare(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)) == 0) - //{ - // int val = 0; - // get_sleep_time(val); - // const char* p_time = NULL; - // if (val == -1 || val > 20000) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_BXM); // changed in 'if (val == "string")' branch. - // else if (val > 0 && val <= 300) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_WFZ); - // else if (val > 300 && val <= 600) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_SFZ); - // else if (val > 600 && val <= 1800) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_BXS); - // else if (val > 1800 && val <= 3600) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_YXS); - // else if (val > 3600 && val <= 7200) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_LXS); - // else if (val > 7200 && val <= 14400) - // p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_SXS); - // if (p_time) - // setting_jsn_.at(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)).at("default") = p_time; - //} - if (v.compare(from_default_language(SANE_STD_OPT_NAME_FEED_STRENGTH)) == 0) - { - int val = 0; - on_get_feedmode(val); - const char* p_feed = NULL; - if (val == 0) - p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_R); - else if (val == 1) - p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_YB); - else if (val == 2) - p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_Q); - - if (p_feed) - setting_jsn_.at(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)).at("default") = p_feed; - - } - if (val == "string") - { - change_string_2_lang_id(v.c_str(), "cur"); - change_string_2_lang_id(v.c_str(), "default"); - if (setting_jsn_.at(v.c_str()).contains("range")) - { - for (int i = 0; i < setting_jsn_.at(v.c_str()).at("range").size(); ++i) - { - int id = -1; - - setting_jsn_.at(v.c_str()).at("range").at(i).get_to(val); - id = lang_get_string_id(val.c_str(), true); - if (id == -1) - { - utils::to_log(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str()); - } - else - setting_jsn_.at(v.c_str()).at("range")[i] = id; - } - } - if (v.compare(from_default_language(SANE_STD_OPT_NAME_LANGUAGE)) == 0) - continue; - - if (init && setting_jsn_.at(v.c_str()).contains("default")) - { - val = get_setting_item_string(v.c_str(), "default"); - - char* buf = NULL; - long size = 0; - - setting_jsn_.at(v.c_str()).at("size").get_to(size); - buf = (char*)malloc(size + 4); - bzero(buf, size + 4); - strcpy(buf, val.c_str()); - set_setting(v.c_str(), buf, &size); - free(buf); - } - } - else if (init && setting_jsn_.at(v.c_str()).contains("default")) - { - if (val == "int") - { - int n = 0; - long size = sizeof(n); - setting_jsn_.at(v.c_str()).at("default").get_to(n); - set_setting(v.c_str(), (char*)&n, &size); - } - else if (val == "float") - { - double d = .0f; - long size = sizeof(d); - setting_jsn_.at(v.c_str()).at("default").get_to(d); - set_setting(v.c_str(), (char*)&d, &size); - } - else if (val == "bool") - { - bool b = false; - long size = sizeof(b); - setting_jsn_.at(v.c_str()).at("default").get_to(b); - set_setting(v.c_str(), (char*)&b, &size); - } - } - } -} void hg_scanner::erase_option(const char* name) { erase_depend_.push_back(name); - setting_jsn_.erase(name); - - std::vector::iterator it = std::find(jsn_children_.begin(), jsn_children_.end(), name); - if (it != jsn_children_.end()) - jsn_children_.erase(it); + setting_jsn_->remove(name); } void hg_scanner::init_settings(const char* json_setting_text) { @@ -3164,22 +3071,22 @@ void hg_scanner::init_settings(const char* json_setting_text) } if (strstr(lang, "{")) txt += strstr(lang, "{") + 1; - jsn_children_.clear(); - setting_jsn_ = jsonconfig::load_json_from_text(txt.c_str(), &jsn_children_); - empty = setting_jsn_.empty(); + setting_jsn_->attach_text(&txt[0]); + empty = setting_jsn_->children() != 0; } if(empty) { - jsn_children_.clear(); - setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text, &jsn_children_); + std::string txt(json_setting_text); + setting_jsn_->attach_text(&txt[0]); } + setting_jsn_->remove("global"); jsn_reorganize(); - utils::to_log(LOG_LEVEL_ALL, "Initialize %d settings ...\n", jsn_children_.size() - 1); + + utils::to_log(LOG_LEVEL_ALL, "Initialize %d settings ...\n", setting_jsn_->children() - 1); notify_setting_result_ = false; - change_setting_language(true); - utils::to_log(LOG_LEVEL_ALL, "Initialize %d settings ... OK\n", jsn_children_.size() - 1); + utils::to_log(LOG_LEVEL_ALL, "Initialize %d settings ... OK\n", setting_jsn_->children() - 1); if (lang_get_cur_code_page() != DEFAULT_CODE_PAGE) on_language_changed(); notify_setting_result_ = true; @@ -3209,36 +3116,16 @@ int hg_scanner::init_settings(int pid) return SCANNER_ERR_OK; } -void hg_scanner::change_string_2_lang_id(const char* name, const char* key) -{ - std::string val(""); - int id = -1; - - if (setting_jsn_.at(name).contains(key)) - { - setting_jsn_.at(name).at(key).get_to(val); - id = lang_get_string_id(val.c_str(), true); - if (id == -1) - { - utils::to_log(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str()); - } - else - setting_jsn_.at(name).at(key) = id; - } -} std::string hg_scanner::get_setting_item_string(const char* name, const char* key) { std::string ret(""); + gb_json* child = nullptr; - if (setting_jsn_.at(name).at(key).is_number()) + setting_jsn_->get_value(name, child); + if (child) { - int n = -1; - setting_jsn_.at(name).at(key).get_to(n); - ret = lang_load_string(n, nullptr); - } - else - { - setting_jsn_.at(name).at(key).get_to(ret); + child->get_value(key, ret); + child->release(); } return std::move(ret); @@ -3663,105 +3550,143 @@ int hg_scanner::close(bool force) return ret; } -int hg_scanner::set_setting(const char* name, void* data, long* len) +int hg_scanner::set_setting(const char* name, void* data, bool to_default) { int ret = SCANNER_ERR_OUT_OF_RANGE; bool hit = false; + long len = 0; + void* buf = data; std::string real_n(setting_name_from(name)); if (real_n.empty()) return ret; + gb_json* child = nullptr; + setting_jsn_->get_value(real_n.c_str(), child); + if (to_default) + { + if (!child) + return SCANNER_ERR_DEVICE_NOT_SUPPORT; + + std::string t(""); + child->get_value("type", t); + if (t == "bool") + { + bool v = false; + child->get_value("default", v); + if (!buf) + buf = new char[sizeof(v)]; + *(bool*)buf = v; + } + else if (t == "int") + { + int v = 0; + child->get_value("default", v); + if (!buf) + buf = new char[sizeof(v)]; + *(int*)buf = v; + } + else if (t == "float") + { + double v = .0f; + child->get_value("default", v); + if (!buf) + buf = new char[sizeof(v)]; + *(double*)buf = v; + } + else if (t == "string") + { + std::string v(""); + child->get_value("default", v); + if (!buf) + buf = new char[v.length() + 4]; + ::strcpy((char*)buf, v.c_str()); + } + else + { + child->release(); + + return SCANNER_ERR_DEVICE_NOT_SUPPORT; + } + } + hit = setting_map_.count(real_n) > 0; if (hit) { - ret = (this->*setting_map_[real_n])(data, len); - if (!setting_jsn_.contains(real_n)) // non-json value, return immediately - return ret; + ret = (this->*setting_map_[real_n])(buf, &len); } else { utils::to_log(LOG_LEVEL_WARNING, "Setting '%s' is not found in base setting functions.\n", real_n.c_str()); - ret = set_setting_value(real_n.c_str(), data, len); + ret = set_setting_value(real_n.c_str(), buf, &len); } - if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED - || ret == SCANNER_ERR_RELOAD_IMAGE_PARAM || ret == SCANNER_ERR_RELOAD_OPT_PARAM) + if (child) // non-gb_json value, return immediately { - std::string type(""), name(get_setting_item_string(real_n.c_str(), "title")); + if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED + || ret == SCANNER_ERR_RELOAD_IMAGE_PARAM || ret == SCANNER_ERR_RELOAD_OPT_PARAM) + { + std::string type(""), name(get_setting_item_string(real_n.c_str(), "title")); - setting_jsn_.at(real_n).at("type").get_to(type); - // setting_jsn_.at(real_n).at("title").get_to(name); - if (type == "string") - { - int id = lang_get_string_id((char*)data, false); - if (id == -1) - setting_jsn_.at(real_n).at("cur") = (char*)data; - else - setting_jsn_.at(real_n).at("cur") = id; - type = (char*)data; + child->get_value("type", type); + if (type == "string") + { + child->set_value("cur", (char*)buf); + } + else if (type == "int") + { + child->set_value("cur", *((int*)buf)); + } + else if (type == "float") + { + child->set_value("cur", *((double*)buf)); + } + else if (type == "bool") + { + child->set_value("cur", *((bool*)buf)); + } } - else if (type == "int") - { - char sn[20] = { 0 }; - setting_jsn_.at(real_n).at("cur") = *((int*)data); - sprintf(sn, "%d", *((int*)data)); - type = sn; - } - else if (type == "float") - { - char sn[20] = { 0 }; - setting_jsn_.at(real_n).at("cur") = *((double*)data); - sprintf(sn, "%f", *((double*)data)); - type = sn; - } - else if (type == "bool") - { - setting_jsn_.at(real_n).at("cur") = *((bool*)data); - type = *((bool*)data) ? "true" : "false"; - } - - /*if (notify_setting_result_) - { - name.insert(0, "\350\256\276\347\275\256 \""); - name += "\" \345\200\274\344\270\272\""; - name += type + "\" \346\210\220\345\212\237\343\200\202"; - notify_ui_working_status(name.c_str()); - }*/ - } - else if (notify_setting_result_) - { - /*std::string n(""); - if (setting_jsn_.contains(real_n)) - { - setting_jsn_.at(real_n).at("title").get_to(n); - } - else - n = std::string("\350\256\276\347\275\256\351\241\271") + real_n; - n.insert(0, "\350\256\276\347\275\256 \""); - n += std::string("\" \345\200\274\345\244\261\350\264\245: ") + hg_scanner_err_name(ret); - notify_ui_working_status(n.c_str());*/ + child->release(); } + if (buf != data) + delete[] buf; return ret; } -int hg_scanner::get_setting(const char* name, char* json_txt_buf, int* len, int* id) +int hg_scanner::get_setting(const char* name, char* buf, int* len, int type) { if (!len) return SCANNER_ERR_INVALID_PARAMETER; - std::string real_n(setting_name_from(name, id)); if (name == nullptr) { - *len = setting_jsn_.size(); + *len = setting_jsn_->children(); return SCANNER_ERR_OK; } - else if (real_n.empty()) + else if (name == PARAM_ALL) + { + std::string text(setting_jsn_->to_string()); + + if (*len <= text.length()) + { + *len = text.length() + 4; + + return SCANNER_ERR_INSUFFICIENT_MEMORY; + } + ::strcpy(buf, text.c_str()); + *len = text.length(); + + return SCANNER_ERR_OK; + } + + std::string real_n(setting_name_from(name)); + gb_json* child = nullptr; + if (real_n.empty()) { return SCANNER_ERR_OUT_OF_RANGE; } - else if (!setting_jsn_.contains(real_n)) + else if (!setting_jsn_->get_value(real_n.c_str(), child) || !child) { utils::to_log(LOG_LEVEL_FATAL, "!!!option(%s) is not found.\n", real_n.c_str()); return SCANNER_ERR_OUT_OF_RANGE; @@ -3769,47 +3694,121 @@ int hg_scanner::get_setting(const char* name, char* json_txt_buf, int* len, int* else { // language can be set outer: - if (real_n == SANE_STD_OPT_NAME_LANGUAGE && setting_jsn_.contains(SANE_STD_OPT_NAME_LANGUAGE)) + if (real_n == SANE_STD_OPT_NAME_LANGUAGE) { LANATTR** lang = lang_get_supported_languages(); for (int i = 0; lang[i]; ++i) { if (lang[i]->cp == lang_get_cur_code_page()) { - setting_jsn_.at(SANE_STD_OPT_NAME_LANGUAGE).at("cur") = lang[i]->id; + child->set_value("cur", (int)lang[i]->id); break; } } } - //json_name.find(real_n) - //auto it = json_name.find(real_n); - //if (it != json_name.end()) - //{ - // int i = it->second; - // - // const char* load = lang_load_string(i); - // if (*load) - // { - // setting_jsn_.at(real_n).at("title") = load; - // } - // - //} - std::string text(setting_jsn_.at(real_n).dump()); - - text.insert(0, "\"" + real_n + "\":"); - if (*len <= text.length()) + if (type == OPT_VAL_CURRENT || type == OPT_VAL_DEFAULT) { - *len = text.length() + 8; + std::string t(""), key(type == OPT_VAL_CURRENT ? "cur" : "default"); + int ret = SCANNER_ERR_OK; - return SCANNER_ERR_INSUFFICIENT_MEMORY; + child->get_value("type", t); + if (t == "bool") + { + bool v = false; + if (*len < sizeof(v)) + { + *len = sizeof(v); + + ret = SCANNER_ERR_INSUFFICIENT_MEMORY; + } + else + { + child->get_value(key.c_str(), v); + *(bool*)buf = v; + *len = sizeof(v); + } + } + else if (t == "int") + { + int v = 0; + if (*len < sizeof(v)) + { + *len = sizeof(v); + + ret = SCANNER_ERR_INSUFFICIENT_MEMORY; + } + else + { + child->get_value(key.c_str(), v); + *(int*)buf = v; + *len = sizeof(v); + } + } + else if (t == "float") + { + double v = false; + if (*len < sizeof(v)) + { + *len = sizeof(v); + + ret = SCANNER_ERR_INSUFFICIENT_MEMORY; + } + else + { + child->get_value(key.c_str(), v); + *(double*)buf = v; + *len = sizeof(v); + } + } + else if (t == "string") + { + std::string v(""); + child->get_value(key.c_str(), v); + if (*len <= v.length()) + { + *len = v.length() + 1; + + ret = SCANNER_ERR_INSUFFICIENT_MEMORY; + } + else + { + ::strcpy(buf, v.c_str()); + *len = v.length(); + } + } + else + { + ret = SCANNER_ERR_NO_DATA; + } + child->release(); + + return ret; + } + else if (type == OPT_VAL_JSON) + { + std::string text(child->to_string()); + + text.insert(0, "\"" + real_n + "\":"); + child->release(); + + if (*len <= text.length()) + { + *len = text.length() + 8; + + return SCANNER_ERR_INSUFFICIENT_MEMORY; + } + else + { + ::strcpy(buf, text.c_str()); + *len = text.length(); + + return SCANNER_ERR_OK; + } } else { - strcpy(json_txt_buf, text.c_str()); - *len = text.length(); - - return SCANNER_ERR_OK; + return SCANNER_ERR_INVALID_PARAMETER; } } } @@ -3833,47 +3832,6 @@ bool hg_scanner::is_online(void) void hg_scanner::on_language_changed(void) { // change the 'size' member of string settings ... - for (size_t i = 1; i < jsn_children_.size(); ++i) - { - std::string v(jsn_children_[i]); - - if (!setting_jsn_.contains(v.c_str())) - continue; - - std::string val(""); - - setting_jsn_.at(v.c_str()).at("type").get_to(val); - if (val != "string") - continue; - - if (setting_jsn_.at(v.c_str()).contains("range")) - { - int old = 0, now = 0; - setting_jsn_.at(v.c_str()).at("size").get_to(old); - for (int i = 0; i < setting_jsn_.at(v.c_str()).at("range").size(); ++i) - { - int id = -1; - - if (setting_jsn_.at(v.c_str()).at("range").at(i).is_number()) - { - setting_jsn_.at(v.c_str()).at("range").at(i).get_to(id); - val = lang_load_string(id, nullptr); - } - else - setting_jsn_.at(v.c_str()).at("range").at(i).get_to(val); - if (now < val.length()) - now = val.length(); - } - now += 15; - now /= 8; - now *= 8; - if (now > old) - { - setting_jsn_.at(v.c_str()).at("size") = now; - utils::to_log(LOG_LEVEL_DEBUG, "Change size of '%s' from %d to %d\n", v.c_str(), old, now); - } - } - } } int hg_scanner::start(void) { @@ -4007,26 +3965,26 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) } else if (code == IO_CTRL_CODE_GET_DEFAULT_VALUE) { - if (*len == 0) + if (*len <= 0) { - *len = setting_jsn_.size(); + *len = setting_jsn_->children(); return SCANNER_ERR_OK; } - else if (*len > setting_jsn_.size()) + else if (*len >= setting_jsn_->children()) { return SCANNER_ERR_OUT_OF_RANGE; } - else if(*len < jsn_children_.size()) - { - if (get_default_value(data, &setting_jsn_.at(jsn_children_[*len]))) - return SCANNER_ERR_OK; - else - return SCANNER_ERR_DATA_DAMAGED; - } else { - return SCANNER_ERR_DATA_DAMAGED; + gb_json* child = setting_jsn_->child(*len); + int ret = SCANNER_ERR_DATA_DAMAGED; + + if (get_default_value(data, child)) + ret = SCANNER_ERR_OK; + child->release(); + + return ret; } } else if (code == IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT) @@ -4099,7 +4057,7 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) } if (data && fw.length()) - strcpy((char*)data, fw.c_str()); + ::strcpy((char*)data, fw.c_str()); return SCANNER_ERR_OK; } @@ -4115,7 +4073,7 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) return SCANNER_ERR_INSUFFICIENT_MEMORY; } if(data && ser.length()) - strcpy((char*)data, ser.c_str()); + ::strcpy((char*)data, ser.c_str()); return SCANNER_ERR_OK; } @@ -4128,7 +4086,7 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) return SCANNER_ERR_INSUFFICIENT_MEMORY; } if(data && ip.length()) - strcpy((char*)data, ip.c_str()); + ::strcpy((char*)data, ip.c_str()); return SCANNER_ERR_OK; } @@ -4271,7 +4229,7 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) { return ret; } - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); return 0; } else if(code == IO_CTRL_CODE_SET_SCAN_LOCK_CHECK_VAL) @@ -4437,7 +4395,7 @@ int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len) *len = str.size(); return SCANNER_ERR_INSUFFICIENT_MEMORY; } - strcpy((char*)data, str.c_str()); + ::strcpy((char*)data, str.c_str()); return SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_GET_SCAN_WITH_HOLE) diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index 6850662..6c183a7 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -13,7 +13,6 @@ //#include #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 jsn_children_; std::vector 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); diff --git a/hgdriver/hgdev/hg_scanner_239.cpp b/hgdriver/hgdev/hg_scanner_239.cpp index 897c765..43dbf6e 100644 --- a/hgdriver/hgdev/hg_scanner_239.cpp +++ b/hgdriver/hgdev/hg_scanner_239.cpp @@ -3,6 +3,7 @@ #include "../../sdk/hginclude/utils.h" #include #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) { diff --git a/hgdriver/hgdev/hg_scanner_302.cpp b/hgdriver/hgdev/hg_scanner_302.cpp index 67416be..c749f6c 100644 --- a/hgdriver/hgdev/hg_scanner_302.cpp +++ b/hgdriver/hgdev/hg_scanner_302.cpp @@ -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(); diff --git a/hgdriver/hgdev/scanner_manager.cpp b/hgdriver/hgdev/scanner_manager.cpp index 2d15a47..9c114cc 100644 --- a/hgdriver/hgdev/scanner_manager.cpp +++ b/hgdriver/hgdev/scanner_manager.cpp @@ -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 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) { diff --git a/hgdriver/hgdev/scanner_manager.h b/hgdriver/hgdev/scanner_manager.h index f819455..c71df2b 100644 --- a/hgdriver/hgdev/scanner_manager.h +++ b/hgdriver/hgdev/scanner_manager.h @@ -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); diff --git a/hgdriver/hgdev/simple_logic.cpp b/hgdriver/hgdev/simple_logic.cpp index 054500a..7bc04c4 100644 --- a/hgdriver/hgdev/simple_logic.cpp +++ b/hgdriver/hgdev/simple_logic.cpp @@ -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; diff --git a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp index 46ad24e..6c35aa1 100644 --- a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp +++ b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp @@ -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) diff --git a/hgsane/entry.cpp b/hgsane/entry.cpp index 6a6521c..676098d 100644 --- a/hgsane/entry.cpp +++ b/hgsane/entry.cpp @@ -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) { diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index 67a0405..a2c60b7 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -1,6 +1,6 @@ #include "sane_hg_mdw.h" -#include "../sdk/json/gb_json.h" +#include "sane_opt/sane_opts.h" #include #include @@ -277,111 +277,6 @@ namespace local_utility ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // fixed id map - static void init_fixed_id(const char* name, int id, std::map& mapid, int* fixid = nullptr) - { - #define TRY_MATCH(n) \ - if(strcmp(SANE_STD_OPT_NAME_##n, name) == 0) \ - { \ - mapid[SANE_OPT_ID_##n] = id; \ - 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); - TRY_MATCH(LANGUAGE); - TRY_MATCH(INITIAL_BOOT_TIME); - TRY_MATCH(DISCARDBLANK); - - //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); - } static std::string un_json_option_name(int id, int *len) { int tmp = sizeof(int); @@ -531,6 +426,11 @@ namespace local_utility } } } + + static void dump_msg(const char* msg) + { + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, msg); + } } @@ -539,7 +439,7 @@ namespace local_utility hg_sane_middleware* hg_sane_middleware::inst_ = nullptr; const SANE_Device** hg_sane_middleware::dev_list_ = nullptr; -hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false) +hg_sane_middleware::hg_sane_middleware(void) : init_ok_(false) { char sane_ver[40] = { 0 }; @@ -553,39 +453,30 @@ hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false) hg_scanner_set_sane_info(GET_BACKEND_NAME, sane_ver); #endif hg_scanner_initialize(local_utility::ui_cb, nullptr); - register_language_changed_notify(&hg_sane_middleware::language_changed, true); - char path[512] = { 0 }; - size_t pos = 0; + offline_ = new device_opts(); + { + DEVINST inst; + inst.opts = offline_; + reload_options(&inst); + } std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait for device OK } hg_sane_middleware::~hg_sane_middleware() { - register_language_changed_notify(&hg_sane_middleware::language_changed, false); - for (size_t i = 0; i < openning_.size(); ++i) + for (auto& v : openning_) { - hg_scanner_close(openning_[i]->dev, true); - hg_sane_middleware::free_device_inst(openning_[i]); + hg_sane_middleware::free_device_instance(v); } + openning_.clear(); hg_scanner_uninitialize(); - if (opt_0_) - local_utility::free_memory(opt_0_); + delete offline_; + + if (hg_sane_middleware::dev_list_) + local_utility::free_memory(hg_sane_middleware::dev_list_); } -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, nullptr, &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); - //} -} const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, int count) { // 将多级指针安排在一个连续的内存空间存放 @@ -653,90 +544,6 @@ 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); -} - -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); - ret = buf; - break; - case SANE_TYPE_FIXED: - sprintf(buf, "%f", hg_sane_middleware::sane_fixed_2_double(*(SANE_Word*)val)); - 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; -} -std::string hg_sane_middleware::string_value_from_json(gb_json* jsn, bool curval) -{ - std::string type(""), key(curval ? "cur" : "default"); - - if (jsn->get_value("type", type)) - { - if (type == "bool") - { - bool val = true; - jsn->get_value(key.c_str(), val); - - return val ? "true" : "false"; - } - else if (type == "int") - { - int val = 0; - jsn->get_value(key.c_str(), val); - - return std::to_string(val); - } - else if (type == "float") - { - double val = 0; - jsn->get_value(key.c_str(), val); - - return std::to_string(val); - } - else if (type == "string") - { - std::string val(""); - jsn->get_value(key.c_str(), val); - - return std::move(val); - } - - } - - return ""; -} scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h) { if (!h) @@ -761,195 +568,207 @@ SANE_Handle hg_sane_middleware::scanner_handle_to_sane(scanner_handle h) return (SANE_Handle)(v); } -SANE_Option_Descriptor* hg_sane_middleware::allocate_descriptor(const char* name, const char* title, const char* desc) +void hg_sane_middleware::free_device_instance(LPDEVINST inst) { - 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 (inst) { - if (desc->name) - local_utility::free_memory((void*)desc->name); - desc->name = nullptr; + if (inst->dev) + hg_scanner_close(inst->dev, true); + if (inst->opts) + delete inst->opts; - 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); + delete inst; } } -SANE_Option_Descriptor* hg_sane_middleware::string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc - , const std::vector& values) + +hg_sane_middleware::LPDEVINST hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv) { - int bytes = (values.size() + 1) * sizeof(SANE_String); - SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc); + LPDEVINST ret = nullptr; + scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h); - 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; // 硬件可设置默认�? - if (values.size()) + for (int i = 0; i < openning_.size(); ++i) { - SANE_String* buf = (SANE_String*)local_utility::acquire_memory(bytes, "string_list"); - char* str = (char*)buf + (values.size() + 1) * sizeof(SANE_String); - - sod->constraint_type = SANE_CONSTRAINT_STRING_LIST; - sod->constraint.string_list = buf; - for (size_t i = 0; i < values.size(); ++i) + if (openning_[i]->dev == handle) { - buf[i] = str; - strcpy(str, values[i].c_str()); - - str += ALIGN_INT(values[i].length() + 1); + ret = openning_[i]; + if (rmv) + openning_.erase(openning_.begin() + i); + break; } } - return sod; + return ret; } -SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc - , bool double_val, double* lower, double* upper, double* step) +hg_sane_middleware::LPDEVINST hg_sane_middleware::find_openning_device(const char* name, bool rmv) { - int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range); - SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc); - - sod->type = double_val ? SANE_TYPE_FIXED : 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; - if (lower || upper) + LPDEVINST ret = nullptr; + + for(int i = 0; i < openning_.size(); ++i) { - 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"); - if (lower) + if (openning_[i]->name == name) { - if (double_val) - range->min = hg_sane_middleware::double_2_sane_fixed(*lower); - else - range->min = (SANE_Word)*lower; + ret = openning_[i]; + if (rmv) + openning_.erase(openning_.begin() + i); + break; } - if (upper) - { - if (double_val) - range->max = hg_sane_middleware::double_2_sane_fixed(*upper); - else - range->max = (SANE_Word)*upper; - } - range->quant = 0; - if (step) - { - if(double_val) - range->quant = hg_sane_middleware::double_2_sane_fixed(*step); - else - range->quant = (SANE_Word)(*step); - } - - sod->constraint.range = range; } - return sod; + return ret; } -SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc - , const std::vector& values) +bool hg_sane_middleware::reload_options(LPDEVINST inst) { - int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range); - SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc); + long len = 0; + char *buf = nullptr; + scanner_err err = hg_scanner_get_option(inst->dev, PARAM_ALL, buf, &len, OPT_VAL_JSON); - 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; // 硬件可设置默认�? - - if (values.size()) + if (err == SCANNER_ERR_INSUFFICIENT_MEMORY) { - 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; - sod->constraint_type = SANE_CONSTRAINT_WORD_LIST; - *val++ = values.size(); - for (size_t i = 0; i < values.size(); ++i) - val[i] = values[i]; - } - //utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes); - - 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& values) -{ - int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range); - SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc); - - 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; // 硬件可设置默认�? - - 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; - 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]); + buf = new char[len + 4]; + err = hg_scanner_get_option(inst->dev, PARAM_ALL, buf, &len, OPT_VAL_JSON); } - return sod; -} -std::string hg_sane_middleware::get_string_in_json(gb_json* jsn, const char* key, bool* has) -{ - std::string str(""); - int id = -1; - - if (has) - *has = false; - - if (jsn->get_value(key, id) && id != -1) + if (err == SCANNER_ERR_OK && len) { - str = lang_load_string(id, &id); - if (has) - *has = true; + if (!inst->opts->init_from(buf, local_utility::dump_msg)) + err = SCANNER_ERR_DATA_DAMAGED; + } + if (buf) + delete[] buf; + + return err == SCANNER_ERR_OK; +} + +scanner_err hg_sane_middleware::read_value(scanner_handle h, const char* name, SANE_Value_Type type, size_t len, void* value, bool to_default) +{ + scanner_err err = SCANNER_ERR_INVALID_PARAMETER; + + if (type == SANE_TYPE_BOOL) + { + bool v = false; + long len = sizeof(v); + err = hg_scanner_get_option(h, name, (char*)&v, &len, to_default ? OPT_VAL_DEFAULT : OPT_VAL_CURRENT); + if (value) + *(SANE_Bool*)value = v ? SANE_TRUE : SANE_FALSE; + } + else if (type == SANE_TYPE_INT) + { + int v = 0; + long len = sizeof(v); + err = hg_scanner_get_option(h, name, (char*)&v, &len, to_default ? OPT_VAL_DEFAULT : OPT_VAL_CURRENT); + if (value) + *(SANE_Int*)value = v; + } + else if (type == SANE_TYPE_FIXED) + { + double v = .0f; + long len = sizeof(v); + err = hg_scanner_get_option(h, name, (char*)&v, &len, to_default ? OPT_VAL_DEFAULT : OPT_VAL_CURRENT); + if (value) + *(SANE_Fixed*)value = hg_sane_middleware::double_2_sane_fixed(v); } else { - bool ok = jsn->get_value(key, str); - if (has) - *has = ok; + long l = len; + err = hg_scanner_get_option(h, name, (char*)value, &l, to_default ? OPT_VAL_DEFAULT : OPT_VAL_CURRENT); } - return std::move(str); + return err; } +scanner_err hg_sane_middleware::write_value(scanner_handle h, const char* name, SANE_Value_Type type, void* value, bool to_default, LPDEVINST optinst, SANE_Int* affect) +{ + scanner_err err = SCANNER_ERR_INVALID_PARAMETER; + + if (type == SANE_TYPE_BOOL) + { + bool v = value ? *(SANE_Bool*)value == SANE_TRUE : false; + err = hg_scanner_set_option(h, name, &v, to_default); + if (value) + *(SANE_Bool*)value = v ? SANE_TRUE : SANE_FALSE; + } + else if (type == SANE_TYPE_INT) + { + int v = value ? *(SANE_Int*)value : 0; + err = hg_scanner_set_option(h, name, &v, to_default); + if (value) + *(SANE_Int*)value = v; + } + else if (type == SANE_TYPE_FIXED) + { + double v = value ? hg_sane_middleware::sane_fixed_2_double(*(SANE_Fixed*)value) : .0f; + err = hg_scanner_set_option(h, name, &v, to_default); + if (value) + *(SANE_Fixed*)value = hg_sane_middleware::double_2_sane_fixed(v); + } + else + { + err = hg_scanner_set_option(h, name, value, to_default); + } + + if (affect) + *affect = 0; + + if (err == SCANNER_ERR_RELOAD_OPT_PARAM || err == SCANNER_ERR_CONFIGURATION_CHANGED) + { + if(optinst) + reload_options(optinst); + if (affect) + *affect = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; + err = SCANNER_ERR_OK; + } + else if (err == SCANNER_ERR_RELOAD_IMAGE_PARAM) + { + err = SCANNER_ERR_OK; + if (affect) + *affect = SANE_INFO_RELOAD_PARAMS; + } + + return err; +} +SANE_Status hg_sane_middleware::get_current_value(LPDEVINST inst, const void* opt, void* value, bool default_val) +{ + std::string val(""); + SANE_Option_Descriptor* desc = inst->opts->get_opt_descriptor(opt); + + if (desc) + { + scanner_err err = read_value(inst->dev, desc->name, desc->type, desc->size, value, default_val); + + return local_utility::scanner_err_2_sane_statu(err); + } + else + { + return SANE_STATUS_INVAL; + } +} +SANE_Status hg_sane_middleware::set_value(LPDEVINST inst, const void* opt, void* value, SANE_Int* affect, bool to_default) +{ + bool empty_value = false; + SANE_Option_Descriptor* desc = inst->opts->get_opt_descriptor(opt); + + if (!desc) + return SANE_STATUS_INVAL; + + scanner_err err = write_value(inst->dev, desc->name, desc->type, value, to_default, inst, affect); + + return local_utility::scanner_err_2_sane_statu(err); +} +SANE_Status hg_sane_middleware::get_option_fixed_id(LPDEVINST inst, const void* opt, void* value) +{ + int fix_id = 0; + + if (inst->opts->get_opt_descriptor(opt, &fix_id)) + { + *(SANE_Int*)value = fix_id; + + return fix_id == -1 ? SANE_STATUS_INVAL : SANE_STATUS_GOOD; + } + else + { + return SANE_STATUS_INVAL; + } +} + void hg_sane_middleware::set_app_callback(void* cb, void* param, int type) { @@ -960,7 +779,8 @@ void hg_sane_middleware::set_app_callback(void* cb, void* param, int type) } void hg_sane_middleware::get_version(SANE_Int* ver) { - local_utility::get_version(ver); + if (ver) + *ver = 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 :) } hg_sane_middleware* hg_sane_middleware::instance(void) { @@ -969,10 +789,6 @@ hg_sane_middleware* hg_sane_middleware::instance(void) 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(); @@ -983,659 +799,6 @@ void hg_sane_middleware::clear(void) } } -void hg_sane_middleware::reload_options(scanner_handle dev) -{ - for (auto& v : openning_) - { - if (dev && dev != v->dev) - continue; - - std::vector opts(std::move(v->opts)); - long count = 0; - - hg_sane_middleware::free_device_inst(v, false); - hg_scanner_get_parameter(v->dev, nullptr, nullptr, &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& 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; - } -} -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 = nullptr; - scanner_err err = SCANNER_ERR_OK; - - if (handle == nullptr) - return SANE_STATUS_INVAL; - - err = hg_scanner_open(&h, devicename, false, nullptr, nullptr, nullptr, rsc); - if (err == SCANNER_ERR_OK) - { - LPDEVINST inst = new DEVINST; - - inst->name = devicename; - inst->dev = h; - openning_.push_back(inst); - *handle = hg_sane_middleware::scanner_handle_to_sane(h); - - if (!local_utility::cb_ui_) - { - long count = 0; - hg_scanner_get_parameter(h, 0, nullptr, &count); - inst->std_opt = new sane_std_opts(count); - } - - return SANE_STATUS_GOOD; - } - else if (err == SCANNER_ERR_ACCESS_DENIED) - { - return SANE_STATUS_ACCESS_DENIED; - } - else - return (SANE_Status)err; // SANE_STATUS_UNSUPPORTED; -} -SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, gb_json* jsn) -{ - std::string title(hg_sane_middleware::get_string_in_json(jsn, "title")), - desc(hg_sane_middleware::get_string_in_json(jsn, "desc")), - val(""); - std::vector constraints; - double lower = .0f, upper = .0f, step = .0f; - bool db_val = false; - int opt_val_size = 0; - - if (!jsn->get_value("type", val)) - return nullptr; - - SANE_Option_Descriptor* ret = nullptr; - if (val == "string") - { - gb_json* range = nullptr; - std::vector constraints; - - jsn->get_value("range", range); - if (range) - { - gb_json* child = range->first_child(); - while(child) - { - if (child->value(val)) - { - local_utility::trans_language_if_was_word_id(val); - constraints.push_back(val); - if (opt_val_size < val.length()) - opt_val_size = val.length(); - } - child->release(); - child = range->next_child(); - } - range->release(); - } - - 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") - { - gb_json* range = nullptr, * child = nullptr; - - jsn->get_value("range", range); - if (range) - { - if (val == "int") - { - int l = 0; - if (range->get_value("min", l)) - { - int u = 0, s = 1; - range->get_value("max", u); - range->get_value("step", s); - lower = l; - upper = u; - step = s; - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%s range: [%d, +%d, %d]\n", name.c_str(), l, s, u); - ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, &lower, &upper, &step); - } - else - { - std::vector constraints; - child = range->first_child(); - while(child) - { - int v = 0; - if(child->value(v)) - constraints.push_back(v); - child->release(); - child = range->next_child(); - } - 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); - step = (upper - lower) / 10.0f; - range->get_value("step", step); - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%s range: (%f, +%f, %f)\n", name.c_str(), lower, step, upper); - ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , true, &lower, &upper, &step); - } - else - { - std::vector constraints; - child = range->first_child(); - while (child) - { - double v = .0f; - if (child->value(v)) - constraints.push_back(v); - child->release(); - child = range->next_child(); - } - ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , constraints); - } - } - range->release(); - } - else - { - ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, nullptr, nullptr, nullptr); - } - } - else if (val == "bool") - { - ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, nullptr, nullptr, nullptr); - 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() - , false, nullptr, nullptr, nullptr); - 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() - , false, nullptr, nullptr, nullptr); - ret->type = SANE_TYPE_GROUP; - } - - // fill the 'size' field, for SANE_ACTION_GET action ... - if (ret) - { - int bytes = 0; - bool bv = false; - - jsn->get_value("size", bytes); - if (bytes < opt_val_size) - { - opt_val_size = ALIGN_INT(opt_val_size + 4); - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "Resize size of '%s' from %d to %d\n", name.c_str(), bytes, opt_val_size); - bytes = opt_val_size; - } - 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) - - val = ""; - jsn->get_value("cat", val); - if (val == "advanced") - { - ret->cap |= SANE_CAP_ADVANCED; - } - - if (strcmp(ret->name, SANE_STD_OPT_NAME_RESOLUTION) == 0) - { - 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) - ret->unit = SANE_UNIT_MM; - - //bool enabled = true; - //if (jsn->get_value("enable", enabled) && !enabled) - // ret->cap |= SANE_CAP_INACTIVE; - - // 关联? - gb_json* depend = nullptr; - 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::iterator it = find_openning_device_in_que(h); - if (it != openning_.end() && parse_depends(h, depend, so, (*it)->masters)) - { - so.enable_now = (ret->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE; - so.name = name; - - (*it)->slaves.push_back(so); - } - depend->release(); - } - } - - 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) -{ - scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h); - std::vector::iterator it = find_openning_device_in_que(handle); - - if (it == openning_.end()) - handle = nullptr; - else - { - if (dev) - *dev = *it; - if (rmv) - { - if (!dev) - hg_sane_middleware::free_device_inst(*it); - openning_.erase(it); - } - } - - return handle; -} -std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt, std::string* key, SANE_Int* id) -{ - char* json_txt = nullptr; - long length = 0; - scanner_err err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length); - std::string ret(""); - - if (err == SCANNER_ERR_INSUFFICIENT_MEMORY) - { - 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) - { - 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; - } - free(json_txt); - } - - return ret; -} -SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id, SANE_Int* fix_id) -{ - std::vector::iterator it = find_openning_device_in_que(handle); - - if (it != openning_.end()) - { - if (IS_PTR_NUMBER(option)) - { - if ((SANE_Int)(long long)option >= SANE_OPT_ID_BASE) - { - 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; - if (fix_id) - *fix_id = v.fixed_no; - return v.desc; - } - } - } - } - - return nullptr; -} - -void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector* changed) -{ - long count = 0; - std::vector::iterator it = find_openning_device_in_que(handle); - - if (changed) - changed->clear(); - hg_scanner_get_parameter(handle, 0, nullptr, &count); - for (int i = 1; i < count; ++i) - { - std::string key(""), - val(get_option_json(handle, (void *)i, &key)); - gb_json* jsn = new gb_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); - } - jsn->release(); - } -} -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) -{ - if (IS_PTR_NUMBER(option)) - { - int id = (int)(uint64_t)option, - l = 0; - std::string name(local_utility::un_json_option_name(id, &l)); - - if(!name.empty()) - { - char *buf = new char[l + 4]; - long len = l; - bool ret = false; - - memcpy(buf, value, l); - buf[l] = 0; - if (hg_scanner_get_parameter(handle, name.c_str(), buf, &len) == SCANNER_ERR_OK) - { - setv(buf, len, value); - - ret = true; - } - delete[] buf; - - return ret; - } - } - - std::string name(""), - val(get_option_json(handle, (void *)option, &name)); - gb_json* jsn = new gb_json(); - 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") - { - int v = 0; - jsn->get_value("cur", v); - // *((SANE_Int*)value) = v; - setv(&v, sizeof(v), value); - 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); - 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); - 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); - estimate += val.length(); - } - if (type) - *type = t; - - std::vector::iterator it = find_openning_device_in_que(handle); - refresh_current_value(*it, name.c_str(), jsn); - - val = hg_sane_middleware::get_string_in_json(jsn, "title"); - - if (setv == &hg_sane_middleware::set_value_to_new) - value = *(void**)value; - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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()); - } - - jsn->release(); - - 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)); - void* data = nullptr; - gb_json* jsn = new gb_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); - if (log) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "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); - if (log) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "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)); - if (log) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "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"); - - if (size < (int)val.length()) - size = val.length(); - data = local_utility::acquire_memory(size + 4, ""); - strcpy((char*)data, val.c_str()); - if (bytes) - *bytes = val.length() + 1; - if (log) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) default value is: %s\n", option, title.c_str(), (char*)data); - } - } - else - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) is '%s' and no value action.\n", option, title.c_str(), val.c_str()); - } - } - jsn->release(); - - if (!data) - { - std::vector::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); - } - } - - return data; -} SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SANE_Bool local_only) { if (!device_list) @@ -1643,29 +806,23 @@ SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SA ScannerInfo * dev = nullptr; long count = 0; - scanner_err hgerr = hg_scanner_enum(dev, &count, local_only); + scanner_err hgerr = hg_scanner_enum(dev, &count, local_only); SANE_Status ret = SANE_STATUS_GOOD; if (hgerr == SCANNER_ERR_INSUFFICIENT_MEMORY) { - count += 4; // 为两次hg_scanner_enum间隙可能新增的设备预留空? + count += 4; dev = (ScannerInfo*)local_utility::acquire_memory(sizeof(ScannerInfo) * count, "hg_sane_middleware::get_devices"); hgerr = hg_scanner_enum(dev, &count, local_only); - if (hgerr != SCANNER_ERR_OK) - { - local_utility::free_memory(dev); - dev = nullptr; - } } if (hgerr == SCANNER_ERR_OK) - { *device_list = hg_sane_middleware::to_sane_device(dev, count); - if (dev) - local_utility::free_memory(dev); - } - else + else ret = local_utility::scanner_err_2_sane_statu(hgerr); + if (dev) + local_utility::free_memory(dev); + if (hg_sane_middleware::dev_list_) local_utility::free_memory(hg_sane_middleware::dev_list_); @@ -1675,469 +832,209 @@ SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SA } SANE_Status hg_sane_middleware::open_device(SANE_String_Const devicename, SANE_Handle* handle) { - char rsc[128]; - SANE_Status ret = SANE_STATUS_GOOD; + if (!handle) + return SANE_STATUS_INVAL; + + char rsc[128] = { 0 }; + scanner_handle h = nullptr; + scanner_err se = hg_scanner_open(&h, devicename, false, nullptr, nullptr, nullptr, rsc); - bzero(rsc, sizeof(rsc)); - ret = open(devicename, handle, nullptr, nullptr, nullptr, rsc); - if (ret == SANE_STATUS_ACCESS_DENIED && rsc[0]) + if (se == SCANNER_ERR_ACCESS_DENIED && rsc[0]) { SANEAUTH auth; - bzero(&auth, sizeof(auth)); + memset(&auth, 0, sizeof(auth)); auth.resource = rsc; if (local_utility::ui_cb(nullptr, SANE_EVENT_NEED_AUTH, (void*)&auth, nullptr, nullptr)) { return SANE_STATUS_CANCELLED; } - ret = open(devicename, handle, auth.name, auth.pwd, auth.method, rsc); + se = hg_scanner_open(&h, devicename, false, auth.name, auth.pwd, auth.method, rsc); } - if (ret == SANE_STATUS_GOOD) + if (se == SCANNER_ERR_OK) { // 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)); + LPDEVINST inst = new DEVINST; + + inst->dev = h; + inst->name = devicename; + inst->opts = new device_opts(); + if(reload_options(inst)) + { + openning_.push_back(inst); + *handle = hg_sane_middleware::scanner_handle_to_sane(h); + } + else + { + hg_sane_middleware::free_device_instance(inst); + *handle = nullptr; + se = SCANNER_ERR_DATA_DAMAGED; + } } - return ret; + return local_utility::scanner_err_2_sane_statu(se); } SANE_Status hg_sane_middleware::close_device(SANE_Handle h) { - scanner_handle hs = find_openning_device(h, true); - SANE_Status err = SANE_STATUS_GOOD; + LPDEVINST inst = 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)); + if (inst) + { + if(inst->dev) + err = local_utility::scanner_err_2_sane_statu(hg_scanner_close(inst->dev, true)); + inst->dev = nullptr; + hg_sane_middleware::free_device_instance(inst); + } 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; - if (!params) return SANE_STATUS_INVAL; - err = hg_scanner_get_img_info(h, params, sizeof(*params)); + LPDEVINST inst = find_openning_device(handle); + scanner_err err = SCANNER_ERR_NOT_START; + + if(inst && inst->dev) + err = hg_scanner_get_img_info(inst->dev, params, sizeof(*params)); return local_utility::scanner_err_2_sane_statu(err); } 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; + LPDEVINST dev = find_openning_device(h); + scanner_err err = SCANNER_ERR_INVALID_PARAMETER; - if(hs) - err = hg_scanner_start(hs, async_event, -1); + if(dev && dev->dev) + err = hg_scanner_start(dev->dev, async_event, -1); return local_utility::scanner_err_2_sane_statu(err); } 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; - long r = bytes ? *bytes : 0; + LPDEVINST dev = find_openning_device(h); + scanner_err err = SCANNER_ERR_INVALID_PARAMETER; + long r = bytes ? *bytes : 0; - if (bytes && hs) + if (bytes) { - err = hg_scanner_read_img_data(hs, (unsigned char*)buf, &r); - *bytes = r; + if (dev && dev->dev) + { + err = hg_scanner_read_img_data(dev->dev, (unsigned char*)buf, &r); + *bytes = r; + } + else + err = SCANNER_ERR_NOT_OPEN; } return local_utility::scanner_err_2_sane_statu(err); } SANE_Status hg_sane_middleware::stop(SANE_Handle h) { - scanner_handle hs = find_openning_device(h); - - if(hs) - hg_scanner_stop(hs); + LPDEVINST dev = find_openning_device(h); + scanner_err err = SCANNER_ERR_OK; - return SANE_STATUS_GOOD; + if (dev && dev->dev) + err = hg_scanner_stop(dev->dev); + + return local_utility::scanner_err_2_sane_statu(err); } SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, const void* option) { SANE_Option_Descriptor* ret = nullptr; - scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h); - std::vector::iterator it = find_openning_device_in_que(handle); - SANE_Int id = -1; + LPDEVINST dev = find_openning_device(h); - 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); - } - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "get_option_descriptor(0)\n"); - return opt_0_; - } + if (dev) + ret = dev->opts->get_opt_descriptor(option); - ret = find_stored_descriptor(handle, option, &id); - if (!ret) - { - std::string key(""), - json_txt(get_option_json(handle, (void*)option, &key, &id)); - - if (json_txt.length()) - { - gb_json* jsn = new gb_json(); - if (jsn->attach_text(&json_txt[0])) - { - ret = from_json(handle, key, jsn); - - if (ret) - { - DEVOPT devopt; - devopt.option_no = id; - devopt.fixed_no = 0; - devopt.desc = ret; - 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)); - - if ((*it)->std_opt) - (*it)->std_opt->init_known_opt(id, ret); - - refresh_current_value(*it, ret->name, jsn); - } - } - jsn->release(); - } - if(!ret && (*it)->std_opt) - ret = (*it)->std_opt->get_option(id); - } - return ret; } -SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do) +SANE_Status hg_sane_middleware::control_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do) { - 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)) + int fix_id = 0; + if (option) { - // 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; - 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); - - if (action == SANE_ACTION_GET_VALUE) - { - if (after_do) - *after_do = 0; - - SANE_Status ret = SANE_STATUS_IO_ERROR; - if (option == 0) + SANE_Option_Descriptor* desc = offline_->get_opt_descriptor(option, &fix_id); + if (desc) { - long count = 0; - hg_scanner_get_parameter(handle, (const char*)option, nullptr, &count); - *((SANE_Int*)value) = count; - ret = SANE_STATUS_GOOD; - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "get option count = %d.\n", count); - } - 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)) + if (action == SANE_ACTION_GET_VALUE || action == SANE_ACTION_GET_DEFAULT_VALUE) { - 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)) - ret = SANE_STATUS_GOOD; - } + scanner_err err = read_value(nullptr, desc->name, desc->type, desc->size, value, action == SANE_ACTION_GET_DEFAULT_VALUE); - return ret; + return local_utility::scanner_err_2_sane_statu(err); + } + else if (action == SANE_ACTION_SET_VALUE || action == SANE_ACTION_SET_AUTO) + { + LPDEVINST inst = find_openning_device(h); + scanner_err err = write_value(nullptr, desc->name, desc->type, value, action == SANE_ACTION_SET_AUTO, inst, after_do); + + return local_utility::scanner_err_2_sane_statu(err); + } + else if (action == SANE_ACTION_GET_FIX_ID) + { + *(SANE_Int*)value = fix_id; + + return SANE_STATUS_GOOD; + } + + return SANE_STATUS_INVAL; + } } + + SANE_Status err = SANE_STATUS_INVAL; + LPDEVINST inst = find_openning_device(h); + + if (!inst) + { + err = local_utility::scanner_err_2_sane_statu(SCANNER_ERR_NOT_OPEN); + } + else if (action == SANE_ACTION_GET_VALUE) + { + if (!option) + { + *(SANE_Int*)value = inst->opts->get_option_count(); + err = SANE_STATUS_GOOD; + } + else + { + err = get_current_value(inst, option, value, false); + } + } + else if (action == SANE_ACTION_SET_VALUE || action == SANE_ACTION_SET_AUTO) + { + err = set_value(inst, option, value, after_do, action == SANE_ACTION_SET_AUTO); + } + + // extension ... 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; + err = get_current_value(inst, option, value, true); } 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) - { - 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; - 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; - } - - 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 - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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); - - return SANE_STATUS_UNSUPPORTED; - } - - 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)) - { - 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); - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "$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); - } - else - { - if (!desc) - { - if (IS_PTR_NUMBER(option)) - { - 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)); - } - - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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 - //{ - // utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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 - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title); - - return SANE_STATUS_INVAL; - } - } - - void* pass = value; - double dv = .0f; - bool bv = false; - long size = desc->size; - - 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); - } - - err = hg_scanner_set_parameter(handle, (const char*)option, pass, &size); // NOTE: change language will lead 'desc' reallocated !!! - - if (sane_type == SANE_TYPE_BOOL) - { - *((SANE_Bool*)value) = bv ? SANE_TRUE : SANE_FALSE; - } - else if (sane_type == SANE_TYPE_FIXED) - { - *((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(dv); - } - v = hg_sane_middleware::option_value_2_string(sane_type, value); - } - - if (prev == v) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc_title.c_str(), v.c_str()); - } - else - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc_title.c_str(), prev.c_str(), v.c_str()); - } - - if (err == SCANNER_ERR_OK) - { - err = (scanner_err)something_after_do(dev, desc_name.c_str(), v.c_str()); - } - else if (err == SCANNER_ERR_NOT_EXACT) - { - err = (scanner_err)(something_after_do(dev, desc_name.c_str(), v.c_str()) | SANE_INFO_INEXACT); - } - else if (err == SCANNER_ERR_CONFIGURATION_CHANGED) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '%s' affects other options value, RELOAD ...\n", desc_title.c_str()); - //on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); - 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; - } - else if(err == SCANNER_ERR_RELOAD_IMAGE_PARAM) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "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) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "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); - 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) - { - status = SANE_STATUS_ACCESS_DENIED; - err = (scanner_err)0; - } - else - { - status = local_utility::scanner_err_2_sane_statu(err); - err = (scanner_err)0; - } - if (after_do) - *after_do = err; - - if (release_value) - local_utility::free_memory(value); - - return status; + err = get_option_fixed_id(inst, option, value); } - return SANE_STATUS_INVAL; + return err; } -bool hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type) +SANE_Status hg_sane_middleware::ex_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len) { - 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); -} -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 nullptr; - - 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) -{ - scanner_handle h = find_openning_device(handle); - - if (!h) - return nullptr; - - return get_default_value(h, option, bytes, log); -} -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); + LPDEVINST dev = find_openning_device(h); int ret = SANE_STATUS_GOOD; // 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); + ret = hg_scanner_control(dev->dev, code, data, len); if (ret == SCANNER_ERR_CONFIGURATION_CHANGED) { int nc = code; utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc); - on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); + reload_options(dev); } return local_utility::scanner_err_2_sane_statu(ret); @@ -2147,433 +1044,3 @@ bool hg_sane_middleware::is_ready(void) return init_ok_; } -/// -/// 关联项处? -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& master, std::vector& curvals) -{ - // 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::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name); - if (it == curvals.end()) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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()); - 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()); - } - - return enabled; -} -bool hg_sane_middleware::is_enable_or(scanner_handle hdev, const std::vector& master, std::vector& curvals) -{ - bool enabled = false; - - for (size_t i = 0; !enabled && i < master.size(); ++i) - { - std::vector::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name); - if (it == curvals.end()) - { - utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, 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()); - 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()); - } - - return enabled; -} - -bool hg_sane_middleware::parse_master_option(const char* depend_str, MASTEROP& mo) -{ - bool ret = true; - double num = .0f; - std::string v(""); - - 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; - - 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, gb_json* jsn, SLAVEOP& so, std::vector& master) -{ - std::string val(""), mn(""); - gb_json* child = jsn->first_child(); - - while(child) - { - MASTEROP mo; - - if (!child->value(val) || !parse_master_option(val.c_str(), mo)) - 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); - so.master.push_back(mo); - if (std::find(master.begin(), master.end(), mo.name) == master.end()) - { - master.push_back(mo.name); - std::sort(master.begin(), master.end()); - } - child->release(); - child = jsn->next_child(); - } - if (child) - child->release(); - - return so.master.size() > 0; -} - -bool hg_sane_middleware::is_associatived(const SLAVEOP& slave, const char* master_name) -{ - bool result = false; - - for (const auto& v: slave.master) - { - if (v.name == master_name) - { - result = true; - break; - } - } - - return result; -} -bool hg_sane_middleware::set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size) -{ - SANE_Option_Descriptor* opt = find_stored_descriptor(h, option); - 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) -{ - int after = 0; - OPTENABLE oe; - std::vector changed_options; - - refresh_current_value(dev, master_name, cur_val); - if (std::find(dev->masters.begin(), dev->masters.end(), master_name) == dev->masters.end()) - { - return after; - } - - oe.name = master_name; - 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) - { - if (dev->slaves[slave].name == changed_options[i].name || - !is_associatived(dev->slaves[slave], changed_options[i].name.c_str())) - continue; - - bool enable = changed_options[i].enable; - int bytes = 0; - // if (enable) - enable = dev->slaves[slave].is_enable(dev->dev, dev->slaves[slave].master, dev->cur_vals); - if (enable == dev->slaves[slave].enable_now) - continue; - - dev->slaves[slave].enable_now = enable; - if (!set_stored_option_enabled(dev->dev, dev->slaves[slave].name.c_str(), enable, &bytes)) - continue; - - OPTEN* op = get_control_enalbe_data(dev, dev->slaves[slave]); - hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, nullptr); - free_control_enable_data(op); - - if (std::find(changed_options.begin(), changed_options.end(), dev->slaves[slave].name) != changed_options.end()) - continue; - - oe.name = dev->slaves[slave].name; - oe.enable = dev->slaves[slave].enable_now; - 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, gb_json* jsn) -{ - std::vector::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name); - if (it == dev->cur_vals.end()) - { - CURVAL cv; - jsn->get_value("type", cv.type); - cv.name = name; - cv.val = hg_sane_middleware::string_value_from_json(jsn, true); - if (cv.type == "string") - local_utility::trans_language_if_was_word_id(cv.val); - dev->cur_vals.push_back(cv); - - return false; - } - else - { - std::string old(it->val); - it->val = hg_sane_middleware::string_value_from_json(jsn, true); - if (it->type == "string") - local_utility::trans_language_if_was_word_id(it->val); - - return old != it->val; - } -} -bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, const char* val) -{ - std::vector::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name); - if (it != dev->cur_vals.end()) - { - 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) -{ - std::vector master; - OPTEN* opt = nullptr; - 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); - } - size += master.size() * sizeof(OPTVAL); - opt = (OPTEN*)malloc(size); - bzero(opt, size); - - opt->enabled = slave.enable_now; - strcpy(opt->name, slave.name.c_str()); - opt->master_count = 0; - for (size_t i = 0; i < master.size(); ++i) - { - std::vector::iterator m = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), master[i]); - if (m == dev->cur_vals.end()) - continue; - - strcpy(opt->master[opt->master_count].name, master[i].c_str()); - 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()); - } - opt->master_count++; - } - - 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) -{ - std::vector changed; - reload_current_value(dev->dev, &changed); - if (changed.size()) - { - for (size_t i = 0; i < changed.size(); ++i) - { - std::vector::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()); - } - } -} -std::vector::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::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(); -} diff --git a/hgsane/sane_hg_mdw.h b/hgsane/sane_hg_mdw.h index 9f0cf1d..9c81138 100644 --- a/hgsane/sane_hg_mdw.h +++ b/hgsane/sane_hg_mdw.h @@ -1,197 +1,65 @@ #pragma once -#include -#include -#include +#include "sane/sane_ex.h" +#include "../sdk/hginclude/huagaoxxx_warraper_ex.h" + #include #include #include -#include -#include -#if defined(WIN32) || defined(_WIN64) -#define bzero(b, s) memset(b, 0, s) -#else -#include -#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 master; - bool (*is_enable)(scanner_handle hdev, const std::vector& master - , std::vector& 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 opts; - std::vector cur_vals; - std::vector slaves; - std::vector masters; - std::map 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 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 openning_; + bool operator==(scanner_handle h) + { + return dev == h; + } + + _dev_inst() + { + dev = nullptr; + name = ""; + opts = nullptr; + } + }DEVINST, * LPDEVINST; + + bool init_ok_; + std::vector 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& 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* 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 - -/// -/// 关联项处理 - - // 添加对多依赖项的支持 - 2022-03-10 - //std::vector 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& master, std::vector& curvals); - static bool is_enable_or(scanner_handle hdev, const std::vector& master, std::vector& curvals); - //std::vector slave_options_; - //std::vector 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& 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 openning_; - std::vector::iterator find_openning_device_in_que(scanner_handle h); - std::vector::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& 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& 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& 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); diff --git a/hgsane/sane_option.cpp b/hgsane/sane_option.cpp index 4e9e289..9c8f19d 100644 --- a/hgsane/sane_option.cpp +++ b/hgsane/sane_option.cpp @@ -409,3 +409,9 @@ scanner_err sane_std_opts::set_value(scanner_handle h, int opt, void* buf) return statu; } + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/hgsane/sane_option.h b/hgsane/sane_option.h index b8dd913..d49c927 100644 --- a/hgsane/sane_option.h +++ b/hgsane/sane_option.h @@ -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 }; + + + diff --git a/sdk/hginclude/huagaoxxx_warraper_ex.h b/sdk/hginclude/huagaoxxx_warraper_ex.h index f24ed65..d4fd7fe 100644 --- a/sdk/hginclude/huagaoxxx_warraper_ex.h +++ b/sdk/hginclude/huagaoxxx_warraper_ex.h @@ -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 // 配置项使能状态改变 /// 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: 启动设备工作 // diff --git a/sdk/json/gb_json.cpp b/sdk/json/gb_json.cpp index ea7ec94..cac63c9 100644 --- a/sdk/json/gb_json.cpp +++ b/sdk/json/gb_json.cpp @@ -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(); diff --git a/sdk/json/gb_json.h b/sdk/json/gb_json.h index f86dca9..4f20e49 100644 --- a/sdk/json/gb_json.h +++ b/sdk/json/gb_json.h @@ -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: diff --git a/twain/ds/scanner.cpp b/twain/ds/scanner.cpp index e22e663..3908dfe 100644 --- a/twain/ds/scanner.cpp +++ b/twain/ds/scanner.cpp @@ -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;