@@ -52,7 +52,6 @@ typedef LONG NTSTATUS;
52
52
53
53
/*#define HIDAPI_USE_DDK*/
54
54
55
- #include <devpropdef.h>
56
55
#include "hidapi_cfgmgr32.h"
57
56
#include "hidapi_hidclass.h"
58
57
#include "hidapi_hidsdi.h"
@@ -409,6 +408,132 @@ static void* hid_internal_get_device_interface_property(const wchar_t* interface
409
408
return property_value ;
410
409
}
411
410
411
+ static void hid_internal_towupper (wchar_t * string )
412
+ {
413
+ for (wchar_t * p = string ; * p ; ++ p ) * p = towupper (* p );
414
+ }
415
+
416
+ static int hid_internal_extract_int_token_value (wchar_t * string , const wchar_t * token )
417
+ {
418
+ int token_value ;
419
+ wchar_t * startptr , * endptr ;
420
+
421
+ startptr = wcsstr (string , token );
422
+ if (!startptr )
423
+ return -1 ;
424
+
425
+ startptr += wcslen (token );
426
+ token_value = wcstol (startptr , & endptr , 16 );
427
+ if (endptr == startptr )
428
+ return -1 ;
429
+
430
+ return token_value ;
431
+ }
432
+
433
+ static void hid_internal_get_usb_info (struct hid_device_info * dev , DEVINST dev_node )
434
+ {
435
+ wchar_t * device_id = NULL , * hardware_ids = NULL ;
436
+
437
+ device_id = hid_internal_get_devnode_property (dev_node , & DEVPKEY_Device_InstanceId , DEVPROP_TYPE_STRING );
438
+ if (!device_id )
439
+ goto end ;
440
+
441
+ /* Normalize to upper case */
442
+ hid_internal_towupper (device_id );
443
+
444
+ /* Check for Xbox Common Controller class (XUSB) device.
445
+ https://docs.microsoft.com/windows/win32/xinput/directinput-and-xusb-devices
446
+ https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput
447
+ */
448
+ if (hid_internal_extract_int_token_value (device_id , L"IG_" ) != -1 ) {
449
+ /* Get devnode parent to reach out USB device. */
450
+ if (CM_Get_Parent (& dev_node , dev_node , 0 ) != CR_SUCCESS )
451
+ goto end ;
452
+ }
453
+
454
+ /* Get the hardware ids from devnode */
455
+ hardware_ids = hid_internal_get_devnode_property (dev_node , & DEVPKEY_Device_HardwareIds , DEVPROP_TYPE_STRING_LIST );
456
+ if (!hardware_ids )
457
+ goto end ;
458
+
459
+ /* Get additional information from USB device's Hardware ID
460
+ https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers
461
+ https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-interfaces-not-grouped-in-collections
462
+ */
463
+ for (wchar_t * hardware_id = hardware_ids ; * hardware_id ; hardware_id += wcslen (hardware_id ) + 1 ) {
464
+ /* Normalize to upper case */
465
+ hid_internal_towupper (hardware_id );
466
+
467
+ if (dev -> release_number == 0 ) {
468
+ /* USB_DEVICE_DESCRIPTOR.bcdDevice value. */
469
+ int release_number = hid_internal_extract_int_token_value (hardware_id , L"REV_" );
470
+ if (release_number != -1 ) {
471
+ dev -> release_number = (unsigned short )release_number ;
472
+ }
473
+ }
474
+
475
+ if (dev -> interface_number == -1 ) {
476
+ /* USB_INTERFACE_DESCRIPTOR.bInterfaceNumber value. */
477
+ int interface_number = hid_internal_extract_int_token_value (hardware_id , L"MI_" );
478
+ if (interface_number != -1 ) {
479
+ dev -> interface_number = interface_number ;
480
+ }
481
+ }
482
+ }
483
+
484
+ /* Try to get USB device manufacturer string if not provided by HidD_GetManufacturerString. */
485
+ if (wcslen (dev -> manufacturer_string ) == 0 ) {
486
+ wchar_t * manufacturer_string = hid_internal_get_devnode_property (dev_node , & DEVPKEY_Device_Manufacturer , DEVPROP_TYPE_STRING );
487
+ if (manufacturer_string ) {
488
+ free (dev -> manufacturer_string );
489
+ dev -> manufacturer_string = manufacturer_string ;
490
+ }
491
+ }
492
+
493
+ /* Try to get USB device serial number if not provided by HidD_GetSerialNumberString. */
494
+ if (wcslen (dev -> serial_number ) == 0 ) {
495
+ DEVINST usb_dev_node = dev_node ;
496
+ if (dev -> interface_number != -1 ) {
497
+ /* Get devnode parent to reach out composite parent USB device.
498
+ https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-the-composite-parent-device
499
+ */
500
+ if (CM_Get_Parent (& usb_dev_node , dev_node , 0 ) != CR_SUCCESS )
501
+ goto end ;
502
+ }
503
+
504
+ /* Get the device id of the USB device. */
505
+ free (device_id );
506
+ device_id = hid_internal_get_devnode_property (usb_dev_node , & DEVPKEY_Device_InstanceId , DEVPROP_TYPE_STRING );
507
+ if (!device_id )
508
+ goto end ;
509
+
510
+ /* Extract substring after last '\\' of Instance ID.
511
+ For USB devices it may contain device's serial number.
512
+ https://docs.microsoft.com/windows-hardware/drivers/install/instance-ids
513
+ */
514
+ for (wchar_t * ptr = device_id + wcslen (device_id ); ptr > device_id ; -- ptr ) {
515
+ /* Instance ID is unique only within the scope of the bus.
516
+ For USB devices it means that serial number is not available. Skip. */
517
+ if (* ptr == L'&' )
518
+ break ;
519
+
520
+ if (* ptr == L'\\' ) {
521
+ free (dev -> serial_number );
522
+ dev -> serial_number = _wcsdup (ptr + 1 );
523
+ break ;
524
+ }
525
+ }
526
+ }
527
+
528
+ /* If we can't get the interface number, it means that there is only one interface. */
529
+ if (dev -> interface_number == -1 )
530
+ dev -> interface_number = 0 ;
531
+
532
+ end :
533
+ free (device_id );
534
+ free (hardware_ids );
535
+ }
536
+
412
537
/* HidD_GetProductString/HidD_GetManufacturerString/HidD_GetSerialNumberString is not working for BLE HID devices
413
538
Request this info via dev node properties instead.
414
539
https://docs.microsoft.com/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html
@@ -452,34 +577,9 @@ static void hid_internal_get_ble_info(struct hid_device_info* dev, DEVINST dev_n
452
577
}
453
578
}
454
579
455
- /* USB Device Interface Number.
456
- It can be parsed out of the Hardware ID if a USB device is has multiple interfaces (composite device).
457
- See https://docs.microsoft.com/windows-hardware/drivers/hid/hidclass-hardware-ids-for-top-level-collections
458
- and https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers
459
-
460
- hardware_id is always expected to be uppercase.
461
- */
462
- static int hid_internal_get_interface_number (const wchar_t * hardware_id )
463
- {
464
- int interface_number ;
465
- wchar_t * startptr , * endptr ;
466
- const wchar_t * interface_token = L"&MI_" ;
467
-
468
- startptr = wcsstr (hardware_id , interface_token );
469
- if (!startptr )
470
- return -1 ;
471
-
472
- startptr += wcslen (interface_token );
473
- interface_number = wcstol (startptr , & endptr , 16 );
474
- if (endptr == startptr )
475
- return -1 ;
476
-
477
- return interface_number ;
478
- }
479
-
480
580
static void hid_internal_get_info (const wchar_t * interface_path , struct hid_device_info * dev )
481
581
{
482
- wchar_t * device_id = NULL , * compatible_ids = NULL , * hardware_ids = NULL ;
582
+ wchar_t * device_id = NULL , * compatible_ids = NULL ;
483
583
CONFIGRET cr ;
484
584
DEVINST dev_node ;
485
585
@@ -493,22 +593,6 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi
493
593
if (cr != CR_SUCCESS )
494
594
goto end ;
495
595
496
- /* Get the hardware ids from devnode */
497
- hardware_ids = hid_internal_get_devnode_property (dev_node , & DEVPKEY_Device_HardwareIds , DEVPROP_TYPE_STRING_LIST );
498
- if (!hardware_ids )
499
- goto end ;
500
-
501
- /* Search for interface number in hardware ids */
502
- for (wchar_t * hardware_id = hardware_ids ; * hardware_id ; hardware_id += wcslen (hardware_id ) + 1 ) {
503
- /* Normalize to upper case */
504
- for (wchar_t * p = hardware_id ; * p ; ++ p ) * p = towupper (* p );
505
-
506
- dev -> interface_number = hid_internal_get_interface_number (hardware_id );
507
-
508
- if (dev -> interface_number != -1 )
509
- break ;
510
- }
511
-
512
596
/* Get devnode parent */
513
597
cr = CM_Get_Parent (& dev_node , dev_node , 0 );
514
598
if (cr != CR_SUCCESS )
@@ -522,13 +606,14 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi
522
606
/* Now we can parse parent's compatible IDs to find out the device bus type */
523
607
for (wchar_t * compatible_id = compatible_ids ; * compatible_id ; compatible_id += wcslen (compatible_id ) + 1 ) {
524
608
/* Normalize to upper case */
525
- for ( wchar_t * p = compatible_id ; * p ; ++ p ) * p = towupper ( * p );
609
+ hid_internal_towupper ( compatible_id );
526
610
527
611
/* USB devices
528
612
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support
529
613
https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */
530
614
if (wcsstr (compatible_id , L"USB" ) != NULL ) {
531
615
dev -> bus_type = HID_API_BUS_USB ;
616
+ hid_internal_get_usb_info (dev , dev_node );
532
617
break ;
533
618
}
534
619
@@ -562,7 +647,6 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi
562
647
}
563
648
end :
564
649
free (device_id );
565
- free (hardware_ids );
566
650
free (compatible_ids );
567
651
}
568
652
@@ -607,9 +691,14 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path,
607
691
/* Create the record. */
608
692
dev = (struct hid_device_info * )calloc (1 , sizeof (struct hid_device_info ));
609
693
694
+ if (dev == NULL ) {
695
+ return NULL ;
696
+ }
697
+
610
698
/* Fill out the record */
611
699
dev -> next = NULL ;
612
700
dev -> path = hid_internal_UTF16toUTF8 (path );
701
+ dev -> interface_number = -1 ;
613
702
614
703
attrib .Size = sizeof (HIDD_ATTRIBUTES );
615
704
if (HidD_GetAttributes (handle , & attrib )) {
0 commit comments