Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs regarding devices_config #3

Closed
rdelcorro opened this issue Aug 17, 2020 · 16 comments
Closed

Docs regarding devices_config #3

rdelcorro opened this issue Aug 17, 2020 · 16 comments

Comments

@rdelcorro
Copy link

Hi @ruundii, first of all this project is exactly what I was looking for. I created https://github.com/rdelcorro/keyboardMux today in order to achieve a similar but simpler goal of converting my USB keyboard to BT. Since your project supports mouse and also BT versions of them, I would like to switch. Is there any docs to setup a simple USB keyboard first? What should I put on devices_config and hid_devices? Since my keyboard is fully programable, I do not need to do any filtering / replacing keys, etc, but rather simply send what it was received to the corresponding target. For the mouse, I have a logitec that has an optional USB dongle that I may be able to use or rather I could link it via BT to the same project.

@ruundii
Copy link
Owner

ruundii commented Aug 17, 2020

Hi,

great to hear it might work for you.
i should have left devices_config as an empty dictionary. it is populated when you configure devices (i.e. select what devices out of those available you want to capture) in the web ui.
in hid_devices you only register filters you want to have available, and then these filters are selected for a device via the web ui.

@rdelcorro
Copy link
Author

Thanks!! I will try it out tomorrow and post back how its doing. One thing I found on my implementation is that after the PC goes to sleep, the keyboard not only does not wake it but also I can't type the password as the device is not re connecting. I will try with yours and report back.

@ruundii
Copy link
Owner

ruundii commented Aug 18, 2020

it should mostly work, i.e. raspberry should initiate reconnection with an exception of after restarting bluetooth on raspberry, or raspberry itself. also, if raspberry or bluetooth is restarted on raspberry reconnection may happen automatically being initiated by host. most hosts will do several attempts to reconnect over few minutes.

bluetooth hid spec defines two flags in the SDP record: HIDNormallyConnectable (0x020D - reconnection from host to device) and HIDReconnectInitiate (0x0205 reconnection from device to host). both these flags are set to true in the current record.
furthermore, the spec also describes that if HIDReconnectInitiate is set to true, then HID device should initiate reconnection on user input. i have put such reconnection logic into my implementation of bluez HID input host profile - when bthidhub sends a hid report over socket to my version of the bluez input host profile, bluez will reconnect.
at the same time, currently I only open the sockets from bluez side to bthidhub on first connect from host to device after bluez start, and this is why after the bluez restart device does not initiate reconnect. this hasn’t been an issue for me so far, but I will try to improve it further in few weeks.

this describes my understanding of how it works, reality may also be different because of some bugs I am now aware of

@rdelcorro
Copy link
Author

Hi @ruundii, I ended up testing it today on a pi zero w and so far I have found:

  • When I plug in a USB keyboard, the UI does show it twice
  • If you press the refresh button, there is a timeout message and the app freezes the pi for a while (even ssh breaks)
  • After I am able to successfully pair the PC (and it shows connected in both places), typing on the keyboard does not send the key press to the PC.

Is there any extra step I am missing?

@ruundii
Copy link
Owner

ruundii commented Aug 18, 2020

interesting,

refresh button - i will remove it, it’s not needed anymore since I implemented websockets, web ui refreshes automatically.

two devices is more interesting though. this means that your keyboard is represented as two devices in the OS. the way it works is that device HID descriptor may combine different functions and OS may create different devices for those different functions. have you tried capturing each one of those two devices?
you may end up creating a simple remapper or modifying an hid descriptor in the sdp record.

could you post your hid descriptor for me to investigate further? it’s a long long hex string
you can get it either via using hid-tools or find in a file with a respective name in your device directory under /sys/bus/hid/devices/. i then should be able to see what reports under what IDs your device may be sending.

@rdelcorro
Copy link
Author

rdelcorro commented Aug 19, 2020

Here is a screenshot of the UI:
image

If I select capture on one, the other gets also selected but no input is sent to the pc

image

Available devices:
/dev/hidraw0:   Apple Inc. Apple Keyboard
/dev/hidraw1:   Apple Inc. Apple Keyboard
Select the device event number [0-1]: 1
# Apple Inc. Apple Keyboard
# 0x05, 0x0c,                    // Usage Page (Consumer Devices)       0
# 0x09, 0x01,                    // Usage (Consumer Control)            2
# 0xa1, 0x01,                    // Collection (Application)            4
# 0x05, 0x0c,                    //  Usage Page (Consumer Devices)      6
# 0x75, 0x01,                    //  Report Size (1)                    8
# 0x95, 0x01,                    //  Report Count (1)                   10
# 0x15, 0x00,                    //  Logical Minimum (0)                12
# 0x25, 0x01,                    //  Logical Maximum (1)                14
# 0x09, 0xcd,                    //  Usage (Play/Pause)                 16
# 0x81, 0x06,                    //  Input (Data,Var,Rel)               18
# 0x09, 0xb5,                    //  Usage (Scan Next Track)            20
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               22
# 0x09, 0xb6,                    //  Usage (Scan Previous Track)        24
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               26
# 0x09, 0xb8,                    //  Usage (Eject)                      28
# 0x81, 0x06,                    //  Input (Data,Var,Rel)               30
# 0x09, 0xe2,                    //  Usage (Mute)                       32
# 0x81, 0x06,                    //  Input (Data,Var,Rel)               34
# 0x09, 0xea,                    //  Usage (Volume Down)                36
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               38
# 0x09, 0xe9,                    //  Usage (Volume Up)                  40
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               42
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               44
# 0xc0,                          // End Collection                      46
#
R: 47 05 0c 09 01 a1 01 05 0c 75 01 95 01 15 00 25 01 09 cd 81 06 09 b5 81 02 09 b6 81 02 09 b8 81 06 09 e2 81 06 09 ea 81 02 09 e9 81 02 81 01 c0
N: Apple Inc. Apple Keyboard
I: 3 05ac 024f
Select the device event number [0-1]: 0
# Apple Inc. Apple Keyboard
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        0
# 0x09, 0x06,                    // Usage (Keyboard)                    2
# 0xa1, 0x01,                    // Collection (Application)            4
# 0x05, 0x07,                    //  Usage Page (Keyboard)              6
# 0x19, 0xe0,                    //  Usage Minimum (224)                8
# 0x29, 0xe7,                    //  Usage Maximum (231)                10
# 0x15, 0x00,                    //  Logical Minimum (0)                12
# 0x25, 0x01,                    //  Logical Maximum (1)                14
# 0x75, 0x01,                    //  Report Size (1)                    16
# 0x95, 0x08,                    //  Report Count (8)                   18
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               20
# 0x95, 0x01,                    //  Report Count (1)                   22
# 0x75, 0x08,                    //  Report Size (8)                    24
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               26
# 0x05, 0x08,                    //  Usage Page (LEDs)                  28
# 0x19, 0x01,                    //  Usage Minimum (1)                  30
# 0x29, 0x05,                    //  Usage Maximum (5)                  32
# 0x95, 0x05,                    //  Report Count (5)                   34
# 0x75, 0x01,                    //  Report Size (1)                    36
# 0x91, 0x02,                    //  Output (Data,Var,Abs)              38
# 0x95, 0x01,                    //  Report Count (1)                   40
# 0x75, 0x03,                    //  Report Size (3)                    42
# 0x91, 0x01,                    //  Output (Cnst,Arr,Abs)              44
# 0x05, 0x07,                    //  Usage Page (Keyboard)              46
# 0x19, 0x00,                    //  Usage Minimum (0)                  48
# 0x2a, 0xff, 0x00,              //  Usage Maximum (255)                50
# 0x95, 0x05,                    //  Report Count (5)                   53
# 0x75, 0x08,                    //  Report Size (8)                    55
# 0x15, 0x00,                    //  Logical Minimum (0)                57
# 0x26, 0xff, 0x00,              //  Logical Maximum (255)              59
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               62
# 0x05, 0xff,                    //  Usage Page (Vendor Usage Page 0xff) 64
# 0x09, 0x03,                    //  Usage (Vendor Usage 0x03)          66
# 0x75, 0x08,                    //  Report Size (8)                    68
# 0x95, 0x01,                    //  Report Count (1)                   70
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               72
# 0xc0,                          // End Collection                      74
#
R: 75 05 01 09 06 a1 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 95 01 75 08 81 01 05 08 19 01 29 05 95 05 75 01 91 02 95 01 75 03 91 01 05 07 19 00 2a ff 00 95 05 75 08 15 00 26 ff 00 81 00 05 ff 09 03 75 08 95 01 81 02 c0
N: Apple Inc. Apple Keyboard
I: 3 05ac 024f

Those are "both" keyboards, but in reality there is just one connected. I also tried with a different one and I get the same result

As a caveat, when I press buttons on the keyboard, nothing shows up on hidtools if I choose the ID 1. If I chose ID 0, I do see the key presses printed, so I suspect your code is using the number 1. Can I somehow delete that ID or is the kernel adding it there?

@ruundii
Copy link
Owner

ruundii commented Aug 19, 2020

cool, thanks.
is it actually a1314 keyboard or some other one?
my a1314 has quite different descriptor and report structure.

for the comparison, this is what my a1314 looks like

0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x01, // Report Size (1)
0x95, 0x05, // Report Count (5)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maximum (Kana)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x75, 0x03, // Report Size (3)
0x95, 0x01, // Report Count (1)
0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x75, 0x08, // Report Size (8)
0x95, 0x06, // Report Count (6)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (0x00)
0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x47, // Report ID (71)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x02, // Collection (Logical)
0x05, 0x06, // Usage Page (Generic Dev Ctrls)
0x09, 0x20, // Usage (Battery Strength)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x11, // Report ID (17)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0xB8, // Usage (Eject)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0xFF, 0x00, // Usage Page (Reserved 0xFF)
0x09, 0x03, // Usage (0x03)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x0C, // Usage Page (Consumer)
0x85, 0x12, // Report ID (18)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x09, 0xCD, // Usage (Play/Pause)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0xB3, // Usage (Fast Forward)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0xB4, // Usage (Rewind)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0xB5, // Usage (Scan Next Track)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0xB6, // Usage (Scan Previous Track)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x13, // Report ID (19)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x06, 0x01, 0xFF, // Usage Page (Vendor Defined 0xFF01)
0x09, 0x0A, // Usage (0x0A)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x01, 0xFF, // Usage Page (Vendor Defined 0xFF01)
0x09, 0x0C, // Usage (0x0C)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x75, 0x01, // Report Size (1)
0x95, 0x06, // Report Count (6)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x09, // Report ID (9)
0x09, 0x0B, // Usage (0x0B)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
0x00, // Unknown (bTag: 0x00, bType: 0x00)

// 225 bytes

basically what i see in your case is that there are indeed two OS devices for different usages.
the first one you posted is for consumer controls - these are top buttons - prev/next track, mute, volume, eject, play/pause. a report for this “device” from what i can tell is one byte long - 7 bits for buttons as a 0/1 flag for each and then another constant bit to align to a byte.
the second one is for keyboard itself. again, from what i see an input keyboard report will be 8 bytes long. first byte will be a byte of flags of modifier keys (ctrl, alt, shift left/right, etc) - pretty standard. then a constant byte. then 5 bytes with keycodes of up to 5 pressed normal keys, and then another byte with some vendor specific keycode - maybe of fn button, maybe for brightness controls, maybe for something else.

to compare, the current hid descriptor in the sdp_record.xml is a bit different from yours:

0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maximum (Kana)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x6D, // Logical Maximum (109)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (0x00)
0x29, 0x6D, // Usage Maximum (0x6D)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID (2)
0x05, 0x0C, // Usage Page (Consumer)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x07, // Report Count (7)
0x09, 0xB5, // Usage (Scan Next Track)
0x09, 0xB6, // Usage (Scan Previous Track)
0x09, 0xB7, // Usage (Stop)
0x09, 0xCD, // Usage (Play/Pause)
0x09, 0xE2, // Usage (Mute)
0x09, 0xE9, // Usage (Volume Increment)
0x09, 0xEA, // Usage (Volume Decrement)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x85, 0x03, // Report ID (3)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x08, // Usage Maximum (0x08)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x00, // Report Count (0)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x40, // Usage (0x40)
0x95, 0x02, // Report Count (2)
0x75, 0x08, // Report Size (8)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x01, 0xF8, // Logical Minimum (-2047)
0x26, 0xFF, 0x07, // Logical Maximum (2047)
0x75, 0x0C, // Report Size (12)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection

// 183 bytes

here you have three possible output reports - one long one for keyboard - modifiers, constant and 6 keys (not 5+1 vendor-specific); another one for similar (not exactly same, as no eject button) consumer control keys as in your first “device”. and a third report is for mouse.

the biggest problem is that reports in my record have ids - 1, 2 and 3, while in yours there are no ids. in my case the report id is a first byte in the hid report (actually second in a message as message also contains bluetooth message id as a first byte - 0xa1 for input reports and 0xa2 for output reports.

to try things out, you can set Default filter for your device in the web ui, then hid_report_filter.py will be used, which adds report id 1 to the message. in theory it should make most of you keys work (except the fancy consumer control keys and the vendor specific key, whatever it is).

you can check my comments on previous 2 issues on general options to consider and some details. i would mainly be thinking around two options:

  1. set your hid descriptor in sdp_record file. then use default filter, but modify the code for it not to insert report id 1. remove bluetooth devices and redo pairing procedure as sdp record is read on pairing. to make the vendor-specific keycode work you may also end up pretending that bt hid hub is the same keyboard as the one you have by setting vendor and product ids.
  2. implement your own filter. just create another filter file, similar to the a1314 filter (but may not end up being as complex, depending in what key remapping you would like). in hid_devices file add it to the list of filters, set it for you device on web ui. and then output report with id 1 for your keyboard reports and report with id 2 for your consumer key reports. in this way you also will be able to do some handling around the vendor-specific button if you end up needing it.

this issue has led me to thinking that a bit later i will try to develop an ability to capture reports not only from hidraw, i.e. before OS processes them, but also after. in this way OS will deal with all the complexity of parsing and handling different hid descriptors and will just give me consistent key events with consistent codes, which i will send to hosts as per hid descriptor in the sdp record. this approach is slightly less flexible, as i may not receive all the vendor-specific events or exotic hid events after those being processed by os/vendor driver, but should work out of box for a much wider range of devices without a need for a device-specific filter

@ruundii
Copy link
Owner

ruundii commented Aug 24, 2020

Hi there,

I have now implemented a keyboard compatibility mode (configurable via web interface on hid devices screen). this functionality captures events via evdev, after those are processed by OS. so all the specifics of various descriptors and reports formats of various keyboards in this way are handled by OS/vendor drivers, I get resulting key codes and send those via bluetooth as hid reports.

Feel free to try it out

Thanks

@rdelcorro
Copy link
Author

rdelcorro commented Aug 29, 2020

Hi @ruundii thanks for the update! I think there is a missing dependency python3-pyudev. After installing, the service now starts.

I added the device in compat mode but its still not sending the key strokes

image
image

Is there any log where I can see that the key events are being received? Also maybe a log for the BT side?

@ruundii
Copy link
Owner

ruundii commented Aug 29, 2020

updated (first i overlooked your devices tab screenshot).
on a devices tab you need to turn on capture from the BT Hid Hub virtual hid raw keyboard. the way it works is that the events captured from evdev are sent to the virtual hid raw device, so everything else works as before based on capturing hid raw reports.

there is some logging, but not at a key press level. you can just stop remapper.service and run remapper.py in commands line. maybe add few tracing print lines to e.g. hid filter
also, on your screenshot here, i see you’ve got remote host paired and a desktop as a bluetooth input device, is it right? are you sure this desktop input device actually works as a keyboard and sends hid reports?

@rdelcorro
Copy link
Author

rdelcorro commented Aug 29, 2020 via email

@ruundii
Copy link
Owner

ruundii commented Aug 29, 2020

what is likely to have happened here is that your DESKTOP-DEJ machine was identified as a bluetooth device when pairing happened. bluetooth hid communications are happening via the same bluetooth ports for both device and host. to distinguish between host and device role I check if the device has HID profile declared via SDP. if it does - then it is a HID device. if it does not - then it is a host.

it is possible that your DESKTOP-DEJ still has HID profile declaration in its SDP from your KB_Mux project. i think if you remove the device (from raspberry side), ensure the sdp record of host does not have HID profile (1124-.... uuid) and then pair again - all should work well. if it does not work you may end up clearing bluetooth storage folders (under /var/lib/bluetooth on both machines).

you can use sdptool to browse what bluetooth profiles are declared on your host and also remove them after you stopped the service which declared this profile

@ruundii
Copy link
Owner

ruundii commented Aug 29, 2020

BTW, having had another look at your hid devices screen - you may need to actually turn on compatibility mode (and then capturing for 2 virtual devices) for both Apple Keyboard devices created by OS for your keyboard

@rdelcorro
Copy link
Author

It does not seem to be the case. Note that the PC is showing the device as a keyboard and properly connected
image

When I try to make any change on the KB screen (capture, compat mode, etc I keep getting 500)

@ruundii
Copy link
Owner

ruundii commented Aug 30, 2020

on the screenshot here - you certainly shouldn’t capture from the virtual hid raw keyboard and apple keyboard at the same time.
maybe there is a bug, possibly some problem of having two virtual hid raw keyboards at the same time. if so, before i resolve it, you can do compatibility mode and capture from one device out of two, the one with all buttons except the volume/play/pause/song control (i understand device description does not help, so just try to see which one it is).

would be interesting too see if there are any issues in console (sudo systemctl status remapper.service) or just run it in the console and see what is happing when it gives 500

to resolve 500 - maybe restart, or set device_config content to an empty dictionary ‘{}’ if just restart does not help.

@Dreamsorcerer
Copy link
Collaborator

I suspect this would be resolved with #23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants