修复IO重叠参数错误;启动失败后进度指示器的隐藏

This commit is contained in:
gb 2022-07-04 16:31:37 +08:00
parent 6cbe8f125c
commit 96f6b45893
3 changed files with 143 additions and 51 deletions

View File

@ -54,6 +54,70 @@ std::string u2utf8(const wchar_t* u)
/////*/////////////////////// /////*///////////////////////
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OVERLAPPED ...
ovl_cls::ovl_cls() : io_bytes_(0)
{
memset(&ovl_, 0, sizeof(ovl_));
ovl_.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
}
ovl_cls::~ovl_cls()
{
CloseHandle(ovl_.hEvent);
}
LPOVERLAPPED ovl_cls::over_lapped(void)
{
return &ovl_;
}
LPDWORD ovl_cls::io_bytes(void)
{
return &io_bytes_;
}
void ovl_cls::reset(void)
{
HANDLE h = ovl_.hEvent;
memset(&ovl_, 0, sizeof(ovl_));
ovl_.hEvent = h;
io_bytes_ = 0;
}
ovl_mgr::ovl_mgr()
{}
ovl_mgr::~ovl_mgr()
{
for (auto& v : ovls_)
v->release();
}
ovl_cls* ovl_mgr::get_ovl(void)
{
std::lock_guard<std::mutex> lock(lock_);
ovl_cls* o = NULL;
for (auto& v : ovls_)
{
if (WaitForSingleObject(v->over_lapped()->hEvent, 0) == WAIT_OBJECT_0)
{
ResetEvent(v->over_lapped()->hEvent);
o = v;
o->add_ref();
o->reset();
break;
}
}
if (!o)
{
o = new ovl_cls();
ovls_.push_back(o);
o->add_ref();
}
return o;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_device ... // usb_device ...
usb_device::usb_device(const char* name) : ref_(1), name_(name ? name : ""), is_ok_(false) usb_device::usb_device(const char* name) : ref_(1), name_(name ? name : ""), is_ok_(false)
@ -366,9 +430,6 @@ bool usb_device::init(void)
int addr = -1; int addr = -1;
clear(); clear();
for (size_t i = 0; i < _countof(ovl_); ++i)
ovl_[i].hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid); UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid);
addr = usb_device::get_device_address(name_.c_str(), &guid); addr = usb_device::get_device_address(name_.c_str(), &guid);
//if (addr != -1) //if (addr != -1)
@ -488,9 +549,6 @@ bool usb_device::init(void)
void usb_device::clear(void) void usb_device::clear(void)
{ {
close(); close();
for (size_t i = 0; i < _countof(ovl_); ++i)
CloseHandle(ovl_[i].hEvent);
if (dev_desc_) if (dev_desc_)
delete dev_desc_; delete dev_desc_;
@ -595,7 +653,7 @@ int usb_device::open(libusb_device_handle** dev_handle)
} }
} }
set_timeout(h); set_timeout(h);
handle_ = (libusb_device_handle*)h; handle_ = h == INVALID_HANDLE_VALUE ? NULL : (libusb_device_handle*)h;
*dev_handle = (libusb_device_handle*)this; *dev_handle = (libusb_device_handle*)this;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
@ -642,27 +700,20 @@ int usb_device::set_timeout(unsigned milliseconds)
int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout) int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout)
{ {
typedef BOOL(WINAPI* file_io)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); typedef BOOL(WINAPI* file_io)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
int ret = LIBUSB_ERROR_PIPE; int ret = LIBUSB_ERROR_NOT_SUPPORTED;
HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_BULK); HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_BULK);
file_io fio = (endpoint & BULKIN_FLAG) ? ReadFile : (file_io)WriteFile; file_io fio = (endpoint & BULKIN_FLAG) ? ReadFile : (file_io)WriteFile;
LPOVERLAPPED ovl = (endpoint & BULKIN_FLAG) ? &ovl_[OVL_BULK_IN] : &ovl_[OVL_BULK_OUT];
if (h) if (h)
{ {
ovl_cls *oc = ovl_mgr_.get_ovl();
DWORD io = 0; DWORD io = 0;
BOOL result = FALSE; BOOL result = fio(h, data, *length, oc->io_bytes(), oc->over_lapped());
HANDLE he = ovl->hEvent;
if (!GetOverlappedResult(h, ovl, &io, FALSE) && GetLastError() == ERROR_IO_INCOMPLETE)
return LIBUSB_ERROR_BUSY;
memset(ovl, 0, sizeof(*ovl));
ovl->hEvent = he;
result = fio(h, data, *length, &io, ovl);
if (result) if (result)
{ {
FlushFileBuffers(h); FlushFileBuffers(h);
*length = io; *length = *oc->io_bytes();
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
} }
else else
@ -670,29 +721,33 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
io = GetLastError(); io = GetLastError();
if (io == ERROR_IO_PENDING) if (io == ERROR_IO_PENDING)
{ {
if (WaitForSingleObject(he, timeout) == WAIT_OBJECT_0) if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
{ {
GetOverlappedResult(h, ovl, &io, FALSE); GetOverlappedResult(h, oc->over_lapped(), &io, FALSE);
*length = io; *length = io;
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
} }
else
ret = LIBUSB_ERROR_TIMEOUT;
} }
else
ret = LIBUSB_ERROR_PIPE;
} }
oc->release();
} }
return ret; return ret;
} }
int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16_t ind, unsigned char* data, uint16_t len, unsigned timeout) int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16_t ind, unsigned char* data, uint16_t len, unsigned timeout)
{ {
int ret = LIBUSB_ERROR_PIPE; int ret = LIBUSB_ERROR_NOT_FOUND;
_IO_BLOCK_EX irp; _IO_BLOCK_EX irp;
if ((HANDLE)handle_ != INVALID_HANDLE_VALUE) if ((HANDLE)handle_ != INVALID_HANDLE_VALUE)
{ {
DWORD io = 0; DWORD io = 0;
LPOVERLAPPED ovl = ovl_ + OVL_CONTROL; ovl_cls *oc = ovl_mgr_.get_ovl();
ResetEvent(ovl->hEvent);
irp.bmRequestType = (type >> 5) & 0x03; irp.bmRequestType = (type >> 5) & 0x03;
irp.bRequest = req; irp.bRequest = req;
irp.fTransferDirectionIn = type >> 7; irp.fTransferDirectionIn = type >> 7;
@ -700,39 +755,51 @@ int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16
irp.uIndex = ind; irp.uIndex = ind;
irp.uLength = len; irp.uLength = len;
irp.uOffset = val; irp.uOffset = val;
if (DeviceIoControl((HANDLE)handle_, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, len, &io, ovl)) if (DeviceIoControl((HANDLE)handle_, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, len, oc->io_bytes(), oc->over_lapped()))
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
else if (GetLastError() == ERROR_IO_PENDING) else if (GetLastError() == ERROR_IO_PENDING)
{ {
ret = WaitForSingleObject(ovl->hEvent, timeout) == WAIT_TIMEOUT ? LIBUSB_ERROR_TIMEOUT : LIBUSB_SUCCESS; ret = WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_TIMEOUT ? LIBUSB_ERROR_TIMEOUT : LIBUSB_SUCCESS;
} }
else
ret = LIBUSB_ERROR_PIPE;
oc->release();
} }
return ret; return ret;
} }
int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout) int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout)
{ {
int ret = LIBUSB_ERROR_PIPE; int ret = LIBUSB_ERROR_NOT_SUPPORTED;
HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_INTERRUPT); HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_INTERRUPT);
DWORD io = 0; DWORD io = 0;
if (h) if (h)
{ {
if (DeviceIoControl(h, IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0, data, *length, &io, &ovl_[OVL_INTERRUPT])) ovl_cls* oc = ovl_mgr_.get_ovl();
if (DeviceIoControl(h, IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0, data, *length, oc->io_bytes(), oc->over_lapped()))
{ {
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
*length = io; *length = *oc->io_bytes();
} }
else else
{ {
io = GetLastError(); io = GetLastError();
if (io == ERROR_IO_PENDING) if (io == ERROR_IO_PENDING)
{ {
GetOverlappedResult(h, &ovl_[OVL_INTERRUPT], &io, TRUE); if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
ret = LIBUSB_SUCCESS; {
GetOverlappedResult(h, oc->over_lapped(), &io, FALSE);
*length = io; *length = io;
ret = LIBUSB_SUCCESS;
} }
else
ret = LIBUSB_ERROR_TIMEOUT;
} }
else
ret = LIBUSB_ERROR_PIPE;
}
oc->release();
} }
return ret; return ret;
@ -791,10 +858,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
bool found = false; bool found = false;
for(size_t i = 0; i < devices_.size(); ++i) for(size_t i = 0; i < devices_.size(); ++i)
{ {
if (!(devices_[i]->id() == id)) if (devices_[i]->id() == id)
continue;
if (!devices_[i]->is_online() && devices_[i]->is_open())
{ {
dev->release(); dev->release();
dev = devices_[i]; dev = devices_[i];

View File

@ -13,6 +13,8 @@
#include <memory> #include <memory>
#include "libusb-1.0/libusb.h" #include "libusb-1.0/libusb.h"
#include "../../../code_device/hgdriver/hgdev/hg_ipc.h"
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f} // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f}
#define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F" #define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F"
#define MONITOR_WINDOW_OWNER L"monitor_wnd_owner" #define MONITOR_WINDOW_OWNER L"monitor_wnd_owner"
@ -29,6 +31,35 @@ typedef struct _dev_id
} }
}DEVID; }DEVID;
class ovl_cls : public refer
{
OVERLAPPED ovl_;
DWORD io_bytes_;
public:
ovl_cls();
protected:
~ovl_cls();
public:
LPOVERLAPPED over_lapped(void);
LPDWORD io_bytes(void);
void reset(void);
};
class ovl_mgr
{
std::mutex lock_;
std::vector<ovl_cls*> ovls_;
public:
ovl_mgr();
~ovl_mgr();
public:
ovl_cls* get_ovl(void);
};
class usb_device // consider as libusb_device class usb_device // consider as libusb_device
{ {
volatile long ref_; volatile long ref_;
@ -38,17 +69,7 @@ class usb_device // consider as libusb_device
bool is_ok_; bool is_ok_;
bool online_; bool online_;
uint8_t port_; uint8_t port_;
ovl_mgr ovl_mgr_;
enum
{
OVL_BULK_IN,
OVL_BULK_OUT,
OVL_CONTROL,
OVL_INTERRUPT,
OVL_MAX,
};
OVERLAPPED ovl_[OVL_MAX];
libusb_device_handle *handle_; // as file handle returned by CreateFile libusb_device_handle *handle_; // as file handle returned by CreateFile
libusb_device_descriptor *dev_desc_; libusb_device_descriptor *dev_desc_;

View File

@ -246,6 +246,9 @@ void scanner::apply_config(void)
} }
void scanner::on_ui_event(int uev, void* sender) void scanner::on_ui_event(int uev, void* sender)
{ {
if (prev_start_result_ != SANE_STATUS_GOOD && sender == indicator_.get())
indicator_.reset();
else
events_.save(uev); events_.save(uev);
} }
int scanner::open(void) int scanner::open(void)
@ -1548,21 +1551,25 @@ COM_API_IMPLEMENT(scanner, int, start(void))
scan_err_ = false; scan_err_ = false;
ret = hg_sane_middleware::instance()->start(handle_, NULL); ret = hg_sane_middleware::instance()->start(handle_, NULL);
if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
indicator_->show(true);
// the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ... // the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ...
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD) if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
ret = hg_sane_middleware::instance()->start(handle_, NULL); ret = hg_sane_middleware::instance()->start(handle_, NULL);
if (ret == SANE_STATUS_GOOD) if (ret == SANE_STATUS_GOOD)
{ {
if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
indicator_->show(true);
unsigned int l = sizeof(img_fmt_); unsigned int l = sizeof(img_fmt_);
SANE_CompressionType cmprsn = img_fmt_.compress.compression; SANE_CompressionType cmprsn = img_fmt_.compress.compression;
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l)) if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l))
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP; img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
img_fmt_.compress.compression = cmprsn; img_fmt_.compress.compression = cmprsn;
} }
else if (indicator_.get())
{
indicator_->notify_scan_over(hg_scanner_err_description(ret), true);
}
prev_start_result_ = ret; prev_start_result_ = ret;
return local_utility::sane_statu_2_scanner_err(ret); return local_utility::sane_statu_2_scanner_err(ret);