Complete the basic work of the scanning process

This commit is contained in:
gb 2023-04-12 17:57:04 +08:00
parent 33545559d3
commit 25a4395bb2
24 changed files with 764 additions and 96 deletions

View File

@ -12,14 +12,20 @@
#include "usb_io.h"
#include <sane_cfg.h>
#define ASYNC_EP
#include <imemory.h>
class UsbDevice
#ifdef ASYNC_EP
: public sane_cfg_provider
#endif
{
#ifdef ASYNC_EP
async_usb_gadget *usb_;
sane_cfg_mgr *cfg_;
uint32_t img_cnt_;
uint32_t scan_id_;
uint32_t dpi_;
std::string cfg_text_;
dyn_mem_ptr unhandled_ep0(struct usb_functionfs_event* pev);
dyn_mem_ptr handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
@ -35,6 +41,12 @@ class UsbDevice
void do_system_command(const char* cmd);
void init(void);
public:
void save_image(MemoryPtr data, bool img);
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* strval = nullptr) override;
virtual int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) override;
#endif
public:

View File

@ -51,7 +51,7 @@ namespace sys_util
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
packet_data_base::packet_data_base() : pack_cmd_(0), pack_id_(0)
, progress_notify_(PROGRESS_NOTIFYER())
, progress_notify_(PROGRESS_NOTIFYER()), user_data_(nullptr)
{}
packet_data_base::~packet_data_base()
{}
@ -59,7 +59,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);
progress_notify_(total, cur_size, err, user_data_);
else
return ENOENT;
}
@ -78,9 +78,10 @@ int packet_data_base::get_packet_id(void)
return pack_id_;
}
void packet_data_base::set_progress_notify(PROGRESS_NOTIFYER notify)
void packet_data_base::set_progress_notify(PROGRESS_NOTIFYER notify, void* param)
{
progress_notify_ = notify;
user_data_ = param;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -18,11 +18,12 @@
//
/* packet parameter keeper, parameter of corresponding packet
*/
#define PROGRESS_NOTIFYER std::function<int(uint64_t/*total*/, uint64_t/*cur-size*/, uint32_t/*err*/)>
#define PROGRESS_NOTIFYER std::function<int(uint64_t/*total*/, uint64_t/*cur-size*/, uint32_t/*err*/, void*/*user data*/)>
class packet_data_base : public refer
{
PROGRESS_NOTIFYER progress_notify_;
void* user_data_;
protected:
uint32_t pack_cmd_;
@ -40,7 +41,7 @@ public:
int get_packet_command(void);
int get_packet_id(void);
void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER());
void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr);
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -380,7 +380,7 @@ bool json::get_value(const char* key, json*& val)
if (child)
{
if (child->type_ == VAL_TYPE_OBJECT)
if (child->type_ == VAL_TYPE_OBJECT || child->type_ == VAL_TYPE_ARRAY)
{
val = child;
ret = true;

View File

@ -120,6 +120,9 @@ enum scanner_status
SCANNER_STATUS_PAPER_ASKEW,
SCANNER_STATUS_FEED_FAILED,
SCANNER_STATUS_NO_PAPER,
SCANNER_STATUS_STAPLE_ON,
SCANNER_STATUS_SIZE_ERR,
SCANNER_STATUS_DOGEAR,
SCANNER_STATUS_CFG_CHANGED, // PACK_BASE::payload - LPCFGVAL
};

View File

@ -30,7 +30,7 @@ sane_cfg_provider::sane_cfg_provider()
sane_cfg_provider::~sane_cfg_provider()
{}
std::string sane_cfg_provider::sane_option_value_get(json* jsn, const char* key)
std::string sane_cfg_provider::sane_option_value_get(json* jsn, const char* key, std::string* strval)
{
std::string type(""), ret("");
@ -41,22 +41,34 @@ std::string sane_cfg_provider::sane_option_value_get(json* jsn, const char* key)
bool v = false;
if (jsn->get_value(key, v))
ret = std::string((char*)&v, sizeof(v));
if(strval)
*strval = v ? "true" : "false";
}
else if (type == "int")
{
int v = false;
int v = 0;
if (jsn->get_value(key, v))
ret = std::string((char*)&v, sizeof(v));
if(strval)
*strval = std::to_string(v);
}
else if (type == "float")
{
double v = false;
if (jsn->get_value(key, v))
ret = std::string((char*)&v, sizeof(v));
if(strval)
{
char buf[80] = {0};
sprintf(buf, "%f", v);
*strval = buf;
}
}
else
{
jsn->get_value(key, ret);
if(strval)
*strval = ret;
}
}
@ -281,19 +293,19 @@ int sane_cfg_mgr::unreg_sane_provider(sane_cfg_provider* prvd)
}
// following APIs' parameters are same as sane_cfg_provider ...
int32_t sane_cfg_mgr::get_config(std::string& text, const char* cfg_name)
int32_t sane_cfg_mgr::get_config(std::string& text, const char* cfg_name, std::string* str)
{
if (cfg_name)
{
if (*cfg_name && cfg_api_.count(cfg_name))
{
size_t len = 0;
int32_t err = cfg_api_[cfg_name].prvd->get_config(nullptr, &len, cfg_name);
int32_t err = cfg_api_[cfg_name].prvd->get_config(nullptr, &len, cfg_name, str);
if (err == ENOMEM)
{
text.resize(len + 1);
err = cfg_api_[cfg_name].prvd->get_config(&text[0], &len, cfg_name);
err = cfg_api_[cfg_name].prvd->get_config(&text[0], &len, cfg_name, str);
text.resize(len);
}

View File

@ -43,7 +43,7 @@ protected:
virtual ~sane_cfg_provider();
public:
static std::string sane_option_value_get(json* jsn, const char* key = "cur"/*cur, default*/);
static std::string sane_option_value_get(json* jsn, const char* key = "cur"/*cur, default*/, std::string* strval = nullptr/*convert value into string*/);
static bool sane_option_value_set(json* jsn, void* data, const char* key = "cur"/*cur, default*/);
public:
@ -56,11 +56,13 @@ public:
// cfg_name - given configuration name, if set, put current value of the configuration in 'buf',
// or put all configurations JSON text in 'buf' if was nullptr. refer to SANE-config
//
// strval - to receive string format value
//
// Return: 0 - on success
// EINVAL - if paramter 'len' was nullptr
// ENOMEM - if size of 'buf' was too small, the minimum size needed is stored in 'len'
// ENOENT - the configuration named 'cfg_name' has not found
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr) = 0;
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* strval = nullptr) = 0;
// Function: set value of configuration named 'cfg_name'
//
@ -110,7 +112,7 @@ public:
int unreg_sane_provider(sane_cfg_provider* prvd); // return 0, ENOENT
// following APIs' parameters are same as sane_cfg_provider ...
int32_t get_config(std::string& text, const char* cfg_name = nullptr);
int32_t get_config(std::string& text, const char* cfg_name = nullptr, std::string* str = nullptr);
int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo);
};
@ -123,7 +125,7 @@ protected:
~hardware();
public:
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr) override;
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* str = nullptr) override;
virtual int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) override;
};
@ -138,7 +140,7 @@ protected:
~img_processor();
public:
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr) override;
virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* str = nullptr) override;
virtual int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) override;
};

View File

@ -321,6 +321,41 @@ namespace sys_util
return 0;
}
std::string get_memory_usage(const char* prog_name)
{
std::string val(get_command_output((std::string("ps -Al | grep ") + prog_name).c_str()));
if(val.length())
{
int cnt = 0;
bool space = false;
for(int i = 0; i < val.length(); ++i)
{
if(val[i] == ' ')
{
if(!space)
{
space = true;
cnt++;
}
}
else
{
space = false;
if(cnt == 9) // this value is unreliable ...
{
val.erase(0, i);
cnt = val.find(" ");
if((size_t)cnt != std::string::npos)
val.erase(cnt);
break;
}
}
}
}
return val;
}
std::string format_readable_bytes(uint64_t bytes)
{
std::string str("\0", 80);

View File

@ -65,6 +65,7 @@ namespace sys_util
}
int32_t get_memory_info(uint64_t* total, uint64_t* available);
std::string get_memory_usage(const char* prog_name); // return output of command "ps -Al | grep prog_name"
std::string format_readable_bytes(uint64_t bytes); // convert to readable text: 512B, 1.21KB, 1.10MB, 3.45GB, 1,234.56GB ...
std::string get_command_output(const char* cmd, uint16_t max_line_len = 256, bool one_line = true);
int get_disk_size(const char* path, uint64_t* total, uint64_t* avail, uint64_t* block_size);

View File

@ -43,12 +43,19 @@ usb_gadget* usb_gadget_config::get_config(void)
}
static void print_mem_usage(const char* tips)
{
std::string size(sys_util::get_memory_usage("scan"));
printf("\n--Memory usage of %s: %s--\n", tips, size.c_str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// async_usb_gadget
async_usb_gadget::async_usb_gadget(usb_gadget* gadget, std::function<FUNCTION_PROTO_UNHANDLED_EP0> unhandled_ep0
, std::function<FUNCTION_PROTO_COMMAND_HANDLE> cmd_handler)
: gadget_(gadget), unhandled_ep0_(unhandled_ep0), handle_cmd_(cmd_handler), threads_(new thread_pool<async_usb_gadget>(this))
, std::function<FUNCTION_PROTO_COMMAND_HANDLE> cmd_handler
, std::function<void(bool)> dev_conn)
: gadget_(gadget), unhandled_ep0_(unhandled_ep0), handle_cmd_(cmd_handler), dev_connect_(dev_conn)
, threads_(new thread_pool<async_usb_gadget>(this))
, enc_head_(ENCRYPT_CMD_NONE), enc_payload_(ENCRYPT_NONE), enc_data_(0)
{
wait_ep0_ = new linux_event("wait_ep0");
@ -56,8 +63,11 @@ async_usb_gadget::async_usb_gadget(usb_gadget* gadget, std::function<FUNCTION_PR
memset((void*)&ep0_status_, 0, sizeof(ep0_status_));
threads_->thread_new(&async_usb_gadget::thread_pump_task);
print_mem_usage("thread_new(&async_usb_gadget::thread_pump_task)");
thread_ep0_id_ = threads_->thread_new(&async_usb_gadget::thread_read_ep0);
print_mem_usage("thread_new(&async_usb_gadget::thread_read_ep0)");
threads_->thread_new(&async_usb_gadget::thread_check_ep0_status);
print_mem_usage("thread_new(&async_usb_gadget::thread_check_ep0_status)");
}
async_usb_gadget::~async_usb_gadget()
@ -125,23 +135,27 @@ int async_usb_gadget::open_bulk(void)
if (gadget_->ep_handles[EP_DESCRIPTOR_IN] < 0)
{
gadget_->ep_handles[EP_DESCRIPTOR_IN] = open(gadget_->ep_path[EP_DESCRIPTOR_IN], O_RDWR);
print_mem_usage("open_bulk_in");
err = gadget_->ep_handles[EP_DESCRIPTOR_IN] == -1 ? errno : 0;
log_cls::log(LOG_LEVEL_ALL, "Open endpoint(%s) = %d (err = %d)\n", gadget_->ep_path[EP_DESCRIPTOR_IN], gadget_->ep_handles[EP_DESCRIPTOR_IN], err);
if(gadget_->ep_handles[EP_DESCRIPTOR_IN] >= 0)
{
status_.in_status = BULK_STATUS_IDLE;
thread_bulk_in_id_ = threads_->thread_new(&async_usb_gadget::thread_write_bulk);
print_mem_usage("thread_new(&async_usb_gadget::thread_write_bulk)");
}
}
if (gadget_->ep_handles[EP_DESCRIPTOR_OUT] < 0)
{
gadget_->ep_handles[EP_DESCRIPTOR_OUT] = open(gadget_->ep_path[EP_DESCRIPTOR_OUT], O_RDWR);
print_mem_usage("open_bulk_out");
err = gadget_->ep_handles[EP_DESCRIPTOR_OUT] == -1 ? errno : 0;
log_cls::log(LOG_LEVEL_ALL, "Open endpoint(%s) = %d (err = %d)\n", gadget_->ep_path[EP_DESCRIPTOR_OUT], gadget_->ep_handles[EP_DESCRIPTOR_OUT], err);
if(gadget_->ep_handles[EP_DESCRIPTOR_OUT] >= 0)
{
status_.out_status = BULK_STATUS_IDLE;
thread_bulk_out_id_ = threads_->thread_new(&async_usb_gadget::thread_read_bulk);
print_mem_usage("thread_new(&async_usb_gadget::thread_read_bulk)");
}
}
@ -225,11 +239,15 @@ int async_usb_gadget::handle_ctrl_message(dyn_mem_ptr data)
if (gadget_->ep_handles[EP_DESCRIPTOR_IN] < 0)
{
open_bulk();
print_mem_usage("open_bulk");
dev_connect_(true);
}
break;
case FUNCTIONFS_DISABLE:
log_cls::log(LOG_LEVEL_ALL, "EP0 FFS DISABLE\n");
dev_connect_(false);
close_bulk();
print_mem_usage("close_bulk");
break;
case FUNCTIONFS_SETUP:
// log_cls::log(LOG_LEVEL_ALL, "%s: control(type-%x, req-%x, ind-%x, val-%x, len-%x)\n", chronograph::now().c_str()
@ -364,8 +382,6 @@ int async_usb_gadget::inner_write_bulk(data_source_ptr data, int* err)
ptr = buf->ptr();
off = 0;
w = write(gadget_->ep_handles[EP_DESCRIPTOR_IN], ptr + off, len);
if(w > 0 && w + off == len)
status_.bytes_to_sent -= w;
while(!reset_bulk_ && w > 0 && w + off < len)
{
status_.bytes_to_sent -= w;
@ -378,10 +394,14 @@ int async_usb_gadget::inner_write_bulk(data_source_ptr data, int* err)
{
if(err)
*err = errno;
log_cls::log(LOG_LEVEL_ALL, "inner_write_bulk error(%d/%d): %d (%s)\n", off, len, errno, strerror(errno));
break;
}
else
{
status_.bytes_to_sent -= w;
total += w;
}
if(data->get_rest() == 0)
break;
@ -389,7 +409,7 @@ int async_usb_gadget::inner_write_bulk(data_source_ptr data, int* err)
}
buf->release();
off = total;
log_cls::log(LOG_LEVEL_ALL, "Finished in send large content with %u bytes.\n", total);
log_cls::log(LOG_LEVEL_ALL, "Finished in sending large content with %u bytes.\n", total);
}
return off;
@ -742,7 +762,7 @@ void async_usb_gadget::thread_pump_task(void)
BASE_PACKET_REPLY(*pack, dh->get_packet_command() + 1, dh->get_packet_id(), err);
reply->set_len(sizeof(PACK_BASE));
log_cls::log(LOG_LEVEL_ALL, "Finished received file with error(Max queue size is %u): %d, total size = 0x%x\n", max_que, err, total_size);
log_cls::log(LOG_LEVEL_ALL, "Finished receiving file with error(Max queue size is %u): %d, total size = 0x%x\n", max_que, err, total_size);
dh->release();
dh = nullptr;

View File

@ -103,6 +103,7 @@ class async_usb_gadget : public refer
std::function<FUNCTION_PROTO_UNHANDLED_EP0> unhandled_ep0_;
std::function<FUNCTION_PROTO_COMMAND_HANDLE> handle_cmd_;
std::function<void(bool)> dev_connect_;
const char* ep0_status_desc(int ep0_status, char* unk_buf/*>= 40 bytes*/);
void set_ep0_status(uint32_t id, int status, int data);
@ -126,7 +127,8 @@ class async_usb_gadget : public refer
public:
async_usb_gadget(usb_gadget* gadget, std::function<FUNCTION_PROTO_UNHANDLED_EP0> unhandled_ep0 = std::function<FUNCTION_PROTO_UNHANDLED_EP0>()
, std::function<FUNCTION_PROTO_COMMAND_HANDLE> cmd_handler = std::function<FUNCTION_PROTO_COMMAND_HANDLE>());
, std::function<FUNCTION_PROTO_COMMAND_HANDLE> cmd_handler = std::function<FUNCTION_PROTO_COMMAND_HANDLE>()
, std::function<void(bool)> dev_conn = std::function<void(bool)>());
protected:
~async_usb_gadget();

File diff suppressed because one or more lines are too long

View File

@ -7,15 +7,24 @@
#include "ireceive.h"
#include "BlockingQueue.h"
#include <functional>
class UsbImageProcQueue
{
void(*img_keeper_)(MemoryPtr, bool, void*);
void* kp_param_;
public:
UsbImageProcQueue(NotifyPtr notify)
UsbImageProcQueue(NotifyPtr notify) : img_keeper_(nullptr), kp_param_(nullptr)
{
this->notify = notify;
}
void push(MemoryPtr image,bool containsimg)
{
if(img_keeper_)
img_keeper_(image, containsimg, kp_param_);
else
{
std::lock_guard<std::mutex> lck(mx);
HGIntInfo info;
@ -33,8 +42,15 @@ public:
if(notify)
notify->notify(&info, sizeof(info));
}
}
void set_image_keeper(void(*img_keeper)(MemoryPtr, bool, void*), void* param)
{
img_keeper_ = img_keeper;
kp_param_ = param;
}
MemoryPtr front()
{
std::lock_guard<std::mutex> lck(mx);

View File

@ -76,14 +76,33 @@ static bool write_regs(unsigned int *regs, int regindex, int creg, std::shared_p
return ret;
}
UsbService::UsbService(std::shared_ptr<IRegsAccess> fgparegs, std::shared_ptr<IRegsAccess> motorregs, std::shared_ptr<IRegsAccess> scannerregs)
UsbService::UsbService(std::shared_ptr<IRegsAccess> fgparegs, std::shared_ptr<IRegsAccess> motorregs, std::shared_ptr<IRegsAccess> scannerregs) : devregs(scannerregs)
{
LOG_INIT();
this->fgparegs = fgparegs;
this->motorregs = motorregs;
this->devregs = scannerregs;
// this->devregs = scannerregs;
auto ctrl_handle = [&](int fd, struct usb_ctrlrequest *setup, unsigned char *buffer) -> bool
{
if(fd== -1)
{
if((uint64_t)setup == (uint64_t)-1)
{
uint32_t *p = (uint32_t*)buffer;
devregs->write((unsigned int)-1, p[1]);
devregs->write((unsigned int)-2, p[0]);
devregs->write((unsigned int)-3, p[3]);
devregs->write((unsigned int)-4, p[2]);
}
else
{
printf("setup = %p\n", setup);
devregs->write(/*SR_CMD*/(unsigned int)(uint64_t)setup, /*SC_START*/(unsigned int)(uint64_t)buffer);
}
return true;
}
printf("req = %x, type = %x, ind = %x, len = %x, val = %x\n", setup->bRequest, setup->bRequestType, setup->wIndex, setup->wLength, setup->wValue);
if (!(setup->bRequestType & USB_TYPE_VENDOR) || (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE)
return false;

View File

@ -498,6 +498,34 @@ namespace sane
return SANE_STATUS_GOOD;
}
else if(action == SANE_ACTION_SET_VALUE && option > 0 && option <= g_opts.size())
{
size_t val_size = 0;
double val = .0f;
void* buf = value;
if (g_opts[option - 1]->type == SANE_TYPE_BOOL)
val_size = sizeof(bool);
else if (g_opts[option - 1]->type == SANE_TYPE_INT)
val_size = sizeof(int);
else if (g_opts[option - 1]->type == SANE_TYPE_FIXED)
{
val_size = sizeof(val);
val = SANE_UNFIX(*(SANE_Int*)value);
buf = &val;
}
else
val_size = strlen((char*)value);
SANE_Status ret = (SANE_Status)dlg->set_option(g_opts[option - 1]->name, value, g_opts[option - 1]->type, val_size, g_opts[option - 1]->size, (int*)info);
if (buf == &val)
{
*(SANE_Int*)value = SANE_FIX(val);
}
return ret;
}
return SANE_STATUS_INVAL;
}
@ -539,6 +567,10 @@ namespace sane
{}
};
#define RETURN_EQUAL(v, e) \
if(v == e) \
return L###e;
template<typename ... Args>
static int msg_box(HWND owner, UINT type, const wchar_t* title, const wchar_t* fmt, Args ... args)
{
@ -551,10 +583,6 @@ static int msg_box(HWND owner, UINT type, const wchar_t* title, const wchar_t* f
}
const wchar_t* peer_bulk_status(int s, wchar_t unk[20])
{
#define RETURN_EQUAL(v, e) \
if(v == e) \
return L###e;
RETURN_EQUAL(s, BULK_STATUS_NOT_START);
RETURN_EQUAL(s, BULK_STATUS_IDLE);
RETURN_EQUAL(s, BULK_STATUS_IO);
@ -565,7 +593,33 @@ const wchar_t* peer_bulk_status(int s, wchar_t unk[20])
return unk;
}
const wchar_t* scanner_status(int s, wchar_t unk[20])
{
RETURN_EQUAL(s, SCANNER_STATUS_READY);
RETURN_EQUAL(s, SCANNER_STATUS_NOT_OPEN);
RETURN_EQUAL(s, SCANNER_STATUS_LOST_CONNECT);
RETURN_EQUAL(s, SCANNER_STATUS_RESET_BULK);
RETURN_EQUAL(s, SCANNER_STATUS_START_SCANNING);
RETURN_EQUAL(s, SCANNER_STATUS_SCANNING);
RETURN_EQUAL(s, SCANNER_STATUS_SCAN_FINISHED);
RETURN_EQUAL(s, SCANNER_STATUS_BUSY);
RETURN_EQUAL(s, SCANNER_STATUS_COVER_OPENNED);
RETURN_EQUAL(s, SCANNER_STATUS_SLEEPING);
RETURN_EQUAL(s, SCANNER_STATUS_COUNT_MODE);
RETURN_EQUAL(s, SCANNER_STATUS_DOUBLE_FEEDED);
RETURN_EQUAL(s, SCANNER_STATUS_PAPER_JAMMED);
RETURN_EQUAL(s, SCANNER_STATUS_PAPER_ASKEW);
RETURN_EQUAL(s, SCANNER_STATUS_FEED_FAILED);
RETURN_EQUAL(s, SCANNER_STATUS_NO_PAPER);
RETURN_EQUAL(s, SCANNER_STATUS_STAPLE_ON);
RETURN_EQUAL(s, SCANNER_STATUS_SIZE_ERR);
RETURN_EQUAL(s, SCANNER_STATUS_DOGEAR);
RETURN_EQUAL(s, SCANNER_STATUS_CFG_CHANGED);
swprintf_s(unk, 18, L"0x%x", s);
return unk;
}
// CDlgScanner 对话框
IMPLEMENT_DYNAMIC(CDlgScanner, CDialogEx)
@ -627,12 +681,22 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
setting_ui_ = NULL;
}
auto progresser = [&](uint64_t total, uint64_t cur, uint32_t err) -> int
static std::string cur_img_file("");
auto progresser = [&](uint64_t total, uint64_t cur, uint32_t err, void* user_data) -> int
{
CDlgScanner* dlg = (CDlgScanner*)user_data;
if (err)
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str());
//::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str());
dlg->set_text(IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str());
else if (cur >= total)
SetDlgItemInt(IDC_EDIT_COUNT, img_cnt_);
{
dlg->set_text(IDC_EDIT_COUNT, std::to_wstring(dlg->img_cnt_).c_str());
if (dlg->is_checked(IDC_CHECK_AUTO_OPEN_IMG))
ShellExecuteA(dlg->m_hWnd, "Open", cur_img_file.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
return 0;
};
@ -644,26 +708,35 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
std::string root(usb::u2a(img_root_.c_str()));
char name[40] = { 0 };
sprintf_s(name, _countof(name) - 1, "scan_%03x.jpg", ++img_cnt_);
sprintf_s(name, _countof(name) - 1, "scan_%04d.jpg", ++img_cnt_);
if (saver->open((root + name).c_str(), size))
{
saver->release();
saver = NULL;
}
else
saver->set_progress_notify(progresser);
{
saver->set_progress_notify(progresser, this);
cur_img_file = root + name;
}
return dynamic_cast<data_holder_ptr>(saver);
}
else
{
// scan stopped ...
::SetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, L"Scan");
wchar_t buf[40] = { 0 };
HWND wnd = GetDlgItem(IDC_EDIT_COUNT)->m_hWnd;
HDC dc = ::GetDC(wnd);
set_text(IDC_BUTTON_SCAN, L"Scan");
::SetTextColor(dc, size ? RGB(255, 0, 0) : RGB(0, 0, 0));
::ReleaseDC(wnd, dc);
if (size)
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Error: " + std::to_wstring(size) + L")").c_str());
set_text(IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Error: " + scanner_status(size, buf) + L")").c_str());
else
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Good)").c_str());
set_text(IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Good)").c_str());
return NULL;
}
};
@ -728,12 +801,19 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
}
}
}
else
{
::SetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, L"Scan");
}
}
void CDlgScanner::get_option(const char* name, void* value, size_t size)
{
scanner_->option_value_get(name, value, size);
}
int CDlgScanner::set_option(const char* name, void* value, int type, size_t len, size_t max_len, int* after)
{
return scanner_->option_value_set(name, type, value, max_len, len, (uint8_t*)after);
}
int CDlgScanner::refresh_bulk_status(void)
{
@ -794,7 +874,7 @@ void CDlgScanner::thread_auto_tx_file(void)
file = loc;
prev.insert(ind, "\\tx");
auto tx_over = [&](uint64_t size, uint64_t cur, uint32_t err_code) -> int
auto tx_over = [&](uint64_t size, uint64_t cur, uint32_t err_code, void* user_data) -> int
{
err = err_code;
if (cur >= size || err_code)
@ -814,15 +894,17 @@ void CDlgScanner::thread_auto_tx_file(void)
if (WaitForSingleObject(auto_wait_, 10 * 60 * 1000) == WAIT_TIMEOUT)
{
msg_box(m_hWnd, MB_OK, L"Send file", L"Wait timeouted!\r\nSend: %s", usb::a2u(file.c_str()).c_str());
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
OnBnClickedCheckRepeat();
// ((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
// OnBnClickedCheckRepeat();
set_check(IDC_CHECK_REPEAT, false);
click_repeat();
break;
}
else if (err)
{
msg_box(m_hWnd, MB_OK | MB_ICONSTOP, L"Send file", L"Failed with error code : %d", err);
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
OnBnClickedCheckRepeat();
set_check(IDC_CHECK_REPEAT, false);
click_repeat();
break;
}
@ -837,23 +919,24 @@ void CDlgScanner::thread_auto_tx_file(void)
if (WaitForSingleObject(auto_wait_, 10 * 60 * 1000) == WAIT_TIMEOUT)
{
msg_box(m_hWnd, MB_OK, L"Receive file", L"Wait timeouted!\r\nReceive to %s", usb::a2u(file.c_str()).c_str());
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
OnBnClickedCheckRepeat();
set_check(IDC_CHECK_REPEAT, false);
click_repeat();
break;
}
else if (err)
{
msg_box(m_hWnd, MB_OK | MB_ICONSTOP, L"Receive file", L"Failed with error code : %d", err);
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
OnBnClickedCheckRepeat();
set_check(IDC_CHECK_REPEAT, false);
click_repeat();
break;
}
Sleep(1000);
}
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
set_check(IDC_CHECK_REPEAT, false);
auto_tx_ = false;
enable_buttons(scanner_ != NULL);
//enable_buttons(scanner_ != NULL);
click_repeat(true);
// msg_box(m_hWnd, MB_OK, L"Repeat S/R", L"exited.");
}
void CDlgScanner::enable_buttons(bool enable)
@ -869,6 +952,34 @@ void CDlgScanner::enable_buttons(bool enable)
GetDlgItem(IDC_BUTTON_SEND_EP0)->EnableWindow(enable);
}
void CDlgScanner::set_text(UINT id, const wchar_t* text)
{
std::wstring* str = new std::wstring(text);
if (!::PostMessageW(m_hWnd, WM_SET_TEXT, id, (LPARAM)str))
delete str;
}
bool CDlgScanner::is_checked(UINT id)
{
bool chk = false;
::SendMessage(m_hWnd, WM_IS_BUTTON_CHECKED, id, (LPARAM)&chk);
return chk;
}
void CDlgScanner::set_check(UINT id, bool checked)
{
::PostMessage(m_hWnd, WM_SET_BUTTON_CHECK, id, checked);
}
void CDlgScanner::click_repeat(bool enable_buttons, bool enable)
{
if (enable_buttons)
::PostMessage(m_hWnd, WM_ENABLE_CTRLS, 1, enable);
else
::PostMessage(m_hWnd, WM_ENABLE_CTRLS, 0, enable);
}
BEGIN_MESSAGE_MAP(CDlgScanner, CDialogEx)
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_OPER, &CDlgScanner::OnTcnSelchangeTabOper)
ON_BN_CLICKED(IDOK, &CDlgScanner::OnBnClickedOk)
@ -884,6 +995,10 @@ BEGIN_MESSAGE_MAP(CDlgScanner, CDialogEx)
ON_BN_CLICKED(IDC_CHECK_AUTO, &CDlgScanner::OnBnClickedCheckAuto)
ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CDlgScanner::OnBnClickedButtonRefresh)
ON_BN_CLICKED(IDC_CHECK_REPEAT, &CDlgScanner::OnBnClickedCheckRepeat)
ON_MESSAGE(WM_SET_TEXT, &CDlgScanner::OnSetText)
ON_MESSAGE(WM_IS_BUTTON_CHECKED, &CDlgScanner::OnIsButtonChecked)
ON_MESSAGE(WM_SET_BUTTON_CHECK, &CDlgScanner::OnSetButtonChecked)
ON_MESSAGE(WM_ENABLE_CTRLS, &CDlgScanner::OnEnableCtrls)
END_MESSAGE_MAP()
@ -961,7 +1076,8 @@ void CDlgScanner::OnTcnSelchangeTabOper(NMHDR* pNMHDR, LRESULT* pResult)
UINT statu[] = {IDC_STATIC_BULK_IN, IDC_STATIC_BULK_OUT, IDC_STATIC_CMD_QUE, IDC_STATIC_SENT_QUE
, IDC_EDIT_BUILK_IN, IDC_EDIT_BULK_OUT, IDC_EDIT_CMD_QUE, IDC_EDIT_SENT_QUE
, IDC_BUTTON_RESET_BULK, IDC_CHECK_AUTO, IDC_BUTTON_REFRESH},
scan[] = {IDC_STATIC_IMG_PATH, IDC_STATIC_COUNT, IDC_EDIT_IMG_PATH, IDC_EDIT_COUNT, IDC_BUTTON_BROWSE_IMG_PATH, IDC_BUTTON_SCAN},
scan[] = {IDC_STATIC_IMG_PATH, IDC_STATIC_COUNT, IDC_EDIT_IMG_PATH, IDC_EDIT_COUNT, IDC_BUTTON_BROWSE_IMG_PATH
, IDC_CHECK_AUTO_OPEN_IMG, IDC_BUTTON_SCAN},
file[] = {IDC_STATIC_LOCAL, IDC_STATIC_REMOTE, IDC_EDIT_LOCAL, IDC_EDIT_REMOTE, IDC_BUTTON_BROWSE_LOCAL
, IDC_BUTTON_SEND, IDC_BUTTON_RECEIVE, IDC_CHECK_REPEAT},
prog[] = {IDC_STATIC_CMD, IDC_STATIC_PARAM, IDC_EDIT_CMD, IDC_EDIT_PARAM, IDC_BUTTON_START_PROG},
@ -1175,3 +1291,33 @@ void CDlgScanner::OnBnClickedCheckRepeat()
}
}
LRESULT CDlgScanner::OnSetText(WPARAM wp, LPARAM lp)
{
std::wstring* str = (std::wstring*)lp;
::SetDlgItemTextW(m_hWnd, wp, str->c_str());
delete str;
return 0;
}
LRESULT CDlgScanner::OnIsButtonChecked(WPARAM wp, LPARAM lp)
{
*(bool*)lp = ((CButton*)GetDlgItem(wp))->GetCheck() == BST_CHECKED;
return 0;
}
LRESULT CDlgScanner::OnSetButtonChecked(WPARAM wp, LPARAM lp)
{
((CButton*)GetDlgItem(wp))->SetCheck(lp ? BST_CHECKED : BST_UNCHECKED);
return 0;
}
LRESULT CDlgScanner::OnEnableCtrls(WPARAM wp, LPARAM lp)
{
if (wp == 0)
OnBnClickedCheckRepeat();
else
enable_buttons(lp);
return 0;
}

View File

@ -80,9 +80,15 @@ protected:
void thread_auto_tx_file(void);
void enable_buttons(bool enable);
void set_text(UINT id, const wchar_t* text);
bool is_checked(UINT id);
void set_check(UINT id, bool checked);
void click_repeat(bool enable_buttons = false, bool enable = true);
public:
void set_device(usb::LPUSBPNP pnp);
void get_option(const char* name, void* value, size_t size);
int set_option(const char* name, void* value, int type, size_t len, size_t max_len, int* after);
public:
CTabCtrl tab_opt_;
@ -101,4 +107,9 @@ public:
afx_msg void OnBnClickedCheckAuto();
afx_msg void OnBnClickedButtonRefresh();
afx_msg void OnBnClickedCheckRepeat();
afx_msg LRESULT OnSetText(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnIsButtonChecked(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnSetButtonChecked(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnEnableCtrls(WPARAM wp, LPARAM lp);
};

View File

@ -72,7 +72,6 @@
#define IDC_STATIC_CMD 1043
#define IDC_STATIC_PARAM 1044
#define IDC_STATIC_COUNT 1045
#define IDC_TAB_OPT 1046
#define IDC_EDIT_CMD_QUE 1047
#define IDC_EDIT_SENT_QUE 1048
#define IDC_EDIT_IND 1049
@ -89,6 +88,8 @@
#define IDC_STATIC_CMD_QUE 1061
#define IDC_STATIC_SENT_QUE 1062
#define IDC_STATIC_OPTS 1063
#define IDC_CHECK1 1064
#define IDC_CHECK_AUTO_OPEN_IMG 1064
#define ID_TRAY_EXIT 32771
// Next default values for new objects
@ -97,7 +98,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 137
#define _APS_NEXT_COMMAND_VALUE 32772
#define _APS_NEXT_CONTROL_VALUE 1064
#define _APS_NEXT_CONTROL_VALUE 1065
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -27,6 +27,11 @@
#define WM_REFRESH_OPTION WM_USER + 311 // WPARAM: source option SN, LPARAM: unused now
#define WM_GET_CONFIG_OBJ WM_USER + 312 // WPARAM: bool*, [in]create new if NULL; [out]created, LPARAM: to receive the gb::sane_config_schm* object
#define WM_SET_TEXT WM_USER + 320 // WPARAM: id; LPARAM: std::wstring*
#define WM_IS_BUTTON_CHECKED WM_USER + 321 // WPARAM: id; LPARAM: bool*
#define WM_SET_BUTTON_CHECK WM_USER + 322 // WPARAM: id; LPARAM: bool
#define WM_ENABLE_CTRLS WM_USER + 323 // WPARAM: id (0 is click repeat button); LPARAM: bool
extern HMODULE g_my_inst;
namespace local_trans

View File

@ -506,11 +506,17 @@ int scanner_handler::option_value_get(const char* name, void* buf, uint32_t size
WAIT_COMMAND(call, clean, roger, buf);
}
int scanner_handler::option_value_set(const char* name, uint32_t type, void* buf, uint32_t size, uint8_t* after)
int scanner_handler::option_value_set(const char* name, uint32_t type, void* buf, uint32_t size, uint32_t val_size, uint8_t* after)
{
struct
{
void* buf;
uint8_t* after;
}param;
auto call = [&](cmd_result* cmd) -> int
{
return usb_->get_setting_val(cmd->get_id(), name);
memcpy(&param, cmd->get_param(), sizeof(param));
return usb_->set_setting(cmd->get_id(), name, type, param.buf, val_size, size);
};
auto clean = [&](cmd_result* cmd) -> int
{
@ -543,11 +549,6 @@ int scanner_handler::option_value_set(const char* name, uint32_t type, void* buf
return nullptr;
};
struct
{
void* buf;
uint8_t* after;
}param;
if (!is_scanner_available())
return ENODEV;

View File

@ -108,7 +108,7 @@ public:
// following methods transferred by Bulk, blocked ...
int option_get_all(std::string& json_opts);
int option_value_get(const char* name, void* buf, uint32_t size/*buffer size of 'buf'*/);
int option_value_set(const char* name, uint32_t type, void* buf, uint32_t size/*buffer size of 'buf'*/, uint8_t* after);
int option_value_set(const char* name, uint32_t type, void* buf, uint32_t size/*buffer size of 'buf'*/, uint32_t val_size, uint8_t* after);
int status_get(void);
void set_image_receiver(std::function<data_holder_ptr(LPPACKIMAGE/*NULL when scanning stopped*/, uint64_t/*size in image, error in stopped*/)> img);

View File

@ -584,10 +584,10 @@ int async_usb_host::get_setting_val(uint32_t pack_id, const char* name)
return 0;
}
int async_usb_host::set_setting(uint32_t pack_id, const char* name, int type, void* val, size_t size)
int async_usb_host::set_setting(uint32_t pack_id, const char* name, int type, void* val, size_t size, size_t size0)
{
int base = sizeof(PACK_BASE),
datal = strlen(name) + 1 + size;
datal = sizeof(CFGVAL) + strlen(name) + 1 + size;
dyn_mem_ptr data(dyn_mem::memory(base + datal)), enc = nullptr;
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
LPCFGVAL param = (LPCFGVAL)pack->payload;
@ -596,6 +596,8 @@ int async_usb_host::set_setting(uint32_t pack_id, const char* name, int type, vo
pack->payload_len = datal;
param->type = type;
param->name_off = 0;
param->max_size = size0;
param->val_size = size;
param->val_off = strlen(name) + 1;
strcpy(param->data, name);
memcpy(param->data + param->val_off, val, size);

View File

@ -85,7 +85,7 @@ public:
int send_heart_beat(uint32_t pack_id);
int get_settings(uint32_t pack_id);
int get_setting_val(uint32_t pack_id, const char* name);
int set_setting(uint32_t pack_id, const char* name, int type, void* val, size_t size/*value size*/);
int set_setting(uint32_t pack_id, const char* name, int type, void* val, size_t size/*value size*/, size_t size0/*max size*/);
int scan_start(uint32_t pack_id);
int scan_stop(uint32_t pack_id);