修复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(const char* name) : ref_(1), name_(name ? name : ""), is_ok_(false)
|
||||
|
@ -366,9 +430,6 @@ bool usb_device::init(void)
|
|||
int addr = -1;
|
||||
|
||||
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);
|
||||
addr = usb_device::get_device_address(name_.c_str(), &guid);
|
||||
//if (addr != -1)
|
||||
|
@ -488,9 +549,6 @@ bool usb_device::init(void)
|
|||
void usb_device::clear(void)
|
||||
{
|
||||
close();
|
||||
for (size_t i = 0; i < _countof(ovl_); ++i)
|
||||
CloseHandle(ovl_[i].hEvent);
|
||||
|
||||
|
||||
if (dev_desc_)
|
||||
delete dev_desc_;
|
||||
|
@ -595,7 +653,7 @@ int usb_device::open(libusb_device_handle** dev_handle)
|
|||
}
|
||||
}
|
||||
set_timeout(h);
|
||||
handle_ = (libusb_device_handle*)h;
|
||||
handle_ = h == INVALID_HANDLE_VALUE ? NULL : (libusb_device_handle*)h;
|
||||
*dev_handle = (libusb_device_handle*)this;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
ovl_cls *oc = ovl_mgr_.get_ovl();
|
||||
DWORD io = 0;
|
||||
BOOL result = FALSE;
|
||||
HANDLE he = ovl->hEvent;
|
||||
BOOL result = fio(h, data, *length, oc->io_bytes(), oc->over_lapped());
|
||||
|
||||
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)
|
||||
{
|
||||
FlushFileBuffers(h);
|
||||
*length = io;
|
||||
*length = *oc->io_bytes();
|
||||
ret = LIBUSB_SUCCESS;
|
||||
}
|
||||
else
|
||||
|
@ -670,29 +721,33 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
|
|||
io = GetLastError();
|
||||
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;
|
||||
ret = LIBUSB_SUCCESS;
|
||||
}
|
||||
else
|
||||
ret = LIBUSB_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
ret = LIBUSB_ERROR_PIPE;
|
||||
}
|
||||
oc->release();
|
||||
}
|
||||
|
||||
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 ret = LIBUSB_ERROR_PIPE;
|
||||
int ret = LIBUSB_ERROR_NOT_FOUND;
|
||||
_IO_BLOCK_EX irp;
|
||||
|
||||
if ((HANDLE)handle_ != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD io = 0;
|
||||
LPOVERLAPPED ovl = ovl_ + OVL_CONTROL;
|
||||
DWORD io = 0;
|
||||
ovl_cls *oc = ovl_mgr_.get_ovl();
|
||||
|
||||
ResetEvent(ovl->hEvent);
|
||||
irp.bmRequestType = (type >> 5) & 0x03;
|
||||
irp.bRequest = req;
|
||||
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.uLength = len;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
DWORD io = 0;
|
||||
|
||||
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;
|
||||
*length = io;
|
||||
*length = *oc->io_bytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
io = GetLastError();
|
||||
if (io == ERROR_IO_PENDING)
|
||||
{
|
||||
GetOverlappedResult(h, &ovl_[OVL_INTERRUPT], &io, TRUE);
|
||||
ret = LIBUSB_SUCCESS;
|
||||
*length = io;
|
||||
if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
|
||||
{
|
||||
GetOverlappedResult(h, oc->over_lapped(), &io, FALSE);
|
||||
*length = io;
|
||||
ret = LIBUSB_SUCCESS;
|
||||
}
|
||||
else
|
||||
ret = LIBUSB_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
ret = LIBUSB_ERROR_PIPE;
|
||||
}
|
||||
oc->release();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -791,10 +858,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
|
|||
bool found = false;
|
||||
for(size_t i = 0; i < devices_.size(); ++i)
|
||||
{
|
||||
if (!(devices_[i]->id() == id))
|
||||
continue;
|
||||
|
||||
if (!devices_[i]->is_online() && devices_[i]->is_open())
|
||||
if (devices_[i]->id() == id)
|
||||
{
|
||||
dev->release();
|
||||
dev = devices_[i];
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <memory>
|
||||
#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}
|
||||
#define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F"
|
||||
#define MONITOR_WINDOW_OWNER L"monitor_wnd_owner"
|
||||
|
@ -29,6 +31,35 @@ typedef struct _dev_id
|
|||
}
|
||||
}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
|
||||
{
|
||||
volatile long ref_;
|
||||
|
@ -38,17 +69,7 @@ class usb_device // consider as libusb_device
|
|||
bool is_ok_;
|
||||
bool online_;
|
||||
uint8_t port_;
|
||||
|
||||
enum
|
||||
{
|
||||
OVL_BULK_IN,
|
||||
OVL_BULK_OUT,
|
||||
OVL_CONTROL,
|
||||
OVL_INTERRUPT,
|
||||
|
||||
OVL_MAX,
|
||||
};
|
||||
OVERLAPPED ovl_[OVL_MAX];
|
||||
ovl_mgr ovl_mgr_;
|
||||
|
||||
libusb_device_handle *handle_; // as file handle returned by CreateFile
|
||||
libusb_device_descriptor *dev_desc_;
|
||||
|
|
|
@ -246,7 +246,10 @@ void scanner::apply_config(void)
|
|||
}
|
||||
void scanner::on_ui_event(int uev, void* sender)
|
||||
{
|
||||
events_.save(uev);
|
||||
if (prev_start_result_ != SANE_STATUS_GOOD && sender == indicator_.get())
|
||||
indicator_.reset();
|
||||
else
|
||||
events_.save(uev);
|
||||
}
|
||||
int scanner::open(void)
|
||||
{
|
||||
|
@ -1548,21 +1551,25 @@ COM_API_IMPLEMENT(scanner, int, start(void))
|
|||
scan_err_ = false;
|
||||
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 ...
|
||||
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
|
||||
ret = hg_sane_middleware::instance()->start(handle_, NULL);
|
||||
|
||||
if (ret == SANE_STATUS_GOOD)
|
||||
{
|
||||
if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
|
||||
indicator_->show(true);
|
||||
|
||||
unsigned int l = sizeof(img_fmt_);
|
||||
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))
|
||||
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
||||
img_fmt_.compress.compression = cmprsn;
|
||||
}
|
||||
else if (indicator_.get())
|
||||
{
|
||||
indicator_->notify_scan_over(hg_scanner_err_description(ret), true);
|
||||
}
|
||||
prev_start_result_ = ret;
|
||||
|
||||
return local_utility::sane_statu_2_scanner_err(ret);
|
||||
|
|
Loading…
Reference in New Issue