bluekitchen / btstack

Dual-mode Bluetooth stack, with small memory footprint.
http://bluekitchen-gmbh.com
Other
1.69k stars 605 forks source link

CAPS Lock LED Output Report #626

Open peterburk opened 2 weeks ago

peterburk commented 2 weeks ago

Is your feature request related to a problem? Please describe.

I'm using bluepad32, which is built using btstack, to create a Bluetooth keyboard -> USB HID bridge (with optional remapping of Cmd->Ctrl for use on Windows). However, the CAPS Lock LED doesn't come on. I've filed an issue with that project, but on reading further, it seems that the CAPS lock key wasn't supported in BTStack Keyboard either.

Describe the solution you'd like Some advice on how to use hids_client_send_write_report with BR/EDR would be very helpful. I'm getting error ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER when trying to send the output report in uni_hid_parser_keyboard.c.

Describe alternatives you've considered A wired solution, the HID Remapper project, doesn't support the Apple Magic Keyboard either (USB enumeration issue).

Additional context I'm using an Apple Magic Keyboard A1843.

mringwal commented 2 weeks ago

Hi Peter. You're lucky with your timing.

The CAPS Lock LED technically is unrelated to the CAPS Lock key and controlled by the HID Host. You can turn it on by sending an output report with the correct format, which is the tricky part as the format is also defined by the HID Descriptor.

Long story short, we've recently reworked our hid parser to provide info on all reports and added minimal support for our hid_host_demo, see https://github.com/bluekitchen/btstack/blob/develop/example/hid_host_demo.c#L200

peterburk commented 2 weeks ago

Thank you for your quick response, and the pointer to the -develop branch!

I just tried the hid_host_demo with the Magic Keyboard, and the CAPS lock LED doesn't come on.

It's definitely sending hid_host_set_leds. During setup, it shows "Found CAPS LOCK in Output Report with ID 0x0001 at bit 1"

I'll experiment some more with sending different Output Reports by hid_host_send_set_report.

mringwal commented 2 weeks ago

Oh.. well, then thanks for reporting. While the output report format is flexible, most keyboards have the CAPS Lock at bit 1 (as reported by your test).

We did test with another keyboards and/or our hid_keyboard_demo, but I use the A1843 as my main keyboard, too. I'll give it a try next week.

peterburk commented 4 days ago

I used PacketLogger on my Mac to find out what the L2CAP commands are:

CAPS lock on: [ 0xA2 0xF1 0x01 0x02 ]

CAPS lock on

CAPS lock off: [ 0xA2 0xF1 0x01 0x00 ]

CAPS lock off

I tried sending it with:

    const uint8_t capsReportFromMac[4] = { 0xA2, 0xF1, 0x01, 0x02 };
    l2cap_send(hid_host_cid, (uint8_t *) capsReportFromMac, 4);

but that didn't work.

I also tested an older Android phone, which didn't show the LED, and a new Android phone, which did.

mringwal commented 4 days ago

Hi Peter. Which version of PacketLogger do you have? While I'm using PacketLogger with BTstack a lot - and just recently found out that it can decode LE Audio properly - I wasn't able to capture live data from my current Sonoma installation.

If you use l2cap_send, you'll need to use the either the HID Control or the HID Interrupt channels, from hid_connection_t, fields interrupt_cid and control_cid. The hid_host_cid only identifies the hid_connection_t to use.

You cal also try to use hid_host_send_report with hid_host_cid , report id = 0xf1, and { 0x01, 0x02 }, and check the packet log. If we're sending the same data, the keyboard should behave the same, too.

peterburk commented 4 days ago

I'm using PacketLogger version 2022.03.30 from Additional_Tools_for_Xcode_15.4.dmg on macOS Sonoma 14.0 running on a MacBook Pro 2014 15" Retina thanks to OpenCore Legacy Patcher.

The example hid_host_demo.c didn't include hid_connection_t, but I tried the following (without success):

    const uint8_t capsReportFromMac[4] = { 0xA2, 0xF1, 0x01, 0x02 };
    hid_device_send_interrupt_message(hid_host_cid, (uint8_t *) capsReportFromMac, 4);
    hid_device_send_control_message(hid_host_cid, (uint8_t *) capsReportFromMac, 4);
    const uint8_t capsReport[2] = { 0x01, 0x02 };
    hid_host_send_set_report(hid_host_cid, HID_REPORT_TYPE_OUTPUT, 0xf1, capsReport, 2);

I'm building the btstack examples for the Raspberry Pi Pico W, rather than Mac, so I can't just use PacketLogger to get the output.