'Unable to send keyboard events to Bluetooth HID connected device

I am able to connect to the Bluetooth HID device successfully and able to control the paired device home button and navigation buttons. But unable to send Keyboard key events properly to the HID device. When I am typing something in the host device, the HID device responding with random actions.

I have the following code for the connection with descriptors array,

override fun onServiceConnected(profile: Int, proxy: BluetoothProfile?) {
            if (profile == BluetoothProfile.HID_DEVICE) {
                mBtHidDevice = proxy as BluetoothHidDevice

                val sdp = BluetoothHidDeviceAppSdpSettings(
                    "HidControl",
                    "Android HID Joystick",
                    "Android",
                    0xC0.toByte(),
                    descriptor
                )
           }
       }

The descriptor array is as below,

private val descriptor = byteArrayOf( // HID descriptor
    0x09,  // bLength
    0x21,  // bDescriptorType - HID
    0x11, 0x01,  // bcdHID (little endian - 1.11)
    0x00,  // bCountryCode
    0x01,  // bNumDescriptors (min 1)
    0x22,  // bDescriptorType - Report
    0x30, 0x00,  // wDescriptorLength (48)
    // Report descriptor
    0x05, 0x01,  // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,  // USAGE (Key board)
    0xa1.toByte(), 0x01,  // COLLECTION (Application)
    0xa1.toByte(), 0x00,  //   COLLECTION (Physical)
    0x05, 0x09,  //     USAGE_PAGE (Button)
    0x19, 0x01,  //     USAGE_MINIMUM (Button 1)
    0x29, 0x04,  //     USAGE_MAXIMUM (Button 4)
    0x15, 0x00,  //     LOGICAL_MINIMUM (0)
    0x25, 0x01,  //     LOGICAL_MAXIMUM (1)
    0x75, 0x01,  //     REPORT_SIZE (1)
    0x95.toByte(), 0x04,  //     REPORT_COUNT (4)
    0x81.toByte(), 0x02,  //     INPUT (Data,Var,Abs)
    0x75, 0x04,  //     REPORT_SIZE (4)
    0x95.toByte(), 0x01,  //     REPORT_COUNT (1)
    0x81.toByte(), 0x03,  //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,  //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,  //     USAGE (X)
    0x09, 0x31,  //     USAGE (Y)
    0x15, 0x81.toByte(),  //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,  //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,  //     REPORT_SIZE (8)
    0x95.toByte(), 0x02,  //     REPORT_COUNT (2)
    0x81.toByte(), 0x02,  //     INPUT (Data,Var,Abs)
    0xc0.toByte(),  //   END_COLLECTION
    0xc0.toByte() // END_COLLECTION
)

Code to send keyboard events to the target device is below

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    Log.d("Key Codes ", "$keyCode + event: $event")
    for (btDev in mBtHidDevice!!.connectedDevices) {

        mBtHidDevice!!.sendReport(
            btDev, 0, byteArrayOf(event!!.keyCode.toByte())
        )
        mBtHidDevice!!.sendReport(
            btDev, 0, byteArrayOf(
                0
            )
        )
    }
    return super.onKeyUp(keyCode, event)

}

Please suggest if I am missing anything here. Thanks for the help!



Solution 1:[1]

You need to use Keyboard Usage Page.

The logical minimum and logical maximum that I see is only from 1 to 4. You wanted those USAGEs alone?

Refer to HID usage table https://www.usb.org/document-library/hid-usage-tables-122

There is a Keyboard use case in the appendix. You can refer to that.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ranjith Kumar