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

fix(usb): detect USB power mode to fallback to BLE #2458

Merged

Commits on Sep 14, 2024

  1. fix(usb): fallback to BLE when USB power detected

    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?
    angweekiat committed Sep 14, 2024
    Configuration menu
    Copy the full SHA
    928baca View commit details
    Browse the repository at this point in the history
  2. Seems to work

    angweekiat committed Sep 14, 2024
    Configuration menu
    Copy the full SHA
    ed78b88 View commit details
    Browse the repository at this point in the history
  3. clean up

    angweekiat committed Sep 14, 2024
    Configuration menu
    Copy the full SHA
    78fdfa2 View commit details
    Browse the repository at this point in the history
  4. more cleanup

    angweekiat committed Sep 14, 2024
    Configuration menu
    Copy the full SHA
    9011524 View commit details
    Browse the repository at this point in the history
  5. minor cleanup

    angweekiat committed Sep 14, 2024
    Configuration menu
    Copy the full SHA
    edb885d View commit details
    Browse the repository at this point in the history