twain2/hugaotwainds/UsbScanEx.cpp

336 lines
7.5 KiB
C++

#include "stdafx.h"
#include "UsbScanEx.h"
#include <tchar.h>
#include <winioctl.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;
}
return m_h_dev;
}
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;
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 {
switch (GetLastError())
{
case ERROR_IO_PENDING:
GetOverlappedResult(h_pipe, lp_overlap, &pdw_ret, TRUE);
return pdw_ret;
case ERROR_FILE_NOT_FOUND:
m_b_is_connected = false;
break;
default:
int a = 0;
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 {
switch (GetLastError())
{
case ERROR_IO_PENDING:
GetOverlappedResult(h_pipe, lp_overlap, &dw_size, TRUE);
return dw_size;
case ERROR_FILE_NOT_FOUND:
m_b_is_connected = false;
break;
default:
int a = 0;
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;
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;
}