int HID_API_EXPORT hid_init(void) { #ifndef HIDAPI_USE_DDK if (!initialized) { // DebugClearText (); if (lookup_functions() < 0) { hid_exit(); DebugAppendText ("initialized FAILED\n"); return -1; } initialized = TRUE; DebugAppendText ("initialized = TRUE;\n"); } #endif return 0; }
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { // TODO: Merge this functions with the Linux version. This function should be platform independent. struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; #ifdef STICK20_DEBUG { // For debugging char text[1000]; sprintf(text,"hid_open: VID %04x PID %04x\n", vendor_id,product_id); DebugAppendText (text); } #endif devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && cur_dev->product_id == product_id) { if (serial_number) { if (wcscmp(serial_number, cur_dev->serial_number) == 0) { path_to_open = cur_dev->path; break; } } else { path_to_open = cur_dev->path; break; } } cur_dev = cur_dev->next; } if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); } hid_free_enumeration(devs); return handle; }
void Response::DebugResponse() { char text[1000]; char text1[1000]; int i; static int Counter = 0; sprintf(text,"%6d :getResponse : ",Counter); Counter++; DebugAppendText (text); for (i=0;i<=64;i++) { sprintf(text,"%02x ",(unsigned char)reportBuffer[i]); DebugAppendText (text); } sprintf(text,"\n"); DebugAppendText (text); // Check device status = deviceStatus = reportBuffer[1] switch (deviceStatus) { case CMD_STATUS_OK : DebugAppendText ((char *)" Device status : CMD_STATUS_OK\n"); break; case CMD_STATUS_WRONG_CRC : DebugAppendText ((char *)" Device status : CMD_STATUS_WRONG_CRC\n"); break; case CMD_STATUS_WRONG_SLOT : DebugAppendText ((char *)" Device status : CMD_STATUS_WRONG_SLOT\n"); break; case CMD_STATUS_SLOT_NOT_PROGRAMMED : DebugAppendText ((char *)" Device status : CMD_STATUS_SLOT_NOT_PROGRAMMED\n"); break; case CMD_STATUS_WRONG_PASSWORD : DebugAppendText ((char *)" Device status : CMD_STATUS_WRONG_PASSWORD\n"); break; case CMD_STATUS_NOT_AUTHORIZED : DebugAppendText ((char *)" Device status : CMD_STATUS_NOT_AUTHORIZED\n"); break; case CMD_STATUS_TIMESTAMP_WARNING : DebugAppendText ((char *)" Device status : CMD_STATUS_TIMESTAMP_WARNING\n"); break; case CMD_STATUS_NO_NAME_ERROR : DebugAppendText ((char *)" Device status : CMD_STATUS_NO_NAME_ERROR\n"); break; default: DebugAppendText ((char *)" Device status : Unknown\n"); break; } // Check last command = lastCommandType = reportBuffer[2] switch (lastCommandType) { case CMD_GET_STATUS : DebugAppendText ((char *)" Last command : CMD_GET_STATUS\n"); break; case CMD_WRITE_TO_SLOT : DebugAppendText ((char *)" Last command : CMD_WRITE_TO_SLOT\n"); break; case CMD_READ_SLOT_NAME : strncpy (text1,data,15); text1[15] = 0; sprintf(text," Last command : CMD_READ_SLOT_NAME -%s-\n",text1); DebugAppendText (text); break; case CMD_READ_SLOT : DebugAppendText ((char *)" Last command : CMD_READ_SLOT\n"); break; case CMD_GET_CODE : DebugAppendText ((char *)" Last command : CMD_GET_CODE\n"); break; case CMD_WRITE_CONFIG : DebugAppendText ((char *)" Last command : CMD_WRITE_CONFIG\n"); break; case CMD_ERASE_SLOT : DebugAppendText ((char *)" Last command : CMD_ERASE_SLOT\n"); break; case CMD_FIRST_AUTHENTICATE : DebugAppendText ((char *)" Last command : CMD_FIRST_AUTHENTICATE\n"); break; case CMD_AUTHORIZE : DebugAppendText ((char *)" Last command : CMD_AUTHORIZE\n"); break; case CMD_GET_PASSWORD_RETRY_COUNT : DebugAppendText ((char *)" Last command : CMD_GET_PASSWORD_RETRY_COUNT\n"); break; case CMD_CLEAR_WARNING : DebugAppendText ((char *)" Last command : CMD_CLEAR_WARNING\n"); break; case CMD_GET_PW_SAFE_SLOT_STATUS : DebugAppendText ((char *)" Last command : CMD_GET_PW_SAFE_SLOT_STATUS\n"); break; case CMD_GET_PW_SAFE_SLOT_NAME : DebugAppendText ((char *)" Last command : CMD_GET_PW_SAFE_SLOT_NAME\n"); break; case CMD_GET_PW_SAFE_SLOT_PASSWORD : DebugAppendText ((char *)" Last command : CMD_GET_PW_SAFE_SLOT_PASSWORD\n"); break; case CMD_GET_PW_SAFE_SLOT_LOGINNAME : DebugAppendText ((char *)" Last command : CMD_GET_PW_SAFE_SLOT_LOGINNAME\n"); break; case CMD_SET_PW_SAFE_SLOT_DATA_1 : DebugAppendText ((char *)" Last command : CMD_SET_PW_SAFE_SLOT_DATA_1\n"); break; case CMD_SET_PW_SAFE_SLOT_DATA_2 : DebugAppendText ((char *)" Last command : CMD_SET_PW_SAFE_SLOT_DATA_2\n"); break; case CMD_PW_SAFE_ERASE_SLOT : DebugAppendText ((char *)" Last command : CMD_PW_SAFE_ERASE_SLOT\n"); break; case CMD_PW_SAFE_ENABLE : DebugAppendText ((char *)" Last command : CMD_PW_SAFE_ENABLE\n"); break; case CMD_PW_SAFE_INIT_KEY : DebugAppendText ((char *)" Last command : CMD_PW_SAFE_INIT_KEY\n"); break; case CMD_PW_SAFE_SEND_DATA : DebugAppendText ((char *)" Last command : CMD_PW_SAFE_SEND_DATA"); break; case CMD_SD_CARD_HIGH_WATERMARK : DebugAppendText ((char *)" Last command : CMD_SD_CARD_HIGH_WATERMARK"); break; case CMD_SET_TIME : DebugAppendText ((char *)" Last command : CMD_SET_TIME\n"); break; case CMD_TEST_COUNTER : DebugAppendText ((char *)" Last command : CMD_TEST_COUNTER\n"); break; case CMD_TEST_TIME : DebugAppendText ((char *)" Last command : CMD_TEST_TIME\n"); break; case CMD_USER_AUTHENTICATE : DebugAppendText ((char *)" Last command : CMD_USER_AUTHENTICATE\n"); break; case CMD_GET_USER_PASSWORD_RETRY_COUNT : DebugAppendText ((char *)" Last command : CMD_GET_USER_PASSWORD_RETRY_COUNT\n"); break; case CMD_USER_AUTHORIZE : DebugAppendText ((char *)" Last command : CMD_USER_AUTHORIZE\n"); break; case CMD_UNLOCK_USER_PASSOWRD : DebugAppendText ((char *)" Last command : CMD_UNLOCK_USER_PASSOWRD\n"); break; case CMD_LOCK_DEVICE : DebugAppendText ((char *)" Last command : CMD_LOCK_DEVICE"); break; case STICK20_CMD_ENABLE_CRYPTED_PARI : DebugAppendText ((char *)" Last command : STICK20_CMD_ENABLE_CRYPTED_PARI \n"); break; case STICK20_CMD_DISABLE_CRYPTED_PARI : DebugAppendText ((char *)" Last command : STICK20_CMD_DISABLE_CRYPTED_PARI \n"); break; case STICK20_CMD_ENABLE_HIDDEN_CRYPTED_PARI : DebugAppendText ((char *)" Last command : STICK20_CMD_ENABLE_HIDDEN_CRYPTED_PARI \n"); break; case STICK20_CMD_DISABLE_HIDDEN_CRYPTED_PARI : DebugAppendText ((char *)" Last command : STICK20_CMD_DISABLE_HIDDEN_CRYPTED_PARI \n"); break; case STICK20_CMD_ENABLE_FIRMWARE_UPDATE : DebugAppendText ((char *)" Last command : STICK20_CMD_ENABLE_FIRMWARE_UPDATE \n"); break; case STICK20_CMD_EXPORT_FIRMWARE_TO_FILE : DebugAppendText ((char *)" Last command : STICK20_CMD_EXPORT_FIRMWARE_TO_FILE \n"); break; case STICK20_CMD_GENERATE_NEW_KEYS : DebugAppendText ((char *)" Last command : STICK20_CMD_GENERATE_NEW_KEYS \n"); break; case STICK20_CMD_FILL_SD_CARD_WITH_RANDOM_CHARS : DebugAppendText ((char *)" Last command : STICK20_CMD_FILL_SD_CARD_WITH_RANDOM_CHARS\n"); break; case STICK20_CMD_WRITE_STATUS_DATA : DebugAppendText ((char *)" Last command : STICK20_CMD_WRITE_STATUS_DATA \n"); break; case STICK20_CMD_ENABLE_READONLY_UNCRYPTED_LUN : DebugAppendText ((char *)" Last command : STICK20_CMD_ENABLE_READONLY_UNCRYPTED_LUN \n"); break; case STICK20_CMD_ENABLE_READWRITE_UNCRYPTED_LUN : DebugAppendText ((char *)" Last command : STICK20_CMD_ENABLE_READWRITE_UNCRYPTED_LUN\n"); break; case STICK20_CMD_SEND_PASSWORD_MATRIX : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_PASSWORD_MATRIX \n"); break; case STICK20_CMD_SEND_PASSWORD_MATRIX_PINDATA : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_PASSWORD_MATRIX_PINDATA \n"); break; case STICK20_CMD_SEND_PASSWORD_MATRIX_SETUP : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_PASSWORD_MATRIX_SETUP \n"); break; case STICK20_CMD_GET_DEVICE_STATUS : DebugAppendText ((char *)" Last command : STICK20_CMD_GET_DEVICE_STATUS \n"); break; case STICK20_CMD_SEND_DEVICE_STATUS : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_DEVICE_STATUS \n"); break; case STICK20_CMD_SEND_HIDDEN_VOLUME_PASSWORD : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_HIDDEN_VOLUME_PASSWORD\n"); break; case STICK20_CMD_SEND_HIDDEN_VOLUME_SETUP : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_HIDDEN_VOLUME_SETUP\n"); break; case STICK20_CMD_SEND_PASSWORD : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_PASSWORD\n"); break; case STICK20_CMD_SEND_NEW_PASSWORD : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_NEW_PASSWORD\n"); break; case STICK20_CMD_CLEAR_NEW_SD_CARD_FOUND : DebugAppendText ((char *)" Last command : STICK20_CMD_CLEAR_NEW_SD_CARD_FOUND\n"); break; case STICK20_CMD_SEND_STARTUP : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_STARTUP\n"); break; case STICK20_CMD_SEND_CLEAR_STICK_KEYS_NOT_INITIATED : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_CLEAR_STICK_KEYS_NOT_INITIATED\n"); break; case STICK20_CMD_SEND_LOCK_STICK_HARDWARE : DebugAppendText ((char *)" Last command : STICK20_CMD_SEND_LOCK_STICK_HARDWARE\n"); break; case STICK20_CMD_PRODUCTION_TEST : DebugAppendText ((char *)" Last command : STICK20_CMD_PRODUCTION_TEST\n"); break; default: DebugAppendText ((char *)" Last command : Unknown\n"); break; } // Check last command status = lastCommandStatus = reportBuffer[7] switch (lastCommandStatus) { case CMD_STATUS_OK : DebugAppendText ((char *)" Last command status : CMD_STATUS_OK\n"); break; case CMD_STATUS_WRONG_CRC : DebugAppendText ((char *)" Last command status : CMD_STATUS_WRONG_CRC\n"); break; case CMD_STATUS_WRONG_SLOT : DebugAppendText ((char *)" Last command status : CMD_STATUS_WRONG_SLOT\n"); break; case CMD_STATUS_SLOT_NOT_PROGRAMMED : DebugAppendText ((char *)" Last command status : CMD_STATUS_SLOT_NOT_PROGRAMMED\n"); break; case CMD_STATUS_WRONG_PASSWORD : DebugAppendText ((char *)" Last command status : CMD_STATUS_WRONG_PASSWORD\n"); break; case CMD_STATUS_NOT_AUTHORIZED : DebugAppendText ((char *)" Last command status : CMD_STATUS_NOT_AUTHORIZED\n"); break; case CMD_STATUS_TIMESTAMP_WARNING : DebugAppendText ((char *)" Last command status : CMD_STATUS_TIMESTAMP_WARNING\n"); break; case CMD_STATUS_NO_NAME_ERROR : DebugAppendText ((char *)" Last command status : CMD_STATUS_NO_NAME_ERROR\n"); break; default: DebugAppendText ((char *)" Last command status : Unknown\n"); break; } // lastCommandCRC = ((uint32_t *)(reportBuffer+3))[0]; // responseCRC = ((uint32_t *)(reportBuffer+61))[0]; }
void Response::DebugResponse() { char text[1000]; char text1[1000]; int i; static int Counter = 0; sprintf(text,"%6d :getResponse: ",Counter); Counter++; DebugAppendText (text); for (i=0;i<=64;i++) { sprintf(text,"%02x ",(unsigned char)reportBuffer[i]); DebugAppendText (text); } sprintf(text,"\n"); DebugAppendText (text); // Check device status = deviceStatus = reportBuffer[1] switch (deviceStatus) { case CMD_STATUS_OK : DebugAppendText (" Device status : CMD_STATUS_OK\n"); break; case CMD_STATUS_WRONG_CRC : DebugAppendText (" Device status : CMD_STATUS_WRONG_CRC\n"); break; case CMD_STATUS_WRONG_SLOT : DebugAppendText (" Device status : CMD_STATUS_WRONG_SLOT\n"); break; case CMD_STATUS_SLOT_NOT_PROGRAMMED : DebugAppendText (" Device status : CMD_STATUS_SLOT_NOT_PROGRAMMED\n"); break; case CMD_STATUS_WRONG_PASSWORD : DebugAppendText (" Device status : CMD_STATUS_WRONG_PASSWORD\n"); break; case CMD_STATUS_NOT_AUTHORIZED : DebugAppendText (" Device status : CMD_STATUS_NOT_AUTHORIZED\n"); break; default: DebugAppendText (" Device status : Unknown\n"); break; } // Check last command = lastCommandType = reportBuffer[2] switch (lastCommandType) { case CMD_GET_STATUS : DebugAppendText (" Last command : CMD_GET_STATUS\n"); break; case CMD_WRITE_TO_SLOT : DebugAppendText (" Last command : CMD_WRITE_TO_SLOT\n"); break; case CMD_READ_SLOT_NAME : strncpy (text1,data,15); text1[15] = 0; sprintf(text," Last command : CMD_READ_SLOT_NAME -%s-\n",text1); DebugAppendText (text); break; case CMD_READ_SLOT : DebugAppendText (" Last command : CMD_READ_SLOT\n"); break; case CMD_GET_CODE : DebugAppendText (" Last command : CMD_GET_CODE\n"); break; case CMD_WRITE_CONFIG : DebugAppendText (" Last command : CMD_WRITE_CONFIG\n"); break; case CMD_ERASE_SLOT : DebugAppendText (" Last command : CMD_ERASE_SLOT\n"); break; case CMD_FIRST_AUTHENTICATE : DebugAppendText (" Last command : CMD_FIRST_AUTHENTICATE\n"); break; case CMD_AUTHORIZE : DebugAppendText (" Last command : CMD_AUTHORIZE\n"); break; case CMD_GET_PASSWORD_RETRY_COUNT : DebugAppendText (" Last command : CMD_GET_PASSWORD_RETRY_COUNT\n"); break; default: DebugAppendText (" Last command : Unknown\n"); break; } // Check last command status = lastCommandStatus = reportBuffer[7] switch (lastCommandStatus) { case CMD_STATUS_OK : DebugAppendText (" Last command status : CMD_STATUS_OK\n"); break; case CMD_STATUS_WRONG_CRC : DebugAppendText (" Last command status : CMD_STATUS_WRONG_CRC\n"); break; case CMD_STATUS_WRONG_SLOT : DebugAppendText (" Last command status : CMD_STATUS_WRONG_SLOT\n"); break; case CMD_STATUS_SLOT_NOT_PROGRAMMED : DebugAppendText (" Last command status : CMD_STATUS_SLOT_NOT_PROGRAMMED\n"); break; case CMD_STATUS_WRONG_PASSWORD : DebugAppendText (" Last command status : CMD_STATUS_WRONG_PASSWORD\n"); break; case CMD_STATUS_NOT_AUTHORIZED : DebugAppendText (" Last command status : CMD_STATUS_NOT_AUTHORIZED\n"); break; default: DebugAppendText (" Last command status : Unknown\n"); break; } // lastCommandCRC = ((uint32_t *)(reportBuffer+3))[0]; // responseCRC = ((uint32_t *)(reportBuffer+61))[0]; }
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 = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; 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; #ifdef STICK20_DEBUG { // For debugging char text[1000]; sprintf(text,"hid_enumerate: Start VID %04x PID %04x\n", vendor_id,product_id); DebugAppendText (text); } #endif if (hid_init() < 0) return NULL; // DebugAppendText ("hid_enumerate: 2\n"); // 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); // device_info_set = SetupDiGetClassDevsA(NULL, 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; #ifdef STICK20_DEBUG_ALL { char text[1000]; sprintf(text,"HandleName: 4c %s\n", driver_name); DebugAppendText (text); } #endif if ((strcmp(driver_name, "HIDClass") == 0) || (strcmp(driver_name, "Keyboard") == 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; } } } #ifdef STICK20_DEBUG_ALL { char text[1000]; sprintf(text,"HandleName: %s\n", device_interface_detail_data->DevicePath); DebugAppendText (text); } #endif // 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); #ifdef STICK20_DEBUG { // For debugging char text[1000]; // sprintf(text,"Check Product-Vendor: Start VID %04x PID %04x\n",attrib.ProductID, attrib.VendorID); // DebugAppendText (text); if ((attrib.VendorID == 0x20A0) && (attrib.ProductID == 0x4109) && (attrib.ProductID == product_id)) { sprintf(text,"*** STICK FOUND\n"); DebugAppendText (text); } } #endif // Check the VID/PID to see if we should add this // device to the enumeration list. if ((vendor_id == 0x0 && product_id == 0x0) || (attrib.VendorID == vendor_id && 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; }