int open_path(const char * path, int print) { int device = async_open_path(path, print); if(device >= 0) { HIDD_ATTRIBUTES attributes = { .Size = sizeof(HIDD_ATTRIBUTES) }; if(HidD_GetAttributes(devices[device].handle, &attributes) == TRUE) { PHIDP_PREPARSED_DATA preparsedData; HIDP_CAPS hidCapabilities; if(HidD_GetPreparsedData(devices[device].handle, &preparsedData) == TRUE) { if(HidP_GetCaps(preparsedData, &hidCapabilities) == HIDP_STATUS_SUCCESS ) { devices[device].write.size = hidCapabilities.OutputReportByteLength; async_set_read_size(device, hidCapabilities.InputReportByteLength); devices[device].hidInfo.vendor_id = attributes.VendorID; devices[device].hidInfo.product_id = attributes.ProductID; devices[device].hidInfo.bcdDevice = attributes.VersionNumber; } else { if (print) { ASYNC_PRINT_ERROR("HidP_GetCaps") } async_close(device); device = -1; } HidD_FreePreparsedData(preparsedData); } else { if (print) { ASYNC_PRINT_ERROR("HidD_GetPreparsedData") } async_close(device); device = -1; } }
void GetDeviceCapabilities(HANDLE DeviceHandle) { //Get the Capabilities structure for the PHIDP_PREPARSED_DATA PreparsedData; /* API function: HidD_GetPreparsedData Returns: a pointer to a buffer containing the information about the device's capabilities. Requires: A handle returned by CreateFile. There's no need to access the buffer directly, but HidP_GetCaps and other API functions require a pointer to the buffer. */ HidD_GetPreparsedData (DeviceHandle, &PreparsedData); /* API function: HidP_GetCaps Learn the device's capabilities. For standard devices such as joysticks, you can find out the specific capabilities of the For a custom device, the software will probably know what the device is capable of, and the call only verifies the information. Requires: the pointer to the buffer returned by HidD_GetPreparsedData. Returns: a Capabilities structure containing the information. */ HidP_GetCaps (PreparsedData, &Capabilities); HidD_FreePreparsedData(PreparsedData); }
int hs_hid_parse_descriptor(hs_handle *h, hs_hid_descriptor *rdesc) { assert(h); assert(h->dev->type == HS_DEVICE_TYPE_HID); assert(rdesc); // semi-hidden Hungarian pointers? Really , Microsoft? PHIDP_PREPARSED_DATA pp; HIDP_CAPS caps; LONG ret; ret = HidD_GetPreparsedData(h->handle, &pp); if (!ret) return hs_error(HS_ERROR_SYSTEM, "HidD_GetPreparsedData() failed"); // NTSTATUS and BOOL are both defined as LONG ret = HidP_GetCaps(pp, &caps); HidD_FreePreparsedData(pp); if (ret != HIDP_STATUS_SUCCESS) return hs_error(HS_ERROR_SYSTEM, "Invalid HID descriptor"); rdesc->usage_page = caps.UsagePage; rdesc->usage = caps.Usage; return 0; }
USBHIDDLL_API bool bWrite_ToHIDDevice(PHANDLE pWriteHandle, LPBYTE lpWriteBuff){ DWORD dwNumberOfBytesWrite; HIDP_CAPS Capabilities; PHIDP_PREPARSED_DATA HidParsedData; BOOL bResult = false; if(*pWriteHandle != NULL){ HidD_GetPreparsedData(*pWriteHandle, &HidParsedData); /* extract the capabilities info */ HidP_GetCaps( HidParsedData ,&Capabilities); /* Free the memory allocated when getting the preparsed data */ HidD_FreePreparsedData(HidParsedData); bResult = WriteFile(*pWriteHandle, lpWriteBuff, Capabilities.OutputReportByteLength, &dwNumberOfBytesWrite, NULL); } return bResult; }
HID_API_EXPORT hid_device* HID_API_CALL hid_open_path(const char *path) { hid_device *dev; HIDP_CAPS caps; PHIDP_PREPARSED_DATA pp_data = NULL; BOOLEAN res; NTSTATUS nt_res; if (hid_init() < 0) { return NULL; } dev = new_hid_device(); /* Open a handle to the device */ dev->device_handle = open_device(path, FALSE); /* Check validity of write_handle. */ if (dev->device_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ register_error(dev, "CreateFile"); goto err; } /* Set the Input Report buffer size to 64 reports. */ res = HidD_SetNumInputBuffers(dev->device_handle, 64); if (!res) { register_error(dev, "HidD_SetNumInputBuffers"); goto err; } /* Get the Input Report length for the device. */ res = HidD_GetPreparsedData(dev->device_handle, &pp_data); if (!res) { register_error(dev, "HidD_GetPreparsedData"); goto err; } nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { register_error(dev, "HidP_GetCaps"); goto err_pp_data; } dev->output_report_length = caps.OutputReportByteLength; dev->input_report_length = caps.InputReportByteLength; HidD_FreePreparsedData(pp_data); dev->read_buf = (char*) malloc(dev->input_report_length); return dev; err_pp_data: HidD_FreePreparsedData(pp_data); err: free_hid_device(dev); return NULL; }
BOOLEAN SwitchLogitech( __in LPTSTR lpDongleName, __in HANDLE hHidDevice, __in BOOL toHID ) { PHIDP_PREPARSED_DATA PreparsedData; if ( !HidD_GetPreparsedData( hHidDevice, &PreparsedData ) ) { LbtReportFunctionError( TEXT("HidD_GetPreparsedData") ); return FALSE; } HIDP_CAPS HidCaps; if ( !HidP_GetCaps( PreparsedData, &HidCaps ) ) { LbtReportFunctionError( TEXT("HidP_GetCaps") ); HidD_FreePreparsedData(PreparsedData); return FALSE; } if ( HidCaps.UsagePage != 0xFF00 || HidCaps.Usage != 0x0001 ) { HidD_FreePreparsedData(PreparsedData); return FALSE; } if ( HidCaps.OutputReportByteLength != sizeof(ToHCIReports[0]) ) { HidD_FreePreparsedData(PreparsedData); return FALSE; } DWORD noReports = toHID ? sizeof(ToHCIReports) / sizeof(ToHCIReports[0]) : sizeof(ToHIDReports) / sizeof(ToHIDReports[0]); for (DWORD i = 0; i < noReports; i++ ) { CHAR ReportBuffer[sizeof(ToHCIReports[0])]; RtlCopyMemory( ReportBuffer, toHID ? ToHCIReports[i] : ToHIDReports[i], sizeof( ToHCIReports[0] ) ); if (!HidD_SetOutputReport( hHidDevice, ReportBuffer, HidCaps.OutputReportByteLength ) ) { LbtReportFunctionError( TEXT("HidD_SetOutputReport") ); HidD_FreePreparsedData(PreparsedData); return FALSE; } } HidD_FreePreparsedData(PreparsedData); LbtReportDongleSwitch( lpDongleName, toHID ); return TRUE; }
BOOLEAN CheckIfOurDevice( HANDLE file, USAGE myUsagePage, USAGE myUsage) { PHIDP_PREPARSED_DATA Ppd = NULL; // The opaque parser info describing this device HIDD_ATTRIBUTES Attributes; // The Attributes of this hid device. HIDP_CAPS Caps; // The Capabilities of this hid device. BOOLEAN result = FALSE; if (!HidD_GetPreparsedData (file, &Ppd)) { printf("Error: HidD_GetPreparsedData failed \n"); goto cleanup; } if (!HidD_GetAttributes(file, &Attributes)) { printf("Error: HidD_GetAttributes failed \n"); goto cleanup; } if (Attributes.VendorID == vmultib_VID && Attributes.ProductID == vmultib_PID) { if (!HidP_GetCaps (Ppd, &Caps)) { printf("Error: HidP_GetCaps failed \n"); goto cleanup; } if ((Caps.UsagePage == myUsagePage) && (Caps.Usage == myUsage)) { printf("Success: Found my device.. \n"); result = TRUE; } } cleanup: if (Ppd != NULL) { HidD_FreePreparsedData (Ppd); } return result; }
void CUSBDevice::setDetail(TCHAR *path){ HANDLE temp; PHIDP_PREPARSED_DATA PreparsedData; delete[] m_pPath; m_pPath = new TCHAR[strlen(path) * sizeof(TCHAR) + 1]; strcpy(m_pPath, path); TRACE("received at addr %x %s\r\n", m_pPath, m_pPath); temp = CreateFile(m_pPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); HidD_GetPreparsedData(temp, &PreparsedData); HidP_GetCaps(PreparsedData, &m_Capabilities); }
bool HIDDeviceManager::initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const { bool result = false; HIDP_CAPS caps; HIDP_PREPARSED_DATA* preparsedData = 0; if (!HidD_GetPreparsedData(hidDev, &preparsedData)) return false; if (HidP_GetCaps(preparsedData, &caps) == HIDP_STATUS_SUCCESS) { desc->Usage = caps.Usage; desc->UsagePage = caps.UsagePage; result = true; } HidD_FreePreparsedData(preparsedData); return result; }
bool Device::open(boost::asio::io_service &io_service, std::shared_ptr<ICallback> callback) { auto handle = CreateFile(m_path.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(handle == INVALID_HANDLE_VALUE) { return false; } m_handle=std::shared_ptr<void>(handle, &::CloseHandle); // get hid caps { HIDP_PREPARSED_DATA* preparsedData=0; if (!HidD_GetPreparsedData(handle, &preparsedData)){ return false; } std::shared_ptr<HIDP_PREPARSED_DATA> parsed( preparsedData, HidD_FreePreparsedData); HIDP_CAPS caps; if (HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS) { return false; } std::cout << "Usage: " << caps.Usage << std::endl; std::cout << "UsagePage: " << caps.UsagePage << std::endl; std::cout << "InputReportByteLength: " << caps.InputReportByteLength << std::endl; std::cout << "OutputReportByteLength: " << caps.OutputReportByteLength << std::endl; std::cout << "FeatureReportByteLength: " << caps.FeatureReportByteLength << std::endl; } // setup stream m_stream=std::make_shared<boost::asio::windows::stream_handle>(io_service, handle); m_callback=callback; beginRead(); m_callback->onConnect(this); return true; }
BOOLEAN SwitchCSR(__in LPTSTR lpDongleName, __in HANDLE hHidDevice, __in BOOL toHID) { PHIDP_PREPARSED_DATA PreparsedData; if (!HidD_GetPreparsedData(hHidDevice, &PreparsedData)) { LbtReportFunctionError(TEXT("HidD_GetPreparsedData")); return FALSE; } HIDP_CAPS HidCaps; if (!HidP_GetCaps(PreparsedData, &HidCaps)) { LbtReportFunctionError(TEXT("HidP_GetCaps")); HidD_FreePreparsedData(PreparsedData); return FALSE; } if (HidCaps.UsagePage != 0xFF00 || HidCaps.Usage != 0x0001) { // HidD_FreePreparsedData(PreparsedData); // return FALSE; } if (HidCaps.FeatureReportByteLength != sizeof(ToHCICSRReports)) { // HidD_FreePreparsedData(PreparsedData); // return FALSE; } CHAR ReportBuffer[sizeof(ToHCICSRReports)]; RtlCopyMemory(ReportBuffer, ToHCICSRReports, sizeof(ToHCICSRReports)); if (!HidD_SetFeature(hHidDevice, ReportBuffer, HidCaps.FeatureReportByteLength)) { LbtReportFunctionError(TEXT("HidD_SetOutputReport")); HidD_FreePreparsedData(PreparsedData); return FALSE; } HidD_FreePreparsedData(PreparsedData); LbtReportDongleSwitch(lpDongleName, toHID); return TRUE; }
/** * constructor */ boca_hid_printer_t *boca_hid_new(const char *device_path) { boca_hid_printer_t *self = (boca_hid_printer_t *) calloc(1, sizeof(boca_hid_printer_t)); if (!self) return NULL; self->device_path = strdup(device_path); #ifdef __WIN32__ HANDLE handle; handle = CreateFile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle != INVALID_HANDLE_VALUE) { PHIDP_PREPARSED_DATA preparsed_data; if (HidD_GetPreparsedData(handle, &preparsed_data)) { HIDP_CAPS capabilities; NTSTATUS ret = HidP_GetCaps(preparsed_data, &capabilities); if (ret == HIDP_STATUS_SUCCESS) { self->input_length = capabilities.InputReportByteLength; self->output_length = capabilities.OutputReportByteLength; self->feature_length = capabilities.FeatureReportByteLength; zsys_info("hid printer: input length %d output length %d feature length %d", self->input_length, self->output_length, self->feature_length); } else { zsys_warning("hid printer: can not get hid printer capabilities."); } } else { zsys_warning("hid printer: can not get hid prepared data"); } CloseHandle(handle); } else { zsys_warning("hid printer: can not open hid device code %d", GetLastError()); } #endif self->device = hid_open_path(self->device_path); if (self->device == NULL) { zsys_error("hid printer: could not create device from path %s", device_path); boca_hid_destroy(&self); return NULL; } return self; }
int RawInputPad::Open() { PHIDP_PREPARSED_DATA pPreparsedData = NULL; //TODO Better place? LoadMappings(mapVector); memset(&this->ovl, 0, sizeof(OVERLAPPED)); memset(&this->ovlW, 0, sizeof(OVERLAPPED)); //this->padState.initStage = 0; this->doPassthrough = !!conf.DFPPass;//TODO per player this->usbHandle = INVALID_HANDLE_VALUE; std::wstring path; { CONFIGVARIANT var(N_JOYSTICK, CONFIG_TYPE_WCHAR); if (LoadSetting(mPort, APINAME, var)) path = var.wstrValue; else return 1; } this->usbHandle = CreateFileW(path.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if(this->usbHandle != INVALID_HANDLE_VALUE) { this->ovl.hEvent = CreateEvent(0, 0, 0, 0); this->ovlW.hEvent = CreateEvent(0, 0, 0, 0); HidD_GetAttributes(this->usbHandle, &(this->attr)); HidD_GetPreparsedData(this->usbHandle, &pPreparsedData); HidP_GetCaps(pPreparsedData, &(this->caps)); HidD_FreePreparsedData(pPreparsedData); return 0; } else fwprintf(stderr, L"Could not open device '%s'.\nPassthrough and FFB will not work.\n", path.c_str()); return 1; }
// 获取设备一些能力信息 USBHIDDLL_API void __stdcall USBHIDGetDeviceCapabilities(USBHANDLE handle, PHIDD_ATTRIBUTES attributes, PHIDP_CAPS caps) { if (handle != INVALID_HANDLE_VALUE) { HidD_GetAttributes(handle, attributes); //Get the Capabilities structure for the device. PHIDP_PREPARSED_DATA PreparsedData; /* API function: HidD_GetPreparsedData Returns: a pointer to a buffer containing the information about the device's capabilities. Requires: A handle returned by CreateFile. There's no need to access the buffer directly, but HidP_GetCaps and other API functions require a pointer to the buffer. */ HidD_GetPreparsedData (handle, &PreparsedData); //DisplayLastError("HidD_GetPreparsedData: "); /* API function: HidP_GetCaps Learn the device's capabilities. For standard devices such as joysticks, you can find out the specific capabilities of the device. For a custom device, the software will probably know what the device is capable of, and the call only verifies the information. Requires: the pointer to the buffer returned by HidD_GetPreparsedData. Returns: a Capabilities structure containing the information. */ HidP_GetCaps (PreparsedData, caps); //No need for PreparsedData any more, so free the memory it's using. HidD_FreePreparsedData(PreparsedData); //DisplayLastError("HidD_FreePreparsedData: ") ; } }
void parse_info_from_path(hid_event* event, char* device_path) { auto write_handle = open_device(device_path, TRUE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ //register_error(dev, "CreateFile"); //goto cont_close; return; } //TODO: clean this shit up HIDD_ATTRIBUTES attrib; attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); event->device_info->product_id = attrib.ProductID; event->device_info->vendor_id = attrib.VendorID; event->device_info->release_number = attrib.VersionNumber; PHIDP_PREPARSED_DATA pp_data = NULL; auto res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { HIDP_CAPS caps; auto nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { event->device_info->usage_page = caps.UsagePage; event->device_info->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } CloseHandle(write_handle); }
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ GUID InterfaceClassGuid; HidD_GetHidGuid(&InterfaceClassGuid); SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; int device_index = 0; int i; if (hid_init() < 0) return NULL; /* Initialize the Windows objects. */ memset(&devinfo_data, 0x0, sizeof(devinfo_data)); devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Iterate over each device in the HID class, looking for the right one. */ for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; HIDD_ATTRIBUTES attrib; res = SetupDiEnumDeviceInterfaces(device_info_set, NULL, &InterfaceClassGuid, device_index, &device_interface_data); if (!res) { /* A return of FALSE from this function means that there are no more devices. */ break; } /* Call with 0-sized detail size, and let the function tell us how long the detail struct needs to be. The size is put in &required_size. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL); /* Allocate a long enough structure for device_interface_detail_data. */ device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); /* Get the detailed data for this device. The detail data gives us the device path for this device, which is then passed into CreateFile() to get a handle to the device. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, device_interface_detail_data, required_size, NULL, NULL); if (!res) { /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); Continue to the next device. */ goto cont; } /* Make sure this device is of Setup Class "HIDClass" and has a driver bound to it. */ for (i = 0; ; i++) { char driver_name[256]; /* Populate devinfo_data. This function will return failure when there are no more interfaces left. */ res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); if (!res) goto cont; res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (!res) goto cont; if (strcmp(driver_name, "HIDClass") == 0) { /* See if there's a driver bound. */ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (res) break; } } //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); /* Open a handle to the device */ write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; } /* Get the Vendor ID and Product ID for this device. */ attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); /* Check the VID/PID to see if we should add this device to the enumeration list. */ if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && (product_id == 0x0 || attrib.ProductID == product_id)) { #define WSTR_LEN 512 const char *str; struct hid_device_info *tmp; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; BOOLEAN res; NTSTATUS nt_res; wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ size_t len; /* VID/PID match. Create the record. */ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { cur_dev->usage_page = caps.UsagePage; cur_dev->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->serial_number = _wcsdup(wstr); } /* Manufacturer String */ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->manufacturer_string = _wcsdup(wstr); } /* Product String */ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->product_string = _wcsdup(wstr); } /* VID/PID */ cur_dev->vendor_id = attrib.VendorID; cur_dev->product_id = attrib.ProductID; /* Release Number */ cur_dev->release_number = attrib.VersionNumber; /* Interface Number. It can sometimes be parsed out of the path on Windows if a device has multiple interfaces. See http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or search for "Hardware IDs for HID Devices" at MSDN. If it's not in the path, it's set to -1. */ cur_dev->interface_number = -1; if (cur_dev->path) { char *interface_component = strstr(cur_dev->path, "&mi_"); if (interface_component) { char *hex_str = interface_component + 4; char *endptr = NULL; cur_dev->interface_number = strtol(hex_str, &endptr, 16); if (endptr == hex_str) { /* The parsing failed. Set interface_number to -1. */ cur_dev->interface_number = -1; } } } } cont_close: CloseHandle(write_handle); cont: /* We no longer need the detail data. It can be freed */ free(device_interface_detail_data); device_index++; } /* Close the device information handle. */ SetupDiDestroyDeviceInfoList(device_info_set); return root; }
// rawhid_open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int rawhid_open(int max, int vid, int pid, int usage_page, int usage) { GUID guid; HDEVINFO info; DWORD index=0, reqd_size; SP_DEVICE_INTERFACE_DATA iface; SP_DEVICE_INTERFACE_DETAIL_DATA *details; HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA hid_data; HIDP_CAPS capabilities; HANDLE h; BOOL ret; hid_t *hid; int count=0; if (first_hid) free_all_hid(); if (max < 1) return 0; if (!rx_event) { rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); InitializeCriticalSection(&rx_mutex); InitializeCriticalSection(&tx_mutex); } HidD_GetHidGuid(&guid); info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (info == INVALID_HANDLE_VALUE) return 0; for (index=0; 1 ;index++) { iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); if (!ret) return count; SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); if (details == NULL) continue; memset(details, 0, reqd_size); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, reqd_size, NULL, NULL); if (!ret) { free(details); continue; } h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); free(details); if (h == INVALID_HANDLE_VALUE) continue; attrib.Size = sizeof(HIDD_ATTRIBUTES); ret = HidD_GetAttributes(h, &attrib); //printf("vid: %4x\n", attrib.VendorID); if (!ret || (vid > 0 && attrib.VendorID != vid) || (pid > 0 && attrib.ProductID != pid) || !HidD_GetPreparsedData(h, &hid_data)) { CloseHandle(h); continue; } if (!HidP_GetCaps(hid_data, &capabilities) || (usage_page > 0 && capabilities.UsagePage != usage_page) || (usage > 0 && capabilities.Usage != usage)) { HidD_FreePreparsedData(hid_data); CloseHandle(h); continue; } HidD_FreePreparsedData(hid_data); hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); if (!hid) { CloseHandle(h); continue; } hid->handle = h; hid->open = 1; add_hid(hid); count++; if (count >= max) return count; } return count; }
BOOLEAN OpenHidDevice ( IN PCHAR DevicePath, IN BOOL HasReadAccess, IN BOOL HasWriteAccess, IN BOOL IsOverlapped, IN BOOL IsExclusive, IN OUT PHID_DEVICE HidDevice ) /*++ RoutineDescription: Given the HardwareDeviceInfo, representing a handle to the plug and play information, and deviceInfoData, representing a specific hid device, open that device and fill in all the relivant information in the given HID_DEVICE structure. return if the open and initialization was successfull or not. --*/ { DWORD accessFlags = 0; DWORD sharingFlags = 0; BOOLEAN bSuccess; INT iDevicePathSize; HRESULT stringReturn; iDevicePathSize = strlen(DevicePath) + 1; HidDevice -> DevicePath = malloc(iDevicePathSize); if (NULL == HidDevice -> DevicePath) { return (FALSE); } stringReturn = StringCbCopy(HidDevice -> DevicePath, iDevicePathSize, DevicePath); if (HasReadAccess) { accessFlags |= GENERIC_READ; } if (HasWriteAccess) { accessFlags |= GENERIC_WRITE; } if (!IsExclusive) { sharingFlags = FILE_SHARE_READ | FILE_SHARE_WRITE; } // // The hid.dll api's do not pass the overlapped structure into deviceiocontrol // so to use them we must have a non overlapped device. If the request is for // an overlapped device we will close the device below and get a handle to an // overlapped device // HidDevice->HidDevice = CreateFile (DevicePath, accessFlags, sharingFlags, NULL, // no SECURITY_ATTRIBUTES structure OPEN_EXISTING, // No special create flags 0, // Open device as non-overlapped so we can get data NULL); // No template file if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) { free(HidDevice -> DevicePath); HidDevice -> DevicePath = INVALID_HANDLE_VALUE ; return FALSE; } HidDevice -> OpenedForRead = HasReadAccess; HidDevice -> OpenedForWrite = HasWriteAccess; HidDevice -> OpenedOverlapped = IsOverlapped; HidDevice -> OpenedExclusive = IsExclusive; // // If the device was not opened as overlapped, then fill in the rest of the // HidDevice structure. However, if opened as overlapped, this handle cannot // be used in the calls to the HidD_ exported functions since each of these // functions does synchronous I/O. // if (!HidD_GetPreparsedData (HidDevice->HidDevice, &HidDevice->Ppd)) { free(HidDevice -> DevicePath); HidDevice -> DevicePath = NULL ; CloseHandle(HidDevice -> HidDevice); HidDevice -> HidDevice = INVALID_HANDLE_VALUE ; return FALSE; } if (!HidD_GetAttributes (HidDevice->HidDevice, &HidDevice->Attributes)) { free(HidDevice -> DevicePath); HidDevice -> DevicePath = NULL; CloseHandle(HidDevice -> HidDevice); HidDevice -> HidDevice = INVALID_HANDLE_VALUE; HidD_FreePreparsedData (HidDevice->Ppd); HidDevice->Ppd = NULL; return FALSE; } if (!HidP_GetCaps (HidDevice->Ppd, &HidDevice->Caps)) { free(HidDevice -> DevicePath); HidDevice -> DevicePath = NULL; CloseHandle(HidDevice -> HidDevice); HidDevice -> HidDevice = INVALID_HANDLE_VALUE; HidD_FreePreparsedData (HidDevice->Ppd); HidDevice->Ppd = NULL; return FALSE; } // // At this point the client has a choice. It may chose to look at the // Usage and Page of the top level collection found in the HIDP_CAPS // structure. In this way it could just use the usages it knows about. // If either HidP_GetUsages or HidP_GetUsageValue return an error then // that particular usage does not exist in the report. // This is most likely the preferred method as the application can only // use usages of which it already knows. // In this case the app need not even call GetButtonCaps or GetValueCaps. // // In this example, however, we will call FillDeviceInfo to look for all // of the usages in the device. // bSuccess = FillDeviceInfo(HidDevice); if (FALSE == bSuccess) { CloseHidDevice(HidDevice); return (FALSE); } if (IsOverlapped) { CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = CreateFile (DevicePath, accessFlags, sharingFlags, NULL, // no SECURITY_ATTRIBUTES structure OPEN_EXISTING, // No special create flags FILE_FLAG_OVERLAPPED, // Now we open the device as overlapped NULL); // No template file if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) { CloseHidDevice(HidDevice); return FALSE; } } return (TRUE); }
bool CLCDConnectionLogitech::HIDInit() { if (GetConnectionState() != CONNECTED || m_pConnectedDevice->GetIndex() != LGLCD_DEVICE_BW) //LGLCD_DEVICE_FAMILY_KEYBOARD_G15) return false; // Logitech G15 int VendorID = 0x046d; int ProductID = 0xc222; //Use a series of API calls to find a HID with a specified Vendor IF and Product ID. HIDD_ATTRIBUTES Attributes; SP_DEVICE_INTERFACE_DATA devInfoData; bool LastDevice = FALSE; int MemberIndex = 0; LONG Result; DWORD Length = 0; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL; HANDLE hDevInfo = NULL; GUID HidGuid; ULONG Required = 0; bool MyDeviceDetected = false; /* API function: HidD_GetHidGuid Get the GUID for all system HIDs. Returns: the GUID in HidGuid. */ HidD_GetHidGuid(&HidGuid); /* API function: SetupDiGetClassDevs Returns: a handle to a device information set for all installed devices. Requires: the GUID returned by GetHidGuid. */ hDevInfo = SetupDiGetClassDevs (&HidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); devInfoData.cbSize = sizeof(devInfoData); //Step through the available devices looking for the one we want. //Quit on detecting the desired device or checking all available devices without success. MemberIndex = 0; LastDevice = FALSE; do { /* API function: SetupDiEnumDeviceInterfaces On return, MyDeviceInterfaceData contains the handle to a SP_DEVICE_INTERFACE_DATA structure for a detected device. Requires: The DeviceInfoSet returned in SetupDiGetClassDevs. The HidGuid returned in GetHidGuid. An index to specify a device. */ Result = SetupDiEnumDeviceInterfaces (hDevInfo, 0, &HidGuid, MemberIndex, &devInfoData); if (Result != 0) { //A device has been detected, so get more information about it. /* API function: SetupDiGetDeviceInterfaceDetail Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure containing information about a device. To retrieve the information, call this function twice. The first time returns the size of the structure in Length. The second time returns a pointer to the data in DeviceInfoSet. Requires: A DeviceInfoSet returned by SetupDiGetClassDevs The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces. The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure. This application doesn't retrieve or use the structure. If retrieving the structure, set MyDeviceInfoData.cbSize = length of MyDeviceInfoData. and pass the structure's address. */ //Get the Length value. //The call will return with a "buffer too small" error which can be ignored. Result = SetupDiGetDeviceInterfaceDetail (hDevInfo, &devInfoData, NULL, 0, &Length, NULL); //Allocate memory for the hDevInfo structure, using the returned Length. detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); //Set cbSize in the detailData structure. detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //Call the function again, this time passing it the returned buffer size. Result = SetupDiGetDeviceInterfaceDetail (hDevInfo, &devInfoData, detailData, Length, &Required, NULL); // Open a handle to the device. // To enable retrieving information about a system mouse or keyboard, // don't request Read or Write access for this handle. /* API function: CreateFile Returns: a handle that enables reading and writing to the device. Requires: The DevicePath in the detailData structure returned by SetupDiGetDeviceInterfaceDetail. */ m_hHIDDeviceHandle = CreateFile (detailData->DevicePath, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); /* API function: HidD_GetAttributes Requests information from the device. Requires: the handle returned by CreateFile. Returns: a HIDD_ATTRIBUTES structure containing the Vendor ID, Product ID, and Product Version Number. Use this information to decide if the detected device is the one we're looking for. */ //Set the Size to the number of bytes in the structure. Attributes.Size = sizeof(Attributes); Result = HidD_GetAttributes (m_hHIDDeviceHandle, &Attributes); //Is it the desired device? MyDeviceDetected = FALSE; if (Attributes.VendorID == VendorID) { if (Attributes.ProductID == ProductID) { //Both the Vendor ID and Product ID match. MyDeviceDetected = TRUE; } else CloseHandle(m_hHIDDeviceHandle); } else CloseHandle(m_hHIDDeviceHandle); //Free the memory used by the detailData structure (no longer needed). free(detailData); } else LastDevice = TRUE; MemberIndex = MemberIndex + 1; } //do while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE)); if (MyDeviceDetected) { PHIDP_PREPARSED_DATA PreparsedData; HidD_GetPreparsedData (m_hHIDDeviceHandle, &PreparsedData); HidP_GetCaps (PreparsedData, &m_HIDCapabilities); HidD_FreePreparsedData(PreparsedData); } //Free the memory reserved for hDevInfo by SetupDiClassDevs. SetupDiDestroyDeviceInfoList(hDevInfo); return MyDeviceDetected; }
bool Controller::registerController(int pDeviceId) { //Required variables to iterate over the device interface DWORD result = 0; LPGUID hidguid = (LPGUID)malloc(sizeof(GUID)); HDEVINFO deviceset; PSP_DEVICE_INTERFACE_DATA deviceInterfaceData = nullptr; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceInfo = nullptr; DWORD buffersize = 0; //malloc check CHECK_NULL(hidguid, SETUP_ERROR); //get hid guid HidD_GetHidGuid(hidguid); //get device list deviceset = SetupDiGetClassDevs(hidguid, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (deviceset == INVALID_HANDLE_VALUE) { goto SETUP_ERROR; } int deviceindex = 0; deviceInterfaceData = (PSP_DEVICE_INTERFACE_DATA)malloc(sizeof(SP_DEVICE_INTERFACE_DATA)); //malloc check CHECK_NULL(deviceInterfaceData, SETUP_ERROR); deviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); //iterate through devices while (SetupDiEnumDeviceInterfaces(deviceset, nullptr, hidguid, deviceindex, deviceInterfaceData)) { //this should fail originally in order to get buffer size if (deviceInterfaceInfo != nullptr) { free(deviceInterfaceInfo); deviceInterfaceInfo = 0; } if (SetupDiGetDeviceInterfaceDetail(deviceset, deviceInterfaceData, nullptr, 0, (PDWORD)&buffersize, nullptr) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto SETUP_ERROR; } deviceInterfaceInfo = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(buffersize); //malloc check CHECK_NULL(deviceInterfaceInfo, SETUP_ERROR); deviceInterfaceInfo->cbSize = sizeof(*deviceInterfaceInfo); //device info buffer allocated, get details if (!SetupDiGetDeviceInterfaceDetail(deviceset, deviceInterfaceData, deviceInterfaceInfo, buffersize, (PDWORD)&buffersize, nullptr)) { goto SETUP_ERROR; } //you must pass in the device id of the hid client to read from if (deviceindex == pDeviceId) { _controllerHandle = CreateFile( deviceInterfaceInfo->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ); if (_controllerHandle == INVALID_HANDLE_VALUE) { Log(L"Error opening HID Device: Error No: %d", GetLastError()); goto HID_SETUP_FAILURE; } else { //get preparsed data if (HidD_GetPreparsedData(_controllerHandle, &_pPreparsedData) == FALSE) { goto HID_SETUP_FAILURE; } //get device capabilities _pCaps = (PHIDP_CAPS)(malloc(sizeof(HIDP_CAPS))); //malloc check CHECK_NULL(_pCaps, HID_SETUP_FAILURE); _succ = HidP_GetCaps(_pPreparsedData, _pCaps); CHECK_HID(_succ, HID_SETUP_FAILURE); //get button capabilities _pButtonCaps = (PHIDP_BUTTON_CAPS)malloc(sizeof(HIDP_BUTTON_CAPS)* _pCaps->NumberInputButtonCaps); //malloc check CHECK_NULL(_pButtonCaps, HID_SETUP_FAILURE); USHORT numInputButtonCaps = _pCaps->NumberInputButtonCaps; _succ = HidP_GetButtonCaps(HidP_Input, _pButtonCaps, &numInputButtonCaps, _pPreparsedData); CHECK_HID(_succ, HID_SETUP_FAILURE); //prep the button usage data structs _pButtonUsages = (PUSAGE)malloc(sizeof(USAGE)*(_pButtonCaps->Range.DataIndexMax - _pButtonCaps->Range.DataIndexMin + 1)); //malloc check CHECK_NULL(_pButtonUsages, HID_SETUP_FAILURE); ULONG numButtonUsages = _pButtonCaps->Range.UsageMax - _pButtonCaps->Range.UsageMin + 1; //get max data length _pInputReport = (PCHAR)malloc(_pCaps->InputReportByteLength); //malloc check CHECK_NULL(_pInputReport, HID_SETUP_FAILURE); DWORD readbytecount = 0; //get value caps _pValueCaps = (PHIDP_VALUE_CAPS)malloc(sizeof(HIDP_VALUE_CAPS)* _pCaps->NumberInputValueCaps); //malloc check CHECK_NULL(_pValueCaps, HID_SETUP_FAILURE); USHORT numInputValueCaps = _pCaps->NumberInputValueCaps; _succ = HidP_GetValueCaps(HidP_Input, _pValueCaps, &numInputValueCaps, _pPreparsedData); CHECK_HID(_succ, HID_SETUP_FAILURE); goto SETUP_DONE; HID_SETUP_FAILURE: clearHidStructures(); return false; } } deviceindex++; deviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); } goto SETUP_DONE; SETUP_ERROR: int err = GetLastError(); return false; SETUP_DONE: if (deviceset != INVALID_HANDLE_VALUE && deviceset != nullptr) { SetupDiDestroyDeviceInfoList(deviceset); } if (hidguid != nullptr) { free(hidguid); } if (deviceInterfaceData != nullptr) { free(deviceInterfaceData); } if (deviceInterfaceInfo != nullptr) { free(deviceInterfaceInfo); } return true; }
/********************************************************************* * * _AddConnection * * Function description * Checks the information about the queried device, if complying with * out vendor page information, add the device to the connection list. * * * Return value: * 1 - O.K., HID device added. * 0 - HID device not compatible. * */ static int _AddConnection(HANDLE hDevList, SP_DEVICE_INTERFACE_DATA * pDevData, CONN_INFO * pConnInfo) { SP_INTERFACE_DEVICE_DETAIL_DATA * pDevDetail; DWORD ReqLen; BOOL succ; HANDLE hDevice; int r; r = 0; ReqLen = 0; pDevDetail = NULL; // Get length of INTERFACE_DEVICE_DETAIL_DATA, allocate buffer // This function call returns the system error "buffer too small" (code 122). // We ignore this return code. SetupDiGetDeviceInterfaceDetail(hDevList, pDevData, NULL, ReqLen, &ReqLen, NULL); pDevDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA*)malloc(ReqLen); if (pDevDetail == NULL ) { // Memory allocation failed return 0; } // Now get the INTERFACE_DEVICE_DETAIL_DATA struct ZeroMemory(pDevDetail,ReqLen); pDevDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); succ = SetupDiGetDeviceInterfaceDetail(hDevList, pDevData, pDevDetail, ReqLen, &ReqLen, NULL); if (succ == FALSE) { // // Could not retrieve information about the device // free(pDevDetail); return 0; } // // Open a device handle to the HID device and retriece HID information // hDevice = CreateFile(pDevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice != INVALID_HANDLE_VALUE) { PHIDP_PREPARSED_DATA pPreparsedData; HIDP_CAPS Capabilities; // // Parse the information from HID device // HidD_GetPreparsedData(hDevice, &pPreparsedData); HidP_GetCaps(pPreparsedData, &Capabilities); // // Does the device match the Vendor specific page implementation? // if (Capabilities.UsagePage == _VendorPage) { HIDD_ATTRIBUTES Attributes; memset(&Attributes, 0, sizeof(Attributes)); Attributes.Size = sizeof(Attributes); HidD_GetAttributes(hDevice, &Attributes); strcpy(pConnInfo->acDevicePath, pDevDetail->DevicePath); pConnInfo->InputReportByteLength = Capabilities.InputReportByteLength; pConnInfo->OutputReportByteLength = Capabilities.OutputReportByteLength; pConnInfo->ProductId = Attributes.ProductID; pConnInfo->VendorId = Attributes.VendorID; r = 1; } CloseHandle(hDevice); } free(pDevDetail); return r; }
// open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) { GUID guid; HDEVINFO info; DWORD index=0, reqd_size; SP_DEVICE_INTERFACE_DATA iface; SP_DEVICE_INTERFACE_DETAIL_DATA *details; HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA hid_data; HIDP_CAPS capabilities; HANDLE h; BOOL ret; hid_t *hid; int count=0; if (first_hid) free_all_hid(); if (max < 1) return 0; if (!rx_event) { rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); InitializeCriticalSection(&rx_mutex); InitializeCriticalSection(&tx_mutex); } HidD_GetHidGuid(&guid); info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (info == INVALID_HANDLE_VALUE) return 0; for (index=0; 1 ;index++) { iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); if (!ret) return count; SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); if (details == NULL) continue; memset(details, 0, reqd_size); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, reqd_size, NULL, NULL); if (!ret) { free(details); continue; } h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // I get ERROR_ACCESS_DENIED with most/all my input devices (mice/trackballs/tablet). // Let's not log it :) if (err == ERROR_ACCESS_DENIED) { free(details); continue; } // qDebug wipes the GetLastError() it seems, so do that after print_win32_err(). print_win32_err(err); qDebug() << "Problem opening handle, path: " << QString().fromWCharArray(details->DevicePath); free(details); continue; } free(details); attrib.Size = sizeof(HIDD_ATTRIBUTES); ret = HidD_GetAttributes(h, &attrib); //printf("vid: %4x\n", attrib.VendorID); if (!ret || (vid > 0 && attrib.VendorID != vid) || (pid > 0 && attrib.ProductID != pid) || !HidD_GetPreparsedData(h, &hid_data)) { CloseHandle(h); continue; } if (!HidP_GetCaps(hid_data, &capabilities) || (usage_page > 0 && capabilities.UsagePage != usage_page) || (usage > 0 && capabilities.Usage != usage)) { HidD_FreePreparsedData(hid_data); CloseHandle(h); continue; } HidD_FreePreparsedData(hid_data); hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); if (!hid) { CloseHandle(h); continue; } // COMMTIMEOUTS CommTimeouts; // CommTimeouts.ReadIntervalTimeout = 100; // 100ms // CommTimeouts.ReadTotalTimeoutConstant = 5; // ms // CommTimeouts.ReadTotalTimeoutMultiplier = 1; // // CommTimeouts.WriteTotalTimeoutConstant = 5; // ms // CommTimeouts.WriteTotalTimeoutMultiplier = 1; // // if (!SetCommTimeouts(h, &CommTimeouts)) // { //// DWORD err = GetLastError(); // // } qDebug("Open: Handle address: %li for num: %i", (long int) h, count); hid->handle = h; add_hid(hid); count++; if (count >= max) return count; } return count; }
USBHIDDLL_API DWORD dwRead_FromHIDDevice(PHANDLE pReadHandle, BYTE byReadBuff[], DWORD len){ DWORD dwNumberOfBytesRead; DWORD dwResponseSW = 0; HIDP_CAPS Capabilities; PHIDP_PREPARSED_DATA HidParsedData; OVERLAPPED HidOverlapped; HANDLE hEvent; LPBYTE lpReadBuff = (LPBYTE)malloc(0x21); /* Create a new event for report capture */ hEvent = CreateEvent(NULL, TRUE, TRUE, ""); /* fill the HidOverlapped structure so that Windows knows which event to cause when the device sends an IN report */ HidOverlapped.hEvent = hEvent; HidOverlapped.Offset = 0; HidOverlapped.OffsetHigh = 0; BOOL bResult = false; // LPCOMMTIMEOUTS lpCommitTimes = (LPCOMMTIMEOUTS)malloc(sizeof(LPCOMMTIMEOUTS)); if(*pReadHandle != NULL){ HidD_GetPreparsedData(*pReadHandle, &HidParsedData); /* extract the capabilities info */ HidP_GetCaps( HidParsedData ,&Capabilities); /* Free the memory allocated when getting the preparsed data */ HidD_FreePreparsedData(HidParsedData); bResult = ReadFile(*pReadHandle, lpReadBuff, Capabilities.InputReportByteLength, &dwNumberOfBytesRead, (LPOVERLAPPED)&HidOverlapped); if ( bResult == 0 ) { // 读取错误信息 DWORD dwResult = GetLastError(); // I/O端口繁忙 if ( dwResult == ERROR_IO_PENDING ) { // 需挂起等待 dwResult = WaitForSingleObject ( HidOverlapped.hEvent, INFINITE ); // I/O端口正常 if ( dwResult == WAIT_OBJECT_0 ) { // 去读取数据的正常返回值 GetOverlappedResult ( *pReadHandle, &HidOverlapped, &dwNumberOfBytesRead, FALSE ); } else { // BOOL bGetTime = GetCommTimeouts(*pReadHandle, lpCommitTimes); free(lpReadBuff); CloseHandle(hEvent); return -1; // 等待超时 } } else { return -1; // 不明错误 } } } for(int i = 0; i < (len + 2); i ++){ byReadBuff[i] = *(lpReadBuff + i + 1); } dwResponseSW |= byReadBuff[len]; dwResponseSW = (dwResponseSW << 8) | (byReadBuff[len + 1]); free(lpReadBuff); CloseHandle(hEvent); return dwResponseSW; }