修复IO重叠参数错误;启动失败后进度指示器的隐藏
This commit is contained in:
parent
6cbe8f125c
commit
96f6b45893
|
@ -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];
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue