From 6deaffbb212195e08f0290fa8cffd0f7cfd1bf6b Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 19 Oct 2022 14:00:23 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8DPNP=20BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/win_usb/win_usb.cpp | 58 +++++++++++++++++++++++++------------- device/win_usb/win_usb.h | 1 + 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/device/win_usb/win_usb.cpp b/device/win_usb/win_usb.cpp index 621d565..bfc80fc 100644 --- a/device/win_usb/win_usb.cpp +++ b/device/win_usb/win_usb.cpp @@ -545,6 +545,8 @@ bool usb_device::is_online(void) void usb_device::set_online(bool online) { online_ = online; + if (!online_) + reg_key_ = ""; } uint8_t usb_device::port(void) { @@ -552,6 +554,10 @@ uint8_t usb_device::port(void) init(); return port_; } +std::string usb_device::reg_path(void) +{ + return reg_key_; +} bool usb_device::init(void) { @@ -1068,7 +1074,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive) if (devices_[i]->is_online()) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already in device queue and received ARRIVE again, discard this event.\n", dev->name().c_str()); - dev->release(); + // dev->release(); return; } else @@ -1090,31 +1096,43 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive) } else { + bool discard = false; for (size_t i = 0; i < devices_.size(); ++i) { - if (!(devices_[i]->id() == id)) + if (devices_[i]->id().vid != id.vid || devices_[i]->id().pid != id.pid) continue; - - dev->release(); - dev = devices_[i]; - dev->add_ref(); - if (dev->is_open()) + if (devices_[i]->reg_path().empty() || usb_device::usb_scan_name(devices_[i]->reg_path().c_str()).empty()) { - if (dev->is_online()) - dev->set_online(false); - else - { - VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str()); - dev->release(); - return; - } - } - else - { - devices_.erase(devices_.begin() + i); dev->release(); + dev = devices_[i]; + dev->add_ref(); + // if (dev->is_open()) + { + if (dev->is_online()) + { + dev->set_online(false); + discard = false; + break; + } + else + { + // VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str()); + // dev->release(); + // return; + discard = true; + } + } + //else + //{ + // devices_.erase(devices_.begin() + i); + // dev->release(); + //} } - break; + } + if (discard) + { + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str()); + return; } } diff --git a/device/win_usb/win_usb.h b/device/win_usb/win_usb.h index 4c50f5b..06121ba 100644 --- a/device/win_usb/win_usb.h +++ b/device/win_usb/win_usb.h @@ -140,6 +140,7 @@ public: bool is_online(void); void set_online(bool online); uint8_t port(void); + std::string reg_path(void); bool init(void); void clear(void); From 4da3fca44b894b68e34fc93165d2074562854d50 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 19 Oct 2022 18:02:12 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8DDLL=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98=EF=BC=88=E5=A5=BD=E5=88=86?= =?UTF-8?q?=E6=95=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- twain/load_sane.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/twain/load_sane.cpp b/twain/load_sane.cpp index 67901e7..3695ee7 100644 --- a/twain/load_sane.cpp +++ b/twain/load_sane.cpp @@ -91,20 +91,27 @@ namespace load_sane_util { HMODULE h = LoadLibraryW(path_dll); int ret = GetLastError(); + wchar_t info[128] = { 0 }; + swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret); + OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str()); if (!h && ret == ERROR_MOD_NOT_FOUND) { std::wstring dir(path_dll); size_t pos = dir.rfind(L'\\'); wchar_t path[MAX_PATH] = { 0 }; - GetCurrentDirectoryW(_countof(path) - 1, path); + GetDllDirectoryW(_countof(path) - 1, path); if (pos != std::wstring::npos) dir.erase(pos); - SetCurrentDirectoryW(dir.c_str()); + OutputDebugStringW((L"[TWAIN]Load: try change directory to " + dir + L"\r\n").c_str()); + SetDllDirectoryW(dir.c_str()); h = LoadLibraryW(path_dll); ret = GetLastError(); - SetCurrentDirectoryW(path); + swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret); + OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str()); + OutputDebugStringW((L"[TWAIN]Load: restore directory to " + std::wstring(path) + L"\r\n").c_str()); + SetDllDirectoryW(path); } if (dll) @@ -142,6 +149,13 @@ namespace load_sane_util } bool is_ok(void) { + wchar_t info[128] = { 0 }; + swprintf_s(info, _countof(info) - 1, L"[TWAIN]Load: sane_inst: %s, is_on: %s, init: %s, uninit: %s\r\n" + , sane_inst != NULL ? "ok" : "not found" + , is_on != NULL ? "ok" : "not found" + , init != NULL ? "ok" : "not found" + , uninit != NULL ? "ok" : "not found"); + return sane_inst != NULL && is_on != NULL && init != NULL && uninit != NULL; } bool is_online(SCANNERID guid) From 84e0b6996d2009c89ef861d62abbfbc145f6151c Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Thu, 20 Oct 2022 14:29:02 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E6=8E=A5=E5=8F=A3=EF=BC=8C=E4=BB=A5=E9=80=82?= =?UTF-8?q?=E5=BA=94=E6=97=A0UI=E6=89=AB=E6=8F=8F=EF=BC=8C=E4=B8=94?= =?UTF-8?q?=E5=9C=A8=E6=97=A0UI=E6=89=AB=E6=8F=8F=E7=BB=93=E6=9D=9F?= =?UTF-8?q?=E6=97=B6=E9=80=9A=E7=9F=A5=E6=94=B9=E4=B8=BAXferReady=EF=BC=88?= =?UTF-8?q?=E5=A5=BD=E5=88=86=E6=95=B0=E4=BA=A7=E5=93=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/s2t_api.h | 2 +- sane/scanner.cpp | 25 +++++++---- sane/scanner.h | 5 ++- twain/twain/huagaods.cpp | 89 +++++++++++++++++++++++----------------- twain/twain/huagaods.hpp | 2 + 5 files changed, 76 insertions(+), 47 deletions(-) diff --git a/sane/s2t_api.h b/sane/s2t_api.h index 3c7846d..499b850 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -147,7 +147,7 @@ struct __declspec(novtable) IScanImg : public IRef }; struct __declspec(novtable) ISaneInvoker : public IRef { - COM_API_DECLARE(int, start(void)); + COM_API_DECLARE(int, start(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); COM_API_DECLARE(int, stop(void)); COM_API_DECLARE(int, get_event(void)); COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1)); diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 3ea424c..b7fb4b1 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -543,14 +543,18 @@ void scanner::on_ui_event(int uev, void* sender) { events_.clear(); ui_hide(); - if(indicator) - events_.save(SANE_EVENT_SCAN_FINISHED); + if(indicator || !indicator_.get()) + uev = SANE_EVENT_SCAN_FINISHED; else - events_.save(SANE_EVENT_UI_CLOSE_SETTING); + uev = SANE_EVENT_UI_CLOSE_SETTING; } - else - events_.save(uev); + + events_.save(uev); } + + int(__stdcall * h)(int, void*) = scanner_ev_handler_; + if (h) + h(uev, evh_param_); } std::string scanner::choose_scanner(const std::vector& scanners) { @@ -634,6 +638,7 @@ int scanner::open(void) } int scanner::close(void) { + scanner_ev_handler_ = NULL; ui_hide(); callback::unreg_callback(this); if (handle_) @@ -2020,10 +2025,13 @@ EX_OPTION_HANDLER_IMPL(search_hole_range) } // ISaneInvoker -COM_API_IMPLEMENT(scanner, int, start(void)) +COM_API_IMPLEMENT(scanner, int, start(int(__stdcall* handle_ev)(int, void*), void* para)) { int ret = SANE_STATUS_GOOD; + scanner_ev_handler_ = handle_ev; + evh_param_ = para; + events_.clear(); images_.clear(); scan_msg_ = "OK"; @@ -2064,6 +2072,7 @@ COM_API_IMPLEMENT(scanner, int, start(void)) } COM_API_IMPLEMENT(scanner, int, stop(void)) { + scanner_ev_handler_ = NULL; return hg_sane_middleware::instance()->stop(handle_); } COM_API_IMPLEMENT(scanner, int, get_event(void)) @@ -2573,7 +2582,7 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) if (indicator_.get()) indicator_->notify_working(); else - events_.save(ev_code); + on_ui_event(ev_code, (void*)ev_code); log_info(L"Scanning ...\r\n", 0); } @@ -2613,7 +2622,7 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) if (indicator_.get()) indicator_->notify_scan_over((char*)data, *len != SCANNER_ERR_OK); else - events_.save(ev_code); + on_ui_event(ev_code, (void*)ev_code); is_scanning_ = false; { diff --git a/sane/scanner.h b/sane/scanner.h index a29e76b..70b7241 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -53,6 +53,9 @@ class scanner : public ISaneInvoker, virtual public refer std::unique_ptr setting_; gb::sane_config* cfg_; + int(__stdcall* scanner_ev_handler_)(int, void*); + void* evh_param_; + void transport_config_file(void); void update_config(void); void load_config(const wchar_t* file); @@ -201,7 +204,7 @@ public: // ISaneInvoker public: - COM_API_OVERRIDE(int, start(void)); + COM_API_OVERRIDE(int, start(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); COM_API_OVERRIDE(int, stop(void)); COM_API_OVERRIDE(int, get_event(void)); COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1)); diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index c52b789..b4caf44 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -654,6 +654,10 @@ void huagao_ds::showmsg(const char* msg, int err) { ShellExecuteA(NULL, "open", huagao_ds::get_hidedlg_path().c_str(), msg, NULL, SW_HIDE); } +int __stdcall huagao_ds::on_scanner_event(int ev, void* param) +{ + return ((huagao_ds*)param)->handle_scanner_event(ev); +} const Identity& huagao_ds::defaultIdentity() noexcept { // remember, we return a reference, therefore the identity must not be placed on the stack of this method @@ -741,49 +745,16 @@ Result huagao_ds::capabilitySet(const Identity& origin, Capability& data) } Result huagao_ds::eventProcess(const Identity&, Event& event) { - static int count_0 = 0; const MSG* msg = (const MSG*)event.event(); if (scanner_.get()) { int ev = scanner_->get_event(); - if (ev == 0) - count_0++; - else - { - wchar_t msg[128] = { 0 }; - if(count_0) - swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", count_0, ev); - else - swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x%x)\r\n", ev); - load_sane_util::log_info(msg, 0); - count_0 = 0; - } - switch (ev) - { - case SANE_EVENT_WORKING: - notifyXferReady(); - break; - case SANE_EVENT_UI_CLOSE_CANCEL: - scanner_->stop(); - // notifyEndWithoutImages(); - break; - case SANE_EVENT_UI_CLOSE_NORMAL: - scanner_->ui_hide(); - case SANE_EVENT_SCAN_FINISHED: - //notifyCloseOk(); - //break; - case SANE_EVENT_UI_CLOSE_SETTING: - notifyCloseCancel(); - break; - case SANE_EVENT_UI_SCAN_COMMAND: - scanner_->ui_show_progress(NULL); - scanner_->start(); - break; - } + handle_scanner_event(ev); } // event.setMessage(Msg::Null); + return { ReturnCode::NotDsEvent, ConditionCode::Success }; } Twpp::Result huagao_ds::deviceEventGet(const Twpp::Identity& origin, Twpp::DeviceEvent& data) @@ -944,8 +915,9 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw())) return seqError(); + int(__stdcall * evf)(int, void*) = m_bIndicator ? NULL : &huagao_ds::on_scanner_event; scanner_->twain_set_transfer((twain_xfer)m_capXferMech); - int err = scanner_->start(); + int err = scanner_->start(evf, this); if (err == SCANNER_ERR_OK) { return success(); @@ -2822,7 +2794,50 @@ DWORD huagao_ds::get_config_number(const wchar_t* sec, const wchar_t* key) { return GetPrivateProfileIntW(sec, key, 0, get_config_file().c_str()); } - +int huagao_ds::handle_scanner_event(int ev) +{ + static int count_0 = 0; + + if (ev == 0) + count_0++; + else + { + wchar_t msg[128] = { 0 }; + if (count_0) + swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", count_0, ev); + else + swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x%x)\r\n", ev); + load_sane_util::log_info(msg, 0); + count_0 = 0; + } + switch (ev) + { + case SANE_EVENT_WORKING: + notifyXferReady(); + break; + case SANE_EVENT_UI_CLOSE_CANCEL: + scanner_->stop(); + // notifyEndWithoutImages(); + break; + case SANE_EVENT_UI_CLOSE_NORMAL: + scanner_->ui_hide(); + case SANE_EVENT_SCAN_FINISHED: + //notifyCloseOk(); + //break; + case SANE_EVENT_UI_CLOSE_SETTING: + if(m_bIndicator) + notifyCloseCancel(); + else + notifyXferReady(); // 好分数需要再通知 FAINT :( - modified on 2022-10-20 + break; + case SANE_EVENT_UI_SCAN_COMMAND: + scanner_->ui_show_progress(NULL); + scanner_->start(); + break; + } + + return 0; +} diff --git a/twain/twain/huagaods.hpp b/twain/twain/huagaods.hpp index 18a5d2a..3e245de 100644 --- a/twain/twain/huagaods.hpp +++ b/twain/twain/huagaods.hpp @@ -44,6 +44,7 @@ class huagao_ds : public Twpp::SourceFromThis { static std::string get_hidedlg_path(void); static void showmsg(const char* msg, int err); + static int __stdcall on_scanner_event(int ev, void* param); void CapabilityPrintf(Twpp::Msg msg, std::string capability, std::string value = ""); Twpp::Result capCommon(const Twpp::Identity& origin, Twpp::Msg msg, Twpp::Capability& data); @@ -53,6 +54,7 @@ class huagao_ds : public Twpp::SourceFromThis { std::wstring get_config_file(void); std::wstring get_config_value(const wchar_t* sec, const wchar_t* key); DWORD get_config_number(const wchar_t* sec, const wchar_t* key); + int handle_scanner_event(int ev); typedef struct _pending_xfer { From eeeb3214f4b472e170e0a5ed3a693f8c38910a26 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Fri, 21 Oct 2022 16:46:20 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E6=89=AB=E6=8F=8F=E4=BB=AA=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=A4=84=E7=90=86=E4=B8=8D=E5=8F=AA=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E4=BA=8EeventProcess=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E6=96=B9=E5=BC=8F=EF=BC=9B=E5=A4=84=E7=90=86=E5=A5=BD?= =?UTF-8?q?=E5=88=86=E6=95=B0=E8=B0=83=E7=94=A8=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/s2t_api.h | 3 +- sane/scanner.cpp | 149 +++++++++++++++++++++++++++++++++++---- sane/scanner.h | 6 +- twain/twain/huagaods.cpp | 87 +++++++++++++++++++++-- 4 files changed, 220 insertions(+), 25 deletions(-) diff --git a/sane/s2t_api.h b/sane/s2t_api.h index 499b850..c304b07 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -147,9 +147,10 @@ struct __declspec(novtable) IScanImg : public IRef }; struct __declspec(novtable) ISaneInvoker : public IRef { - COM_API_DECLARE(int, start(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); + COM_API_DECLARE(int, start(void)); COM_API_DECLARE(int, stop(void)); COM_API_DECLARE(int, get_event(void)); + COM_API_DECLARE(void, set_event_callback(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1)); COM_API_DECLARE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_DECLARE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz diff --git a/sane/scanner.cpp b/sane/scanner.cpp index b7fb4b1..751d1d4 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -15,7 +15,6 @@ #pragma comment(lib, "Shlwapi.lib") - static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt); #define SET_SANE_OPT_ID(id, id_name, name, val, extension) \ @@ -55,6 +54,7 @@ extern "C" extern SANE_Status inner_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param); extern SANE_Status inner_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len); + extern const char* inner_sane_err_desc(SANE_Status err); } namespace callback @@ -229,6 +229,91 @@ namespace callback return ""; } + + static BOOL CALLBACK main_wnd(HWND hwnd, LPARAM param) + { + DWORD pid = 0; + + GetWindowThreadProcessId(hwnd, &pid); + if (pid != GetCurrentProcessId()) + return TRUE; + + if (((void**)param)[1] == NULL) + { + HWND parent = GetParent(hwnd); + while (IsWindow(parent)) + { + hwnd = parent; + parent = GetParent(hwnd); + } + parent = hwnd; + if (!IsWindowVisible(parent)) + return TRUE; + + RECT r = { 0 }; + GetWindowRect(parent, &r); + if (RECT_H(r) > 50 && RECT_W(r) > 50) + { + *(HWND*)param = parent; + + return FALSE; + } + } + else + { + wchar_t val[128] = { 0 }; + GetClassNameW(hwnd, val, _countof(val) - 1); + if (wcscmp(val, L"#32770")) + return TRUE; + + GetWindowTextW(hwnd, val, _countof(val) - 1); + if (*((std::wstring**)param)[1] == val) + { + *(HWND*)param = hwnd; + + return FALSE; + } + } + + return TRUE; + } + static HWND find_main_wnd(void) + { + HWND wnd[2] = { NULL }; + + EnumWindows(main_wnd, (LPARAM)wnd); + + return wnd[0]; + } + static DWORD WINAPI btm(LPVOID para) + { + std::wstring* title[2] = { NULL, (std::wstring*)para }; + + Sleep(100); + EnumWindows(main_wnd, (LPARAM)title); + if (IsWindow((HWND)title[0])) + { + RECT r = { 0 }; + GetWindowRect((HWND)title[0], &r); + SetWindowPos((HWND)title[0], HWND_TOPMOST, r.left, r.top, RECT_W(r), RECT_H(r), SWP_SHOWWINDOW | SWP_NOSENDCHANGING); + SetFocus((HWND)title[0]); + } + + delete title[1]; + + return 0; + } + static void bring_message_box_topmost(const wchar_t* title) + { + DWORD id = 0; + std::wstring* t(new std::wstring(title)); + HANDLE h = CreateThread(NULL, 0, btm, t, 0, &id); + + if (h) + CloseHandle(h); + else + delete t; + } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -236,6 +321,7 @@ namespace callback scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START) , dpi_(200), tmp_path_(L""), img_ind_(0) , scanner_name_(L""), cfg_(NULL), is_ui_wait_img_(false), is_scanning_(false) + , scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL) { cfg_ = new gb::sane_config(); tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str()); @@ -463,7 +549,9 @@ void scanner::update_config(void) notice.erase(0, pos + 2); pos = notice.find("\r\n"); } - MessageBoxW(NULL, msg.c_str(), L"\u52A0\u8F7D\u914D\u7F6E", MB_OK | MB_ICONINFORMATION); + if (!IsWindow(app_wnd_)) + callback::bring_message_box_topmost(L"\u52A0\u8F7D\u914D\u7F6E"); + MessageBoxW(app_wnd_, msg.c_str(), L"\u52A0\u8F7D\u914D\u7F6E", MB_OK | MB_ICONINFORMATION); } } void scanner::load_config(const wchar_t* file) @@ -533,11 +621,25 @@ void scanner::apply_config(void) } void scanner::on_ui_event(int uev, void* sender) { + int(__stdcall * h)(int, void*) = scanner_ev_handler_; + if (h) + { + h(uev, evh_param_); + return; + } + bool indicator = sender == indicator_.get(); if (prev_start_result_ != SANE_STATUS_GOOD && indicator) indicator_.reset(); else { + if (uev == SANE_EVENT_UI_SCAN_COMMAND) + { + ui_show_progress(NULL); + start(); + return; + } + if (/*events_.count() > 5 && !is_ui_wait_img_ &&*/ (uev == SANE_EVENT_UI_CLOSE_CANCEL || uev == SANE_EVENT_UI_CLOSE_NORMAL || uev == SANE_EVENT_UI_CLOSE_SETTING)) { @@ -551,10 +653,6 @@ void scanner::on_ui_event(int uev, void* sender) events_.save(uev); } - - int(__stdcall * h)(int, void*) = scanner_ev_handler_; - if (h) - h(uev, evh_param_); } std::string scanner::choose_scanner(const std::vector& scanners) { @@ -631,7 +729,11 @@ int scanner::open(void) else { std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8)); - MessageBoxW(NULL, msg.c_str(), L"\u6253\u5F00\u5931\u8D25", MB_OK | MB_ICONERROR); + HWND parent = callback::find_main_wnd(); + + if (!IsWindow(parent)) + callback::bring_message_box_topmost(L"\u6253\u5F00\u5931\u8D25"); + MessageBoxW(parent, msg.c_str(), L"\u6253\u5F00\u5931\u8D25", MB_OK | MB_ICONERROR); } return ret; @@ -2025,17 +2127,15 @@ EX_OPTION_HANDLER_IMPL(search_hole_range) } // ISaneInvoker -COM_API_IMPLEMENT(scanner, int, start(int(__stdcall* handle_ev)(int, void*), void* para)) +COM_API_IMPLEMENT(scanner, int, start(void)) { int ret = SANE_STATUS_GOOD; - scanner_ev_handler_ = handle_ev; - evh_param_ = para; - events_.clear(); images_.clear(); scan_msg_ = "OK"; scan_err_ = false; + app_wnd_ = setting_.get() ? setting_->hwnd() : callback::find_main_wnd(); ret = hg_sane_middleware::instance()->start(handle_, NULL); // the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ... @@ -2060,10 +2160,12 @@ COM_API_IMPLEMENT(scanner, int, start(int(__stdcall* handle_ev)(int, void*), voi else { std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8)); - HWND parent = setting_.get() ? setting_->hwnd() : NULL; + if (indicator_.get()) indicator_->show(false); - MessageBoxW(parent, msg.c_str(), L"\u542F\u52A8\u5931\u8D25", MB_OK | MB_ICONERROR); + if (!IsWindow(app_wnd_)) + callback::bring_message_box_topmost(L"\u542F\u52A8\u5931\u8D25"); + MessageBoxW(app_wnd_, msg.c_str(), L"\u542F\u52A8\u5931\u8D25", MB_OK | MB_ICONERROR); } prev_start_result_ = ret; is_scanning_ = ret == SANE_STATUS_GOOD; @@ -2079,6 +2181,11 @@ COM_API_IMPLEMENT(scanner, int, get_event(void)) { return events_.take(); } +COM_API_IMPLEMENT(scanner, void, set_event_callback(int(__stdcall* handle_ev)(int, void*), void* para)) +{ + scanner_ev_handler_ = handle_ev; + evh_param_ = para; +} COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds)) { int count = get_scanned_images(milliseconds); @@ -2551,8 +2658,10 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bo } COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent)) { - if(setting_.get() && IsWindowVisible(setting_->hwnd())) + if (setting_.get() && IsWindowVisible(setting_->hwnd())) parent = setting_->hwnd(); + else if (!IsWindow(parent)) + parent = callback::find_main_wnd(); indicator_.reset(new dlg_indicator(parent)); indicator_->set_ui_event_notify(&scanner::ui_callback, this); @@ -2619,10 +2728,20 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) } else if (ev_code == SANE_EVENT_SCAN_FINISHED) { + err_ = *len; if (indicator_.get()) indicator_->notify_scan_over((char*)data, *len != SCANNER_ERR_OK); else - on_ui_event(ev_code, (void*)ev_code); + { + if (*len) + { + std::wstring msg(local_trans::a2u((char*)data, CP_UTF8)); + if(!IsWindow(app_wnd_)) + callback::bring_message_box_topmost(L"\u9519\u8BEF"); + MessageBoxW(app_wnd_, msg.c_str(), L"\u9519\u8BEF", MB_OK); + } + on_ui_event(ev_code, (void*)ev_code); + } is_scanning_ = false; { diff --git a/sane/scanner.h b/sane/scanner.h index 70b7241..092bc57 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -54,7 +54,8 @@ class scanner : public ISaneInvoker, virtual public refer gb::sane_config* cfg_; int(__stdcall* scanner_ev_handler_)(int, void*); - void* evh_param_; + void* evh_param_; + HWND app_wnd_; // for MessageBox void transport_config_file(void); void update_config(void); @@ -204,9 +205,10 @@ public: // ISaneInvoker public: - COM_API_OVERRIDE(int, start(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); + COM_API_OVERRIDE(int, start(void)); COM_API_OVERRIDE(int, stop(void)); COM_API_OVERRIDE(int, get_event(void)); + COM_API_OVERRIDE(void, set_event_callback(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL)); COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1)); COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index b4caf44..022ac2e 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -604,7 +604,24 @@ float trans_range(float val, float min_from, float max_from, float min_to, float return val; } +static void log_attr_access(int attr, int method) +{ + wchar_t msg[128] = { 0 }; + const wchar_t* op = L"Unknown Oper"; +#define METHOD_DESC(oper) \ + if (method == (int)Msg::oper) \ + op = L###oper; + + METHOD_DESC(Set) + else METHOD_DESC(Reset) + else METHOD_DESC(Get) + else METHOD_DESC(GetCurrent) + else METHOD_DESC(GetDefault) + + swprintf_s(msg, _countof(msg) - 1, L"%s %04x\r\n", op, attr); + load_sane_util::log_info(msg, 0); +} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // huagao_ds ... @@ -750,7 +767,8 @@ Result huagao_ds::eventProcess(const Identity&, Event& event) { int ev = scanner_->get_event(); - handle_scanner_event(ev); + if(ev) + handle_scanner_event(ev); } // event.setMessage(Msg::Null); @@ -808,6 +826,7 @@ Result huagao_ds::identityOpenDs(const Identity& id) return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) }; } // ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str())); + scanner_->set_event_callback(&huagao_ds::on_scanner_event, this); if (get_config_number(L"twain-app", L"flow") == TWAIN_APP_TRANSFER_REVERSE) { cur_head_ = new SANE_Parameters; @@ -825,6 +844,7 @@ Result huagao_ds::identityCloseDs(const Identity&) // ui_.reset(); if (scanner_.get()) { + scanner_->set_event_callback(); scanner_.reset(); } if (singleton_) @@ -915,17 +935,16 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw())) return seqError(); - int(__stdcall * evf)(int, void*) = m_bIndicator ? NULL : &huagao_ds::on_scanner_event; scanner_->twain_set_transfer((twain_xfer)m_capXferMech); - int err = scanner_->start(evf, this); + int err = scanner_->start(); if (err == SCANNER_ERR_OK) { return success(); } else { - if (err == SCANNER_ERR_DEVICE_NO_PAPER) - return { ReturnCode::Failure, ConditionCode::NoMedia }; + // if (err == SCANNER_ERR_DEVICE_NO_PAPER) + return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) }; return bummer(); } @@ -956,7 +975,7 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) if (!scanner_->wait_image()) { notifyCloseOk(); - return bummer(); + return success(); // 好分数需要返回成功 } ok = scanner_->get_first_image_header(&head); } @@ -1366,6 +1385,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::SupportedCaps] = msgSupportGetAll; m_caps[CapType::SupportedCaps] = [this](Msg msg, Capability& data) { + log_attr_access((int)CapType::SupportedCaps, (int)msg); if ((msg == Msg::Get) || (Msg::GetCurrent == msg) || (Msg::GetDefault == msg)) { data = Capability::createArray(m_caps.size()); auto arr = data.array(); @@ -1386,6 +1406,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::XferCount] = msgSupportGetAllSetReset; m_caps[CapType::XferCount] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::XferCount, (int)msg); if (msg == Msg::Set) { auto item = data.currentItem(); if (item > 65535 || item < -1 || item == 0) { @@ -1411,6 +1432,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::Indicators] = msgSupportGetAllSetReset; m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::Indicators, (int)msg); if (Msg::Set == msg) { auto show = data.currentItem(); m_bIndicator = show; @@ -1423,7 +1445,8 @@ void huagao_ds::init_support_caps(void) m_query[CapType::DeviceOnline] = msgSupportGetAll; m_caps[CapType::DeviceOnline] = [this](Msg msg, Capability& data) -> Result { - CapabilityPrintf(msg, enum2str(CapType::DeviceOnline)); + log_attr_access((int)CapType::DeviceOnline, (int)msg); + // CapabilityPrintf(msg, enum2str(CapType::DeviceOnline)); switch (msg) { case Msg::Get: case Msg::GetCurrent: @@ -1441,6 +1464,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::ICompression] = msgSupportGetAllSetReset; m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::ICompression, (int)msg); if (!scanner_.get()) return seqError(); if (Msg::Set == msg) { @@ -1490,6 +1514,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IBitDepth] = msgSupportGetAllSetReset; m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IBitDepth, (int)msg); int now = 0, init = 0; std::vector all; GET_SANE_OPT(int, scanner_, ex_color_mode, &now, &init, &all, NULL); @@ -1532,6 +1557,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IXResolution] = msgSupportGetAllSetReset; m_caps[CapType::IXResolution] = [this](Msg msg, Capability& data) { + log_attr_access((int)CapType::IXResolution, (int)msg); if (!scanner_.get()) return seqError(); std::vector values; @@ -1596,6 +1622,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::ISupportedSizes] = msgSupportGetAllSetReset; m_caps[CapType::ISupportedSizes] = [this](Msg msg, Capability& data) { + log_attr_access((int)CapType::ISupportedSizes, (int)msg); int now = 0, init = 0; std::vector all; @@ -1624,6 +1651,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IPhysicalWidth] = msgSupportGetAll; m_caps[CapType::IPhysicalWidth] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IPhysicalWidth, (int)msg); switch (msg) { case Msg::Get: case Msg::GetCurrent: @@ -1645,6 +1673,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IPhysicalHeight] = msgSupportGetAll; m_caps[CapType::IPhysicalHeight] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IPhysicalHeight, (int)msg); switch (msg) { case Msg::Get: case Msg::GetCurrent: @@ -1669,6 +1698,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IXferMech] = msgSupportGetAllSetReset; m_caps[CapType::IXferMech] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IXferMech, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech == XferMech::Native || mech == XferMech::Memory || mech == XferMech::File) { @@ -1690,6 +1720,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IPixelType] = msgSupportGetAllSetReset; m_caps[CapType::IPixelType] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IPixelType, (int)msg); if (!scanner_.get()) return seqError(); std::vector values; @@ -1735,6 +1766,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticColorEnabled] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticColorEnabled] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticColorEnabled, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); int ret = SCANNER_ERR_OK, val = mech ? COLOR_AUTO_MATCH : COLOR_RGB; @@ -1750,6 +1782,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticColorNonColorPixelType] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticColorNonColorPixelType] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticColorNonColorPixelType, (int)msg); if (msg == Msg::Set) { int mech = (int)data.currentItem(); //int now = 0; @@ -1774,6 +1807,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IJpegQuality] = msgSupportGetAllSetReset; m_caps[CapType::IJpegQuality] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IJpegQuality, (int)msg); SANE_FinalImgFormat fif; fif.img_format = SANE_IMAGE_TYPE_JPG; if (Msg::Set == msg) { @@ -1800,6 +1834,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IOrientation] = msgSupportGetAllSetReset; m_caps[CapType::IOrientation] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IOrientation, (int)msg); CapabilityPrintf(msg, enum2str(CapTypeEx::IOrientation), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); @@ -1816,6 +1851,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IRotation] = msgSupportGetAllSetReset; m_caps[CapType::IRotation] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IRotation, (int)msg); if (Msg::Set == msg) { auto res = data.currentItem(); float angle = res.toFloat(); @@ -1847,6 +1883,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::FeederEnabled] = msgSupportGetAllSetReset; m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::FeederEnabled, (int)msg); CapabilityPrintf(msg, enum2str(CapType::FeederEnabled), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); @@ -1861,6 +1898,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::DuplexEnabled] = msgSupportGetAllSetReset; m_caps[CapType::DuplexEnabled] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::DuplexEnabled, (int)msg); if (Msg::Set == msg) { bool mech = data.currentItem(); int ret = SCANNER_ERR_OK; @@ -1874,6 +1912,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::AutoFeed] = msgSupportGetAllSetReset; m_caps[CapType::AutoFeed] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::AutoFeed, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); m_bAutoFeed = mech; @@ -1884,6 +1923,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IImageFileFormat] = msgSupportGetAllSetReset; m_caps[CapType::IImageFileFormat] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::IImageFileFormat, (int)msg); SANE_FinalImgFormat now, init; std::vector all; GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &now, &init, &all, NULL); @@ -1923,6 +1963,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticDeskew] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticDeskew] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticDeskew, (int)msg); if (Msg::Set == msg) { auto atuodsw = data.currentItem(); int ret = SCANNER_ERR_OK; @@ -1936,6 +1977,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticRotate] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticRotate, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); float direction = mech ? AUTO_MATIC_ROTATE : .0f; @@ -1952,6 +1994,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::SerialNumber] = msgSupportGetAll; m_caps[CapType::SerialNumber] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::SerialNumber, (int)msg); Str255 str; std::string v(""); GET_SANE_OPT(std::string, scanner_, ex_serial, &v, NULL, NULL, NULL); @@ -1961,6 +2004,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::AutoScan] = msgSupportGetAllSetReset; m_caps[CapType::AutoScan] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::AutoScan, (int)msg); if (Msg::Set == msg) { auto autoscan = data.currentItem(); m_autoscan = autoscan; @@ -1973,6 +2017,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutoSize] = msgSupportGetAllSetReset; m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutoSize, (int)msg); CapabilityPrintf(msg, enum2str(CapType::IAutoSize), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto autosize = data.currentItem(); @@ -1989,6 +2034,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticBorderDetection] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticBorderDetection, (int)msg); if (Msg::Set == msg) { auto autodetectborder = data.currentItem(); int ret = SCANNER_ERR_OK; @@ -2006,6 +2052,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutoDiscardBlankPages] = msgSupportGetAllSetReset; m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutoDiscardBlankPages, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); bool discard = mech == DiscardBlankPages::Auto; @@ -2021,6 +2068,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CAP_TYPE_EX_DISCARD_BLANK_RECEIPT] = msgSupportGetAllSetReset; m_caps[(CapType)CAP_TYPE_EX_DISCARD_BLANK_RECEIPT] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CAP_TYPE_EX_DISCARD_BLANK_RECEIPT, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); bool discard = mech == DiscardBlankPages::Auto; @@ -2037,6 +2085,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IFilter] = msgSupportGetAllSetReset; m_caps[CapType::IFilter] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IFilter, (int)msg); if (Msg::Set == msg) { auto mech = data.currentItem(); int ret = SCANNER_ERR_OK, val = to_sane_filter((Filter)mech); @@ -2072,6 +2121,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IBrightness] = msgSupportGetAllSetReset; m_caps[CapType::IBrightness] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IBrightness, (int)msg); int init = 128, l = 1, u = 255, step = 1, now = 128; int ret = SCANNER_ERR_OK; GET_SANE_OPT_RANGE(int, scanner_, bright, &now, &init, &l, &u, &step); @@ -2107,6 +2157,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IContrast] = msgSupportGetAllSetReset; m_caps[CapType::IContrast] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IContrast, (int)msg); int init = 4, l = 1, u = 7, step = 1, now = 4; int ret = SCANNER_ERR_OK; GET_SANE_OPT_RANGE(int, scanner_, contrast, &now, &init, &l, &u, &step); @@ -2142,6 +2193,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO] = msgSupportGetAllSetReset; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO, (int)msg); float init = .0f, l = .0f, u = .0f, step = .0f, now = .0f; int ret = SCANNER_ERR_OK; GET_SANE_OPT_RANGE(float, scanner_, search_hole_range, &now, &init, &l, &u, &step); @@ -2178,6 +2230,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IGamma] = msgSupportGetAllSetReset; m_caps[CapType::IGamma] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IGamma, (int)msg); float init = .0f, l = .0f, u = .0f, step = .0f, now = .0f; int ret = SCANNER_ERR_OK; GET_SANE_OPT_RANGE(float, scanner_, gamma, &now, &init, &l, &u, &step); @@ -2207,11 +2260,13 @@ void huagao_ds::init_support_caps(void) m_query[CapType::CustomDsData] = msgSupportGetAll; m_caps[CapType::CustomDsData] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::CustomDsData, (int)msg); return CapSupGetAll(msg, data, Bool(true), Bool(true)); }; m_query[CapType::DoubleFeedDetection] = msgSupportGetAllSetReset; m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::DoubleFeedDetection, (int)msg); if (Msg::Set == msg) { auto atuodsw = data.currentItem(); int ret = SCANNER_ERR_OK; @@ -2229,6 +2284,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType::IAutomaticCropUsesFrame] = msgSupportGetAll; m_caps[CapType::IAutomaticCropUsesFrame] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::IAutomaticCropUsesFrame, (int)msg); bool yes = false; GET_SANE_OPT(bool, scanner_, ex_is_paper_auto_crop, &yes, NULL, NULL, NULL); BYTE crop = yes; @@ -2237,12 +2293,14 @@ void huagao_ds::init_support_caps(void) m_query[CapType::FeederLoaded] = msgSupportGetAll; m_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result { + log_attr_access((int)CapType::FeederLoaded, (int)msg); Bool paperon = scanner_->is_paper_on(); return CapSupGetAll(msg, data, paperon, paperon); }; m_query[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = msgSupportGetAllSetReset; m_caps[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_FOLD, (int)msg); if (Msg::Set == msg || Msg::Reset == msg) { auto fold = data.currentItem(); if (msg == Msg::Reset) @@ -2259,6 +2317,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_DOGEAR_DIST)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_DOGEAR_DIST)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_DOGEAR_DIST, (int)msg); int now = 10, init = 10, l = 0, u = 100, s = 10; GET_SANE_OPT_RANGE(int, scanner_, dogear_size, &now, &init, &l, &u, &s); if (Msg::Set == msg || Msg::Reset == msg) { @@ -2278,6 +2337,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_CROP_MODEL)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_CROP_MODEL)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_CROP_MODEL, (int)msg); bool cur = false, def = false; GET_SANE_OPT(bool, scanner_, ex_is_paper_auto_crop, &cur, &def, NULL, NULL); if (Msg::Set == msg || Msg::Reset == msg) @@ -2294,6 +2354,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_MULTI_OUT_TYPE] = msgSupportGetAllSetReset; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_MULTI_OUT_TYPE] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_MULTI_OUT_TYPE, (int)msg); int cur = MULTI_OUT_NONE, def = MULTI_OUT_NONE; std::vector all; GET_SANE_OPT(int, scanner_, ex_multiout_type, &cur, &def, &all, NULL); @@ -2321,6 +2382,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType(CapTypeEx::CAP_TYPE_EX_TO_BE_SCAN)] = msgSupportGetAllSetReset; m_caps[CapType(CapTypeEx::CAP_TYPE_EX_TO_BE_SCAN)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_TO_BE_SCAN, (int)msg); if (Msg::Set == msg || Msg::Reset == msg) { auto tobe = data.currentItem(); if (msg == Msg::Reset) @@ -2337,6 +2399,7 @@ void huagao_ds::init_support_caps(void) m_query[CapType(CapTypeEx::CAP_TYPE_EX_SCAN_WITH_HOLE)] = msgSupportGetAllSetReset; m_caps[CapType(CapTypeEx::CAP_TYPE_EX_SCAN_WITH_HOLE)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_SCAN_WITH_HOLE, (int)msg); if (Msg::Set == msg || Msg::Reset == msg) { auto tobe = data.currentItem(); if (msg == Msg::Reset) @@ -2353,6 +2416,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = msgSupportGetAll; m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_ENCODE, (int)msg); std::string code(""); GET_SANE_OPT(std::string, scanner_, ex_device_code, &code, NULL, NULL, NULL); Str255 str; @@ -2363,6 +2427,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_POWER_LEVEL)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_POWER_LEVEL)] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_POWER_LEVEL, (int)msg); int cur = SANE_POWER_MINUTES_30, def = SANE_POWER_MINUTES_30; std::vector all; GET_SANE_OPT(int, scanner_, ex_power, &cur, &def, &all, NULL); @@ -2390,6 +2455,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD] = msgSupportGetAllSetReset; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD, (int)msg); if (Msg::Set == msg) { auto convex = data.currentItem(); int ret = SCANNER_ERR_OK; @@ -2407,6 +2473,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = msgSupportGetAllSetReset; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_SHARPEN, (int)msg); int cur = MULTI_OUT_NONE, def = MULTI_OUT_NONE; std::vector all; GET_SANE_OPT(int, scanner_, ex_sharpen, &cur, &def, &all, NULL); @@ -2434,6 +2501,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = msgSupportGetAllSetReset; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR, (int)msg); int cur = FILTER_NONE, def = FILTER_NONE; std::vector vals; GET_SANE_OPT(int, scanner_, ex_color_enhance, &cur, &def, &vals, NULL); @@ -2470,6 +2538,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION] = msgSupportGetAll; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION, (int)msg); std::string ver(""); GET_SANE_OPT(std::string, scanner_, ex_hardware_version, &ver, NULL, NULL, NULL); Str255 str; @@ -2480,6 +2549,7 @@ void huagao_ds::init_support_caps(void) m_query[(CapType)CapTypeEx::CAP_TYPE_EX_IP] = msgSupportGetAll; m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_IP] = [this](Msg msg, Capability& data)->Result { + log_attr_access((int)CapTypeEx::CAP_TYPE_EX_IP, (int)msg); std::string ip(""); GET_SANE_OPT(std::string, scanner_, ex_ip, &ip, NULL, NULL, NULL); Str255 str; @@ -2522,6 +2592,7 @@ void huagao_ds::init_support_caps_ex(void) #define SET_SANE_CAP_ENUM(ctype, ttype, name) \ m_query[(CapType)CAP_EX_SANE_##name] = msgSupportGetAllSetReset; \ m_caps[(CapType)CAP_EX_SANE_##name] = [this](Msg msg, Capability& data) -> Result { \ + log_attr_access((int)CAP_EX_SANE_##name, (int)msg); \ ctype now, init; \ std::vector all; \ GET_SANE_OPT(ctype, scanner_, name, &now, &init, &all, NULL); \ @@ -2571,6 +2642,7 @@ void huagao_ds::init_support_caps_ex(void) #define SET_SANE_CAP_RANGE(ctype, ttype, name) \ m_query[(CapType)CAP_EX_SANE_##name] = msgSupportGetAllSetReset; \ m_caps[(CapType)CAP_EX_SANE_##name] = [this](Msg msg, Capability& data) -> Result { \ + log_attr_access((int)CAP_EX_SANE_##name, (int)msg); \ ctype now, init, lower, upper, step; \ std::vector all; \ GET_SANE_OPT_RANGE(ctype, scanner_, name, &now, &init, &lower, &upper, &step); \ @@ -2611,6 +2683,7 @@ void huagao_ds::init_support_caps_ex(void) #define SET_SANE_CAP(ctype, ttype, name) \ m_query[(CapType)CAP_EX_SANE_##name] = msgSupportGetAllSetReset; \ m_caps[(CapType)CAP_EX_SANE_##name] = [this](Msg msg, Capability& data) -> Result { \ + log_attr_access((int)CAP_EX_SANE_##name, (int)msg); \ ctype now, init; \ GET_SANE_OPT(ctype, scanner_, name, &now, &init, NULL, NULL); \ if (msg == Msg::Set || msg == Msg::Reset) \ From e45ef83b4a72cc0b7266a07069ef9cde9bc93284 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Fri, 21 Oct 2022 18:09:33 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E6=89=AB=E6=8F=8F=E5=87=BA=E9=94=99=E6=97=B6=EF=BC=8C=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E8=AE=BE=E7=BD=AE=E7=95=8C=E9=9D=A2=E4=B8=8D=E9=80=80?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/scanner.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 751d1d4..8479e52 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -621,14 +621,32 @@ void scanner::apply_config(void) } void scanner::on_ui_event(int uev, void* sender) { + bool indicator = sender == indicator_.get(); + if (uev == SANE_EVENT_SCAN_FINISHED || uev == SANE_EVENT_UI_CLOSE_NORMAL || uev == SANE_EVENT_UI_CLOSE_CANCEL) + { + if (indicator) + indicator_.reset(); + + if (err_ && setting_.get()) + { + return; + } + is_scanning_ = false; + } + int(__stdcall * h)(int, void*) = scanner_ev_handler_; if (h) { + if (SANE_EVENT_UI_CLOSE_SETTING == uev) + { + is_scanning_ = false; + setting_.reset(); + } + h(uev, evh_param_); return; } - bool indicator = sender == indicator_.get(); if (prev_start_result_ != SANE_STATUS_GOOD && indicator) indicator_.reset(); else @@ -2174,7 +2192,6 @@ COM_API_IMPLEMENT(scanner, int, start(void)) } COM_API_IMPLEMENT(scanner, int, stop(void)) { - scanner_ev_handler_ = NULL; return hg_sane_middleware::instance()->stop(handle_); } COM_API_IMPLEMENT(scanner, int, get_event(void)) @@ -2742,7 +2759,7 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) } on_ui_event(ev_code, (void*)ev_code); } - is_scanning_ = false; + // is_scanning_ = false; { wchar_t msg[128] = { 0 }; From 9f33e4db8513958b7eb82d1dea285eba523a6d92 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sat, 22 Oct 2022 10:06:38 +0800 Subject: [PATCH 06/12] v4.33 --- device/scanner.rc | 8 ++++---- sane/sane.rc | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/device/scanner.rc b/device/scanner.rc index 0fc2f61..1044de6 100644 --- a/device/scanner.rc +++ b/device/scanner.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,32,10000,22287 - PRODUCTVERSION 4,32,10000,22287 + FILEVERSION 4,33,10000,22295 + PRODUCTVERSION 4,33,10000,22295 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "宁波华高信息科技有限公司" VALUE "FileDescription", "华高扫描仪应用程序" - VALUE "FileVersion", "4.32.10000.22287" + VALUE "FileVersion", "4.33.10000.22295" VALUE "InternalName", "scanner.dll" VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022" VALUE "OriginalFilename", "scanner.dll" VALUE "ProductName", "HUAGOScan" - VALUE "ProductVersion", "4.32.10000.22287" + VALUE "ProductVersion", "4.33.10000.22295" END END BLOCK "VarFileInfo" diff --git a/sane/sane.rc b/sane/sane.rc index f06683b..2a17800 100644 --- a/sane/sane.rc +++ b/sane/sane.rc @@ -271,8 +271,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,32,10000,22287 - PRODUCTVERSION 4,32,10000,22287 + FILEVERSION 4,33,10000,22295 + PRODUCTVERSION 4,33,10000,22295 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -289,12 +289,12 @@ BEGIN BEGIN VALUE "CompanyName", "宁波华高信息科技有限公司" VALUE "FileDescription", "华高扫描仪应用程序" - VALUE "FileVersion", "4.32.10000.22287" + VALUE "FileVersion", "4.33.10000.22295" VALUE "InternalName", "sane.dll" VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022" VALUE "OriginalFilename", "sane.dll" VALUE "ProductName", "HUAGOScan" - VALUE "ProductVersion", "4.32.10000.22287" + VALUE "ProductVersion", "4.33.10000.22295" END END BLOCK "VarFileInfo" From aa5c9ad9043bba3a5d23f33cc08d2dcbf67bc0da Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Mon, 24 Oct 2022 16:17:32 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E6=9B=B4=E6=94=B9USB=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=A0=87=E8=AF=86=EF=BC=8C=E4=BB=A5=E4=B8=8D=E5=B8=A6GUID?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E7=9A=84=E8=AE=BE=E5=A4=87=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E4=B8=BA=E5=88=A4=E6=96=AD=E4=BE=9D=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/win_usb/win_usb.cpp | 580 ++++++++++++++----------------------- device/win_usb/win_usb.h | 59 ++-- 2 files changed, 244 insertions(+), 395 deletions(-) diff --git a/device/win_usb/win_usb.cpp b/device/win_usb/win_usb.cpp index bfc80fc..7bf95ab 100644 --- a/device/win_usb/win_usb.cpp +++ b/device/win_usb/win_usb.cpp @@ -146,15 +146,10 @@ ovl_cls* ovl_mgr::get_ovl(void) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // usb_device ... -usb_device::usb_device(const char* name) : ref_(1), name_(name ? name : ""), is_ok_(false) - , dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000), reg_key_("") +usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false) + , dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000) { - bzero(&guid_, sizeof(guid_)); - id_ = usb_device::vid_pid_from_name(name); - - GUID guid; - UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid); - id_.addr = usb_device::get_device_address(name_.c_str(), &guid); + memset(&guid_, 0, sizeof(guid_)); } usb_device::~usb_device() { @@ -202,23 +197,20 @@ int usb_device::set_timeout(HANDLE h) //SetCommTimeouts(h, &to); } -DEVID usb_device::vid_pid_from_name(const char* name) +void usb_device::vid_pid_from_name(const char* name, int* vid, int* pid) { // name: \\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed} - DEVID id; std::string s(name ? name : ""); size_t pos = 0; std::transform(s.begin(), s.end(), s.begin(), tolower); pos = s.find("vid_"); - if (pos != std::string::npos) - id.vid = usb_device::from_hex_string(s.c_str() + pos + 4); + if (pos != std::string::npos && vid) + *vid = usb_device::from_hex_string(s.c_str() + pos + 4); pos = s.find("pid_"); - if (pos != std::string::npos) - id.pid = usb_device::from_hex_string(s.c_str() + pos + 4); - - return id; + if (pos != std::string::npos && pid) + *pid = usb_device::from_hex_string(s.c_str() + pos + 4); } DWORD usb_device::from_hex_string(const char* hex_str) { @@ -242,222 +234,15 @@ DWORD usb_device::from_hex_string(const char* hex_str) return v; } -std::string usb_device::driver_key_name(HANDLE file) +std::string usb_device::name_without_guid(const char* name) { - ULONG nBytes = 0; - USB_HCD_DRIVERKEY_NAME driverKeyName = { 0 }; - BOOL success = DeviceIoControl(file, IOCTL_GET_HCD_DRIVERKEY_NAME, &driverKeyName, sizeof(driverKeyName), &driverKeyName, sizeof(driverKeyName), &nBytes, NULL); - std::string ret(""); + std::string no_guid(name); + size_t pos = no_guid.find("#{"); - if (success && driverKeyName.ActualLength > nBytes) - { - PUSB_HCD_DRIVERKEY_NAME buf = (PUSB_HCD_DRIVERKEY_NAME)GlobalAlloc(GPTR, driverKeyName.ActualLength); - nBytes = driverKeyName.ActualLength; - success = DeviceIoControl(file, IOCTL_GET_HCD_DRIVERKEY_NAME, &buf, nBytes, &buf, nBytes, &nBytes, NULL); - if (success) - { - ret = u2utf8(buf->DriverKeyName); - } - GlobalFree(buf); - } + if (pos != std::string::npos) + no_guid.erase(pos); - return ret; -} -std::string usb_device::parent_hub_path_name(int vid, int pid, int *addr, std::string* reg_key) -{ - std::string ret(""); - GUID guid = GUID_DEVINTERFACE_USB_HUB; - HDEVINFO dev = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - int port = addr ? *addr : -1; - - if (dev) - { - SP_DEVICE_INTERFACE_DATA id = { 0 }; - SP_DEVINFO_DATA did; - int ind = 0; - - id.cbSize = sizeof(id); - while (SetupDiEnumDeviceInterfaces(dev, NULL, &guid, ind++, &id)) - { - PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL; - DWORD size = 0; - - if (!SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, 0, &size, NULL) && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - int bytes = size + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 40; - buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[bytes]; - memset(buf, 0, bytes * 2); - buf->cbSize = sizeof(*buf); - if (SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, buf->cbSize + size, NULL, NULL)) - { - std::string n(u2utf8(buf->DevicePath)); - if (find_vid_pid_in_hub(n.c_str(), vid, pid, &port, reg_key)) - ret = n; - } - delete[] buf; - if (ret.length()) - break; - } - } - SetupDiDestroyDeviceInfoList(dev); - } - if (addr) - *addr = port; - VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "Parent hub for %04X:%04X is: %s (+%d)\r\n", vid, pid, ret.c_str(), port); - - return ret; -} -bool usb_device::find_vid_pid_in_hub(const char* utf8_hub_path_name, int vid, int pid, int* addr, std::string* reg_key) -{ - bool ret = false; - HANDLE h = CreateFileA(utf8_hub_path_name, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (h == INVALID_HANDLE_VALUE) - return ret; - - int bytes = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + (sizeof(USB_PIPE_INFO) * 30); - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)new char[bytes]; - memset(connectionInfoEx, 0, bytes); - if (addr && *addr != -1) - { - connectionInfoEx->ConnectionIndex = *addr; - DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, connectionInfoEx, - bytes, connectionInfoEx, bytes, (LPDWORD)&bytes, NULL); - ret = connectionInfoEx->DeviceDescriptor.idVendor == vid && connectionInfoEx->DeviceDescriptor.idProduct == pid; - if (ret && reg_key) - { - char buf[512] = { 0 }; - USB_NODE_CONNECTION_DRIVERKEY_NAME* name = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)buf; - name->ConnectionIndex = *addr; - name->ActualLength = (sizeof(buf) - sizeof(*name)) / 2 - 1; - DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, name, sizeof(*name), name, name->ActualLength, (LPDWORD)&bytes, NULL); - *reg_key = u2utf8(name->DriverKeyName); - } - } - else - { - for (int i = 1; !ret; ++i) - { - DWORD len = bytes; - connectionInfoEx->ConnectionIndex = i; - if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, connectionInfoEx, - bytes, connectionInfoEx, bytes, (LPDWORD)&bytes, NULL)) - break; - ret = connectionInfoEx->DeviceDescriptor.idVendor == vid && connectionInfoEx->DeviceDescriptor.idProduct == pid; - } - if (ret && addr) - *addr = connectionInfoEx->ConnectionIndex; - } - delete[] connectionInfoEx; - CloseHandle(h); - - return ret; -} -int usb_device::get_device_address(const char* device_name, LPGUID lpguid) -{ - int addr = -1; - GUID guid = lpguid ? *lpguid : GUID_DEVINTERFACE_USB_DEVICE; - HDEVINFO dev = NULL; - std::string ret(""), src(device_name); - - dev = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (dev) - { - SP_DEVICE_INTERFACE_DATA id = { 0 }; - SP_DEVINFO_DATA did; - int ind = 0; - size_t pos = src.find("{"); - - if (pos != std::string::npos) - src.erase(pos); - id.cbSize = sizeof(id); - while (SetupDiEnumDeviceInterfaces(dev, NULL, &guid, ind++, &id)) - { - PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL; - DWORD size = 0; - - ret = ""; - if (!SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, 0, &size, NULL) && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[size + 4]; - memset(buf, 0, (size + 4) * 2); - buf->cbSize = sizeof(*buf); - if (SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, buf->cbSize + size, NULL, NULL)) - { - wchar_t* l = wcsstr(buf->DevicePath, L"{"); - if (l) - *l = 0; - ret = u2utf8(buf->DevicePath); - } - delete buf; - } - - if (stricmp(ret.c_str(), src.c_str())) - continue; - - SP_DEVINFO_DATA dd = { 0 }; - dd.cbSize = sizeof(dd); - // for (int i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dd); ++i) - if (SetupDiEnumDeviceInfo(dev, ind - 1, &dd)) - { - SetupDiGetDeviceRegistryPropertyA(dev, &dd, SPDRP_ADDRESS, NULL, (PBYTE)&addr, sizeof(addr), NULL); - } - break; - } - SetupDiDestroyDeviceInfoList(dev); - } - - return addr; -} -std::string usb_device::usb_scan_name(DEVID id, const char* guid) -{ - // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F} - HKEY key = NULL, root = NULL; - std::string path("SYSTEM\\CurrentControlSet\\Control\\Class\\{"), name(""); - char val[256] = { 0 }; - int ind = 0, err = 0; - - path += guid; - path += "}"; - err = RegOpenKeyA(HKEY_LOCAL_MACHINE, path.c_str(), &root); - if (root) - { - DWORD index = 0; - - while (RegEnumKeyA(root, index++, val, _countof(val) - 1) == ERROR_SUCCESS) - { - RegOpenKeyA(root, val, &key); - if (key) - { - DWORD len = _countof(val) - 1, - type = REG_SZ; - if (RegQueryValueExA(key, "MatchingDeviceId", NULL, &type, (LPBYTE)val, &len) == ERROR_SUCCESS) - { - val[len] = 0; - DEVID cid = usb_device::vid_pid_from_name(val); - if (cid.vid == id.vid && cid.pid == id.pid) - { - len = _countof(val) - 1; - type = REG_SZ; - if (RegQueryValueExA(key, "CreateFileName", NULL, &type, (LPBYTE)val, &len) == ERROR_SUCCESS) - { - val[len] = 0; - name = val; - } - } - } - RegCloseKey(key); - if (!name.empty()) - break; - } - memset(val, 0, sizeof(val)); - } - RegCloseKey(root); - } - - return name; + return no_guid; } std::string usb_device::usb_scan_name(const char* reg_key) { @@ -496,21 +281,6 @@ long usb_device::release(void) return ref; } -bool usb_device::operator==(const char* name) -{ - return name_ == name; -} -bool usb_device::operator==(const DEVID& id) -{ - return id_.vid == id.vid && id_.pid == id.pid; -} - -usb_device& usb_device::operator=(const DEVID& id) -{ - id_ = id; - - return *this; -} usb_device& usb_device::operator=(const GUID& guid) { guid_ = guid; @@ -520,16 +290,16 @@ usb_device& usb_device::operator=(const GUID& guid) std::string usb_device::name(void) { - return name_; + return udev_.name; +} +USBDEV& usb_device::dev(void) +{ + return udev_; } GUID usb_device::guid(void) { return guid_; } -DEVID usb_device::id(void) -{ - return id_; -} bool usb_device::is_ok(void) { return is_ok_; @@ -545,40 +315,41 @@ bool usb_device::is_online(void) void usb_device::set_online(bool online) { online_ = online; - if (!online_) - reg_key_ = ""; } uint8_t usb_device::port(void) { if (!dev_desc_) init(); - return port_; + + return udev_.port; +} +uint8_t usb_device::address(void) +{ + if (!dev_desc_) + init(); + + return udev_.addr; } std::string usb_device::reg_path(void) { - return reg_key_; + return udev_.driver_key; } bool usb_device::init(void) { PUSBDEVICEINFO info = NULL; GUID guid; - int addr = -1; clear(); - UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid); - addr = usb_device::get_device_address(name_.c_str(), &guid); - //if (addr != -1) + usb_monitor::enum_usb_device(&usb_monitor::find_parent_hub, &udev_, true); + VLOG_MINI_3(LOG_LEVEL_ALL, "Device '%s' at hub '%s + %d'\r\n", udev_.name.c_str(), udev_.hub.c_str(), udev_.port); + if (!udev_.hub.empty()) { - std::string path(usb_device::parent_hub_path_name(id_.vid, id_.pid, &addr, ®_key_)); - if (!path.empty()) + HANDLE h = CreateFileA(udev_.hub.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h != INVALID_HANDLE_VALUE) { - HANDLE h = CreateFileA(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h != INVALID_HANDLE_VALUE) - { - info = enumerate_hub_port(h, addr); - CloseHandle(h); - } + info = enumerate_hub_port(h, udev_.port); + CloseHandle(h); } } @@ -587,7 +358,7 @@ bool usb_device::init(void) if (info) { - port_ = addr; + udev_.addr = info->ConnectionInfo->DeviceAddress; if (info->ConnectionInfo) { dev_desc_ = new libusb_device_descriptor; @@ -681,7 +452,6 @@ bool usb_device::init(void) free_usb_device_info(info); } - id_.addr = port_; return is_ok_; } @@ -709,10 +479,6 @@ void usb_device::clear(void) cfg_desc_.clear(); is_ok_ = false; } -void usb_device::online_statu_changed(bool online) -{ - online_ = online; -} int usb_device::get_descriptor(libusb_device_descriptor* desc) { if (dev_desc_) @@ -731,8 +497,8 @@ int usb_device::get_descriptor(libusb_device_descriptor* desc) desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_HID; else desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_VENDOR_SPEC; - desc->idVendor = id_.vid; - desc->idProduct = id_.pid; + desc->idVendor = udev_.vid; + desc->idProduct = udev_.pid; desc->bcdUSB = 0x200; // USB2.0 ? desc->bcdDevice = 0; // ? desc->bDescriptorType = libusb_descriptor_type::LIBUSB_DT_DEVICE; @@ -765,7 +531,7 @@ int usb_device::open(libusb_device_handle** dev_handle) if (!dev_desc_) init(); - HANDLE h = open_usb(name_.c_str()); + HANDLE h = open_usb(udev_.name.c_str()); if (h == INVALID_HANDLE_VALUE) { *dev_handle = NULL; @@ -775,22 +541,19 @@ int usb_device::open(libusb_device_handle** dev_handle) USBSCAN_PIPE_CONFIGURATION upc = { 0 }; DWORD cbr = 0; - std::string fmt("\\%d"), root(""); // (usb_device::usb_scan_name(reg_key_.empty() ? id_ : reg_key_.c_str())); - - if (reg_key_.length()) - root = usb_device::usb_scan_name(reg_key_.c_str()); - if (root.empty()) - root = usb_device::usb_scan_name(id_); + std::string fmt("\\%d"), root(""); + if (udev_.driver_key.length()) + root = usb_device::usb_scan_name(udev_.driver_key.c_str()); if (root.empty()) { - VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", name_.c_str()); - root = name_; + VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", udev_.name.c_str()); + root = udev_.name; fmt = "\\%04d"; } else { - VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), name_.c_str()); + VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str()); } if (DeviceIoControl(h, IOCTL_GET_PIPE_CONFIGURATION, NULL, 0, &upc, sizeof(upc), &cbr, NULL)) { @@ -1018,6 +781,121 @@ usb_monitor::~usb_monitor() quit(); } +int usb_monitor::enum_usb_device(bool(__stdcall* found_usb)(LPUSBDEV dev, void* param), void* param, bool hub) +{ + GUID hid = hub ? GUID_DEVINTERFACE_USB_HUB : GUID_DEVINTERFACE_USB_DEVICE; + HDEVINFO dev_info = NULL; + int ind = 0; + SP_DEVICE_INTERFACE_DATA id = { 0 }; + SP_DEVINFO_DATA sdd = { 0 }; + + dev_info = SetupDiGetClassDevsW(&hid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (!dev_info) + return GetLastError(); + + id.cbSize = sizeof(id); + while (SetupDiEnumDeviceInterfaces(dev_info, NULL, &hid, ind++, &id)) + { + PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL; + DWORD size = 0; + + SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, 0, &size, NULL); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[size + 4]; + memset(buf, 0, (size + 4) * 2); + buf->cbSize = sizeof(*buf); + if (SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, buf->cbSize + size, NULL, NULL)) + { + USBDEV dev; + DWORD len = size; + + dev.name = u2utf8(buf->DevicePath); + usb_device::vid_pid_from_name(dev.name.c_str(), &dev.vid, &dev.pid); + sdd.cbSize = sizeof(sdd); + SetupDiEnumDeviceInfo(dev_info, ind - 1, &sdd); + if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DRIVER, NULL, (PBYTE)buf->DevicePath, len, &len)) // driver key + dev.driver_key = u2utf8(buf->DevicePath); + len = size; + if(SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DEVICEDESC, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description + dev.desc = u2utf8(buf->DevicePath); + len = size; + if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_ADDRESS, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description + dev.port = *(int*)buf->DevicePath; + if (!found_usb(&dev, param)) + { + delete[](char*)buf; + break; + } + } + delete[](char*)buf; + } + id.cbSize = sizeof(id); + } + SetupDiDestroyDeviceInfoList(dev_info); + + return ERROR_SUCCESS; +} +bool __stdcall usb_monitor::find_all_usb_devices(LPUSBDEV dev, void* param/*std::vector* */) +{ + std::vector* devs = (std::vector*)param; + + devs->push_back(*dev); + + return true; +} +bool __stdcall usb_monitor::usb_dev_by_name(LPUSBDEV dev, void* param/*LPUSBDEV*/) +{ + LPUSBDEV devt = (LPUSBDEV)param; + + if (stricmp(usb_device::name_without_guid(devt->name.c_str()).c_str(), usb_device::name_without_guid(dev->name.c_str()).c_str()) == 0) + { + devt->driver_key = dev->driver_key; + devt->desc = dev->desc; + devt->vid = dev->vid; + devt->pid = dev->pid; + devt->port = dev->port; + + return false; + } + + return true; +} +bool __stdcall usb_monitor::find_parent_hub(LPUSBDEV hub, void* param/*LPUSBDEV*/) +{ + LPUSBDEV t = (LPUSBDEV)param; + + if (t->driver_key.empty() || t->port == 0) + return false; + + HANDLE h = CreateFileA(hub->name.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + bool go = true; + char buf[512] = { 0 }; + DWORD bytes = 0; + + if (h == INVALID_HANDLE_VALUE) + return true; + + USB_NODE_CONNECTION_DRIVERKEY_NAME* name = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)buf; + name->ConnectionIndex = t->port; + name->ActualLength = (sizeof(buf) - sizeof(*name)) / 2 - 1; + if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, name, sizeof(*name), name, name->ActualLength, &bytes, NULL)) + { + if (u2utf8(name->DriverKeyName) == t->driver_key) + { + t->hub = hub->name; + go = false; + } + } + CloseHandle(h); + + return go; +} +bool usb_monitor::is_desired_usb_device(int vid, int pid) +{ + return vid == PRODUCT_VID || vid == PRODUCT_VENDOR_HG1; +} + LRESULT CALLBACK usb_monitor::monitor_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { usb_monitor* monitor = (usb_monitor*)GetPropW(hwnd, MONITOR_WINDOW_OWNER); @@ -1056,20 +934,15 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive) { std::lock_guard lock(lock_); int ev = arrive ? LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED : LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT; - DEVID id = dev->id(); - - if (id.vid != PRODUCT_VID && id.vid != PRODUCT_VENDOR_HG1) - return; - - VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "WINUSB %04X:%04X(%d) %s\r\n", dev->id().vid, dev->id().pid, dev->id().addr, - arrive ? "Connected" : "Left"); + std::string noguid(usb_device::name_without_guid(dev->name().c_str())); if (arrive) { bool found = false; for(size_t i = 0; i < devices_.size(); ++i) { - if (devices_[i]->id() == id) + // if (devices_[i]->name() == dev->name()) + if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0) { if (devices_[i]->is_online()) { @@ -1079,6 +952,8 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive) } else { + devices_[i]->clear(); + devices_[i]->dev() = dev->dev(); // use NEW connection info ... dev->release(); dev = devices_[i]; dev->add_ref(); @@ -1097,36 +972,25 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive) else { bool discard = false; + for (size_t i = 0; i < devices_.size(); ++i) { - if (devices_[i]->id().vid != id.vid || devices_[i]->id().pid != id.pid) - continue; - if (devices_[i]->reg_path().empty() || usb_device::usb_scan_name(devices_[i]->reg_path().c_str()).empty()) + // if (devices_[i]->name() == dev->name()) + if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0) { dev->release(); dev = devices_[i]; dev->add_ref(); - // if (dev->is_open()) + if (dev->is_online()) { - if (dev->is_online()) - { - dev->set_online(false); - discard = false; - break; - } - else - { - // VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str()); - // dev->release(); - // return; - discard = true; - } + dev->set_online(false); + discard = false; } - //else - //{ - // devices_.erase(devices_.begin() + i); - // dev->release(); - //} + else + { + discard = true; + } + break; } } if (discard) @@ -1153,67 +1017,54 @@ int usb_monitor::on_usb_pnp(WPARAM wp, LPARAM lp) return wp == DBT_DEVICEQUERYREMOVE; } + std::string utf8(u2utf8(dev->dbcc_name)); if (wp == DBT_DEVICEQUERYREMOVE) - return cur_dev_name_ != u2utf8(dev->dbcc_name); + return cur_dev_name_ != utf8; - VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, u2utf8(dev->dbcc_name).c_str()); + VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, utf8.c_str()); - usb_device* ud = new usb_device(u2utf8(dev->dbcc_name).c_str()); + int vid = 0, + pid = 0; + usb_device::vid_pid_from_name(utf8.c_str(), &vid, &pid); + if (!usb_monitor::is_desired_usb_device(vid, pid)) + return 0; + + USBDEV udev; + udev.name = utf8; + usb_monitor::enum_usb_device(&usb_monitor::usb_dev_by_name, &udev); + if (wp == DBT_DEVICEARRIVAL && udev.driver_key.empty()) + { + VLOG_MINI_1(LOG_LEVEL_FATAL, "Failed: driver key for '%s' is not found!\r\n", utf8.c_str()); + } + + usb_device* ud = new usb_device(udev); *ud = dev->dbcc_classguid; if (!PostThreadMessageW(handle_msg_id_, MSG_DEVICE_PNP, wp == DBT_DEVICEARRIVAL, (LPARAM)ud)) ud->release(); return ret; } -void usb_monitor::find_usb(std::vector& usb_devs) -{ - GUID hid = GUID_DEVINTERFACE_USB_DEVICE; // GUID_DEVINTERFACE_USB_HUB - HDEVINFO dev_info = NULL; - int ind = 0; - SP_DEVICE_INTERFACE_DATA id = { 0 }; - - // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed} - // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB - // UuidFromStringW((RPC_WSTR)WIN_USB_GUID, &hid); - - dev_info = SetupDiGetClassDevsW(&hid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (!dev_info) - return; - - id.cbSize = sizeof(id); - while (SetupDiEnumDeviceInterfaces(dev_info, NULL, &hid, ind++, &id)) - { - PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL; - DWORD size = 0; - - SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, 0, &size, NULL); - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[size + 4]; - memset(buf, 0, (size + 4) * 2); - buf->cbSize = sizeof(*buf); - if (SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, buf->cbSize + size, NULL, NULL)) - { - usb_devs.push_back(u2utf8(buf->DevicePath)); - } - delete[](char*)buf; - } - id.cbSize = sizeof(id); - } - SetupDiDestroyDeviceInfoList(dev_info); -} void usb_monitor::find_usb_and_trigger_event(void) { - std::vector old(found_usb_devs_); + std::vector old(found_usb_devs_); found_usb_devs_.clear(); - find_usb(found_usb_devs_); + usb_monitor::enum_usb_device(&usb_monitor::find_all_usb_devices, &found_usb_devs_); for (size_t i = 0; i < found_usb_devs_.size(); ++i) { - std::vector::iterator it = std::find(old.begin(), old.end(), found_usb_devs_[i]); + if (!usb_monitor::is_desired_usb_device(found_usb_devs_[i].vid, found_usb_devs_[i].pid)) + { + found_usb_devs_.erase(found_usb_devs_.begin() + i); + i--; + } + } + + for (size_t i = 0; i < found_usb_devs_.size(); ++i) + { + std::vector::iterator it = std::find(old.begin(), old.end(), found_usb_devs_[i]); if (it == old.end()) { - usb_device* dev = new usb_device(found_usb_devs_[i].c_str()); + usb_device* dev = new usb_device(found_usb_devs_[i]); notify_usb_event(dev, true); dev->release(); } @@ -1223,7 +1074,7 @@ void usb_monitor::find_usb_and_trigger_event(void) for (size_t i = 0; i < old.size(); ++i) { - usb_device* dev = new usb_device(old[i].c_str()); + usb_device* dev = new usb_device(old[i]); notify_usb_event(dev, false); dev->release(); } @@ -1276,13 +1127,8 @@ void usb_monitor::thread_run_device_event_wnd(void) DEV_BROADCAST_HDR dbh = { 0 }; HDEVNOTIFY notify = NULL; - find_usb(found_usb_devs_); - for (size_t i = 0; i < found_usb_devs_.size(); ++i) - { - usb_device* dev = new usb_device(found_usb_devs_[i].c_str()); - notify_usb_event(dev, true); - dev->release(); - } + // mannual triggered at beginning ... + find_usb_and_trigger_event(); dbh.dbch_size = sizeof(dbh); dbh.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE; @@ -1292,7 +1138,7 @@ void usb_monitor::thread_run_device_event_wnd(void) DEV_BROADCAST_DEVICEINTERFACE_A di = { 0 }; di.dbcc_size = (sizeof(di) + 3) / 4 * 4; di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &di.dbcc_classguid); + UuidFromStringA((RPC_CSTR)IMAGE_CLASS_GUID, &di.dbcc_classguid); notify = RegisterDeviceNotificationA(wnd_monitor_, &di, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "RegisterDeviceNotificationA = 0x%08x, error = %d. di.dbcc_size = %d\n", notify, GetLastError(), di.dbcc_size); if (!notify) @@ -1605,6 +1451,6 @@ uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device* device) if(!device) return 0; - return ((usb_device*)device)->port(); + return ((usb_device*)device)->address(); } diff --git a/device/win_usb/win_usb.h b/device/win_usb/win_usb.h index 06121ba..981a46d 100644 --- a/device/win_usb/win_usb.h +++ b/device/win_usb/win_usb.h @@ -15,25 +15,33 @@ // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f} -#define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F" +#define IMAGE_CLASS_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F" #define MONITOR_WINDOW_OWNER L"monitor_wnd_owner" -typedef struct _dev_id +typedef struct _usb_dev { - int vid; - int pid; - int addr; + // all members are in utf8 + std::string name; // \\?\usb#vid_0bda&pid_0129#20100201396000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed} + std::string driver_key; // {6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0016 + std::string desc; // USB Composite Device + std::string hub; // parent hub + int vid; + int pid; + int port; // port on the hub, also be ConnectionIndex + int addr; // connection address - struct _dev_id() + struct _usb_dev() { - memset(this, 0, sizeof(struct _dev_id)); + name = driver_key = desc = hub = ""; + vid = pid = port = 0; + addr = -1; } - bool operator==(const struct _dev_id& r) + bool operator==(const struct _usb_dev& r) { - return vid == r.vid && pid == r.pid && r.addr == addr; + return name == r.name; } -}DEVID; +}USBDEV, * LPUSBDEV; class ovl_cls// : public refer { @@ -83,12 +91,9 @@ class usb_device // consider as libusb_device { volatile long ref_; GUID guid_; - std::string name_; - std::string reg_key_; - DEVID id_; + USBDEV udev_; bool is_ok_; bool online_; - uint8_t port_; ovl_mgr ovl_mgr_; libusb_device_handle *handle_; // as file handle returned by CreateFile @@ -108,15 +113,12 @@ class usb_device // consider as libusb_device int set_timeout(HANDLE h); public: - usb_device(const char* name); + usb_device(const USBDEV& dev); - static DEVID vid_pid_from_name(const char* name); // device name like '\\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}' + static void vid_pid_from_name(const char* name, int *vid, int *pid); // device name like '\\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}' static DWORD from_hex_string(const char* hex_str); - static std::string driver_key_name(HANDLE file); - static std::string parent_hub_path_name(int vid, int pid, int *addr = NULL, std::string* reg_key = NULL); + static std::string name_without_guid(const char* name); static bool find_vid_pid_in_hub(const char* utf8_hub_path_name, int vid, int pid, int *addr/*if *addr is not -1 or NULL, search the device with vid:pid and set the address in addr if it was not null, or-else chekc the device at *addr is vid:pid or not*/, std::string* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); - static int get_device_address(const char* device_name, LPGUID lpguid); - static std::string usb_scan_name(DEVID id, const char* guid = HG_SCANNER_GUID); // return \\.\Usbscan1 ... static std::string usb_scan_name(const char* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); // return \\.\Usbscan1 ... long add_ref(void); @@ -126,25 +128,21 @@ protected: ~usb_device(); public: - bool operator==(const char* name); - bool operator==(const DEVID& id); - - usb_device& operator=(const DEVID& id); usb_device& operator=(const GUID& guid); std::string name(void); + USBDEV& dev(void); GUID guid(void); - DEVID id(void); bool is_ok(void); bool is_open(void); bool is_online(void); void set_online(bool online); uint8_t port(void); + uint8_t address(void); std::string reg_path(void); bool init(void); void clear(void); - void online_statu_changed(bool online); int get_descriptor(libusb_device_descriptor* desc); int get_config_descriptor(int index, libusb_config_descriptor** desc); int open(libusb_device_handle** dev_handle); @@ -178,14 +176,13 @@ class usb_monitor // consider as libusb_context HWND wnd_monitor_; std::string cur_dev_name_; volatile bool run_; - std::vector found_usb_devs_; + std::vector found_usb_devs_; static LRESULT CALLBACK monitor_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); static void register_monitor_wnd(const wchar_t* cls); void notify_usb_event(usb_device*& dev, bool arrive); int on_usb_pnp(WPARAM wp, LPARAM lp); - void find_usb(std::vector& usb_devs); void find_usb_and_trigger_event(void); public: @@ -195,6 +192,12 @@ public: static usb_monitor* usb_monitor_; static UINT find_usb_timer_; // set when RegisterDeviceNotification failed + static int enum_usb_device(bool(__stdcall* found_usb)(LPUSBDEV dev, void* param), void* param, bool hub = false); + static bool __stdcall find_all_usb_devices(LPUSBDEV dev, void* param/*std::vector* */); + static bool __stdcall usb_dev_by_name(LPUSBDEV dev, void* param/*LPUSBDEV*/); + static bool __stdcall find_parent_hub(LPUSBDEV hub, void* param/*LPUSBDEV*/); + static bool is_desired_usb_device(int vid, int pid); + public: usb_callback* reg_callback(libusb_hotplug_callback_fn cb, void* param); void unreg_callback(usb_callback* cb); From 369e88e0eda7d934fe9752856eb2dec0e7b5609c Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Mon, 24 Oct 2022 16:58:09 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E6=8A=98=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/s2t_api.h | 1 + sane/scanner.cpp | 2 ++ sane/scanner.h | 1 + twain/twain/huagaods.cpp | 5 ++++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sane/s2t_api.h b/sane/s2t_api.h index c304b07..9aae19d 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -245,6 +245,7 @@ struct __declspec(novtable) ISaneInvoker : public IRef SANE_OPTION_ID_API(search_hole_range_t); // 绌垮瓟鎼滅储鑼冨洿 - 涓 SANE_OPTION_ID_API(is_erase_hole_b); // 绌垮瓟绉婚櫎 - 涓 SANE_OPTION_ID_API(search_hole_range_b); // 绌垮瓟鎼滅储鑼冨洿 - 涓 + SANE_OPTION_ID_API(fold_direction); // 瀵规姌妯″紡 // SANE-ex option ID: SANE_OPTION_ID_API_EX(multiout_type); // int diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 8479e52..d3c4534 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -877,6 +877,7 @@ int scanner::init_options_id(void) else SET_OPT_ID(search_hole_range_t, SEARCH_HOLE_RANGE_T, extension_none) else SET_OPT_ID(is_erase_hole_b, RID_HOLE_B, extension_none) else SET_OPT_ID(search_hole_range_b, SEARCH_HOLE_RANGE_B, extension_none) + else SET_OPT_ID(fold_direction, FOLD_TYPE, extension_none) op_id++; } @@ -2560,6 +2561,7 @@ SANE_OPTION_ID_IMPLEMENT(is_erase_hole_t) SANE_OPTION_ID_IMPLEMENT(search_hole_range_t) SANE_OPTION_ID_IMPLEMENT(is_erase_hole_b) SANE_OPTION_ID_IMPLEMENT(search_hole_range_b) +SANE_OPTION_ID_IMPLEMENT(fold_direction) // SANE-ex option ID: SANE_OPTION_ID_IMPLEMENT(ex_multiout_type) diff --git a/sane/scanner.h b/sane/scanner.h index 092bc57..4262370 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -292,6 +292,7 @@ public: SANE_OPTION_ID(search_hole_range_t); // 绌垮瓟鎼滅储鑼冨洿 - 涓 SANE_OPTION_ID(is_erase_hole_b); // 绌垮瓟绉婚櫎 - 涓 SANE_OPTION_ID(search_hole_range_b); // 绌垮瓟鎼滅储鑼冨洿 - 涓 + SANE_OPTION_ID(fold_direction); // 瀵规姌妯″紡 // SANE-ex option ID: SANE_OPTION_ID(ex_multiout_type); // int diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index 022ac2e..7f7962c 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -138,7 +138,9 @@ enum CapTypeEx : unsigned short { CAP_EX_SANE_is_erase_hole_t, CAP_EX_SANE_search_hole_range_t, CAP_EX_SANE_is_erase_hole_b, - CAP_EX_SANE_search_hole_range_b, // END for SANE设备层原始设置项透传属性 + CAP_EX_SANE_search_hole_range_b, + CAP_EX_SANE_fold_direction, + // END for SANE设备层原始设置项透传属性 ///////////////////////////////////////////////////////////////////////// }; enum // .twain/first.cfg: [twain-app] flow=0 @@ -2842,6 +2844,7 @@ void huagao_ds::init_support_caps_ex(void) ADD_SANE_CAP(search_hole_range_t); // 穿孔搜索范围 - 上 ADD_SANE_CAP(is_erase_hole_b); // 穿孔移除 - 下 ADD_SANE_CAP(search_hole_range_b); // 穿孔搜索范围 - 下 + ADD_SANE_CAP(fold_direction); // 对折方向 } std::wstring huagao_ds::get_config_file(void) { From 942c8f8748dbada13a7f5442052b49d338c30b16 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Mon, 24 Oct 2022 17:32:30 +0800 Subject: [PATCH 09/12] rebuild v4.33 --- device/scanner.rc | 8 ++++---- sane/sane.rc | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/device/scanner.rc b/device/scanner.rc index 1044de6..cad428b 100644 --- a/device/scanner.rc +++ b/device/scanner.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,33,10000,22295 - PRODUCTVERSION 4,33,10000,22295 + FILEVERSION 4,33,10000,22297 + PRODUCTVERSION 4,33,10000,22297 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "宁波华高信息科技有限公司" VALUE "FileDescription", "华高扫描仪应用程序" - VALUE "FileVersion", "4.33.10000.22295" + VALUE "FileVersion", "4.33.10000.22297" VALUE "InternalName", "scanner.dll" VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022" VALUE "OriginalFilename", "scanner.dll" VALUE "ProductName", "HUAGOScan" - VALUE "ProductVersion", "4.33.10000.22295" + VALUE "ProductVersion", "4.33.10000.22297" END END BLOCK "VarFileInfo" diff --git a/sane/sane.rc b/sane/sane.rc index 2a17800..64436e9 100644 --- a/sane/sane.rc +++ b/sane/sane.rc @@ -271,8 +271,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,33,10000,22295 - PRODUCTVERSION 4,33,10000,22295 + FILEVERSION 4,33,10000,22297 + PRODUCTVERSION 4,33,10000,22297 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -289,12 +289,12 @@ BEGIN BEGIN VALUE "CompanyName", "宁波华高信息科技有限公司" VALUE "FileDescription", "华高扫描仪应用程序" - VALUE "FileVersion", "4.33.10000.22295" + VALUE "FileVersion", "4.33.10000.22297" VALUE "InternalName", "sane.dll" VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022" VALUE "OriginalFilename", "sane.dll" VALUE "ProductName", "HUAGOScan" - VALUE "ProductVersion", "4.33.10000.22295" + VALUE "ProductVersion", "4.33.10000.22297" END END BLOCK "VarFileInfo" From 93ad04eb6a75ae4183ed883a0e607a6212173952 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Tue, 25 Oct 2022 16:41:09 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E8=B0=83=E6=95=B4JSON=EF=BC=8C=E4=B8=BA?= =?UTF-8?q?=E7=BB=9F=E4=B8=80APP=E9=85=8D=E7=BD=AE=E5=81=9A=E5=87=86?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/DlgPage.cpp | 10 +-- sane/DlgPage.h | 4 +- sane/DlgSetting.cpp | 4 +- sane/DlgSetting.h | 6 +- sane/gb_json.cpp | 161 +++++++++++++++++++++++++++----------------- sane/gb_json.h | 35 ++++++++-- sane/scanner.cpp | 9 ++- sane/scanner.h | 4 +- 8 files changed, 149 insertions(+), 84 deletions(-) diff --git a/sane/DlgPage.cpp b/sane/DlgPage.cpp index acf2e9f..6294c4a 100644 --- a/sane/DlgPage.cpp +++ b/sane/DlgPage.cpp @@ -158,9 +158,9 @@ void dlg_base::notify_ui_event(int ev) if (ui_event_notify_) ui_event_notify_(ev, this, ui_notify_param_); } -gb::sane_config* dlg_base::get_config(void) +gb::sane_config_schm* dlg_base::get_config(void) { - gb::sane_config* cfg = NULL; + gb::sane_config_schm* cfg = NULL; SendMessage(parent_, WM_GET_CONFIG_OBJ, 0, (LPARAM)&cfg); @@ -796,7 +796,7 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) { SANE_Fixed val = SANE_FIX(dlg.x_in_mm()); SANE_Int after = 0; - gb::sane_config* cfg = get_config(); + gb::sane_config_schm* cfg = get_config(); sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_SET_VALUE, &val, &after); if (cfg) @@ -833,7 +833,7 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) dlg.get_gamma(&gamma); sane_.sane_io_control_api(dev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &len); - gb::sane_config* cfg = get_config(); + gb::sane_config_schm* cfg = get_config(); if (cfg) cfg->config_changed(id_custom_gamma_, (char*)&gamma, sizeof(gamma), true); } @@ -1077,7 +1077,7 @@ void dlg_page::control_action(HWND wnd) { SANE_Int after = 0; SANE_Status statu = sane_.sane_control_option_api(dev_, id - dlg_page::dyn_id_base, SANE_ACTION_SET_VALUE, val, &after); - gb::sane_config* cfg = get_config(); + gb::sane_config_schm* cfg = get_config(); done_ = false; if (cfg) { diff --git a/sane/DlgPage.h b/sane/DlgPage.h index dea3b04..306ea50 100644 --- a/sane/DlgPage.h +++ b/sane/DlgPage.h @@ -22,7 +22,7 @@ extern HMODULE g_my_inst; namespace gb { - class sane_config; + class sane_config_schm; } class dlg_base @@ -41,7 +41,7 @@ protected: virtual void on_font_changed(void); void create(void); void notify_ui_event(int ev); - gb::sane_config* get_config(void); + gb::sane_config_schm* get_config(void); public: dlg_base(HWND parent, UINT idd); diff --git a/sane/DlgSetting.cpp b/sane/DlgSetting.cpp index 22403aa..ab8183e 100644 --- a/sane/DlgSetting.cpp +++ b/sane/DlgSetting.cpp @@ -58,7 +58,7 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) refresh_controls((int)wp); break; case WM_GET_CONFIG_OBJ: - *((gb::sane_config**)lp) = cfg_; + *((gb::sane_config_schm**)lp) = cfg_; break; default: ret = FALSE; @@ -351,7 +351,7 @@ void dlg_setting::refresh_controls(int src_sn) } } -void dlg_setting::set_config(gb::sane_config* cfg, const wchar_t* file) +void dlg_setting::set_config(gb::sane_config_schm* cfg, const wchar_t* file) { cfg_ = cfg; cfg_file_ = file; diff --git a/sane/DlgSetting.h b/sane/DlgSetting.h index d81fc79..efc005f 100644 --- a/sane/DlgSetting.h +++ b/sane/DlgSetting.h @@ -17,7 +17,7 @@ namespace gb { - class sane_config; + class sane_config_schm; } class dlg_setting : public dlg_base { @@ -29,7 +29,7 @@ class dlg_setting : public dlg_base bool err_; int id_help_; int id_restore_; - gb::sane_config* cfg_; + gb::sane_config_schm* cfg_; std::wstring cfg_file_; HWND tab_; @@ -55,7 +55,7 @@ public: ~dlg_setting(); public: - void set_config(gb::sane_config* cfg, const wchar_t* file); + void set_config(gb::sane_config_schm* cfg, const wchar_t* file); HWND window(void); HWND parent(void); //void show(void); diff --git a/sane/gb_json.cpp b/sane/gb_json.cpp index 28da594..cf1d576 100644 --- a/sane/gb_json.cpp +++ b/sane/gb_json.cpp @@ -31,6 +31,34 @@ namespace gb return ret; } + refer::refer() : ref_(1) + {} + refer::~refer() + {} + + long refer::add_ref(void) + { +#if defined(WIN32) || defined(_WIN64) + return InterlockedIncrement(&ref_); +#else + return ++ref_; +#endif + } + long refer::release(void) + { +#if defined(WIN32) || defined(_WIN64) + long ref = InterlockedDecrement(&ref_); +#else + long ref = --ref_; +#endif + + if (ref == 0) + delete this; + + return ref; + } + + json::json(char* json_txt) : obj_(0), cur_child_(0), is_array_(false) { memset(&walk_head_, 0, sizeof(walk_head_)); @@ -325,7 +353,7 @@ namespace gb val = new json(); if (!val->attach_cjson(obj)) { - delete val; + val->release(); return false; } @@ -831,19 +859,19 @@ namespace gb namespace gb { - std::string sane_config::opt_data_appendix_("_data"); + std::string sane_config_schm::opt_data_appendix_("_data"); - sane_config::sane_config() : jsn_(NULL), bkp_(NULL), in_setting_(false) + sane_config_schm::sane_config_schm() : jsn_(NULL), bkp_(NULL), in_setting_(false), scheme_name_("") { def_val_ = new gb::json(); } - sane_config::~sane_config() + sane_config_schm::~sane_config_schm() { clear(); - delete def_val_; + def_val_->release(); } - bool sane_config::hex(unsigned char ch, unsigned char* val) + bool sane_config_schm::hex(unsigned char ch, unsigned char* val) { bool ret = true; @@ -864,15 +892,15 @@ namespace gb return ret; } - bool sane_config::hex_char(const char* data, unsigned char* val) + bool sane_config_schm::hex_char(const char* data, unsigned char* val) { unsigned char v = 0; bool ret = false; - if (sane_config::hex(*data++, &v)) + if (sane_config_schm::hex(*data++, &v)) { v <<= 4; - if (sane_config::hex(*data++, &v)) + if (sane_config_schm::hex(*data++, &v)) { if (val) *val = v; @@ -883,13 +911,13 @@ namespace gb return ret; } - bool sane_config::is_option_data(std::string& name) + bool sane_config_schm::is_option_data(std::string& name) { - size_t pos = name.find(sane_config::opt_data_appendix_); + size_t pos = name.find(sane_config_schm::opt_data_appendix_); if (pos != std::string::npos) { - if (pos + sane_config::opt_data_appendix_.length() == name.length()) + if (pos + sane_config_schm::opt_data_appendix_.length() == name.length()) { name.erase(pos); @@ -900,17 +928,17 @@ namespace gb return false; } - void sane_config::clear() + void sane_config_schm::clear() { if (jsn_) - delete jsn_; + jsn_->release(); jsn_ = NULL; if (bkp_) - delete bkp_; + bkp_->release(); bkp_ = NULL; file_ = L""; } - std::string sane_config::to_hex_letter(const char* data, size_t bytes) + std::string sane_config_schm::to_hex_letter(const char* data, size_t bytes) { std::string hex(""); const unsigned char* ptr = (const unsigned char*)data; @@ -924,7 +952,7 @@ namespace gb return hex; } - std::string sane_config::from_hex_letter(const char* data, size_t bytes) + std::string sane_config_schm::from_hex_letter(const char* data, size_t bytes) { std::string stream(""); @@ -932,7 +960,7 @@ namespace gb for (size_t i = 0; i < bytes; ++i) { unsigned char ch = 0; - if (!sane_config::hex_char(data, &ch)) + if (!sane_config_schm::hex_char(data, &ch)) break; stream.append(1, ch); data += 2; @@ -940,7 +968,7 @@ namespace gb return stream; } - std::string sane_config::default_value(const char* hex_title) + std::string sane_config_schm::default_value(const char* hex_title) { std::string val(""); @@ -949,7 +977,7 @@ namespace gb return val; } - bool sane_config::load_from_file(const wchar_t* file) + bool sane_config_schm::load_from_file(const wchar_t* file) { clear(); @@ -975,7 +1003,7 @@ namespace gb return ret; } - bool sane_config::load_from_mem(const char* mem) + bool sane_config_schm::load_from_mem(const char* mem) { gb::base64 b64; std::string stream(b64.decode(mem, lstrlenA(mem))); @@ -984,7 +1012,7 @@ namespace gb jsn_ = new gb::json(); if (!jsn_->attach_text(&stream[0])) { - delete jsn_; + jsn_->release(); jsn_ = NULL; return false; @@ -992,7 +1020,7 @@ namespace gb return true; } - bool sane_config::save_to(const wchar_t* file) + bool sane_config_schm::save_to(const wchar_t* file) { bool ret = false; std::string encode(to_text_stream()); @@ -1014,43 +1042,43 @@ namespace gb return ret; } - void sane_config::set_default_value(int sn, const char* name, const char* val, size_t bytes) + void sane_config_schm::set_default_value(int sn, const char* name, const char* val, size_t bytes) { id_name_[sn] = name; def_val_->set_value(name, to_hex_letter(val, bytes).c_str()); } - bool sane_config::first_config(std::string& name, std::string& val) + bool sane_config_schm::first_config(std::string& name, std::string& val) { bool ret = false; std::string raw_v(""); if (jsn_ && jsn_->first_child(raw_v, &name)) { - val = sane_config::from_hex_letter(raw_v.c_str(), raw_v.length()); + val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); ret = true; } return ret; } - bool sane_config::next_config(std::string& name, std::string& val) + bool sane_config_schm::next_config(std::string& name, std::string& val) { bool ret = false; std::string raw_v(""); if (jsn_ && jsn_->next_child(raw_v, &name)) { - val = sane_config::from_hex_letter(raw_v.c_str(), raw_v.length()); + val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); ret = true; } return ret; } - void sane_config::begin_setting(bool restore) + void sane_config_schm::begin_setting(bool restore) { if (bkp_) - delete bkp_; + bkp_->release(); bkp_ = jsn_; in_setting_ = true; jsn_ = new gb::json(); @@ -1061,7 +1089,7 @@ namespace gb jsn_->attach_text(&stream[0]); } } - void sane_config::config_changed(const char* name, const char* val, size_t bytes) + void sane_config_schm::config_changed(const char* name, const char* val, size_t bytes, bool extra) { std::string hex_v(to_hex_letter(val, bytes)), def(default_value(name)); @@ -1070,58 +1098,57 @@ namespace gb jsn_->remove(name); else jsn_->set_value(name, hex_v.c_str()); + + if (extra) + { + jsn_->set_value((name + sane_config_schm::opt_data_appendix_).c_str(), hex_v.c_str()); + } + else + { + def = default_value(name); + if (hex_v == def) + { + jsn_->remove(name); + jsn_->remove((name + sane_config_schm::opt_data_appendix_).c_str()); + } + else + jsn_->set_value(name, hex_v.c_str()); + } } - void sane_config::config_changed(int sn, const char* val, size_t bytes, bool extra) + void sane_config_schm::config_changed(int sn, const char* val, size_t bytes, bool extra) { - std::string name(""), - hex_v(to_hex_letter(val, bytes)), - def(""); + std::string name(""); if (id_name_.count(sn)) { name = id_name_[sn]; - if (extra) - { - name += sane_config::opt_data_appendix_; - jsn_->set_value(name.c_str(), hex_v.c_str()); - } - else - { - def = default_value(name.c_str()); - if (hex_v == def) - { - jsn_->remove(name.c_str()); - jsn_->remove((name + sane_config::opt_data_appendix_).c_str()); - } - else - jsn_->set_value(name.c_str(), hex_v.c_str()); - } + config_changed(name.c_str(), val, bytes, extra); } } - void sane_config::remove_config(const char* name) + void sane_config_schm::remove_config(const char* name) { if (jsn_) jsn_->remove(name); } - void sane_config::end_setting(bool cancel) + void sane_config_schm::end_setting(bool cancel) { if (in_setting_) { if (cancel) { - delete jsn_; + jsn_->release(); jsn_ = bkp_; bkp_ = NULL; } else if (bkp_) { - delete bkp_; + bkp_->release(); bkp_ = NULL; } } in_setting_ = false; } - int sane_config::id_from_name(const char* name) + int sane_config_schm::id_from_name(const char* name) { for (const auto& v : id_name_) { @@ -1131,7 +1158,7 @@ namespace gb return -1; } - std::string sane_config::to_text_stream(void) + std::string sane_config_schm::to_text_stream(void) { if (jsn_) { @@ -1151,7 +1178,7 @@ namespace gb else return ""; } - std::string sane_config::get_version(void) + std::string sane_config_schm::get_version(void) { std::string ver(""); @@ -1160,7 +1187,15 @@ namespace gb return ver; } - void sane_config::update(bool(__stdcall* is_float)(int, void*), void* param, const char* (__stdcall* t2n)(const char*), std::string* discard) + std::string sane_config_schm::get_scheme_name(void) + { + return scheme_name_; + } + void sane_config_schm::set_scheme_name(const char* name) + { + scheme_name_ = name ? name : ""; + } + void sane_config_schm::update(bool(__stdcall* is_float)(int, void*), void* param, const char* (__stdcall* t2n)(const char*), std::string* discard) { if (!jsn_) return; @@ -1184,7 +1219,7 @@ namespace gb changed = true; do { - jsn_->change_key(name.c_str(), t2n(sane_config::from_hex_letter(name.c_str(), name.length()).c_str())); + jsn_->change_key(name.c_str(), t2n(sane_config_schm::from_hex_letter(name.c_str(), name.length()).c_str())); } while (jsn_->next_child(val, &name)); } } @@ -1213,4 +1248,10 @@ namespace gb if (changed) save_to(NULL); } + + + + + /////////////////////////////////////////////////////////////////////////////////// + // scanner_cfg } diff --git a/sane/gb_json.h b/sane/gb_json.h index 4a24ef1..be55419 100644 --- a/sane/gb_json.h +++ b/sane/gb_json.h @@ -12,7 +12,21 @@ namespace gb { - class json + class refer + { + volatile long ref_; + + protected: + refer(); + virtual ~refer(); + + public: + long add_ref(void); + long release(void); + }; + + + class json : public refer { cJSON *obj_; cJSON *cur_child_; @@ -23,9 +37,11 @@ namespace gb cJSON* find_child(cJSON *parent, std::vector& path, bool create, cJSON*** addr = NULL); cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL); + protected: + ~json(); + public: json(char* json_txt = 0); - ~json(); static std::string to_string(cJSON* root, bool formatted); static std::string get_value_as_string(cJSON* root, bool integer = false); @@ -82,23 +98,26 @@ namespace gb std::string decode(const char* data, size_t bytes); }; - class sane_config + class sane_config_schm : public refer { + std::string scheme_name_; std::wstring file_; json* jsn_; json* bkp_; json* def_val_; bool in_setting_; - std::map id_name_; + std::map id_name_; // (id, default-val) void clear(); std::string to_hex_letter(const char* data, size_t bytes); std::string from_hex_letter(const char* data, size_t bytes); std::string default_value(const char* name); + protected: + ~sane_config_schm(); + public: - sane_config(); - ~sane_config(); + sane_config_schm(); static std::string opt_data_appendix_; static bool hex(unsigned char ch, unsigned char* val); @@ -113,13 +132,15 @@ namespace gb bool first_config(std::string& name, std::string& val); bool next_config(std::string& name, std::string& val); void begin_setting(bool restore = false); - void config_changed(const char* name, const char* val, size_t bytes); + void config_changed(const char* name, const char* val, size_t bytes, bool extra = false); void config_changed(int sn, const char* val, size_t bytes, bool extra = false); void remove_config(const char* name); void end_setting(bool cancel); int id_from_name(const char* name); std::string to_text_stream(void); std::string get_version(void); + std::string get_scheme_name(void); + void set_scheme_name(const char* name); void update(bool(__stdcall* is_float)(int, void*), void* param, const char*(__stdcall* t2n)(const char*), std::string* discard = NULL); }; } diff --git a/sane/scanner.cpp b/sane/scanner.cpp index d3c4534..0f6b2aa 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -323,7 +323,7 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS , scanner_name_(L""), cfg_(NULL), is_ui_wait_img_(false), is_scanning_(false) , scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL) { - cfg_ = new gb::sane_config(); + cfg_ = new gb::sane_config_schm(); tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str()); { char* tmp = getenv("LOCALAPPDATA"); @@ -350,7 +350,10 @@ scanner::~scanner() { close(); if (cfg_) - delete cfg_; + { + cfg_->release(); + cfg_ = NULL; + } } bool scanner::is_belong_serial(int vid, int pid, SCANNERID serial) @@ -574,7 +577,7 @@ void scanner::apply_config(void) int id = cfg_->id_from_name(n.c_str()); if (id == -1) { - if (gb::sane_config::is_option_data(n)) + if (gb::sane_config_schm::is_option_data(n)) { id = cfg_->id_from_name(n.c_str()); if (id == is_custom_gamma_id_) diff --git a/sane/scanner.h b/sane/scanner.h index 4262370..6ef08ca 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -26,7 +26,7 @@ class dlg_indicator; class dlg_setting; namespace gb { - class sane_config; + class sane_config_schm; } class scanner : public ISaneInvoker, virtual public refer @@ -51,7 +51,7 @@ class scanner : public ISaneInvoker, virtual public refer SANE_FinalImgFormat img_fmt_; std::unique_ptr indicator_; std::unique_ptr setting_; - gb::sane_config* cfg_; + gb::sane_config_schm* cfg_; int(__stdcall* scanner_ev_handler_)(int, void*); void* evh_param_; From 6c350e3b0507dcda9668ff55bccb45fbe6e448c1 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 26 Oct 2022 14:41:18 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9JSON=E4=BB=A5=E5=85=BC?= =?UTF-8?q?=E5=AE=B9APP=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/gb_json.cpp | 562 +++++++++++++++++++++++++++++++++++++++++++---- sane/gb_json.h | 91 +++++++- sane/scanner.cpp | 4 +- 3 files changed, 609 insertions(+), 48 deletions(-) diff --git a/sane/gb_json.cpp b/sane/gb_json.cpp index cf1d576..428b8b0 100644 --- a/sane/gb_json.cpp +++ b/sane/gb_json.cpp @@ -30,6 +30,29 @@ namespace gb return ret; } + static int load_mini_file(const char* file, std::string& cont) + { + FILE* src = fopen(file, "rb"); + if (src) + { + size_t size = 0; + char *buf = NULL; + + fseek(src, 0, SEEK_END); + size = ftell(src); + fseek(src, 0, SEEK_SET); + buf = new char[size + 4]; + memset(buf, 0, size + 4); + fread(buf, 1, size, src); + fclose(src); + cont = std::string(buf, size); + delete[] buf; + + return 0; + } + else + return errno; + } refer::refer() : ref_(1) {} @@ -856,19 +879,209 @@ namespace gb } } +namespace updater +{ + static std::string hg_model_from_pid(const char* pid) + { + if (strcmp(pid, "7823") == 0) + return "G200"; + char m[] = { 'G', pid[0], '0', '0', 0}; + + return std::string(m) + " - " + pid; + } + static std::string hv_model_from_pid(const char* pid) + { + std::string m(""); + if (strcmp(pid, "1000") == 0) + m = "HW-1000NS"; + else if (strcmp(pid, "1002") == 0) + m = "HW-1000"; + else if (strcmp(pid, "7000") == 0) + m = "HW-7000NS"; + else if (strcmp(pid, "7002") == 0) + m = "HW-7000"; + else if (strcmp(pid, "7039") == 0) + m = "HW-7000NS"; + else + m = std::string("HW-") + pid; + + return m + " - " + pid; + } + static std::string lsc_model_from_pid(const char* pid) + { + if (strcmp(pid, "8200") == 0) + return "G42S - 8200"; + else + { + char m[] = {'G', pid[1], pid[2], 'S', 0}; + + return std::string(m) + " - " + pid; + } + } + static std::string scanner_chinese_name_2_model(const char* cn) + { + static const char* hg = "\345\215\216\351\253\230", + * hw = "\346\261\211\347\216\213", + * lsc = "\347\253\213\346\200\235\350\276\260", + * smy = "\346\211\253\346\217\217\344\273\252\342\200\224G", + * f = strstr(cn, hg); + std::string model(""); + std::string(* model_from_pid)(const char* pid) = nullptr; + + if (f == cn) + { + model = "HUAGOSCAN "; + model_from_pid = hg_model_from_pid;; + } + else if (strstr(cn, hw) == cn) + { + model = "Hanvon "; + model_from_pid = hv_model_from_pid;; + } + else if (strstr(cn, lsc) == cn) + { + model = "LANXUMSCAN "; + model_from_pid = lsc_model_from_pid;; + } + else + return ""; + + f = strstr(cn, smy); + if (!f) + return ""; + + f += strlen(smy); + model += model_from_pid(f); + + return model; + } + static int update_app_config(const char* scanner_name, const char* jsn_txt, const char* path, gb::scanner_cfg::LPUDF lpfunc) + { + std::string scanner(""), jsn_str(jsn_txt); + std::vector efiles; + + if ((unsigned char)scanner_name[0] > 0x7f) + scanner = scanner_chinese_name_2_model(scanner_name); + else + scanner = scanner_name; + + gb::json* jsn = new gb::json(); + int cur_sel = -1, ret = 0; + gb::scanner_cfg* cfg = nullptr; + if (!jsn->attach_text(&jsn_str[0])) + { + jsn->release(); + return EINVAL; + } + + if (jsn->first_child(jsn_str)) + { + gb::json* child = new gb::json(); + if (child->attach_text(&jsn_str[0])) + { + if (!child->get_value("cur_sel", cur_sel)) + ret = EINVAL; + } + if (ret == 0) + { + cfg = new gb::scanner_cfg(); + int ind = 0; + while (jsn->next_child(jsn_str)) + { + if (!child->attach_text(&jsn_str[0])) + { + ret = EINVAL; + break; + } + + std::string schm_name(""); + if (!child->get_value("scheme", schm_name)) + { + ret = EINVAL; + break; + } + + gb::json* items = nullptr; + if (!child->get_value("opts", items) || !items) + { + ret = EINVAL; + break; + } + + gb::sane_config_schm* schm = new gb::sane_config_schm(); + if (items->first_child(jsn_str)) + { + do + { + std::string name(""), val(""); + gb::json* item = new gb::json(); + if (item->attach_text(&jsn_str[0])) + { + if (item->get_value("name", name) && item->get_value("value", val)) + { + name = lpfunc->title2name(name.c_str(), lpfunc->func_param); + lpfunc->trans_number(name.c_str(), val, lpfunc->func_param); + schm->set_value(name.c_str(), val.c_str(), val.length()); + + val = ""; + item->get_value("extra", val); + if (val.length() && gb::load_mini_file(val.c_str(), val) == 0) + { + schm->set_value(name.c_str(), val.c_str(), val.length(), true); + item->get_value("extra", val); + efiles.push_back(val); + } + } + } + item->release(); + } while (items->next_child(jsn_str)); + } + items->release(); + + cfg->add_scheme(schm, schm_name.c_str()); + schm->release(); + if (ind++ == cur_sel) + cfg->select_scheme(schm_name.c_str()); + } + } + child->release(); + } + jsn->release(); + if (cfg) + { + if (ret == 0) + { + cfg->save((path + scanner + ".cfg").c_str()); + for (auto& v : efiles) + rename(v.c_str(), (v + "_bk").c_str()); + } + cfg->release(); + } + + return ret; + } +} namespace gb { std::string sane_config_schm::opt_data_appendix_("_data"); - sane_config_schm::sane_config_schm() : jsn_(NULL), bkp_(NULL), in_setting_(false), scheme_name_("") + sane_config_schm::sane_config_schm(scanner_cfg* scanner) : jsn_(NULL), bkp_(NULL), in_setting_(false), scheme_name_("") + , scanner_(scanner) { + char empty[8] = { "{}" }; + jsn_ = new gb::json(); + jsn_->attach_text(empty); def_val_ = new gb::json(); + if (scanner_) + scanner_->add_ref(); } sane_config_schm::~sane_config_schm() { clear(); def_val_->release(); + if (scanner_) + scanner_->release(); } bool sane_config_schm::hex(unsigned char ch, unsigned char* val) @@ -936,7 +1149,7 @@ namespace gb if (bkp_) bkp_->release(); bkp_ = NULL; - file_ = L""; + // file_ = ""; } std::string sane_config_schm::to_hex_letter(const char* data, size_t bytes) { @@ -977,36 +1190,22 @@ namespace gb return val; } - bool sane_config_schm::load_from_file(const wchar_t* file) + bool sane_config_schm::load_from_file(const char* file) { clear(); - bool ret = false; - FILE* src = _wfopen(file, L"rb"); - if (src) - { - size_t size = 0; - char* buf = NULL; - gb::base64 b64; + std::string cont(""); - fseek(src, 0, SEEK_END); - size = ftell(src); - fseek(src, 0, SEEK_SET); - buf = new char[size + 4]; - memset(buf, 0, size + 4); - fread(buf, 1, size, src); - fclose(src); - ret = load_from_mem(buf); - delete[] buf; - } file_ = file; + if (gb::load_mini_file(file, cont)) + return false; - return ret; + return load_from_mem(cont.c_str()); } - bool sane_config_schm::load_from_mem(const char* mem) + bool sane_config_schm::load_from_mem(const char* mem, bool in_b64) { gb::base64 b64; - std::string stream(b64.decode(mem, lstrlenA(mem))); + std::string stream(in_b64 ? b64.decode(mem, lstrlenA(mem)) : mem); clear(); jsn_ = new gb::json(); @@ -1020,7 +1219,7 @@ namespace gb return true; } - bool sane_config_schm::save_to(const wchar_t* file) + bool sane_config_schm::save_to(const char* file) { bool ret = false; std::string encode(to_text_stream()); @@ -1030,7 +1229,7 @@ namespace gb if (encode.length()) { - FILE* dst = _wfopen(file, L"wb"); + FILE* dst = fopen(file, "wb"); if (dst) { @@ -1091,13 +1290,7 @@ namespace gb } void sane_config_schm::config_changed(const char* name, const char* val, size_t bytes, bool extra) { - std::string hex_v(to_hex_letter(val, bytes)), - def(default_value(name)); - - if (hex_v == def) - jsn_->remove(name); - else - jsn_->set_value(name, hex_v.c_str()); + std::string hex_v(to_hex_letter(val, bytes)); if (extra) { @@ -1105,7 +1298,7 @@ namespace gb } else { - def = default_value(name); + std::string def = default_value(name); if (hex_v == def) { jsn_->remove(name); @@ -1130,6 +1323,15 @@ namespace gb if (jsn_) jsn_->remove(name); } + void sane_config_schm::set_value(const char* name, const char* val, size_t bytes, bool extra) + { + std::string hex_v(to_hex_letter(val, bytes)); + + if (extra) + jsn_->set_value((name + sane_config_schm::opt_data_appendix_).c_str(), hex_v.c_str()); + else + jsn_->set_value(name, hex_v.c_str()); + } void sane_config_schm::end_setting(bool cancel) { if (in_setting_) @@ -1158,22 +1360,26 @@ namespace gb return -1; } - std::string sane_config_schm::to_text_stream(void) + std::string sane_config_schm::to_text_stream(bool b64, bool with_ver) { if (jsn_) { + if(with_ver) { char ver[40] = { 0 }; sprintf_s(ver, "%u.%u", VERSION_MAIN, VERSION_SUB); jsn_->set_value("ver", ver); } - std::string cont(jsn_->to_string(false)), encode(""); - gb::base64 b64; + std::string cont(jsn_->to_string(false)); + if (b64) + { + gb::base64 b64; - encode = b64.encode(cont.c_str(), cont.length()); + cont = b64.encode(cont.c_str(), cont.length()); + } - return encode; + return cont; } else return ""; @@ -1254,4 +1460,284 @@ namespace gb /////////////////////////////////////////////////////////////////////////////////// // scanner_cfg + std::string scanner_cfg::global_name_ = "global"; + std::string scanner_cfg::cur_sel_ = "cur"; + std::string scanner_cfg::default_setting_name_ = "\351\273\230\350\256\244\350\256\276\347\275\256"; // utf-8: 榛樿璁剧疆 + + scanner_cfg::scanner_cfg() : path_(""), scanner_name_(""), global_(new json()) + { + init_version(); + init_select(); + } + scanner_cfg::~scanner_cfg() + { + clear(); + global_->release(); + } + + bool scanner_cfg::update(const char* file, LPUDF func) + { + std::string cont(""), name(""), path(file); + int ret = gb::load_mini_file(file, cont); + base64 b64; + json *jsn = nullptr; + bool ok = true; + + if (ret) + return false; + else if (cont.empty()) + return true; + + cont = b64.decode(cont.c_str(), cont.length()); + jsn = new json(); + if (!jsn->attach_text(&cont[0])) + { + jsn->release(); + return false; + } + + cont = ""; + ret = path.rfind(PATH_SYMBOL[0]); + if (ret++ != std::string::npos) + path.erase(ret); + if (jsn->first_child(cont, &name)) + { + do + { + ok &= updater::update_app_config(name.c_str(), cont.c_str(), path.c_str(), func) == 0; + } while (jsn->next_child(cont, &name)); + } + jsn->release(); + if (ok) + rename(file, (std::string(file) + "_bk").c_str()); + + return true; + } + + void scanner_cfg::clear(void) + { + global_->set_value("ver", ""); + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + + for (size_t i = 0; i < schemes_.size(); ++i) + schemes_[i].schm->release(); + schemes_.clear(); + scanner_name_ = ""; + } + void scanner_cfg::init_version(void) + { + char vstr[40] = { 0 }; + + sprintf(vstr, "%u.%u", VERSION_MAIN, VERSION_SUB); + global_->set_value("ver", vstr); + } + void scanner_cfg::init_select(void) + { + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + } + void scanner_cfg::walk_sibling_schemes(cJSON* first) + { + if (!first) + return; + + cJSON* next = first->next; + std::string name(first->string ? "" : first->string), + cont(""); + CFGSCHM sch; + + first->next = nullptr; + cont = json::to_string(first, false); + if (name == scanner_cfg::global_name_) + { + global_->attach_text(&cont[0]); + } + else + { + sch.schm = new sane_config_schm(); + if (sch.schm->load_from_mem(cont.c_str(), false)) + { + sch.name = sane_config_schm::from_hex_letter(name.c_str(), name.length()); + sch.schm->set_scheme_name(sch.name.c_str()); + schemes_.push_back(sch); + } + else + sch.schm->release(); + } + + first->next = next; + walk_sibling_schemes(next); + } + + int scanner_cfg::load_file(const char* file) + { + std::string cont(""); + int ret = gb::load_mini_file(file, cont); + + if (ret == 0) + ret = load_mem(cont.c_str()); + + if (ret == 0 && scanner_name_.empty()) + { + const char* name = strrchr(file, PATH_SYMBOL[0]); + if (name++ == nullptr) + name = file; + + scanner_name_ = name; + ret = scanner_name_.rfind('.'); + if (ret != std::string::npos) + scanner_name_.erase(ret); + ret = 0; + } + + return ret; + } + int scanner_cfg::load_mem(const char* mem) + { + cJSON* root = cJSON_Parse(mem); + + if (!root) + return EINVAL; + + clear(); + walk_sibling_schemes(root->child); + cJSON_Delete(root); + + return 0; + } + int scanner_cfg::save(const char* file) + { + if (!file && path_.empty() && scanner_name_.empty()) + return EINVAL; + + std::string cont("{\"" + scanner_cfg::global_name_ + "\":"), + f(file ? file : path_ + scanner_name_), + v(""); + int sel = -1; + + if (!global_->get_value("ver", v) || v.empty()) + init_version(); + if (!global_->get_value(scanner_cfg::cur_sel_.c_str(), sel) || sel >= schemes_.size()) + init_select(); + + cont += global_->to_string(false); + for (auto& v: schemes_) + { + cont += ",\"" + sane_config_schm::to_hex_letter(v.name.c_str(), v.name.length()) + "\":"; + cont += v.schm->to_text_stream(false, false); + } + cont += "}"; + + base64 b64; + FILE* dst = fopen(f.c_str(), "wb"); + + if (!dst) + return errno; + + f = b64.encode(cont.c_str(), cont.length()); + fwrite(f.c_str(), 1, f.length(), dst); + fclose(dst); + + return 0; + } + + void scanner_cfg::get_all_schemes(std::vector& schemes) + { + schemes.push_back(scanner_cfg::default_setting_name_); + for (auto& v : schemes_) + schemes.push_back(v.name); + } + sane_config_schm* scanner_cfg::get_scheme(const char* scheme_name) + { + sane_config_schm* found = nullptr; + + if (scheme_name) + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), scheme_name); + if (it != schemes_.end()) + found = it->schm; + } + else + { + int ind = -1; + + global_->get_value(scanner_cfg::cur_sel_.c_str(), ind); + if (ind >= 0 && ind < schemes_.size()) + found = schemes_[ind].schm; + } + + if (found) + found->add_ref(); + + return found; + } + bool scanner_cfg::remove_scheme(const char* scheme_name) + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), scheme_name); + + if (it != schemes_.end()) + { + int id = it - schemes_.begin(), + ind = -1; + + it->schm->release(); + schemes_.erase(it); + global_->get_value(scanner_cfg::cur_sel_.c_str(), ind); + if (ind == id) + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + else if (ind > id) + global_->set_value(scanner_cfg::cur_sel_.c_str(), ind - 1); + + return true; + } + + return false; + } + bool scanner_cfg::select_scheme(const char* scheme_name) + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), scheme_name); + + if (it == schemes_.end()) + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + else + global_->set_value(scanner_cfg::cur_sel_.c_str(), it - schemes_.begin()); + + return true; + } + + sane_config_schm* scanner_cfg::copy_scheme(const char* cp_from_name) // for UI setting, call release() if not use anymore + { + if (!cp_from_name) + return nullptr; + else if (scanner_cfg::default_setting_name_ == cp_from_name) + return new sane_config_schm(); + else + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), cp_from_name); + if (it == schemes_.end()) + return nullptr; + + std::string cont(it->schm->to_text_stream()); + sane_config_schm* schm = new sane_config_schm(); + schm->load_from_mem(cont.c_str()); + + return schm; + } + } + bool scanner_cfg::add_scheme(sane_config_schm* schm, const char* name) + { + if (name && std::find(schemes_.begin(), schemes_.end(), name) != schemes_.end()) + return false; + + CFGSCHM cs; + cs.name = name ? name : schm->get_scheme_name(); + cs.schm = schm; + if (cs.name == scanner_cfg::global_name_) + return false; + + schemes_.push_back(cs); + schm->set_scheme_name(cs.name.c_str()); + schm->add_ref(); + + return true; + } } diff --git a/sane/gb_json.h b/sane/gb_json.h index be55419..35ffec5 100644 --- a/sane/gb_json.h +++ b/sane/gb_json.h @@ -2,6 +2,9 @@ #if defined(WIN32) || defined(_WIN64) #include +#define PATH_SYMBOL "\\" +#else +#define PATH_SYMBOL "/" #endif // #include "cJSON.h" @@ -12,6 +15,7 @@ namespace gb { + class scanner_cfg; class refer { volatile long ref_; @@ -101,7 +105,8 @@ namespace gb class sane_config_schm : public refer { std::string scheme_name_; - std::wstring file_; + scanner_cfg *scanner_; + std::string file_; json* jsn_; json* bkp_; json* def_val_; @@ -109,25 +114,25 @@ namespace gb std::map id_name_; // (id, default-val) void clear(); - std::string to_hex_letter(const char* data, size_t bytes); - std::string from_hex_letter(const char* data, size_t bytes); std::string default_value(const char* name); protected: ~sane_config_schm(); public: - sane_config_schm(); + sane_config_schm(scanner_cfg* scanner = nullptr); static std::string opt_data_appendix_; static bool hex(unsigned char ch, unsigned char* val); static bool hex_char(const char* data, unsigned char* val); + static std::string to_hex_letter(const char* data, size_t bytes); + static std::string from_hex_letter(const char* data, size_t bytes); static bool is_option_data(std::string& name); // reset baase option name into 'name' if name was option data, and return true public: - bool load_from_file(const wchar_t* file); - bool load_from_mem(const char* mem); - bool save_to(const wchar_t* file); + bool load_from_file(const char* file); + bool load_from_mem(const char* mem, bool in_b64 = true); + bool save_to(const char* file); void set_default_value(int sn, const char* name, const char* val, size_t bytes); bool first_config(std::string& name, std::string& val); bool next_config(std::string& name, std::string& val); @@ -135,12 +140,82 @@ namespace gb void config_changed(const char* name, const char* val, size_t bytes, bool extra = false); void config_changed(int sn, const char* val, size_t bytes, bool extra = false); void remove_config(const char* name); + void set_value(const char* name, const char* val, size_t bytes, bool extra = false); void end_setting(bool cancel); int id_from_name(const char* name); - std::string to_text_stream(void); + std::string to_text_stream(bool b64 = true, bool with_ver = true); std::string get_version(void); std::string get_scheme_name(void); void set_scheme_name(const char* name); void update(bool(__stdcall* is_float)(int, void*), void* param, const char*(__stdcall* t2n)(const char*), std::string* discard = NULL); }; + + class scanner_cfg : public refer + { + // format: in base64 + // + // { + // "global": { + // "ver": "4.33", + // "cur": -1 + // }, + // "scheme_1": sane_config_schm*, + // "scheme_2": sane_config_schm*, + // "scheme_3": sane_config_schm*, + // ... + // } + // + std::string path_; + std::string scanner_name_; // scanner type: HUAGOSCAN G100 - 0100 + json *global_; // version, current scheme, ... + + typedef struct _cfg_schm + { + std::string name; + sane_config_schm* schm; + + bool operator==(const char* n) + { + return name == n; + } + }CFGSCHM; + std::vector schemes_; + + static std::string global_name_; + static std::string cur_sel_; + static std::string default_setting_name_; + + void clear(void); + void init_version(void); + void init_select(void); + void walk_sibling_schemes(cJSON* first); + + protected: + ~scanner_cfg(); + + public: + scanner_cfg(); + + typedef struct _update_func + { + void(__stdcall* trans_number)(const char* name, std::string& val, void* param); + const char* (__stdcall* title2name)(const char* title, void* param); + std::string discard_msg; // update failed items ... + void* func_param; + }UDF, *LPUDF; + static bool update(const char* file, LPUDF func); + + public: + int load_file(const char* file); + int load_mem(const char* mem); + int save(const char* file = nullptr); + + void get_all_schemes(std::vector& schemes); // return all schemes name queue, the first is always be 'Default settings' + sane_config_schm* get_scheme(const char* scheme_name = nullptr/*return current scheme if was null*/); // call sane_config_schm::release() if not use anymore + bool remove_scheme(const char* scheme_name); + bool select_scheme(const char* scheme_name); + + sane_config_schm* copy_scheme(const char* cp_from_name); // for UI setting, call release() if not use anymore + bool add_scheme(sane_config_schm* schm, const char* name = nullptr); + }; } diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 0f6b2aa..447ea51 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -559,12 +559,12 @@ void scanner::update_config(void) } void scanner::load_config(const wchar_t* file) { - cfg_->load_from_file(file); + cfg_->load_from_file(local_trans::u2a(file).c_str()); update_config(); } void scanner::save_config(const wchar_t* file) { - cfg_->save_to(file); + cfg_->save_to(local_trans::u2a(file).c_str()); } void scanner::apply_config(void) { From de9d416ddd89e869185033ff1d379a6df3bd7921 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Thu, 27 Oct 2022 10:45:37 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E5=BA=94=E7=94=A8=E8=B7=A8=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/gb_json.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sane/gb_json.cpp b/sane/gb_json.cpp index 428b8b0..add68b7 100644 --- a/sane/gb_json.cpp +++ b/sane/gb_json.cpp @@ -1159,7 +1159,7 @@ namespace gb for (size_t i = 0; i < bytes; ++i) { - sprintf_s(buf, _countof(buf) - 1, "%02X", ptr[i]); + sprintf(buf, "%02X", ptr[i]); hex += buf; } @@ -1205,7 +1205,7 @@ namespace gb bool sane_config_schm::load_from_mem(const char* mem, bool in_b64) { gb::base64 b64; - std::string stream(in_b64 ? b64.decode(mem, lstrlenA(mem)) : mem); + std::string stream(in_b64 ? b64.decode(mem, strlen(mem)) : mem); clear(); jsn_ = new gb::json(); @@ -1367,7 +1367,7 @@ namespace gb if(with_ver) { char ver[40] = { 0 }; - sprintf_s(ver, "%u.%u", VERSION_MAIN, VERSION_SUB); + sprintf(ver, "%u.%u", VERSION_MAIN, VERSION_SUB); jsn_->set_value("ver", ver); } @@ -1448,7 +1448,7 @@ namespace gb } while (jsn_->next_child(val, &name)); } } - sprintf_s(vs, _countof(vs) - 1, "%u.%u", VERSION_MAIN, VERSION_SUB); + sprintf(vs, "%u.%u", VERSION_MAIN, VERSION_SUB); jsn_->set_value("ver", vs); if (changed) @@ -1699,7 +1699,7 @@ namespace gb if (it == schemes_.end()) global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); else - global_->set_value(scanner_cfg::cur_sel_.c_str(), it - schemes_.begin()); + global_->set_value(scanner_cfg::cur_sel_.c_str(), (int)(it - schemes_.begin())); return true; }