-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
fix(usb): detect USB power mode to fallback to BLE #2458
fix(usb): detect USB power mode to fallback to BLE #2458
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
One major question about testing/statuses for another scenario.
Update `zmk_usb_get_conn_state` mapping to only treat `USB_DC_CONFIGURED` and `USB_DC_RESUME` as succesful HID connection. This is a naive solution for zmkfirmware#841, where having a USB-power cable without data driving the keyboard, like a power bank, still has the firmware thinking that it's connected to a host and futilely send data over USB. When the power cable is plugged in, the USB DC status (from Zephyr) goes through the following states: ``` USB_DC_CONNECTED -> USB_DC_SUSPEND ``` While for data cables: ``` USB_DC_CONNECTED -> USB_DC_SUSPEND -> USB_DC_RESUME -> USB_DC_RESET -> USB_DC_CONFIGURED ``` The enum mapping changes do allow the firmware to differentiate the 2 cases, but I'm unable to find any USB or USB HID specifications that explicitly states that the host machine will do the USB configuration step before the USB HID connection is considered complete. Just for safety sake, I added `USB_DC_RESUME` to be considered as successful too. Steps to reproduce original issue --------------------------------- 1. (Setup) Have ZMK keyboard with bluetooth profile enabled, set to prefer sending to USB 2. Power on keyboard via USB via power bank 3. Type, text should not show up anywhere ('consumed' by power bank) Testing ------ Built and flashed firmware with the commit changes, ran the same steps above, text showed up on expected device. Tested using 2 laptops (Ubuntu / Windows) using 2 different power banks. Logs (before) ----------------- ``` --- Started keyboard via battery [00:00:00.554,992] <inf> zmk: Welcome to ZMK! ... [00:00:01.133,514] <dbg> zmk: zmk_usb_get_conn_state: state: 11 --- Plugged power bank to keyboard [00:00:03.959,777] <inf> usb_hid: Device connected [00:00:03.959,808] <dbg> zmk: zmk_usb_get_conn_state: state: 2 [00:00:03.959,838] <dbg> zmk: zmk_usb_get_conn_state: state: 2 [00:00:03.959,869] <dbg> zmk: get_selected_transport: Only BLE is ready. [00:00:03.962,890] <inf> usb_hid: Device suspended [00:00:03.962,921] <dbg> zmk: zmk_usb_get_conn_state: state: 5 [00:00:03.962,951] <dbg> zmk: zmk_usb_get_conn_state: state: 5 [00:00:03.962,982] <dbg> zmk: get_selected_transport: Both endpoint transports are ready. Using 0 [00:00:03.962,982] <dbg> zmk: zmk_endpoints_send_report: usage page 0x07 [00:00:03.963,012] <dbg> zmk: zmk_endpoints_send_report: usage page 0x0C [00:00:03.963,073] <inf> zmk: Endpoint changed: USB ``` Logs with mapping changes (after) --------------------------------- ``` --- Started keyboard via battery [00:00:00.547,943] <inf> zmk: Welcome to ZMK! ... [00:00:00.549,804] <dbg> zmk: zmk_usb_get_conn_state: state: 11 ... --- Plugged power bank to keyboard [00:00:03.686,065] <inf> usb_hid: Device connected [00:00:03.686,126] <dbg> zmk: zmk_usb_get_conn_state: state: 2 [00:00:03.686,126] <dbg> zmk: zmk_usb_get_conn_state: state: 2 [00:00:03.686,157] <dbg> zmk: get_selected_transport: Only BLE is ready. [00:00:03.689,208] <inf> usb_hid: Device suspended [00:00:03.689,239] <dbg> zmk: zmk_usb_get_conn_state: state: 5 [00:00:03.689,270] <dbg> zmk: zmk_usb_get_conn_state: state: 5 [00:00:03.689,270] <dbg> zmk: get_selected_transport: Only BLE is ready. ``` Concerns -------- - This should work for USB Boot Protocol Support, but I have yet to test it. - TODO: Check what happens when keyboard that doesn't have bluetooth profiles has a power bank plugged into it - Above test isn't comprehensive. Maybe this can be a config option instead to catch unknown cases?
3dc8662
to
78fdfa2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally had a chance to give this a test on a real device. Works like a champ from my few test scenarios. Thanks so much for the PR! I am going to suggest we leave some of our docs around this issue as-is for now, pending further real world testing with your change in place.
Update
zmk_usb_is_hid_ready
to check that HID configuration from the host has been done, before allowing the keyboard to be used as a HID device.This is done by adding
bool is_configured
and toggling it off when the device is disconnected, and enabling it whenusb_status == USB_DC_CONFIGURED
.This is a naive solution for #841, where having a USB-power cable without data driving the keyboard, like a power bank, still has the firmware thinking that it's connected to a host and futilely sending data over USB.
When the cable to a power source is plugged in, the USB DC status (from Zephyr) goes through the following states:
While for cables to a host machine:
The status code list can be found at https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/drivers/usb/usb_dc.h#L33-L58
In the case of a power bank being plugged in, the code changes above allow
zmk_usb_is_hid_ready
to declare that HID isn't ready yet, and thus allowsendpoints.c
to fallback to BLE connection.Steps to reproduce the original issue
&out OUT_USB
)Testing
CONFIG_USB_DEVICE_REMOTE_WAKEUP=y
) and for boot protocol (CONFIG_ZMK_USB_BOOT=y
).Concerns