QString pjrc_rawhid::getserial(int num) { hid_t *hid = get_hid(num); if (!hid) return ""; if (!hid->handle) return ""; // Should we do some "critical section" stuff here?? char temp[126]; if (!HidD_GetSerialNumberString(hid->handle, temp, sizeof(temp))) { DWORD err = GetLastError(); print_win32_err(err); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged hid_close(hid); emit deviceUnplugged(num); return ""; } return QString("Error"); } return QString().fromUtf16((ushort*)temp,-1); }
int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { BOOL res; res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * maxlen); if (!res) { register_error(dev, "HidD_GetSerialNumberString"); 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; }
BOOLEAN Hid::GetSerialNumberString(HANDLE HidDeviceObject, void *Buffer, ULONG BufferLength) { return HidD_GetSerialNumberString(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; }
bool CUsbhidioc::FindTheHID(int unitNumber) { //Use a series of API calls to find a HID with a matching Vendor and Product ID. HIDD_ATTRIBUTES Attributes; SP_DEVICE_INTERFACE_DATA devInfoData; bool LastDevice = FALSE; int MemberIndex; LONG Result; int unitIndex; char unitIDSerial[64]; //These are the vendor and product IDs to look for. const unsigned int VendorID = 0x04d8; // Uses Microchip's Vendor ID. const unsigned int ProductID = 0x0033; // PICkit 2 Flash Starter Kit Length = 0; detailData = NULL; DeviceHandle=NULL; /* 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; unitIndex = 0; LastDevice = FALSE; do { DeviceDetected=false; /* 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); // **** IMPORTANT **** // sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) should equal 5. // In C++ Builder, go to Project/Options/Advanced Compiler/Data Alignment // and select "byte" align. //Call the function again, this time passing it the returned buffer size. Result = SetupDiGetDeviceInterfaceDetail (hDevInfo, &devInfoData, detailData, Length, &Required, NULL); Result = GetLastError (); //Open a handle to the device. /* API function: CreateFile Returns: a handle that enables reading and writing to the device. Requires: The DevicePath in the detailData structure returned by SetupDiGetDeviceInterfaceDetail. */ DeviceHandle=CreateFile (detailData->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL); if ((int)DeviceHandle != -1) { /* 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 (DeviceHandle, &Attributes); if (Result != 0) { //Is it the desired device? DeviceDetected = false; if (Attributes.VendorID == VendorID) { if (Attributes.ProductID == ProductID) { //Both the Product and Vendor IDs match. if (unitNumber == unitIndex) { // Get Unit ID serial string HidD_GetSerialNumberString(DeviceHandle, unitIDSerial, 64); int x = 2; if ((unitIDSerial[0] == 0x09) || (unitIDSerial[0] == 0x00)) { m_UnitID[0] = '-'; m_UnitID[1] = 0; } else { m_UnitID[0] = unitIDSerial[0]; for (; x < 28; x+=2) { m_UnitID[x/2] = unitIDSerial[x]; if ((unitIDSerial[x] == 0) || (unitIDSerial[x] == 0xE0)) break; m_UnitID[x] = 0; m_UnitID[x+1] = 0; } } DeviceDetected = true; PrepareForOverlappedTransfer(); } else { CloseHandle(DeviceHandle); unitIndex++; } } //if (Attributes.ProductID == ProductID) else //The Product ID doesn't match. CloseHandle(DeviceHandle); } //if (Attributes.VendorID == VendorID) else //The Vendor ID doesn't match. CloseHandle(DeviceHandle); //Free the memory used by the detailData structure (no longer needed). free(detailData); } //if (Result != 0) else //SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check. LastDevice=TRUE; } } //If we haven't found the device yet, and haven't tried every available device, //try the next one. MemberIndex = MemberIndex + 1; } //do while ((LastDevice == FALSE) && (DeviceDetected == false) && (MemberIndex < 24)); // check 24 devices max //Free the memory reserved for hDevInfo by SetupDiClassDevs. SetupDiDestroyDeviceInfoList(hDevInfo); return DeviceDetected; }
//----------------------------------------------------------------------------- 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; }