Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Bluetooth HID host on Android 5.0+ working

I have a bluetooth HID device that I need to get working with my app running on a Nexus 7 2013 tablet running custom build forked from android 5.0. so:

  • @hide is not a constraint
  • Changes to AOSP are permitted
  • Any Android version 5.0* - 5.1* is fine

Now my device has a keyboard, AND sends and accepts some vendor-specific HID reports. By working, I mean sending and receiving all HID reports

Based on the AOSP source-code exploration I have done, it seems that:

  1. The HidService service broadcasts BluetoothInputDevice.ACTION_REPORT intents for all input HID reports [My app has a BroadcastReceiver to receive ACTION_REPORT intents]

  2. BluetoothInputDevice provides other interfaces like setReport(), sendData(), connect() etc through HidService.

  3. BluetoothInputDevice uses HidService to provide HID device interface.

  4. HidService.java is a JNI wrapper over com_android_bluetooth_hid.cpp

  5. com_android_bluetooth_hid.cpp, on initialization of HidService, will register its own callbacks to Bluedroid

I have added logs to AOSP to trace calls and seems all the above is correct.

BUT

The get_report_callback() in com_android_bluetooth_hid.cpp never gets called, and consequently, My app does not receive ACTION_REPORT intents.

If I send dummy ACTION_REPORT intents from my app, then my BroadcastReceiver receives those intents.

My HID device is connected and working, as I do see keys received in edittext field within my app.

Is there any way I could receive my device's HID reports in my app? through intents or through any other way?

If I could receive through Intents, is there any step that I missed? I basically just have BroadcastReceiver with intent filter and BLUETOOTH and BLUETOOTH_ADMIN permissions for receiving HID reports.

If any other method must be used, please suggest.

like image 583
GPS Avatar asked Sep 26 '22 09:09

GPS


1 Answers

[Update 2]

I probably didn't mention it clearly, but devices I work with implement HID over GATT and are BLE devices.

On newer Android versions (7,8,9), I am able to receive HID reports by subscribing to HID report notifications, Adding BLUETOOTH_PRIVILEGGED permission, and installing as platform app.

No other Android code jugglery was necessary for these versions. I didn't (and won't) test with older versions of Android, but this solution might already work there.


[Previous Answer]

BluetoothInputDevice didn't work at all.

I used /dev/hidraw* from C code to access the bluetooth hidraw devices.

mac address is NOT reported by /dev/hidraw* nodes.

In Android 5.x they work and all set/send/recv report operations are working. get not tested.

On Android 6.x, only recv operation is working from /dev/hidraw. set/send are not working. get not tested.

I will post update when I have better answer.


Update

I modified bluedroid and added a small unix-socket server within it. Bluedroid delivers all incoming HID reports to this server, and accepts outgoing HID reports from it. My app communicate with this server over unnamed socket. All is well.

I just needed to setup socket's permissions SELinux correctly for this to work.

This works for all versions of Bluedroid I could test with (4.4 - 6.0), but every version of Bluedroid needs it's own version of patch.

like image 137
GPS Avatar answered Nov 01 '22 09:11

GPS