Need new backend for BLE under Windows #282
Labels
No labels
3rdparty
Android
API
Author does not respond
bsd
bug
build system/CI
ci-virtual-device
CMake
Contributions Welcome
Core
dependencies
device-specific
documentation
don't_merge
duplicate
enhancement
Example
Haiku
hidraw
hotplug
info required
invalid
libusb
macOS
Misc
Not an issue
question
Release
Test
Test GUI
Windows
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-libusb/hidapi#282
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I am using the python wrapper of this library, pyhidapi
when I check the product_string of the Bluetooth HID device, it returns None.
I noticed that in windows this library is using HidD_GetProductString to get the name of the HID device.
So I asked in Microsoft community and they replied this function will not work on BLE device but will work on the classic Bluetooth.
However, it still not working after I change to use Bluetooth classic HID device.
Therefore, I would like to ask if anyone successfully gets the Bluetooth classic HID Device product string with Windows10 before.
Or I just messed up with some other stuff.
I think this may be relevant to you:
https://stackoverflow.com/questions/65970214/where-does-bluetooth-and-other-devices-get-its-information-from#comment116656875_65970214
The other thing that comes to my mind: is your device a Mouse-/Keyboard-like device? In other words - does hid_open_path falls-back to no read/write access (
open_device(path, FALSE)) ?My device is not the mouse-/keyboard-like device, I set the report descriptor to a custom report, and when I try to read write the device, the python program did not warn me with no read/write access.
This one is interesting, did the question mean that the product name can be seen like this


But showing generic name in hid device like this
Then HidD_GetProductString is provided in Win32API instead of WinRT?
And it is possible that in that question, a BLE device is used which the Microsoft guy replied HidD_GetProductString not supported.
Right now what I'm scared about is I did something wrong on the device side, so it would be better if anyone can test with their classic Bluetooth HID device.
To verify your device, you could try using macOS version of the library (you'd need mac of course) or hidraw backend on Linux.
Just to isolate is it Windows-specific or not.
What I'm scared of is I did something wrong for what Windows required. I had tested with Linux before and it can even get the product name of the BLE device. So my problem is really Windows specific
Just checked DualShock4 controller connected via Bluetooth and can confirm that it is working:
Also checked Xbox Series Controller Model 1914 connected via Bluetooth LE: only
HidD_GetAttributesis working fine with that controller.Tests are done on Windows 10 Version 1909.
This is how it is seen in Windows "Bluetooth & other devices" screen:

Here is control panel screenshot:

Here is joy.cpl:

Seems there is impossible to get "Xbox Wireless Controller XXXXXX" string for Bluetooth LE device via HID API. Also Bluetooth LE APIs are not exposed via classic IOCTLs and only usable via Windows.Devices.Bluetooth.GenericAttributeProfile WinRT API. See https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/BluetoothLE/cppwinrt for example code.
This looks like a potential alternative backend for Windows:
https://docs.microsoft.com/en-us/uwp/api/windows.devices.humaninterfacedevice?view=winrt-20348
I woundner if it works with BluetoothLE devices properly, i.e. so we could use Windows.Devices.HumanInterfaceDevice instead of Windows.Devices.Bluetooth.
I tried this yesterday when I try to build an hidapi version with winrt API
Somehow I can't find how to use it to perform the action of hid_read
And I can't use winrt API only for windows version hidapi, as we are missing winrt API to get the serial number and manufacturer string
So right now I'm trying to build a version that uses winrt API to get the product string if the HidD_GetProductString return a null pointer
That is
GetInputReportAsync()I believe that should be possible using Windows.Devices. API
I think this function is related to hid_get_input_report instead of hid_read?
Then I'm not quite sure, as I am using the Windows.Devices.Enumerate.DeviceInformation API
And I not quite understand how the Windows.Device API works
hid_read reads any input report from async queue, reports that device sends asyncronously (interrupt pipe).
get_input_report(report_id, ...) gets a report with specific report ID from the device on demand.
Functionally, GetInputReportAsync(UInt16) matches hid_get_input_report, and GetInputReportAsync() - hid_read.
Yeap, this looks right.
I see
Well, this API didn't provide serial number string and manufacturer name.
Have you tried to print all of Windows.Devices.Enumerate.DeviceInformation.Properties ?
Yes, somehow it only got these 8 keys
System.Devices.ContainerId
System.Devices.InterfaceClassGuid
System.Devices.DeviceInstanceId
System.Devices.InterfaceEnabled
System.Devices.GlyphIcon
System.Devices.IsDefault
System.Devices.Icon
System.ItemNameDisplay
That's unfortuante.
I guess as an alternative it should be possible to get/open a Windows.Devices.BluetoothDevice from Windows.Devices.Enumerate.DeviceInformation and ask for its SerialNumberString
I don't think so.
First, we don't know whether we are facing a Bluetooth device or a USB device.
Second, with the path of the hid device, I don't think it can open a Bluetooth device or a USB device.
Also you can try these functions for Bluetooth LE device: https://docs.microsoft.com/windows-hardware/drivers/bluetooth/bluetooth-low-energy-functions
Thx, I will check it later.
But first I would like to check if the original code can communicate with ble hid first.
If it is possible, then I may just modify windows/hid.c to use winrt API to get the product name when HidD_GetProductString failed to do its work.
More investigation gives me more info about HID device:
{00001124-0000-1000-8000-00805f9b34fb}- then its Bluetooth HID device (HID SERVICE spec at bluetooth website).{00001812-0000-1000-8000-00805f9b34fb}- then its Bluetooth LE HID device (HID OVER GATT spec at bluetooth website).Those UUIDs are listed at https://www.bluetooth.com/specifications/assigned-numbers/ as 16-bit values. See "Service Discovery" spec for clarification.
Okay, so the current API won't work with ble hid
I am thinking of switching winrt API for this library
However I'm stuck on using winrt API in C
Anyone can give me some guide to do it?
WinRT is available as part of Windows SDK.
Typical location of the headers:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\winrt\windows.devices.enumeration.h
When you build environment is ready, you should nornally do:
#include <winrt\windows.devices.enumeration.h>NOTE: I believe WinRT is designed more like C++ API (not a C API), and I'm not sure is it usable from C in general.
Yeah, I know about this
But consider the library we are having now is using C, I can't change it to C++
What I am thinking right now is doing something like this
But I'm still missing some guide to use these API properly (like how to initiate the API, exit the API)
P.S. We need to keep using C because libraries similar to this is not using the dll file, they are using the source file directly
@LeeChunHei you can do it but code will be creepy. Example: https://github.com/libsdl-org/SDL/blob/main/src/joystick/windows/SDL_windows_gaming_input.c
Thanks, this example looks useful to me.
I know it will be creepy, I already know that when I saw those long macro names.
Since we need to go this way only because WinAPI HID API doesn't work with BluetoorhLE devices, maybe it would be much easier to use this instead:
https://docs.microsoft.com/en-us/windows/win32/api/bluetoothleapis/
I think it's a bit hard to use this to communicate with the ble hid device?
As we need to deal with those hid protocol by ourselves.
And we also need to combine it with normal USB hid device.
Anyway, I will check if the winrt HID API can communicate with the BLE device, if everything goes well, I will try to make a pull request about changing to winrt API (May takes forever, as those API in C is so creepy)
I don't suggest using ble API for everything - only to get Manufacturer/Serial/Product strings if we detect it is a BleLE device.
If I understand it correctly - everything else works fine with standard WinAPI HID API.
NOTE: we can only accept WinRT API as an alternative backend, not a replacement.
No, from my test, I don't think we can communicate ble hid device with Win32API
Because you've tried and it doesn't work?
Yes, I use the python wrapper of hidapi with my esp32 ble hid device
When I try to write the device, it returns -1 instead of how many byte I wrote
Is it because you want to keep the compatibility with older version windows?
So I should use a macro to separate two backend?
@LeeChunHei I have some working code for BLE HID device info:
github.com/DJm00n/RawInputDemo@d718a0a613I can query device name (same as seen in joy.cpl), manufacturer, mac address, vid, pid, version.
Can you confirm that your device implements a single usage_page/usage pair or that you open a correct device?
Ideally - a separate .c file, e.g.: winrt/hid.c
I can confirm that my device implement correctly, it can be communicated under linux
Is Xbox One S Wireless Controller a good test device for this case? I never really used an HID BLE device with HIDAPI before. I always use USB HID devices. I also have Wii Remote.
So we have two issues issues here:
I think @DJm00n tested that Bluetooth classic HID (DualShock4) can have the product string correctly shown.
So maybe there is no problem with classic HID in Windows, maybe is just my esp32 with btstack have problem to show the product string in Windows
But BLE device is for sure that not work with current HID backend API.
I see. Thanks for the clarifications.
@mcuee afaik only Xbox Series Controller Model 1914 seen with VID:045E PID:0B13 (PID:0B12 over USB) can work over BLE connection (HID over GATT). Older versions are working via usual Bluetooth 4 (HID over L2CAP).
You can see controller model number on the sticker in battery compartment.
@LeeChunHei I have ESP32 devices as well but never really play with Bluetooth. Maybe I will try that as well in the future.
@DJm00n Thanks. My one is the old model 1708 so it is not compatible with BLE then.
This seems another difficult question that my question in OSR NTDEV forum got no answers.
https://community.osr.com/discussion/292943/windows-hid-api-and-bluetooth-low-energy
Oh, and BTW: I think there is absolutely no sense implementing winrt backend for HIDAPI in
C.It better be in
C++. It can be compiled by latest MSVC compilers only (with one of the latest Windows SDK).The only thing we will get by implementing it in
C- a complicated and unreadable code.To be clear: it is possible/fairly easy to have both: pure
Cinterface andC++implementation.XD, right now I'm kinda close to finishing the backend with WinRT with c only, but not doing any testing yet since I'm very busy now.
And I would like to keep using c interface such that it is possible for other programs in the c language to build with it?
For example python wrappers like this https://github.com/trezor/cython-hidapi.
It will allows other languages to integrate just fine.
Do you have a WIP branch or something?
I can take a quick look and show my suggestions regarding using C++ as the implementation.
Ah, no
Because I just do this coding by myself and I'm kinda lazy to do the git stuff.
Maybe I setup it tmr and tells you the branch.
@Youw
This is the code I'm working on now https://github.com/LeeChunHei/hidapi
It's in the winrt folder under master branch as I forgot to create a new branch.
I currently test the code by compiling the dll and paste it into the python installation directory and testing its functionality with this python package.
I found that if I use the WinRT HID API, a few devices cannot be open (maybe those keyboard mouse stuff?), so there will be less device listed if you call hid_enumerate compare to the original API
PR #309 should fix this issue.
@LeeChunHei could you please test my PR #309?
@LeeChunHei
This seems to work reasonably well based on the outputs of hidtest. It does list main HID device, including the Bluetooth mouse, but I do not have any BLE HID device for testing.
click to expand
hidapi main line git output:
click to expand
@LeeChunHei
Which ESP32 BLE HID FW are you using? I found a few here but I have never used Arduino (haha, do not laugh at me) or Espressif's ESP-IDF before. I only played a bit with MicroPython with the ESP32.
https://github.com/lemmingDev/ESP32-BLE-Gamepad (and the links the author refers to)
https://github.com/asterics/esp32_mouse_keyboard
https://github.com/olegos76/nimble_kbdhid_example
Micropython example is not ready yet.
https://github.com/micropython/micropython/pull/6559
@mcuee
I use the BLE hid example inside Espressif's ESP-IDF to build the ESP32 firmware
So i'm not sure about how to use micropython or Arduino to make that firmware
@DJm00n
Sure, but I will need to find some spare time first
Thanks. I just downloaded ESP-IDF onto my Mac Mini M1 and then I can build the default BLE HID example. Unfortunately it does not seem to work on my cheap ESP32 board -- my Mac can not connected to it even though the device shows up as "ESP BLE HID2" from the Bluetooth Devices list.
@LeeChunHei I have changed the title to remove the "product name for Bluetooth classic HID in Windows 10" portion, as it seems to work well with the current HIDAPI codes, based on the testing results from @DJm00n . You can refer to my Logitech Bluetooth Mouse output which also shows that the current HIDAPI code is working. So that portion is probably just related to ESP32.
@LeeChunHei Interestingly the ESP32 BLE HID device has no issues under my Windows 10 20H2 Dell Laptop.
@DJm00n Output from #309 seems to show that it is working.
@LeeChunHei Your WinRT branch seems to work fine as well.