mirror of http://192.168.1.51:8099/lmh188/twain3.0
357 lines
8.5 KiB
C++
357 lines
8.5 KiB
C++
#include "stdafx.h"
|
|
#include "UsbScanEx.h"
|
|
#include <tchar.h>
|
|
#include <winioctl.h>
|
|
#include "filetools.h"
|
|
|
|
UsbScanEx::UsbScanEx(int index)
|
|
{
|
|
m_h_dev = INVALID_HANDLE_VALUE;
|
|
timeout = 100;
|
|
m_h_index = index;
|
|
memset(ov, 0, sizeof(ov));
|
|
CTRL_IN_OUT = 3;
|
|
for (int i = 0; i < (sizeof(ov) / sizeof(ov[0])); i++)
|
|
ov[i].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
}
|
|
|
|
UsbScanEx::~UsbScanEx()
|
|
{
|
|
if (m_h_dev != INVALID_HANDLE_VALUE)
|
|
close();
|
|
|
|
for (int i = 0; i < (sizeof(ov) / sizeof(ov[0])); i++)
|
|
CloseHandle(ov[i].hEvent);
|
|
}
|
|
|
|
bool UsbScanEx::open()
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
TCHAR szDevPath[MAX_PATH] = { 0 };
|
|
DWORD cbRet = 0;
|
|
|
|
USBSCAN_TIMEOUT ut;
|
|
ut.TimeoutEvent = 1;
|
|
ut.TimeoutRead = 1;
|
|
ut.TimeoutWrite = 1;
|
|
|
|
_stprintf(szDevPath, TEXT("\\\\.\\Usbscan%d"), m_h_index);
|
|
m_h_dev = CreateFile(szDevPath,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED,
|
|
NULL);
|
|
if (m_h_dev != INVALID_HANDLE_VALUE) {
|
|
m_b_is_connected = TRUE;
|
|
b_ret = DeviceIoControl(m_h_dev, (DWORD)IOCTL_GET_PIPE_CONFIGURATION,
|
|
NULL, 0, &m_usbscan_config, sizeof(USBSCAN_PIPE_CONFIGURATION),
|
|
&cbRet, NULL);
|
|
if (b_ret && m_usbscan_config.NumberOfPipes > 0) {
|
|
for (int by_i = 0x00; (ULONG)by_i < m_usbscan_config.NumberOfPipes; by_i++) {
|
|
|
|
TCHAR szPipePath[MAX_PATH] = { 0 };
|
|
_stprintf(szPipePath, TEXT("\\\\.\\Usbscan%d\\%d"), m_h_index, by_i);
|
|
m_usb_pipes[by_i].pipe_info = m_usbscan_config.PipeInfo[by_i];
|
|
m_usb_pipes[by_i].h_pipe = CreateFile(szPipePath,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED,
|
|
NULL);
|
|
if (m_usbscan_config.PipeInfo[by_i].PipeType == USBSCAN_PIPE_INTERRUPT) {
|
|
INT_IN = by_i;
|
|
}
|
|
else {
|
|
if (m_usbscan_config.PipeInfo[by_i].EndpointAddress & 0x80) {
|
|
BULK_IN = by_i;
|
|
}
|
|
else {
|
|
BULK_OUT = by_i;
|
|
}
|
|
}
|
|
b_ret = DeviceIoControl(m_usb_pipes[by_i].h_pipe, IOCTL_SET_TIMEOUT, &ut, sizeof(ut), NULL, 0, &cbRet, NULL);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
CloseHandle(m_h_dev);
|
|
m_h_dev = INVALID_HANDLE_VALUE;
|
|
}
|
|
FileTools::writelog(log_lv::log_INFO,"USB Open!");
|
|
return m_h_dev;
|
|
}
|
|
|
|
void UsbScanEx::set_usbhotplug_callback(usbhotplug_callback callback, void* userdata)
|
|
{
|
|
hotplug_call = callback;
|
|
usrdata = userdata;
|
|
}
|
|
|
|
bool UsbScanEx::close()
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
BYTE by_i = 0x00;
|
|
|
|
if (m_h_dev != INVALID_HANDLE_VALUE) {
|
|
BOOL bState = FALSE;
|
|
DWORD cbRet = 0;
|
|
OVERLAPPED overlapped;
|
|
PIPE_TYPE pipeType = ALL_PIPE;
|
|
|
|
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
overlapped.hEvent =
|
|
CreateEvent(NULL, // pointer to security attributes
|
|
FALSE, // automatic reset
|
|
FALSE, // initialize to nosignaled
|
|
NULL); // pointer to the event-object name
|
|
bState =
|
|
DeviceIoControl(m_h_dev,
|
|
(DWORD)IOCTL_CANCEL_IO,
|
|
(LPVOID)&pipeType,
|
|
sizeof(PIPE_TYPE),
|
|
NULL,
|
|
0,
|
|
&cbRet,
|
|
&overlapped);
|
|
WaitForSingleObject(overlapped.hEvent, 1000);
|
|
CloseHandle(overlapped.hEvent);
|
|
|
|
for (by_i = 0x00; by_i < m_usbscan_config.NumberOfPipes; by_i++) {
|
|
CancelIo(m_usb_pipes[by_i].h_pipe);
|
|
CloseHandle(m_usb_pipes[by_i].h_pipe);
|
|
m_usb_pipes[by_i].h_pipe = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
CancelIo(m_h_dev);
|
|
b_ret = CloseHandle(m_h_dev);
|
|
if (b_ret) {
|
|
m_h_dev = INVALID_HANDLE_VALUE;
|
|
b_ret = TRUE;
|
|
}
|
|
}
|
|
m_b_is_connected = FALSE;
|
|
FileTools::writelog(log_lv::log_INFO,"USB Close!");
|
|
return b_ret;
|
|
}
|
|
|
|
void UsbScanEx::set_timeout(int timeout)
|
|
{
|
|
this->timeout = timeout;
|
|
}
|
|
|
|
int UsbScanEx::read_bulk(void* data, int len)
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
HANDLE h_pipe = m_usb_pipes[BULK_IN].h_pipe;
|
|
unsigned long pdw_ret = len;
|
|
LPOVERLAPPED lp_overlap = ov + BULK_IN;
|
|
lp_overlap->Internal = 0;
|
|
lp_overlap->InternalHigh = 0;
|
|
lp_overlap->Offset = 0;
|
|
lp_overlap->OffsetHigh = 0;
|
|
lp_overlap->Pointer = 0;
|
|
|
|
if (m_h_dev != NULL) {
|
|
b_ret = ReadFile(h_pipe, data, len, &pdw_ret, lp_overlap);
|
|
|
|
if (b_ret) {
|
|
return pdw_ret;
|
|
}
|
|
else {
|
|
int error_code = GetLastError();
|
|
switch (error_code)
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
GetOverlappedResult(h_pipe, lp_overlap, &pdw_ret, TRUE);
|
|
return pdw_ret;
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_ACCESS_DENIED:
|
|
m_b_is_connected = false;
|
|
FileTools::writelog(log_lv::log_WARN, "errorcode =" + std::to_string(error_code));
|
|
if (hotplug_call) {
|
|
hotplug_call(true, usrdata);
|
|
}
|
|
break;
|
|
default:
|
|
FileTools::writelog(log_INFO,"Usb read_bulk error code : " + std::to_string(error_code));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int UsbScanEx::write_bulk(void* data, int len)
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
HANDLE h_pipe = m_usb_pipes[BULK_OUT].h_pipe;
|
|
void* p_data = data;
|
|
unsigned long dw_size = len;
|
|
LPOVERLAPPED lp_overlap = ov + BULK_OUT;
|
|
if (m_h_dev == INVALID_HANDLE_VALUE)
|
|
return TRUE;
|
|
b_ret = WriteFile(h_pipe, p_data, dw_size, &dw_size, lp_overlap);
|
|
if (b_ret) {
|
|
return dw_size;
|
|
}
|
|
else {
|
|
int errorcode = GetLastError();
|
|
switch (errorcode)
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
GetOverlappedResult(h_pipe, lp_overlap, &dw_size, TRUE);
|
|
return dw_size;
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_ACCESS_DENIED:
|
|
m_b_is_connected = false;
|
|
FileTools::writelog(log_lv::log_WARN,"errorcode ="+ std::to_string(errorcode));
|
|
if (hotplug_call) {
|
|
hotplug_call(true, usrdata);
|
|
}
|
|
break;
|
|
default:
|
|
FileTools::writelog(log_INFO,"Usb write_bulk error code: " + std::to_string(errorcode));
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int UsbScanEx::control_msg(int rtype, int req, int value, int index, int len, void* data)
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
_IO_BLOCK_EX irp;
|
|
DWORD dw_ret;
|
|
|
|
if (m_h_dev == INVALID_HANDLE_VALUE)
|
|
return TRUE;
|
|
irp.uOffset = value;
|
|
irp.uLength = len;
|
|
irp.uIndex = index;
|
|
irp.pbyData = (LPBYTE)data;
|
|
irp.fTransferDirectionIn = (rtype >> 7);
|
|
irp.bRequest = req;
|
|
irp.bmRequestType = (rtype >> 5) & 0x03;
|
|
|
|
LPOVERLAPPED lp_overlap = ov + CTRL_IN_OUT;
|
|
b_ret = DeviceIoControl(m_h_dev, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, len, &dw_ret, lp_overlap);
|
|
|
|
if (!b_ret)
|
|
b_ret = WaitForSingleObject(lp_overlap->hEvent, timeout) == WAIT_OBJECT_0;
|
|
|
|
return b_ret;
|
|
}
|
|
|
|
bool UsbScanEx::is_open()
|
|
{
|
|
return m_h_dev != INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
bool UsbScanEx::is_connected()
|
|
{
|
|
return is_open();//m_b_is_connected;
|
|
}
|
|
|
|
int UsbScanEx::read_int(void* data, int len)
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
DWORD dw_ret = 0L;
|
|
HANDLE h_pipe = m_usb_pipes[INT_IN].h_pipe;
|
|
LPOVERLAPPED lp_overlap = ov + INT_IN;
|
|
|
|
if (m_h_dev == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
|
|
b_ret = DeviceIoControl(h_pipe, (DWORD)IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0,
|
|
data, len, &dw_ret, lp_overlap);
|
|
|
|
if (b_ret) {
|
|
return dw_ret;
|
|
}
|
|
else {
|
|
switch (GetLastError())
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
GetOverlappedResult(h_pipe, lp_overlap, &dw_ret, TRUE);
|
|
return dw_ret;
|
|
|
|
case ERROR_FILE_NOT_FOUND:
|
|
m_b_is_connected = false;
|
|
FileTools::writelog(log_lv::log_ERROR,"USB connection error: ERROR_FILE_NOT_FOUND");
|
|
if (hotplug_call) {
|
|
hotplug_call(true, usrdata);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
UsbScan_List::~UsbScan_List()
|
|
{
|
|
}
|
|
|
|
std::list<std::shared_ptr<IUsb>> UsbScan_List::find_all()
|
|
{
|
|
auto devs = find_all_usb();
|
|
std::list<std::shared_ptr<IUsb>> usbs;
|
|
for (auto inter = devs.begin(); inter != devs.end(); inter++) {
|
|
usbs.push_back(std::shared_ptr<IUsb>(new UsbScanEx(inter->index)));
|
|
}
|
|
return usbs;
|
|
}
|
|
|
|
std::list<std::shared_ptr<IUsb>> UsbScan_List::find_vid_pid(int vid, int pid)
|
|
{
|
|
auto devs = find_all_usb();
|
|
std::list<std::shared_ptr<IUsb>> usbs;
|
|
for (auto inter = devs.begin(); inter != devs.end(); inter++) {
|
|
if (inter->vid == vid && inter->pid == pid)
|
|
usbs.push_back(std::shared_ptr<IUsb>(new UsbScanEx(inter->index)));
|
|
}
|
|
return usbs;
|
|
}
|
|
|
|
std::list<usb_scan_dev_info> UsbScan_List::find_all_usb()
|
|
{
|
|
BOOL b_ret = FALSE;
|
|
DWORD cbRet = 0;
|
|
TCHAR szDevPath[MAX_PATH] = { 0 };
|
|
DEVICE_DESCRIPTOR dev_desc;
|
|
HANDLE h_dev;
|
|
std::list<usb_scan_dev_info> usbs;
|
|
usb_scan_dev_info dev_info;
|
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
|
|
_stprintf(szDevPath, TEXT("\\\\.\\Usbscan%d"), i);
|
|
h_dev = CreateFile(szDevPath,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED,
|
|
NULL);
|
|
if (h_dev != INVALID_HANDLE_VALUE) {
|
|
b_ret = DeviceIoControl(h_dev, (DWORD)IOCTL_GET_DEVICE_DESCRIPTOR,
|
|
&dev_desc, sizeof(dev_desc), &dev_desc, sizeof(dev_desc),
|
|
&cbRet, NULL);
|
|
if (b_ret != 0) {
|
|
dev_info.index = i;
|
|
dev_info.vid = dev_desc.usVendorId;
|
|
dev_info.pid = dev_desc.usProductId;
|
|
usbs.push_back(dev_info);
|
|
}
|
|
CloseHandle(h_dev);
|
|
}
|
|
}
|
|
|
|
return usbs;
|
|
}
|