hidapi, windows: sync with mainstream: change MAX_STRING_WCHARS to 126.
This merges mainstream commit
4f2e91bae8
(authored by Vladimir Gladkov) into ours. From the original commit log:
Win32 HID API doc says: For USB devices, the maximum string length is
126 wide characters (not including the terminating NULL character).
For certain USB devices, using a buffer larger or equal to 127 wchars
results in successful completion of HID API functions, but a broken
string is stored in the output buffer. This behaviour persists even if
HID API is bypassed and HID IOCTLs are passed to the HID driver directly
(IOCTL_HID_GET_MANUFACTURER_STRING, IOCTL_HID_GET_PRODUCT_STRING, etc).
So, the buffer MUST NOT exceed 126 wchars.
windows: refactor ULONGLONG hid_internal_get_info(...) ->
hid_internal_detect_bus_type_result hid_internal_detect_bus_type(...)
hid_internal_detect_bus_type is now only responsible for detection of
the bus type; rename it accordingly. Also, mixing an internal flag and
DEV_INST into an ULONGLONG retval feels kinda hackish; use a cleaner
approach instead (add an internal flag to help distinguishing between
BLUETOOTH and BLE devices, then clear it once we are done).
This commit is contained in:
parent
26e3ca7387
commit
98bec6749f
1 changed files with 69 additions and 17 deletions
|
@ -72,6 +72,15 @@ typedef LONG NTSTATUS;
|
||||||
/* BLUETOOTH_DEVICE_NAME_SIZE from bluetoothapis.h is 256 */
|
/* BLUETOOTH_DEVICE_NAME_SIZE from bluetoothapis.h is 256 */
|
||||||
#define MAX_STRING_WCHARS 256
|
#define MAX_STRING_WCHARS 256
|
||||||
|
|
||||||
|
/* For certain USB devices, using a buffer larger or equal to 127 wchars results
|
||||||
|
in successful completion of HID API functions, but a broken string is stored
|
||||||
|
in the output buffer. This behaviour persists even if HID API is bypassed and
|
||||||
|
HID IOCTLs are passed to the HID driver directly. Therefore, for USB devices,
|
||||||
|
the buffer MUST NOT exceed 126 WCHARs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_STRING_WCHARS_USB 126
|
||||||
|
|
||||||
static struct hid_api_version api_version = {
|
static struct hid_api_version api_version = {
|
||||||
.major = HID_API_VERSION_MAJOR,
|
.major = HID_API_VERSION_MAJOR,
|
||||||
.minor = HID_API_VERSION_MINOR,
|
.minor = HID_API_VERSION_MINOR,
|
||||||
|
@ -719,11 +728,22 @@ end:
|
||||||
}
|
}
|
||||||
#endif /* HIDAPI_IGNORE_DEVICE */
|
#endif /* HIDAPI_IGNORE_DEVICE */
|
||||||
|
|
||||||
static void hid_internal_get_info(const wchar_t* interface_path, struct hid_device_info* dev)
|
/* Unfortunately, HID_API_BUS_xxx constants alone aren't enough to distinguish between BLUETOOTH and BLE */
|
||||||
|
|
||||||
|
#define HID_API_BUS_FLAG_BLE 0x01
|
||||||
|
|
||||||
|
typedef struct hid_internal_detect_bus_type_result_ {
|
||||||
|
DEVINST dev_node;
|
||||||
|
hid_bus_type bus_type;
|
||||||
|
unsigned int bus_flags;
|
||||||
|
} hid_internal_detect_bus_type_result;
|
||||||
|
|
||||||
|
static hid_internal_detect_bus_type_result hid_internal_detect_bus_type(const wchar_t* interface_path)
|
||||||
{
|
{
|
||||||
wchar_t *device_id = NULL, *compatible_ids = NULL;
|
wchar_t *device_id = NULL, *compatible_ids = NULL;
|
||||||
CONFIGRET cr;
|
CONFIGRET cr;
|
||||||
DEVINST dev_node;
|
DEVINST dev_node;
|
||||||
|
hid_internal_detect_bus_type_result result = { 0 };
|
||||||
|
|
||||||
/* Get the device id from interface path */
|
/* Get the device id from interface path */
|
||||||
device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
|
device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
|
||||||
|
@ -754,42 +774,45 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi
|
||||||
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support
|
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support
|
||||||
https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */
|
https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */
|
||||||
if (wcsstr(compatible_id, L"USB") != NULL) {
|
if (wcsstr(compatible_id, L"USB") != NULL) {
|
||||||
dev->bus_type = HID_API_BUS_USB;
|
result.bus_type = HID_API_BUS_USB;
|
||||||
hid_internal_get_usb_info(dev, dev_node);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bluetooth devices
|
/* Bluetooth devices
|
||||||
https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */
|
https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */
|
||||||
if (wcsstr(compatible_id, L"BTHENUM") != NULL) {
|
if (wcsstr(compatible_id, L"BTHENUM") != NULL) {
|
||||||
dev->bus_type = HID_API_BUS_BLUETOOTH;
|
result.bus_type = HID_API_BUS_BLUETOOTH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bluetooth LE devices */
|
/* Bluetooth LE devices */
|
||||||
if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) {
|
if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) {
|
||||||
dev->bus_type = HID_API_BUS_BLUETOOTH;
|
result.bus_type = HID_API_BUS_BLUETOOTH;
|
||||||
hid_internal_get_ble_info(dev, dev_node);
|
result.bus_flags |= HID_API_BUS_FLAG_BLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I2C devices
|
/* I2C devices
|
||||||
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */
|
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */
|
||||||
if (wcsstr(compatible_id, L"PNP0C50") != NULL) {
|
if (wcsstr(compatible_id, L"PNP0C50") != NULL) {
|
||||||
dev->bus_type = HID_API_BUS_I2C;
|
result.bus_type = HID_API_BUS_I2C;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SPI devices
|
/* SPI devices
|
||||||
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */
|
https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */
|
||||||
if (wcsstr(compatible_id, L"PNP0C51") != NULL) {
|
if (wcsstr(compatible_id, L"PNP0C51") != NULL) {
|
||||||
dev->bus_type = HID_API_BUS_SPI;
|
result.bus_type = HID_API_BUS_SPI;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.dev_node = dev_node;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
free(device_id);
|
free(device_id);
|
||||||
free(compatible_ids);
|
free(compatible_ids);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *hid_internal_UTF16toUTF8(const wchar_t *src)
|
static char *hid_internal_UTF16toUTF8(const wchar_t *src)
|
||||||
|
@ -836,7 +859,10 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path,
|
||||||
HIDD_ATTRIBUTES attrib;
|
HIDD_ATTRIBUTES attrib;
|
||||||
PHIDP_PREPARSED_DATA pp_data = NULL;
|
PHIDP_PREPARSED_DATA pp_data = NULL;
|
||||||
HIDP_CAPS caps;
|
HIDP_CAPS caps;
|
||||||
wchar_t string[MAX_STRING_WCHARS];
|
wchar_t string[MAX_STRING_WCHARS + 1];
|
||||||
|
ULONG len;
|
||||||
|
ULONG size;
|
||||||
|
hid_internal_detect_bus_type_result detect_bus_type_result;
|
||||||
|
|
||||||
/* Create the record. */
|
/* Create the record. */
|
||||||
dev = (struct hid_device_info*)calloc(1, sizeof(struct hid_device_info));
|
dev = (struct hid_device_info*)calloc(1, sizeof(struct hid_device_info));
|
||||||
|
@ -870,25 +896,46 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path,
|
||||||
HidD_FreePreparsedData(pp_data);
|
HidD_FreePreparsedData(pp_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* detect bus type before reading string descriptors */
|
||||||
|
detect_bus_type_result = hid_internal_detect_bus_type(path);
|
||||||
|
dev->bus_type = detect_bus_type_result.bus_type;
|
||||||
|
|
||||||
|
len = dev->bus_type == HID_API_BUS_USB ? MAX_STRING_WCHARS_USB : MAX_STRING_WCHARS;
|
||||||
|
string[len] = L'\0';
|
||||||
|
size = len * sizeof(wchar_t);
|
||||||
|
|
||||||
/* Serial Number */
|
/* Serial Number */
|
||||||
string[0] = L'\0';
|
string[0] = L'\0';
|
||||||
HidD_GetSerialNumberString(handle, string, sizeof(string));
|
HidD_GetSerialNumberString(handle, string, size);
|
||||||
string[MAX_STRING_WCHARS - 1] = L'\0';
|
|
||||||
dev->serial_number = _wcsdup(string);
|
dev->serial_number = _wcsdup(string);
|
||||||
|
|
||||||
/* Manufacturer String */
|
/* Manufacturer String */
|
||||||
string[0] = L'\0';
|
string[0] = L'\0';
|
||||||
HidD_GetManufacturerString(handle, string, sizeof(string));
|
HidD_GetManufacturerString(handle, string, size);
|
||||||
string[MAX_STRING_WCHARS - 1] = L'\0';
|
|
||||||
dev->manufacturer_string = _wcsdup(string);
|
dev->manufacturer_string = _wcsdup(string);
|
||||||
|
|
||||||
/* Product String */
|
/* Product String */
|
||||||
string[0] = L'\0';
|
string[0] = L'\0';
|
||||||
HidD_GetProductString(handle, string, sizeof(string));
|
HidD_GetProductString(handle, string, size);
|
||||||
string[MAX_STRING_WCHARS - 1] = L'\0';
|
|
||||||
dev->product_string = _wcsdup(string);
|
dev->product_string = _wcsdup(string);
|
||||||
|
|
||||||
hid_internal_get_info(path, dev);
|
/* now, the portion that depends on string descriptors */
|
||||||
|
switch (dev->bus_type) {
|
||||||
|
case HID_API_BUS_USB:
|
||||||
|
hid_internal_get_usb_info(dev, detect_bus_type_result.dev_node);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HID_API_BUS_BLUETOOTH:
|
||||||
|
if (detect_bus_type_result.bus_flags & HID_API_BUS_FLAG_BLE)
|
||||||
|
hid_internal_get_ble_info(dev, detect_bus_type_result.dev_node);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HID_API_BUS_UNKNOWN:
|
||||||
|
case HID_API_BUS_SPI:
|
||||||
|
case HID_API_BUS_I2C:
|
||||||
|
/* shut down -Wswitch */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -1572,7 +1619,12 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int
|
||||||
{
|
{
|
||||||
BOOL res;
|
BOOL res;
|
||||||
|
|
||||||
res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * (DWORD) MIN(maxlen, MAX_STRING_WCHARS));
|
if (dev->device_info && dev->device_info->bus_type == HID_API_BUS_USB && maxlen > MAX_STRING_WCHARS_USB) {
|
||||||
|
string[MAX_STRING_WCHARS_USB] = L'\0';
|
||||||
|
maxlen = MAX_STRING_WCHARS_USB;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)maxlen * sizeof(wchar_t));
|
||||||
if (!res) {
|
if (!res) {
|
||||||
register_winapi_error(dev, L"HidD_GetIndexedString");
|
register_winapi_error(dev, L"HidD_GetIndexedString");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue