#include "stdafx.h" #include "UsbScanEx.h" #include #include #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> UsbScan_List::find_all() { auto devs = find_all_usb(); std::list> usbs; for (auto inter = devs.begin(); inter != devs.end(); inter++) { usbs.push_back(std::shared_ptr(new UsbScanEx(inter->index))); } return usbs; } std::list> UsbScan_List::find_vid_pid(int vid, int pid) { auto devs = find_all_usb(); std::list> usbs; for (auto inter = devs.begin(); inter != devs.end(); inter++) { if (inter->vid == vid && inter->pid == pid) usbs.push_back(std::shared_ptr(new UsbScanEx(inter->index))); } return usbs; } std::list 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 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; }