From 955584c89457911b23e948668c6a954f23b245ef Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sat, 9 Dec 2023 18:22:26 +0800 Subject: [PATCH] add file_map; add palt_types.h; fix device_opt --- hgdriver/hgdev/hg_scanner.cpp | 62 +++- hgdriver/hgdev/hg_scanner.h | 9 +- hgdriver/hgdev/scanner/async_usb_host.cpp | 67 +++- hgdriver/hgdev/scanner/async_usb_host.h | 2 + hgdriver/hgdev/scanner/scanner_handler.cpp | 50 +-- hgdriver/hgdev/usb_manager.cpp | 170 +++++++++- hgdriver/hgdev/usb_manager.h | 4 +- hgdriver/hgdev/user-opt/user.cpp | 6 +- sdk/base/data.cpp | 351 +++++++++++++++++++-- sdk/base/data.h | 49 ++- sdk/base/packet.h | 12 +- sdk/base/plat_types.h | 127 ++++++++ sdk/base/utils.cpp | 144 +++++++-- sdk/base/utils.h | 30 +- sdk/sane_opt_json/base_opt.cpp | 2 +- sdk/sane_opt_json/base_opt.h | 1 - sdk/sane_opt_json/device_opt.cpp | 88 +++++- sdk/sane_opt_json/device_opt.h | 1 + 18 files changed, 1047 insertions(+), 128 deletions(-) create mode 100644 sdk/base/plat_types.h diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index ce7d91b..8b7df6f 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -108,6 +108,10 @@ PACKIMAGE img_receiver::head(void) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // hg_scanner +static std::string device_opt_json[] = { + "{\"tx-prog\":{\"cat\":\"none\",\"group\":\"\\u9ad8\\u7ea7\\u8bbe\\u7f6e\",\"title\":\"\\u6587\\u4ef6\\u4f20\\u8f93\\u8fdb\\u5ea6\",\"desc\":\"\\u4f20\\u8f93\\u6587\\u4ef6\\u5b8c\\u6210\\u767e\\u5206\\u6bd4\",\"type\":\"float\",\"ui-pos\":0,\"auth\":0,\"size\":8,\"ownread\":true,\"cur\":0.000000,\"default\":0.000000}}" +}; + hg_scanner::hg_scanner(ONLNSCANNER* dev, imgproc_mgr* imgproc, hguser* user, std::vector* constopts) : dev_(*dev), status_(SCANNER_ERR_OPENED_BY_OTHER_PROCESS) , msg_(from_default_language("\350\256\276\345\244\207\345\267\262\347\273\217\350\242\253\350\277\233\347\250\213 '%s' \345\215\240\347\224\250")) @@ -142,11 +146,11 @@ hg_scanner::hg_scanner(ONLNSCANNER* dev, imgproc_mgr* imgproc, hguser* user, std dev_opts_->add(v); } #ifdef USE_SAFE_THREAD - auto tf = [this](void*) -> void + auto tf = [this](void) -> void { thread_image_processor(); }; - imgpr_thread_.start(tf, nullptr, "hg_scanner::thread_image_processor"); + imgpr_thread_.start(tf, "hg_scanner::thread_image_processor", NULL); #else imgpr_thread_.reset(new std::thread(&hg_scanner::thread_image_processor, this)); #endif @@ -205,6 +209,16 @@ void hg_scanner::init(void) if (ret == SCANNER_ERR_OK) { + std::string pc(""); + for (auto& v : device_opt_json) + pc += v; + if (pc.length()) + pc.erase(0, 1); + if (opts.length()) + opts[opts.length() - 1] = ','; + else + opts = "{"; + opts += pc; ret = scanner_->option_get_all(opts); set_opt_json_text(&opts[0]); if(user_) @@ -233,6 +247,23 @@ void hg_scanner::thread_image_processor(void) //processor->release(); } +char* hg_scanner::get_value(const char* name, void* value, size_t* size, int* err) +{ + char* ret = nullptr; + + if (strcmp(name, "tx-prog") == 0) + { + ret = (char*)malloc(sizeof(double)); + + *(double*)ret = tx_prg_; + if (size) + *size = sizeof(double); + if (err) + *err = status_; + } + + return ret; +} int hg_scanner::set_value(const char* name, void* val) { int type = DATA_TYPE_BOOL, @@ -344,8 +375,11 @@ int hg_scanner::read_image_data(uint8_t* buf, size_t* len) { return SCANNER_ERR_OK; } -int hg_scanner::status(void) +int hg_scanner::status(EP0REPLYSTATUS* ds) { + if (ds) + scanner_->get_scanner_status(ds); + return status_; } std::string hg_scanner::status_message(void) @@ -363,3 +397,25 @@ device_option* hg_scanner::get_device_opt(void) return dev_opts_; } +int hg_scanner::file_transfer(const char* local, const char* remote, bool to_remote) +{ + auto prog = [this](uint64_t total, uint64_t txed, uint32_t err, void* user) -> int + { + double now = txed; + now /= total; + + tx_prg_ = now; + status_ = err; + if (err) + utils::to_log(LOG_LEVEL_WARNING, "File transfer error: %d (at %ld/%ld)\n", err, txed, total); + else if (txed >= total) + utils::to_log(LOG_LEVEL_DEBUG, "File transfer finished(%ld/%ld) with error %d\n", txed, total, err); + + + return 0; + }; + + tx_prg_ = .0f; + + return scanner_->file_transfer(local, remote, to_remote, prog); +} diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index 4512ede..cfe02b1 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -81,6 +81,8 @@ class hg_scanner : public sane_opt_provider scanner_handler *scanner_ = nullptr; hguser *user_ = nullptr; + double tx_prg_ = .0f; // file transfer progress + volatile bool cancelled_ = false; volatile bool run_ = true; safe_fifo raw_imgs_; @@ -105,6 +107,7 @@ protected: // sane_opt_provider public: + virtual char* get_value(const char* name, void* value, size_t* size, int* err = nullptr) override; virtual int set_value(const char* name, void* val) override; // scanner operation ... @@ -115,8 +118,12 @@ public: int re_connect(void); int get_image_info(SANE_Parameters* pii); int read_image_data(uint8_t* buf, size_t* len); - int status(void); + int status(EP0REPLYSTATUS* ds = nullptr); std::string status_message(void); bool is_online(void); + + // advanced functions ... +public: device_option* get_device_opt(void); + int file_transfer(const char* local, const char* remote, bool to_remote); // get_value("tx-prog", (double*)percent) to query progress }; diff --git a/hgdriver/hgdev/scanner/async_usb_host.cpp b/hgdriver/hgdev/scanner/async_usb_host.cpp index c5d786a..34b62b6 100644 --- a/hgdriver/hgdev/scanner/async_usb_host.cpp +++ b/hgdriver/hgdev/scanner/async_usb_host.cpp @@ -135,6 +135,31 @@ int async_usb_host::start(libusb_device* dev) bulk_out_.claimed = 1; } + // check version ... + { + libusb_device_descriptor dd = { 0 }; + char product[128] = { 0 }; + int ver = 1; + + if (libusb_get_device_descriptor(dev, &dd) == LIBUSB_SUCCESS) + { + libusb_get_string_descriptor_ascii(usb_handle_, dd.iProduct, (unsigned char*)product, _countof(product) - 1); + utils::to_log(LOG_LEVEL_DEBUG, "Product: '%s'\n", product); + + char* v = strstr(product, "(V"); + if (v) + { + ver = atoi(v + 2); + } + } + if (ver < 2) + { + stop(); + + return EPROTONOSUPPORT; + } + } + run_ = true; libusb_ref_device(dev); usb_dev_ = dev; @@ -362,21 +387,21 @@ void async_usb_host::thread_pump_task(void) void async_usb_host::create_worker_threads(void) { #ifdef USE_SAFE_THREAD - auto thread_w = [this](void*) -> void + auto thread_w = [this](void) -> void { thread_write_bulk(); }; - auto thread_r = [this](void*) -> void + auto thread_r = [this](void) -> void { thread_read_bulk(); }; - auto thread_p = [this](void*) -> void + auto thread_p = [this](void) -> void { thread_pump_task(); }; - thread_w_.start(thread_w, nullptr, "async_usb_host::thread_write_bulk"); - thread_r_.start(thread_r, nullptr, "async_usb_host::thread_read_bulk"); - thread_p_.start(thread_p, nullptr, "async_usb_host::thread_pump_task"); + thread_w_.start(thread_w, "async_usb_host::thread_write_bulk"); + thread_r_.start(thread_r, "async_usb_host::thread_read_bulk"); + thread_p_.start(thread_p, "async_usb_host::thread_pump_task"); #else thread_w_.reset(new std::thread(&async_usb_host::thread_write_bulk, this)); thread_r_.reset(new std::thread(&async_usb_host::thread_read_bulk, this)); @@ -524,6 +549,7 @@ dyn_mem_ptr async_usb_host::handle_data_in(dyn_mem_ptr& data, uint32_t* used, pa int async_usb_host::get_peer_protocol_version(uint16_t* ver) { + SIMPLE_LOCK(io_lock_); uint16_t v = 0; int err = libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN , USB_REQ_EP0_GET_PROTO_VER, 0, 0 @@ -537,6 +563,8 @@ int async_usb_host::get_peer_protocol_version(uint16_t* ver) } int async_usb_host::get_peer_status(LPEP0REPLYSTATUS status) { + SIMPLE_LOCK(io_lock_); + return libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN , USB_REQ_EP0_GET_STATUS, 0, 0 , (unsigned char*)status, sizeof(*status) @@ -546,17 +574,23 @@ int async_usb_host::restart_peer_bulk(uint32_t timeout) { EP0REPLYSTATUS status = { 0 }; chronograph tc; + int ok = 0, w = 0, + err = 0; + + { + SIMPLE_LOCK(io_lock_); err = libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN - , USB_REQ_EP0_RESET_BULK, 0, 0 - , (unsigned char*)&ok, sizeof(ok) - , 1000); + , USB_REQ_EP0_RESET_BULK, 0, 0 + , (unsigned char*)&ok, sizeof(ok) + , 1000); + } tc.reset(); while ((err = get_peer_status(&status)) == 0 && ok == 0) { - if (status.in_status == BULK_STATUS_IDLE) + if (status.in_status == WORKER_STATUS_IDLE) break; std::this_thread::sleep_for(std::chrono::milliseconds(5)); @@ -571,6 +605,8 @@ int async_usb_host::restart_peer_bulk(uint32_t timeout) } int async_usb_host::reset_io_buffer_size(unsigned short size) { + SIMPLE_LOCK(io_lock_); + libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT , USB_REQ_EP0_SET_BULK_BUFFER, 0, size , nullptr, 0 @@ -597,9 +633,12 @@ int async_usb_host::set_gadget_encrypting_method(uint32_t cmd_enc, uint32_t payl pack->enc_cmd = cmd_enc; pack->encrypt = payload_enc; pack->enc_data = enc_data; - err = libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR, USB_REQ_EP0_SET_ENCRYPT, 0, 0 - , (unsigned char*)pack, sizeof(*pack) - , 1000); + { + SIMPLE_LOCK(io_lock_); + err = libusb_control_transfer(usb_handle_, LIBUSB_REQUEST_TYPE_VENDOR, USB_REQ_EP0_SET_ENCRYPT, 0, 0 + , (unsigned char*)pack, sizeof(*pack) + , 1000); + } ptr->release(); return err; @@ -861,6 +900,8 @@ int async_usb_host::cancel_write(void) } int async_usb_host::raw_control(uint8_t type, uint8_t req, uint16_t ind, uint16_t val, uint16_t len, void* data) { + SIMPLE_LOCK(io_lock_); + return libusb_control_transfer(usb_handle_, type , req, val, ind , (unsigned char*)data, len diff --git a/hgdriver/hgdev/scanner/async_usb_host.h b/hgdriver/hgdev/scanner/async_usb_host.h index f6e4a20..e13d4ef 100644 --- a/hgdriver/hgdev/scanner/async_usb_host.h +++ b/hgdriver/hgdev/scanner/async_usb_host.h @@ -39,6 +39,8 @@ class async_usb_host : public refer libusb_device* usb_dev_; USBEP bulk_in_; USBEP bulk_out_; + MUTEX io_lock_; + safe_fifo in_que_; safe_fifo out_que_; #ifdef USE_SAFE_THREAD diff --git a/hgdriver/hgdev/scanner/scanner_handler.cpp b/hgdriver/hgdev/scanner/scanner_handler.cpp index 23ea631..3fbc2b5 100644 --- a/hgdriver/hgdev/scanner/scanner_handler.cpp +++ b/hgdriver/hgdev/scanner/scanner_handler.cpp @@ -543,21 +543,18 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa if (to_device) { uint64_t size = 0; - FILE *src = fopen(local_path, "rb"); + file_reader *reader = new file_reader(); + int err = reader->open(local_path, true, local_off); - if (!src) - return errno; - FSEEK(src, 0, SEEK_END); - size = FTELL(src); - FSEEK(src, local_off, SEEK_SET); - if (size <= local_off) - { - fclose(src); - - return EOVERFLOW; - } - size -= local_off; utils::to_log(LOG_LEVEL_DEBUG, "Send '%s' to '%s' ...\r\n", local_path, remote_path); + if (err) + { + utils::to_log(LOG_LEVEL_FATAL, "Send file failed in open local file '%s': %d\n", local_path, err); + reader->release(); + return err; + } + size = reader->get_rest(); + reader->set_progress_notify(progress); auto call = [&](cmd_result* cmd) -> int { @@ -565,10 +562,10 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa }; auto clean = [&](cmd_result* cmd) -> int { - FILE* src = (FILE*)cmd->get_param(); + file_reader* reader = (file_reader*)cmd->get_param(); - if (src) - fclose(src); + if (reader) + reader->release(); return 0; }; @@ -589,10 +586,8 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa } else { - file_reader_ptr freader = new file_reader(); - - int err = freader->attach((FILE*)cmd->set_param(nullptr)); - freader->set_progress_notify(progress); + file_reader_ptr freader = (file_reader_ptr)cmd->set_param(nullptr); + if (err) { // cancel tx-file ... @@ -614,7 +609,7 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa return ret; }; - WAIT_COMMAND(call, clean, roger, src); + WAIT_COMMAND(call, clean, roger, reader); } else { @@ -630,10 +625,13 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa { LPPACK_BASE pack = (LPPACK_BASE)data->ptr(); LPTXFILE pfi = (LPTXFILE)pack->payload; + dyn_mem_ptr reply = dyn_mem::memory(sizeof(PACK_BASE)); *used = sizeof(PACK_BASE) + pack->payload_len; *more = nullptr; utils::to_log(LOG_LEVEL_DEBUG, "Receive file - Roger result: %d\r\n", pack->data); + BASE_PACKET_REPLY((*(LPPACK_BASE)reply->ptr()), PACK_CMD_FILE_READ_REQ_ROGER, pack->pack_id, -1); + reply->set_len(sizeof(PACK_BASE)); if (pack->data == 0) { if (cmd->is_over()) @@ -644,19 +642,21 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa else { file_saver* fsaver = new file_saver(); - int err = fsaver->open(local_path, pfi->size); - fsaver->set_progress_notify(progress); + int err = fsaver->open(local_path, pfi->size, true, local_off); if (err) { // cancel tx-file ... cmd->set_error_code(err); + (*(LPPACK_BASE)reply->ptr()).data = err; fsaver->release(); reset_message_que(); utils::to_log(LOG_LEVEL_DEBUG, "Receive file - open local file failed: %d\r\n", err); } else { + fsaver->set_progress_notify(progress); *more = dynamic_cast(fsaver); + (*(LPPACK_BASE)reply->ptr()).data = 0; status_ = SCANNER_STATUS_BUSY; utils::to_log(LOG_LEVEL_DEBUG, "Receive file - beginning ...\r\n"); } @@ -664,7 +664,7 @@ int scanner_handler::file_transfer(const char* local_path, const char* remote_pa } cmd->trigger(); - return nullptr; + return reply; }; utils::to_log(LOG_LEVEL_DEBUG, "Receive '%s' to '%s' ...\r\n", remote_path, local_path); @@ -805,6 +805,8 @@ int scanner_handler::close(void) } int scanner_handler::reset_message_que(void) { + return 0; + int err = usb_->cancel_write(); status_ = SCANNER_STATUS_RESET_BULK; diff --git a/hgdriver/hgdev/usb_manager.cpp b/hgdriver/hgdev/usb_manager.cpp index 9cd49fa..ccd8400 100644 --- a/hgdriver/hgdev/usb_manager.cpp +++ b/hgdriver/hgdev/usb_manager.cpp @@ -19,6 +19,147 @@ void memset(void* buf, unsigned char fill, int len) } #endif +#ifdef TEST_HGSCANNER +const char* hg_scanner_err_name(int err, char* buf) +{ + RETURN_IF(err, SANE_STATUS_GOOD); + RETURN_IF(err, SANE_STATUS_UNSUPPORTED); + RETURN_IF(err, SANE_STATUS_CANCELLED); + RETURN_IF(err, SANE_STATUS_DEVICE_BUSY); + RETURN_IF(err, SANE_STATUS_INVAL); + RETURN_IF(err, SANE_STATUS_EOF); + RETURN_IF(err, SANE_STATUS_JAMMED); + RETURN_IF(err, SANE_STATUS_NO_DOCS); + RETURN_IF(err, SANE_STATUS_COVER_OPEN); + RETURN_IF(err, SANE_STATUS_IO_ERROR); + RETURN_IF(err, SANE_STATUS_NO_MEM); + RETURN_IF(err, SANE_STATUS_ACCESS_DENIED); + RETURN_IF(err, SCANNER_ERR_INVALID_PARAMETER); + RETURN_IF(err, SCANNER_ERR_USER_CANCELED); + RETURN_IF(err, SCANNER_ERR_INSUFFICIENT_MEMORY); + RETURN_IF(err, SCANNER_ERR_ACCESS_DENIED); + RETURN_IF(err, SCANNER_ERR_IO_PENDING); + RETURN_IF(err, SCANNER_ERR_NOT_EXACT); + RETURN_IF(err, SCANNER_ERR_CONFIGURATION_CHANGED); + RETURN_IF(err, SCANNER_ERR_RELOAD_IMAGE_PARAM); + RETURN_IF(err, SCANNER_ERR_RELOAD_OPT_PARAM); + RETURN_IF(err, SCANNER_ERR_NOT_OPEN); + RETURN_IF(err, SCANNER_ERR_NOT_START); + RETURN_IF(err, SCANNER_ERR_NOT_ANY_MORE); + RETURN_IF(err, SCANNER_ERR_NO_DATA); + RETURN_IF(err, SCANNER_ERR_HAS_DATA_YET); + RETURN_IF(err, SCANNER_ERR_OUT_OF_RANGE); + RETURN_IF(err, SCANNER_ERR_IO); + RETURN_IF(err, SCANNER_ERR_TIMEOUT); + RETURN_IF(err, SCANNER_ERR_OPEN_FILE_FAILED); + RETURN_IF(err, SCANNER_ERR_CREATE_FILE_FAILED); + RETURN_IF(err, SCANNER_ERR_WRITE_FILE_FAILED); + RETURN_IF(err, SCANNER_ERR_DATA_DAMAGED); + RETURN_IF(err, SCANNER_ERR_OPENED_BY_OTHER_PROCESS); + RETURN_IF(err, SCANNER_ERR_USB_INIT_FAILED); + RETURN_IF(err, SCANNER_ERR_USB_REGISTER_PNP_FAILED); + RETURN_IF(err, SCANNER_ERR_USB_CLAIM_INTERFACE_FAILED); + RETURN_IF(err, SCANNER_ERR_DEVICE_NOT_FOUND); + RETURN_IF(err, SCANNER_ERR_DEVICE_NOT_SUPPORT); + RETURN_IF(err, SCANNER_ERR_DEVICE_BUSY); + RETURN_IF(err, SCANNER_ERR_DEVICE_SLEEPING); + RETURN_IF(err, SCANNER_ERR_DEVICE_COUNT_MODE); + RETURN_IF(err, SCANNER_ERR_DEVICE_STOPPED); + RETURN_IF(err, SCANNER_ERR_DEVICE_COVER_OPENNED); + RETURN_IF(err, SCANNER_ERR_DEVICE_NO_PAPER); + RETURN_IF(err, SCANNER_ERR_DEVICE_FEEDING_PAPER); + RETURN_IF(err, SCANNER_ERR_DEVICE_DOUBLE_FEEDING); + RETURN_IF(err, SCANNER_ERR_DEVICE_PAPER_JAMMED); + RETURN_IF(err, SCANNER_ERR_DEVICE_STAPLE_ON); + RETURN_IF(err, SCANNER_ERR_DEVICE_PAPER_SKEW); + RETURN_IF(err, SCANNER_ERR_DEVICE_SIZE_CHECK); + RETURN_IF(err, SCANNER_ERR_DEVICE_DOGEAR); + RETURN_IF(err, SCANNER_ERR_DEVICE_NO_IMAGE); + RETURN_IF(err, SCANNER_ERR_DEVICE_SCANN_ERROR); + RETURN_IF(err, SCANNER_ERR_DEVICE_PC_BUSY); + RETURN_IF(err, SCANNER_ERR_DEVICE_ISLOCK); + RETURN_IF(err, SCANNER_ERR_DEVICE_MAYBE_IS_HOLE); + RETURN_IF(err, SCANNER_ERR_DEVICE_DEVS_BOOTING); + RETURN_IF(err, SCANNER_ERR_DEVICE_UNKNOWN_STATUS); + RETURN_IF(err, SCANNER_ERR_LANG_PAK_LOST); + RETURN_IF(err, SCANNER_ERR_THROW_EXCEPTION); + + sprintf(buf, "Unknown error: 0x%X", err); + + return buf; +} +const char* hg_scanner_err_description(int err) +{ + RETURN_DESC_IF(err, SCANNER_ERR_OK); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NOT_SUPPORT); + RETURN_DESC_IF(err, SCANNER_ERR_USER_CANCELED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_BUSY); + RETURN_DESC_IF(err, SCANNER_ERR_INVALID_PARAMETER); + RETURN_DESC_IF(err, SCANNER_ERR_NO_DATA); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_PAPER_JAMMED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NO_PAPER); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_COVER_OPENNED); + RETURN_DESC_IF(err, SCANNER_ERR_IO); + RETURN_DESC_IF(err, SCANNER_ERR_INSUFFICIENT_MEMORY); + + RETURN_DESC_IF(err, SCANNER_ERR_ACCESS_DENIED); + RETURN_DESC_IF(err, SCANNER_ERR_INSUFFICIENT_MEMORY); + RETURN_DESC_IF(err, SCANNER_ERR_ACCESS_DENIED); + RETURN_DESC_IF(err, SCANNER_ERR_IO_PENDING); + RETURN_DESC_IF(err, SCANNER_ERR_NOT_EXACT); + RETURN_DESC_IF(err, SCANNER_ERR_CONFIGURATION_CHANGED); + RETURN_DESC_IF(err, SCANNER_ERR_RELOAD_IMAGE_PARAM); + RETURN_DESC_IF(err, SCANNER_ERR_RELOAD_OPT_PARAM); + RETURN_DESC_IF(err, SCANNER_ERR_NOT_OPEN); + RETURN_DESC_IF(err, SCANNER_ERR_NOT_START); + RETURN_DESC_IF(err, SCANNER_ERR_NOT_ANY_MORE); + RETURN_DESC_IF(err, SCANNER_ERR_NO_DATA); + RETURN_DESC_IF(err, SCANNER_ERR_HAS_DATA_YET); + RETURN_DESC_IF(err, SCANNER_ERR_OUT_OF_RANGE); + RETURN_DESC_IF(err, SCANNER_ERR_IO); + RETURN_DESC_IF(err, SCANNER_ERR_TIMEOUT); + RETURN_DESC_IF(err, SCANNER_ERR_OPEN_FILE_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_CREATE_FILE_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_WRITE_FILE_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_DATA_DAMAGED); + RETURN_DESC_IF(err, SCANNER_ERR_OPENED_BY_OTHER_PROCESS); + RETURN_DESC_IF(err, SCANNER_ERR_USB_INIT_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_USB_REGISTER_PNP_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_USB_CLAIM_INTERFACE_FAILED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NOT_FOUND); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NOT_SUPPORT); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_BUSY); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_SLEEPING); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_COUNT_MODE); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_STOPPED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_COVER_OPENNED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NO_PAPER); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_FEEDING_PAPER); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_DOUBLE_FEEDING); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_PAPER_JAMMED); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_STAPLE_ON); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_PAPER_SKEW); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_SIZE_CHECK); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_DOGEAR); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_NO_IMAGE); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_SCANN_ERROR); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_PC_BUSY); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_ISLOCK); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_MAYBE_IS_HOLE); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_DEVS_BOOTING); + RETURN_DESC_IF(err, SCANNER_ERR_DEVICE_UNKNOWN_STATUS); + if (err == SCANNER_ERR_LANG_PAK_LOST) + return "SCANNER_ERR_LANG_PAK_LOST"; + + // NOTE: multi-thread unsafe here + static char g_unk_err[128] = { 0 }; + strcpy(g_unk_err, from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_UNKNOWN_ERROR)); + sprintf(g_unk_err + strlen(g_unk_err), ":0x%x", err); + + return g_unk_err; +} +#endif + usb_manager* usb_manager::inst_ = NULL; uint8_t usb_manager::uninit_uint8 = 0x0ff; @@ -37,11 +178,11 @@ usb_manager::usb_manager() : run_(true) wait_pnp_.set_debug_info("Waiting PNP"); #ifdef USE_SAFE_THREAD - auto tf = [this](void*) -> void + auto tf = [this](void) -> void { thread_notify_usb_event(); }; - usb_notify_thread_.start(tf, nullptr, "usb_manager::thread_notify_usb_event"); + usb_notify_thread_.start(tf, "usb_manager::thread_notify_usb_event"); #else if (!usb_notify_thread_.get()) { @@ -134,11 +275,11 @@ int usb_manager::register_usb_pnp(void) void usb_manager::init_notify_thread() { #ifdef USE_SAFE_THREAD - auto tf = [this](void*) -> void + auto tf = [this](void) -> void { thread_trigger_usb_event(); }; - usb_monitor_thread_.start(tf, nullptr, "usb_manager::thread_trigger_usb_event"); + usb_monitor_thread_.start(tf, "usb_manager::thread_trigger_usb_event"); #else if(!usb_monitor_thread_.get()) { @@ -804,6 +945,23 @@ void usb_io::init_after_open(void) close(); last_err_ = err; } + else + { + libusb_device_descriptor dd = { 0 }; + char product[128] = { 0 }; + + if (libusb_get_device_descriptor(dev_info_.device, &dd) == LIBUSB_SUCCESS) + { + libusb_get_string_descriptor_ascii(handle_, dd.iProduct, (unsigned char*)product, _countof(product) - 1); + utils::to_log(LOG_LEVEL_DEBUG, "Product: %s\n", product); + + char* v = strstr(product, "(V"); + if (v) + { + ver_ = atoi(v + 2); + } + } + } } void usb_io::open(void) { @@ -1138,6 +1296,10 @@ int usb_io::get_pid(void) { return dev_info_.pid; } +int usb_io::get_ver(void) +{ + return ver_; +} void usb_io::on_disconnected(void) { diff --git a/hgdriver/hgdev/usb_manager.h b/hgdriver/hgdev/usb_manager.h index 0113442..dad823f 100644 --- a/hgdriver/hgdev/usb_manager.h +++ b/hgdriver/hgdev/usb_manager.h @@ -1,7 +1,7 @@ #pragma once #if defined(WIN32) || defined(_WIN64) -#include "win_usb/win_usb.h" +#include #else #include @@ -158,6 +158,7 @@ class usb_io int last_err_; std::string init_err_msg_; libusb_device *ref_device_; + int ver_ = 1; // endpoint ports usb_manager::USBTRANSENDP endpoints_; @@ -197,6 +198,7 @@ public: libusb_device* get_usb_device(void); // 获取该USB对象 int get_vid(void); // 获取连接到该USB端口上的设备VID int get_pid(void); // 获取连接到该USB端口上的设备PID + int get_ver(void); void on_disconnected(void); std::string init_error_msg(void); diff --git a/hgdriver/hgdev/user-opt/user.cpp b/hgdriver/hgdev/user-opt/user.cpp index 6e559a7..0c977b1 100644 --- a/hgdriver/hgdev/user-opt/user.cpp +++ b/hgdriver/hgdev/user-opt/user.cpp @@ -1,8 +1,8 @@ #include "user.h" -#include "../../../sdk/include/huagao/brand.h" -#include "../../../sdk/include/huagao/hgscanner_error.h" -#include "../../../sdk/include/sane/sane_ex.h" +#include +#include +#include diff --git a/sdk/base/data.cpp b/sdk/base/data.cpp index f8fbac4..7c2a13c 100644 --- a/sdk/base/data.cpp +++ b/sdk/base/data.cpp @@ -3,10 +3,11 @@ #include -#if defined(WIN32) || defined(_WIN64) +#if OS_WIN #else #include #include +#include #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -20,7 +21,7 @@ packet_data_base::~packet_data_base() int packet_data_base::notify_progress(uint64_t total, uint64_t cur_size, uint32_t err) { if (progress_notify_) - progress_notify_(total, cur_size, err, user_data_); + return progress_notify_(total, cur_size, err, user_data_); else return ENOENT; } @@ -30,6 +31,10 @@ void packet_data_base::set_packet_param(uint32_t cmd, uint32_t id) pack_cmd_ = cmd; pack_id_ = id; } +void packet_data_base::set_session_id(uint32_t session_id) +{ + session_id_ = session_id; +} int packet_data_base::get_packet_command(void) { return pack_cmd_; @@ -38,6 +43,10 @@ int packet_data_base::get_packet_id(void) { return pack_id_; } +uint32_t packet_data_base::get_session_id(void) +{ + return session_id_; +} void packet_data_base::set_progress_notify(PROGRESS_NOTIFYER notify, void* param) { @@ -52,6 +61,9 @@ data_holder::data_holder() data_holder::~data_holder() {} +void data_holder::cancel(void) +{} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -137,11 +149,16 @@ file_saver::file_saver(void) : size_(0), wrote_(0), path_(""), check_(""), dst_( {} file_saver::~file_saver() { + utils::to_log(LOG_LEVEL_DEBUG, "Write file(%s) over(%ld/%ld).\n", path_.c_str(), wrote_, size_); close(); } void file_saver::close(void) { + if (map_) + map_->release(); + map_ = nullptr; + if(dst_) fclose(dst_); dst_ = nullptr; @@ -150,17 +167,48 @@ void file_saver::close(void) path_ = check_ = ""; } -int file_saver::open(const char* path, uint64_t size, const char* check) +int file_saver::set_verify_data(const char* data, size_t len) +{ + if (data) + check_ = std::string(data, len); + else + check_ = ""; + + return 0; +} +int file_saver::open(const char* path, uint64_t size, bool in_mem, size_t off) { int err = 0; close(); - dst_ = fopen(path, "wb"); - if(dst_) + wrote_ = off; + path_ = path; + size_ = size; + + if (in_mem) + { + map_ = new file_map(); + err = map_->open(path, size, false); + if (err || !map_->map()) + { + map_->release(); + map_ = nullptr; + } + else + return err; + } + + err = utils::make_file_size(path, wrote_); + dst_ = fopen(path, "ab+"); + if (dst_) { unsigned long long space = 0; + std::string dir(path); + size_t pos = dir.rfind(PATH_SEPARATOR[0]); - err = utils::get_disk_space(path, nullptr, &space, nullptr); + if (pos != std::string::npos) + dir.erase(pos); + err = utils::get_disk_space(dir.c_str(), nullptr, &space, nullptr); if (err || space < size * 1.5) { fclose(dst_); @@ -169,12 +217,6 @@ int file_saver::open(const char* path, uint64_t size, const char* check) if (err == 0) err = ENOSPC; } - else - { - path_ = path; - size_ = size; - check_ = check ? check : ""; - } } else { @@ -186,8 +228,22 @@ int file_saver::open(const char* path, uint64_t size, const char* check) int file_saver::put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) { - if(!dst_) + if (!dst_) + { + if (map_) + { + // fix me: we consider whole file is all mapped in memory + int w = *size > size_ - wrote_ ? size_ - wrote_ : *size; + memcpy(map_->buffer() + wrote_, data, w); + *size = w; + wrote_ += w; + notify_progress(size_, wrote_, 0); + + return 0; + } + return ENOENT; + } int w = *size > size_ - wrote_ ? size_ - wrote_ : *size, real_w = fwrite(data, 1, w, dst_), // should handle error here ! @@ -216,7 +272,14 @@ uint32_t file_saver::get_required(void) { return size_ - wrote_; } - +void file_saver::cancel(void) +{ + std::string discard(path_); + + utils::to_log(LOG_LEVEL_DEBUG, "Discard receiving file (%u/%u): '%s'.\n", wrote_, size_, path_.c_str()); + close(); + remove(discard.c_str()); +} @@ -385,12 +448,41 @@ file_reader::~file_reader() { if(src_) fclose(src_); + if (map_) + map_->release(); + utils::to_log(LOG_LEVEL_DEBUG, "Read file(%s) over(%ld/%ld).\n", path_.c_str(), consume_, len_); } -int file_reader::open(const char* file) +int file_reader::open(const char* file, bool in_mem, size_t off) { if(src_) fclose(src_); + src_ = nullptr; + consume_ = off; + + if (in_mem) + { + map_ = new file_map(); + if (map_->open(file, 0, true) || !map_->map()) + { + map_->release(); + map_ = nullptr; + } + else + { + if (map_->total_size() <= off) + { + map_->release(); + map_ = nullptr; + + return EOVERFLOW; + } + path_ = file; + len_ = map_->total_size(); + + return 0; + } + } src_ = fopen(file, "rb"); if(!src_) @@ -398,9 +490,15 @@ int file_reader::open(const char* file) FSEEK(src_, 0, SEEK_END); len_ = FTELL(src_); - FSEEK(src_, 0, SEEK_SET); + FSEEK(src_, consume_, SEEK_SET); path_ = file; - consume_ = 0; + if (len_ <= consume_) + { + fclose(src_); + src_ = nullptr; + + return EOVERFLOW; + } return 0; } @@ -411,6 +509,11 @@ int file_reader::attach(FILE* f) fclose(src_); src_ = nullptr; } + if (map_) + { + map_->release(); + map_ = nullptr; + } uint64_t cur = FTELL(f); @@ -439,7 +542,7 @@ FILE* file_reader::detach(void) bool file_reader::is_memory_block(void) { - return false; + return map_ != nullptr; } uint32_t file_reader::get_rest(void) { @@ -449,14 +552,27 @@ uint32_t file_reader::get_rest(void) // following API valid when is_memory_block() return true uint8_t* file_reader::ptr(void) { - return nullptr; + return map_ ? map_->buffer() : nullptr; } // following API valid when is_memory_block() return false int file_reader::fetch_data(void* buf, uint32_t* size) { if (!src_) + { + if (map_) + { + if (*size + consume_ >= len_) + *size = len_ - consume_; + memcpy(buf, map_->buffer() + consume_, *size); + consume_ += *size; + notify_progress(len_, consume_, 0); + + return 0; + } + return ENODATA; + } size_t r = fread(buf, 1, *size, src_); // fix me if ERROR occurs !!! @@ -471,3 +587,200 @@ int file_reader::fetch_data(void* buf, uint32_t* size) return 0; } + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +file_map::file_map() +{ + utils::get_page_size(&os_map_size_); +} +file_map::~file_map() +{ + close(); +} + +void file_map::unmap(void) +{ + if (buf_) +#if OS_WIN + UnmapViewOfFile(buf_); +#else + munmap(buf_, map_size_); +#endif + + buf_ = nullptr; + map_off_ = map_size_ = off_ = 0; +} + +int file_map::open(const char* file, uint64_t size, bool readonly) +{ + close(); + + std::string oper(readonly ? "open" : "create"); + +#if OS_WIN + HANDLE h = INVALID_HANDLE_VALUE; + DWORD access = PAGE_READONLY; + if (readonly) + { + h = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } + else + { + access = PAGE_READWRITE; + h = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } + if (h == INVALID_HANDLE_VALUE) + { + utils::to_log(LOG_LEVEL_WARNING, "FileMapping: %s '%s' failed: %d\n", oper.c_str(), file, GetLastError()); + return EFAULT; + } + + if (readonly) + { + DWORD* hi = (DWORD*)&size + 1, + * lo = (DWORD*)&size; + *lo = GetFileSize(h, hi); + } + else + { + LONG lo = size & 0x0ffffffff, + hi = size >> 32; + DWORD ret = SetFilePointer(h, lo, &hi, FILE_BEGIN); + if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) + { + CloseHandle(h); + remove(file); + utils::to_log(LOG_LEVEL_WARNING, "FileMapping: no space(%ld) for '%s'.\n", size, file); + + return ENOSPC; + } + else + { + // write a byte to ensure map success + SetFilePointer(h, -1, NULL, FILE_CURRENT); + lo = 0; + WriteFile(h, &lo, 1, &ret, NULL); + } + } + map_ = CreateFileMappingA(h, NULL, access, 0, 0, NULL); + access = GetLastError(); + CloseHandle(h); + if (!map_) + { + remove(file); + map_ = INVALID_HANDLE_VALUE; + utils::to_log(LOG_LEVEL_WARNING, "FileMapping: create mapping object for '%s' failed: %d.\n", file, access); + + return EFAULT; + } +#else + if (readonly) + map_ = (HANDLE)::open(file, O_RDONLY, 0644); + else + { + int err = utils::make_file_size(file, size); + if(err) + { + utils::to_log(LOG_LEVEL_FATAL, "FileMapping: make file(%s) size(%ld) = %d\n", file, size, err); + return err; + } + map_ = (HANDLE)::open(file, O_RDWR, 0666); + utils::to_log(LOG_LEVEL_DEBUG, "FileMapping: open('%s', O_APPEND, 0666) = %p\n", file, map_); + } + if (map_ == INVALID_HANDLE_VALUE) + { + int err = errno; + + if(!readonly) + remove(file); + utils::to_log(LOG_LEVEL_WARNING, "FileMapping: create mapping object for '%s' failed: %d.\n", file, err); + + return err; + } +#endif + + path_file_ = file; + total_ = size; + read_only_ = readonly; + + return 0; +} +int file_map::close(void) +{ + unmap(); + + if (map_ != INVALID_HANDLE_VALUE) +#if OS_WIN + CloseHandle(map_); +#else + ::close((int)(long)map_); +#endif + + map_ = INVALID_HANDLE_VALUE; + total_ = 0; + + return 0; +} +uint64_t file_map::total_size(void) +{ + return total_; +} +uint8_t* file_map::map(uint64_t off, uint32_t* size) +{ + uint32_t len = 0; + + unmap(); + + if (!size) + size = &len; + + if (off < total_) + { + DWORD hi = 0, + lo = 0, + cnt = 0; + + map_off_ = off / os_map_size_ * os_map_size_; + off_ = off - map_off_; + hi = map_off_ >> 32; + lo = map_off_; + cnt = total_ - map_off_; + if (cnt - off > *size && *size) + { + cnt = ALIGN_TO(*size + off, os_map_size_); + if(cnt > total_ - map_off_) + cnt = total_ - map_off_; + } + map_size_ = cnt; +#if OS_WIN + buf_ = (uint8_t*)MapViewOfFile(map_, read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, hi, lo, map_size_); +#else + int priv = PROT_READ, prot = MAP_PRIVATE; + if (!read_only_) + { + priv |= PROT_WRITE; + prot = MAP_SHARED; + } + buf_ = (uint8_t*)mmap(nullptr, map_size_, priv, prot, (int)(long)map_, map_off_); + if(buf_ == INVALID_HANDLE_VALUE) + buf_ = nullptr; +#endif + if (!buf_) + { + utils::to_log(LOG_LEVEL_WARNING, "FileMapping: request map(%p + %u), real map(%p + %u) failed: %d\n" + , off, *size, map_off_, map_size_, GetLastError()); + *size = 0; + } + else + *size = cnt - off; + } + + return buf_ ? buf_ + off_ : nullptr; +} +uint8_t* file_map::buffer(void) +{ + return buf_ ? buf_ + off_ : nullptr; +} diff --git a/sdk/base/data.h b/sdk/base/data.h index e3e6a50..e5a30d5 100644 --- a/sdk/base/data.h +++ b/sdk/base/data.h @@ -27,6 +27,7 @@ class packet_data_base : public refer protected: uint32_t pack_cmd_; uint32_t pack_id_; + uint32_t session_id_ = -1; public: packet_data_base(); @@ -37,12 +38,44 @@ protected: public: void set_packet_param(uint32_t cmd, uint32_t id); + void set_session_id(uint32_t session_id); + int get_packet_command(void); int get_packet_id(void); + uint32_t get_session_id(void); void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr); }; +class file_map : public refer +{ + bool read_only_ = false; // + uint32_t os_map_size_ = 0; // desired mapping size of OS + uint64_t total_ = 0; // total size of the whole file + HANDLE map_ = INVALID_HANDLE_VALUE; // handle of the map-object + std::string path_file_; // local file + + uint64_t map_off_ = 0; // offset in the file of current mapping buffer + uint32_t map_size_ = 0; // size of current mapping buffer + uint32_t off_ = 0; // offset to align to os_map_size_ + uint8_t* buf_ = nullptr; // current mapping buffer + + void unmap(void); + +public: + file_map(); + +protected: + ~file_map(); + +public: + int open(const char* file, uint64_t size, bool readonly); + int close(void); + uint64_t total_size(void); + uint8_t* map(uint64_t off = 0, uint32_t* size = 0); // size - in: desired size, 0 is from off to end; out: real size + uint8_t* buffer(void); +}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // /* data_holder, used when data is also required for a certain packet @@ -58,6 +91,7 @@ public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) = 0; // return error code virtual bool is_complete(void) = 0; virtual uint32_t get_required(void) = 0; + virtual void cancel(void); }; class mem_holder : public data_holder @@ -107,6 +141,7 @@ class file_saver : public data_holder std::string path_; std::string check_; FILE *dst_; + file_map *map_ = nullptr; uint32_t pack_cmd_; uint32_t pack_id_; @@ -118,12 +153,14 @@ protected: ~file_saver(); public: - int open(const char* path, uint64_t size, const char* check = nullptr); + int set_verify_data(const char* data, size_t len); + int open(const char* path, uint64_t size, bool in_mem = false, size_t off = 0); public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override; virtual bool is_complete(void) override; virtual uint32_t get_required(void) override; + virtual void cancel(void) override; }; @@ -198,9 +235,10 @@ public: class file_reader : public data_source { - size_t len_; - size_t consume_; - FILE *src_; + size_t len_; + size_t consume_; + FILE *src_ = nullptr; + file_map *map_ = nullptr; std::string path_; public: @@ -210,7 +248,7 @@ protected: ~file_reader(); public: - int open(const char* file); + int open(const char* file, bool in_mem, size_t off = 0); int attach(FILE* f); FILE* detach(void); @@ -225,6 +263,7 @@ public: virtual int fetch_data(void* buf, uint32_t* size) override; }; + CLS_PTR(packet_data_base); CLS_PTR(data_holder); CLS_PTR(mem_holder); diff --git a/sdk/base/packet.h b/sdk/base/packet.h index e40ae4c..dfc51e2 100644 --- a/sdk/base/packet.h +++ b/sdk/base/packet.h @@ -50,13 +50,13 @@ enum ep0_req USB_REQ_EP0_SET_ENCRYPT, // 设置加密方式, req = me, ind = 0, val = 0, len = sizeof(PACK_BASE) USB_REQ_EP0_SET_BULK_BUFFER, // 设置bulk缓冲区大小系数, req = me, ind = coef, val = 0, len = 0 }; -enum bulk_status +enum woker_status { - BULK_STATUS_NOT_START = 0, // has not initialized - BULK_STATUS_IDLE, // wait IO - BULK_STATUS_IO, // in reading or writing - BULK_STATUS_ERROR, // error occurs - BULK_STATUS_RESET, // in reset(close and reopen) process + WORKER_STATUS_NOT_START = 0, // has not start + WORKER_STATUS_IDLE, // idle + WORKER_STATUS_BUSY, // in working + WORKER_STATUS_ERROR, // error occurs + WORKER_STATUS_RESET, // in reset(close and reopen) process }; enum packet_cmd diff --git a/sdk/base/plat_types.h b/sdk/base/plat_types.h new file mode 100644 index 0000000..17f31ce --- /dev/null +++ b/sdk/base/plat_types.h @@ -0,0 +1,127 @@ +#pragma once + +#if defined(WIN32) || defined(_WIN64) +#define OS_WIN 1 +#else +#define OS_WIN 0 +#endif + +#define SIZE_KB(n) ((n) * 1024) +#define SIZE_MB(n) SIZE_KB(n * 1024) +#define SIZE_GB(n) SIZE_MB(n * 1024) + +#define SEC_2_MS(s) ((s) * 1000) +#define MSEC_2_US(ms) ((ms) * 1000) +#define SEC_2_US(s) MSEC_2_US(SEC_2_MS(s)) + +#define ALIGN_TO(v, align) (((v) + (align) - 1) / (align) * (align)) +#define ALIGN_INT(v) ALIGN_TO(v, sizeof(int)) + +#define RETURN_ENUM_STR(v, e) \ + if(v == e) \ + return #e; + + +#if !OS_WIN // migrate codes from windows to linux ... +#include +#include +#include +#include +#include + +#pragma pack(push) +#pragma pack(1) +typedef struct BITMAPFILEHEADER +{ + u_int16_t bfType; + u_int32_t bfSize; + u_int16_t bfReserved1; + u_int16_t bfReserved2; + u_int32_t bfOffBits; +}BITMAPFILEHEADER; + +typedef struct BITMAPINFOHEADER +{ + u_int32_t biSize; + u_int32_t biWidth; + u_int32_t biHeight; + u_int16_t biPlanes; + u_int16_t biBitCount; + u_int32_t biCompression; + u_int32_t biSizeImage; + u_int32_t biXPelsPerMeter; + u_int32_t biYPelsPerMeter; + u_int32_t biClrUsed; + u_int32_t biClrImportant; +}BITMAPINFODEADER; +#pragma pack(pop) +#define BI_RGB 0 +#define MAKEWORD(a, b) (((a) & 0x0ff) | (((b) & 0x0ff) << 8)) +#define MAKELONG(a, b) (((a) & 0x0ffff) | (((b) & 0x0ffff) << 16)) +#define _countof(a) (sizeof(a) / sizeof((a)[0])) + +typedef long LONG; +typedef void* HANDLE; +typedef void* HWND; +typedef void* HMODULE; +typedef void* LPVOID; +typedef void* FARPROC; +typedef unsigned int DWORD; +typedef unsigned short WORD; +typedef unsigned short UINT16; +typedef unsigned char BYTE; +typedef int BOOL; + +#define TRUE 1 +#define FALSE 0 +#define MAX_PATH 256 +#define huge +#define FAR +#define NEAR +#define LOWORD(v) ((v) & 0x0ffff) +#define HIWORD(v) (((v) >> 16) & 0x0ffff) +#define PASCAL __attribute__((stdcall)) +#define _countof(a) (sizeof(a) / sizeof(a[0])) +#define LOAD_WITH_ALTERED_SEARCH_PATH RTLD_NOW +#define FreeLibrary dlclose +#define GetProcAddress dlsym +#define GetPrivateProfileIntW GetPrivateProfileIntA +#define lstrlenA strlen +#define lstrlenW strlen + +#define DLL_EXTESION "so" +#define PATH_SEPARATOR "/" +#define STRICMP strcasecmp +#define MKDIR(a, b) mkdir(a, b) +#define STDCALL +#define ERROR_CANCELLED 1223 +#define USB_TIMEOUT_INFINITE 0 +#define FSEEK fseek +#define FTELL ftell +#define INVALID_HANDLE_VALUE ((HANDLE)(-1)) + + +extern DWORD GetLastError(void); +extern DWORD GetPrivateProfileIntA(const char* app, const char* key, DWORD def, const char* file); +extern DWORD GetPrivateProfileStringA(const char* app, const char* key, const char* init, char* buf, size_t len, const char* file); +extern void Sleep(DWORD milliseconds); +extern int GetModuleFileNameA(HMODULE module, char* buf, size_t len); // NOTE: parameter 'module' is consinder as a part of the module file name +extern uint64_t GetCurrentProcessId(void); +extern uint64_t GetCurrentThreadId(void); + +#else +#include + +#define bzero(a, l) memset(a, 0, l) +#define DLL_EXTESION "dll" +#define PATH_SEPARATOR "\\" +#define STRICMP stricmp +#define MKDIR(a, b) mkdir(a) +#define STDCALL __stdcall +#define sem_t HANDLE +#define USB_TIMEOUT_INFINITE -1 +#define FSEEK _fseeki64 +#define FTELL _ftelli64 +#define pid_t int + +#endif diff --git a/sdk/base/utils.cpp b/sdk/base/utils.cpp index 5dd40bf..574c626 100644 --- a/sdk/base/utils.cpp +++ b/sdk/base/utils.cpp @@ -1,6 +1,5 @@ #include "utils.h" -#include "huagao/brand.h" #include "ini_file.h" @@ -71,6 +70,8 @@ int gettimeofday(TIMEV* tv, struct timezone* tz) #include #include +#define PRODUCT_VENDOR "HuaGo" + static std::mutex ini_lock_; static std::map ini_files_; static std::string debug_cfg_file_ = ""; @@ -195,13 +196,13 @@ int GetModuleFileNameA(HMODULE module, char* buf, size_t len) return len; } -int GetCurrentThreadId(void) +uint64_t GetCurrentThreadId(void) { - return pthread_self(); + return (uint64_t)pthread_self(); } -int GetCurrentProcessId(void) +uint64_t GetCurrentProcessId(void) { - return getpid(); + return (uint64_t)getpid(); } #endif @@ -235,7 +236,7 @@ class log_cls } else { - std::string sep("\n\n===================================================================================================================\n"); + std::string sep("\n\n========================================================================================================================\n"); fwrite(sep.c_str(), sizeof(sep[0]), sep.length(), file_); } @@ -548,7 +549,7 @@ namespace utils } #endif - std::string get_command_result(const char* cmd, int len) + std::string get_command_result(const char* cmd, int len, int *err) { std::string result(""); @@ -556,6 +557,8 @@ namespace utils #else FILE* src = popen(cmd, "r"); + if(err) + *err = 0; if (src) { char buf[128] = { 0 }; @@ -572,8 +575,18 @@ namespace utils } rv = fread(buf, 1, sizeof(buf) - 1, src); } + if(rv == -1 && err) + { + *err = errno; + utils::to_log(LOG_LEVEL_DEBUG, "Failed to excute shell command '%s' in read pipe: %d - %s\n", cmd, errno, strerror(errno)); + } pclose(src); } + else if(err) + { + *err = errno; + utils::to_log(LOG_LEVEL_DEBUG, "Failed to excute shell command '%s' in open pipe: %d - %s\n", cmd, errno, strerror(errno)); + } #endif return std::move(result); @@ -973,6 +986,36 @@ namespace utils { return rename(from, to); } + int make_file_size(const char* file, uint64_t size) + { + int err = 0; + + get_command_result(("fallocate -l " + std::to_string(size) + " " + file).c_str(), -1, &err); + if(err == 0) + { + get_command_result(("truncate -s " + std::to_string(size) + " " + file).c_str(), -1, &err); + if(err == 0) + { + FILE* dst = fopen(file, "rb"); + if(dst) + { + uint64_t rs = 0; + + FSEEK(dst, 0, SEEK_END); + rs = FTELL(dst); + fclose(dst); + if(rs != size) + err = ENOSPC; + } + else + err = errno; + } + } + if(err) + remove(file); + + return err; + } int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block) { @@ -1044,7 +1087,7 @@ namespace utils return ps; } - void init_log(log_type type, log_level level, const char* fn_appendix) + std::string init_log(log_type type, log_level level, const char* fn_appendix) { std::string file(""); @@ -1062,10 +1105,13 @@ namespace utils if (fn_appendix) file += fn_appendix; file += ".log"; + printf("log file: %s\n", file.c_str()); } log_cls::instance()->set_log_type(type, &file[0]); log_cls::instance()->set_log_level(level); + + return std::move(file); } void uninit(void) { @@ -1846,40 +1892,92 @@ int shared_memory::write(const char* data, size_t len) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // safe_thread -safe_thread::safe_thread() : name_("") -{} +safe_thread::safe_thread() : excep_que_("thread-exception") +{ + notify_thread_.reset(new std::thread(&safe_thread::thread_notify_exception, this)); +} safe_thread::~safe_thread() { - if (thread_.get() && thread_->joinable()) - thread_->join(); + run_ = false; + excep_que_.trigger(); + + if(notify_thread_->joinable()) + notify_thread_->join(); + + for(auto& v: threads_) + { + if(v.thread.get() && v.thread->joinable()) + v.thread->join(); + } + threads_.clear(); } -void safe_thread::thread_worker(std::function func, void* param, std::function on_exception) +void safe_thread::thread_worker(std::function func, std::string name, void* addr) { try { - func(param); + utils::to_log(LOG_LEVEL_DEBUG, "+++ safe_thread of '%s(%p) - %p' is running ...\n", name.c_str(), addr, GetCurrentThreadId()); + func(); + utils::to_log(LOG_LEVEL_DEBUG, "--- safe_thread of '%s - %p' exited.\n", name.c_str(), GetCurrentThreadId()); return; } catch (std::exception e) { - utils::to_log(LOG_LEVEL_FATAL, "Exception in thread '%s': %s\n", name_.c_str(), e.what()); + utils::to_log(LOG_LEVEL_FATAL, "Exception in thread '%p - %s': %s\n", GetCurrentThreadId(), name.c_str(), e.what()); } catch (...) { - utils::to_log(LOG_LEVEL_FATAL, "Unknown exception in thread '%s'!\n", name_.c_str()); + utils::to_log(LOG_LEVEL_FATAL, "Unknown exception in thread '%p - %s'!\n", GetCurrentThreadId(), name.c_str()); + } + excep_que_.save(name, true); +} +void safe_thread::thread_notify_exception(void) +{ + while(run_) + { + std::string name(""); + if(excep_que_.take(name, true)) + { + if(excep_handler_) + excep_handler_(name.c_str()); + } } - if (on_exception) - on_exception(); } -int safe_thread::start(std::function f, void* param, const char* thread_name, std::function on_exception) +void safe_thread::set_exception_handler(std::function on_exception) { - if (thread_.get() && thread_->joinable()) - thread_->join(); + excep_handler_ = on_exception; +} +int safe_thread::start(std::function f, const char* thread_name, void* addr) +{ + SAFETHRD st; - name_ = thread_name ? thread_name : ""; - thread_.reset(new std::thread(&safe_thread::thread_worker, this, f, param, on_exception)); + st.name = thread_name ? thread_name : ""; + st.thread.reset(new std::thread(&safe_thread::thread_worker, this, f, thread_name, addr)); + + { + SIMPLE_LOCK(lock_); + threads_.push_back(st); + } return 0; } +int safe_thread::stop(const char* thread_name) +{ + int ret = ENOENT; + + SIMPLE_LOCK(lock_); + for(int i = 0; i < threads_.size(); ++i) + { + if(threads_[i].name == thread_name) + { + if(threads_[i].thread.get() && threads_[i].thread->joinable()) + threads_[i].thread->join(); + threads_.erase(threads_.begin() + i); + ret = 0; + break; + } + } + + return ret; +} \ No newline at end of file diff --git a/sdk/base/utils.h b/sdk/base/utils.h index 3307695..811c833 100644 --- a/sdk/base/utils.h +++ b/sdk/base/utils.h @@ -5,7 +5,7 @@ #pragma once -#include +#include "plat_types.h" #include #include #include @@ -37,7 +37,7 @@ namespace utils std::string utf82ansi(const char* utf8); std::string ansi2utf8(const char* ansi); - std::string get_command_result(const char* cmd, int len = -1); + std::string get_command_result(const char* cmd, int len = -1, int *err = nullptr); std::string get_local_data_path(void); std::string temporary_path(void); std::string format_current_time(void); @@ -57,11 +57,13 @@ namespace utils void set_ini_value(const char* seg, const char* key, const char* val, const char* cfg_file); int enum_file(const char* folder, bool recursive, bool/*return false to stop enumeration*/(STDCALL* found)(const char* path_name, bool dir, void* param), void* param); int move_file(const char* from, const char* to); + int make_file_size(const char* file, uint64_t size); // truncate or extend file size to 'size', create if not exist int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block); unsigned int get_page_size(unsigned int* map_unit = nullptr); - void init_log(log_type type, log_level level = LOG_LEVEL_ALL, const char* fn_appendix = nullptr/*appendix to default log-file-name*/); + // return logging file path if 'type' was LOG_TYPE_FILE + std::string init_log(log_type type, log_level level = LOG_LEVEL_ALL, const char* fn_appendix = nullptr/*appendix to default log-file-name*/); void uninit(void); void log_info(const char* info, int level = LOG_LEVEL_ALL); void log_mem_info(const char* desc, const void* data, size_t bytes, int level = LOG_LEVEL_ALL); // log as 0x12345678 00 01 02 ... @@ -342,15 +344,27 @@ public: class safe_thread { - std::unique_ptr thread_; - std::string name_; - - void thread_worker(std::function func, void* param, std::function on_exception); + typedef struct _safe_thrd + { + std::string name; + std::shared_ptr thread; + }SAFETHRD; + volatile bool run_ = true; + MUTEX lock_; + std::unique_ptr notify_thread_; + std::vector threads_; + safe_fifo excep_que_; + std::function excep_handler_ = std::function(); + + void thread_worker(std::function func, std::string name, void* addr); + void thread_notify_exception(void); public: safe_thread(void); ~safe_thread(); public: - int start(std::function f, void* param, const char* thread_name, std::function on_exception = std::function()); + void set_exception_handler(std::function on_exception = std::function()); + int start(std::function f, const char* thread_name, void* addr = nullptr); + int stop(const char* thread_name); }; diff --git a/sdk/sane_opt_json/base_opt.cpp b/sdk/sane_opt_json/base_opt.cpp index 3a7dcca..70ae256 100644 --- a/sdk/sane_opt_json/base_opt.cpp +++ b/sdk/sane_opt_json/base_opt.cpp @@ -1,7 +1,7 @@ #include "base_opt.h" #include -#include "../../../sdk/include/huagao/hgscanner_error.h" +#include sane_opt_provider::sane_opt_provider() diff --git a/sdk/sane_opt_json/base_opt.h b/sdk/sane_opt_json/base_opt.h index c6ce6e6..6f163cd 100644 --- a/sdk/sane_opt_json/base_opt.h +++ b/sdk/sane_opt_json/base_opt.h @@ -8,7 +8,6 @@ #include #include #include // for refer -#include class sane_opt_provider : public refer { diff --git a/sdk/sane_opt_json/device_opt.cpp b/sdk/sane_opt_json/device_opt.cpp index aa4d564..59aa556 100644 --- a/sdk/sane_opt_json/device_opt.cpp +++ b/sdk/sane_opt_json/device_opt.cpp @@ -1,13 +1,19 @@ #include "device_opt.h" #include -#include #include "base_opt.h" -#include #include #include +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +static const char* empty_from_default_language(const char* deflang) +{ + return deflang; +} +static const char*(*from_def_lang)(const char*) = empty_from_default_language; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // image-processing jsons ... @@ -380,7 +386,7 @@ bool device_option::is_equal_f(gb_json* opt, void* val, void* v1, void* v2) } bool device_option::is_equal_s(gb_json* opt, void* val, void* v1, void* v2) { - return strcmp((char*)val, from_default_language((char*)v1)) == 0; + return strcmp((char*)val, from_def_lang((char*)v1)) == 0; } bool device_option::is_less_b(gb_json* opt, void* val, void* v1, void* v2) @@ -397,7 +403,7 @@ bool device_option::is_less_f(gb_json* opt, void* val, void* v1, void* v2) } bool device_option::is_less_s(gb_json* opt, void* val, void* v1, void* v2) { - return strcmp((char*)val, from_default_language((char*)v1)) < 0; + return strcmp((char*)val, from_def_lang((char*)v1)) < 0; } bool device_option::is_great_b(gb_json* opt, void* val, void* v1, void* v2) @@ -414,7 +420,7 @@ bool device_option::is_great_f(gb_json* opt, void* val, void* v1, void* v2) } bool device_option::is_great_s(gb_json* opt, void* val, void* v1, void* v2) { - return strcmp((char*)val, from_default_language((char*)v1)) > 0; + return strcmp((char*)val, from_def_lang((char*)v1)) > 0; } bool device_option::is_between_b(gb_json* opt, void* val, void* v1, void* v2) @@ -431,8 +437,8 @@ bool device_option::is_between_f(gb_json* opt, void* val, void* v1, void* v2) } bool device_option::is_between_s(gb_json* opt, void* val, void* v1, void* v2) { - return strcmp((char*)val, from_default_language((char*)v1)) >= 0 && - strcmp((char*)val, from_default_language((char*)v2)) <= 0; + return strcmp((char*)val, from_def_lang((char*)v1)) >= 0 && + strcmp((char*)val, from_def_lang((char*)v2)) <= 0; } bool device_option::is_opt_enabled(gb_json* opt, void* val, void* v1, void* v2) @@ -1152,13 +1158,42 @@ void device_option::insert_option(gb_json* opt, sane_opt_provider* from, const c } else { - int index = -1; + int index = -1, pos = -1; if (group) index = insert_group(group, group); - index = next_group(index + 1); + // insert poisition according to 'ui-pos' + if (!opt->get_value("ui-pos", pos) || pos == -1) + { + index = next_group(index + 1); + } + else + { + for (index++; index < origin_->children(); ++index) + { + gb_json* sib = origin_->child(index); + std::string t(""); + int sit = -1; + + if (!sib->get_value("type", t) || t == JSON_SANE_TYPE_GROUP) + { + sib->release(); + break; + } + if (!sib->get_value("ui-pos", sit) || sit == -1) + { + sib->release(); + break; + } + sib->release(); + + if (pos < sit) + break; + } + } origin_->insert(index, opt->key().c_str(), opt); + src_[opt->key()] = from; from->add_ref(); } @@ -1298,13 +1333,30 @@ gb_json* device_option::copy_opt(gb_json* from) // 1: language changed ... (title, description, string-list) if (to->get_value("title", val)) - to->set_value("title", from_default_language(val.c_str())); + to->set_value("title", from_def_lang(val.c_str())); if (to->get_value("desc", val)) - to->set_value("desc", from_default_language(val.c_str())); + to->set_value("desc", from_def_lang(val.c_str())); // 2: enabled ... if (slaver_.count(to->key())) - to->set_value("enabled", slaver_[to->key()]->value(&device_option::calc_simple_logic_expression, this)); + { + bool enable = slaver_[to->key()]->value(&device_option::calc_simple_logic_expression, this); + to->set_value("enabled", enable); + if (src_.count(to->key())) + { + src_[to->key()]->enable(to->key().c_str(), enable); + + sane_opt_provider* next = src_[to->key()]->get_following(to->key().c_str()); + while (next) + { + next->enable(to->key().c_str(), enable); + + sane_opt_provider* next1 = next->get_following(to->key().c_str()); + next->release(); + next = next1; + } + } + } // 3: default value ... if (init_value_.count(to->key())) @@ -1409,18 +1461,18 @@ gb_json* device_option::copy_opt(gb_json* from) for(int i = 0; i < range_value_[to->key()]->count(); ++i) { if(!val.empty()) - *dst += from_default_language(val.c_str()); + *dst += from_def_lang(val.c_str()); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } else { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); - dst->set_value("min", from_default_language(val.c_str())); + dst->set_value("min", from_def_lang(val.c_str())); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); - dst->set_value("max", from_default_language(val.c_str())); + dst->set_value("max", from_def_lang(val.c_str())); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); - dst->set_value("step", from_default_language(val.c_str())); + dst->set_value("step", from_def_lang(val.c_str())); } } } @@ -1621,6 +1673,10 @@ std::string device_option::get_group(int ind, bool title) else return ""; } +void device_option::set_from_default_language_api(const char*(*fdl)(const char*)) +{ + from_def_lang = fdl ? fdl : empty_from_default_language; +} void device_option::clear(void) { diff --git a/sdk/sane_opt_json/device_opt.h b/sdk/sane_opt_json/device_opt.h index e347822..e8c48e9 100644 --- a/sdk/sane_opt_json/device_opt.h +++ b/sdk/sane_opt_json/device_opt.h @@ -351,6 +351,7 @@ public: static std::string trans_group(const char* utf8, bool to_title); static std::string get_group(int ind, bool title); + static void set_from_default_language_api(const char*(*fdl)(const char*)); public: void clear(void);