int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { BOOL res; res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * maxlen); if (!res) { register_error(dev, "HidD_GetManufacturerString"); return -1; } return 0; }
void HIDDeviceManager::initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const { // Documentation mentions 126 as being the max for USB. wchar_t strBuffer[196]; // HidD_Get*String functions return nothing in buffer on failure, // so it's ok to do this without further error checking. strBuffer[0] = 0; HidD_GetManufacturerString(hidDev, strBuffer, sizeof(strBuffer)); desc->Manufacturer = strBuffer; strBuffer[0] = 0; HidD_GetProductString(hidDev, strBuffer, sizeof(strBuffer)); desc->Product = strBuffer; strBuffer[0] = 0; HidD_GetSerialNumberString(hidDev, strBuffer, sizeof(strBuffer)); desc->SerialNumber = strBuffer; }
int usbOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs) { GUID hidGuid; /* GUID for HID driver */ HDEVINFO deviceInfoList; SP_DEVICE_INTERFACE_DATA deviceInfo; SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL; DWORD size; int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */ int errorCode = USB_ERROR_NOTFOUND; HANDLE handle = INVALID_HANDLE_VALUE; HIDD_ATTRIBUTES deviceAttributes; HidD_GetHidGuid(&hidGuid); deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); deviceInfo.cbSize = sizeof(deviceInfo); for(i=0;;i++){ if(handle != INVALID_HANDLE_VALUE){ CloseHandle(handle); handle = INVALID_HANDLE_VALUE; } if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo)) break; /* no more entries */ /* first do a dummy call just to determine the actual size required */ SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL); if(deviceDetails != NULL) free(deviceDetails); deviceDetails = malloc(size); deviceDetails->cbSize = sizeof(*deviceDetails); /* this call is for real: */ SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL); DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath)); /* attempt opening for R/W -- we don't care about devices which can't be accessed */ handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL); if(handle == INVALID_HANDLE_VALUE){ DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError())); /* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */ continue; } deviceAttributes.Size = sizeof(deviceAttributes); HidD_GetAttributes(handle, &deviceAttributes); DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", deviceAttributes.VendorID, deviceAttributes.ProductID)); if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product) continue; /* ignore this device */ errorCode = USB_ERROR_NOTFOUND; if(vendorName != NULL && productName != NULL){ char buffer[512]; if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){ DEBUG_PRINT(("error obtaining vendor name\n")); errorCode = USB_ERROR_IO; continue; } convertUniToAscii(buffer); DEBUG_PRINT(("vendorName = \"%s\"\n", buffer)); if(strcmp(vendorName, buffer) != 0) continue; if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){ DEBUG_PRINT(("error obtaining product name\n")); errorCode = USB_ERROR_IO; continue; } convertUniToAscii(buffer); DEBUG_PRINT(("productName = \"%s\"\n", buffer)); if(strcmp(productName, buffer) != 0) continue; } break; /* we have found the device we are looking for! */ } SetupDiDestroyDeviceInfoList(deviceInfoList); if(deviceDetails != NULL) free(deviceDetails); if(handle != INVALID_HANDLE_VALUE){ *device = (usbDevice_t *)handle; errorCode = 0; } return errorCode; }
BOOLEAN Hid::GetManufacturerString(HANDLE HidDeviceObject, void *Buffer, ULONG BufferLength) { return HidD_GetManufacturerString(HidDeviceObject, Buffer, BufferLength); }
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; }
//----------------------------------------------------------------------------- int dbg_enumerate(debugger_t *debuggers, int size) { GUID hid_guid; HDEVINFO hid_dev_info; HIDD_ATTRIBUTES hid_attr; SP_DEVICE_INTERFACE_DATA dev_info_data; PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data; DWORD detail_size; HANDLE handle; int rsize = 0; HidD_GetHidGuid(&hid_guid); hid_dev_info = SetupDiGetClassDevs(&hid_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); dev_info_data.cbSize = sizeof(dev_info_data); for (int i = 0; i < size; i++) { if (FALSE == SetupDiEnumDeviceInterfaces(hid_dev_info, 0, &hid_guid, i, &dev_info_data)) break; SetupDiGetDeviceInterfaceDetail(hid_dev_info, &dev_info_data, NULL, 0, &detail_size, NULL); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buf_alloc(detail_size); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); SetupDiGetDeviceInterfaceDetail(hid_dev_info, &dev_info_data, detail_data, detail_size, NULL, NULL); handle = CreateFile(detail_data->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE != handle) { hid_attr.Size = sizeof(hid_attr); HidD_GetAttributes(handle, &hid_attr); if (DBG_VID == hid_attr.VendorID && DBG_PID == hid_attr.ProductID) { wchar_t wstr[MAX_STRING_SIZE]; char str[MAX_STRING_SIZE]; debuggers[rsize].path = strdup(detail_data->DevicePath); HidD_GetSerialNumberString(handle, (PVOID)wstr, MAX_STRING_SIZE); wcstombs(str, wstr, MAX_STRING_SIZE); debuggers[rsize].serial = strdup(str); HidD_GetManufacturerString(handle, (PVOID)wstr, MAX_STRING_SIZE); wcstombs(str, wstr, MAX_STRING_SIZE); debuggers[rsize].manufacturer = strdup(str); HidD_GetProductString(handle, (PVOID)wstr, MAX_STRING_SIZE); wcstombs(str, wstr, MAX_STRING_SIZE); debuggers[rsize].product = strdup(str); rsize++; } CloseHandle(handle); } buf_free(detail_data); } SetupDiDestroyDeviceInfoList(hid_dev_info); return rsize; }
//------------------------------------------------------------------------------ HANDLE DNAUSB::openDevice( const int vid, const int pid, const char* vendor, char* product ) { HANDLE handle = INVALID_HANDLE_VALUE; // from DDK const GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; for( int tries = 0; (tries < 10) && (handle == INVALID_HANDLE_VALUE) ; tries++ ) { HANDLE deviceSet = SetupDiGetClassDevs( &GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE ); if ( deviceSet == INVALID_HANDLE_VALUE ) { break; } SP_INTERFACE_DEVICE_DATA interfaceInfo; SP_DEVINFO_DATA deviceInfoData; interfaceInfo.cbSize = sizeof( interfaceInfo ); deviceInfoData.cbSize = sizeof( SP_DEVINFO_DATA ); BYTE buf[1024]; DWORD size; int i=0; if( SetupDiEnumDeviceInfo(deviceSet, i++, &deviceInfoData) ) { DWORD interfaceNumber = 0; while ( SetupDiEnumDeviceInterfaces( deviceSet, 0, &GUID_DEVINTERFACE_HID, interfaceNumber++, &interfaceInfo) ) { SP_DEVICE_INTERFACE_DETAIL_DATA *details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)buf; details->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256; if ( !SetupDiGetDeviceInterfaceDetail( deviceSet, &interfaceInfo, details, size, 0, 0 ) ) { Log( "SetupDiGetDeviceInterfaceDetail failed [%d]", GetLastError() ); continue; } Cstr temp; temp.toChar( details->DevicePath ); temp.toLower(); Log( "Considering [%s]", temp.c_str() ); const char* vidStr = strstr( temp.c_str(), "vid" ); if ( !vidStr ) { Log( "vid not found [%s]", temp.c_str() ); continue; } vidStr += 3; for( ; *vidStr && !isxdigit(*vidStr); vidStr++ ); if ( !vidStr ) { Log( "could not find valid vid [%s]", temp.c_str() ); continue; } if ( strtol(vidStr, 0, 16) != vid ) { continue; } const char* pidStr = strstr( temp.c_str(), "pid" ); if ( !pidStr ) { Log( "pid not found [%s]", temp.c_str() ); continue; } pidStr += 3; for( ; *pidStr && !isxdigit(*pidStr); pidStr++ ); if ( !pidStr ) { Log( "could not find valid pid [%s]", temp.c_str() ); continue; } if ( strtol(pidStr, 0, 16) != pid ) { continue; } int openFlag = 0; // may be FILE_FLAG_OVERLAPPED handle = CreateFile( details->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL ); if ( handle == INVALID_HANDLE_VALUE ) { Log( "could not open device" ); continue; } if( !HidD_GetManufacturerString(handle, buf, 1024) ) { CloseHandle( handle ); handle = INVALID_HANDLE_VALUE; Log( "could not fetch manufacturer string" ); continue; } temp.toChar( (wchar_t*)buf ); Log( "manufacturer [%s]", temp.c_str() ); if ( !temp.isMatch(vendor, false) ) { CloseHandle( handle ); handle = INVALID_HANDLE_VALUE; continue; } Sleep(10); if ( product ) { HidD_GetProductString( handle, buf, 1024 ); temp.toChar( (wchar_t*)buf ); strcpy( product, temp.c_str() ); } break; } } SetupDiDestroyDeviceInfoList( deviceSet ); if ( handle == INVALID_HANDLE_VALUE ) { Arch::sleep( 2000 ); } } return handle; }