Open DJm00n opened 1 year ago
The GATT Read Characteristic Value or Read Long Characteristic Value subprocedures are used to read a Report characteristic containing Output Report data. This procedure maps to a Get_Report (Output) request in USB HID [2].
The GATT Write Characteristic Value sub-procedure is used to write to a Report characteristic containing Output Report data. This procedure maps to a Set_Report (Output) request in USB HID [2]. The GATT Write Without Response sub-procedure is also used to write to a Report characteristic containing Output Report data, and this procedure maps to Data Output in USB HID [2].
https://www.bluetooth.com/specifications/specs/human-interface-device-service-1-0/
HidD_SetOutputReport becomes IOCTL_HID_SET_OUTPUT_REPORT WriteFile becomes IOCTL_HID_WRITE_REPORT
Output items make Output reports accessible via the Control pipe with a Set_Report (Output) command. Output type reports can optionally be sent via an Interrupt Out pipe.
The Control pipe is used for: ... Transmitting data when polled by the HID class driver (using the Get_Report request).
The Interrupt Out pipe is optional. If a device declares an Interrupt Out endpoint then Output reports are transmitted by the host to the device through the Interrupt Out endpoint. If no Interrupt Out endpoint is declared then Output reports are transmitted to a device through the Control endpoint, using Set_Report(Output) requests.
https://www.usb.org/document-library/device-class-definition-hid-111
The later only proves that we cannot unconditionally replace WriteFile
with SetOutputReport
, I guess.
As for bug "WriteFile() doesn't work correctly" I think we could have a per-device, WinAPI-specific option to use HidD_SetOutputReport
as hid_write
implementation.
Or do you think we can predict for which devices WriteFile
is going to fail? Is it known to be specific to BLE or smth?
As far as I understand, in BLE case API works like this:
WriteFile
-> IOCTL_HID_WRITE_REPORT
-> Data Output
-> GATT Write Without Response
-> ATT_OP_WRITE_CMD
-> 0x52
HidD_SetOutputReport
-> IOCTL_HID_SET_OUTPUT_REPORT
-> Set_Report (Output)
-> GATT Write Characteristic Value
-> ATT_OP_WRITE_REQ
-> 0x12
According to the HIDS spec Read/Write/Write Without Response
are mandatory for Report: Output Report Type
characteristic.
But seems some devices are not declaring Write Without Response
and in result WriteFile
call is failing (for example Stadia Controller with new "Bluetooth mode" firmware is known to have such issues).
I'll try to debug this to find out more.
But seems some devices are not declaring
Write Without Response
Would be great to figure out if it is possible to check its support over WinAPI before trying to use WriteFile
(e.g. if it is a part of some descriptor, or just device fails to respond on a specific command).
Looks like Windows Bluetooth drivers have issues with sending output reports with
WriteFile
. Need to investigate this and try to useHidD_SetOutputReport
as a fallback.https://stackoverflow.com/questions/29480144/hidapi-sending-packet-smaller-than-caps-outputreportbytelength https://social.msdn.microsoft.com/Forums/ie/en-US/834d2cf2-672d-424b-a126-dbc69f3f75a2/hiddsetoutputreportwritefile-bluetooth-low-energy-windows-81
Related https://github.com/libsdl-org/SDL/issues/7224