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

Have to Unplug / Re-Plug USB Host Keyboard #8886

Open
FoamyGuy opened this issue Feb 5, 2024 · 19 comments
Open

Have to Unplug / Re-Plug USB Host Keyboard #8886

FoamyGuy opened this issue Feb 5, 2024 · 19 comments
Assignees
Milestone

Comments

@FoamyGuy
Copy link
Collaborator

FoamyGuy commented Feb 5, 2024

CircuitPython version

Adafruit CircuitPython 9.0.0-beta.0 on 2024-01-27; Adafruit Feather RP2040 USB Host with rp2040

Code/REPL

print("hello")

Behavior

I've tested various states of powering on the microcontroller with and without the USB Keyboard plugged in to the host port and found that if the microcontroller powers up with the keyboard plugged in, the keyboard will not work until it has been unplugged and re-plugged.

I tested the following scenarios:

  • start with microcontroller unplugged and USB Keyboard unplugged
  • plug in the microcontroller to power
  • minimal code executes and completes instantly-ish
  • plug in the USB Keyboard to the USB Host port
  • The keyboard works and is able to press ctrl-C and then start typing into the REPL
  • Start with microcontroller unplugged from power, but with the USB Keyboard plugged in to the USB Host port
  • plug in the microcontroller to power
  • minimal code executes and completes instantly-ish
  • The keyboard plugged in to the host port is unresponsive ctrl-C nor any other keys seem to do anything.
  • Can restart the MCU multiple times with ctrl-D / ctrl-C from the keyboard plugged in to the PC and connected via tio. Still the keyboard plugged in to USB Host port is unresponsive
  • Unplug the keyboard from USB Host port and re-plug it back in
  • Now the keyboard plugged in to USB Host port works, ctrl-C and other key presses can be sent to interact with the REPL

Description

No response

Additional information

I noticed that there is a board.USB_HOST_5V_POWER pin defined in this device. I attempted to use digitalio to toggle it off and back on to simulate the unplug / re-plug action but it raised an error about pin in use. I only tested from code.py but will attempt from boot.py later.

If it is possible to toggle that pin and have it serve the same purpose as unplugging and re-plugging then user code would have a way to work around this issue without needing the explicit action from the human user to unplug and re-plug.

@FoamyGuy FoamyGuy added the bug label Feb 5, 2024
@FoamyGuy
Copy link
Collaborator Author

FoamyGuy commented Feb 5, 2024

I tried toggling that pin in boot.py as well with this code:

usb_host_power = digitalio.DigitalInOut(board.USB_HOST_5V_POWER)
usb_host_power.direction = digitalio.Direction.OUTPUT
usb_host_power.value = False
time.sleep(0.5)
usb_host_power.value = True

But it still results in the same ValueError: USB_HOST_5V_POWER in use that came from code.py as well.

@tannewt tannewt added the usb label Feb 5, 2024
@tannewt tannewt added this to the 9.0.0 milestone Feb 5, 2024
@jepler
Copy link
Member

jepler commented Feb 16, 2024

With #8937 you will be able to use the USB_HOST_5V_POWER pin from code

@tannewt tannewt assigned tannewt and unassigned jepler Feb 22, 2024
@tannewt
Copy link
Member

tannewt commented Feb 23, 2024

@hathach How do we initialize the USB host stuff so that we can see devices that are already attached? Do we need to toggle power or is there a TinyUSB bug here?

@hathach
Copy link
Member

hathach commented Feb 24, 2024

@hathach How do we initialize the USB host stuff so that we can see devices that are already attached? Do we need to toggle power or is there a TinyUSB bug here?

when initializing usb host, it should reset controller, any current attached device should go to enumeration process as newly plugged. Otherwise, it is a bug with controller, in this case is the pio-usb controller. Let me try to reproduc this first, @FoamyGuy do you have any quick code.py to test with.

@FoamyGuy
Copy link
Collaborator Author

@hathach during this test I was not using any specific code. I think just the default print("hello world") file that comes from a storage format.

The code itself wasn't trying to interact with the keyboard. I was trying to use the keyboard to interact with the REPL after the code finished executing.

@tannewt
Copy link
Member

tannewt commented Feb 27, 2024

@hathach CircuitPython 9 will automatically use a connected keyboard as input. This is done by the supervisor using the TinyUSB host HID driver. So, no specific code.py is needed on the RP2040 USB host feather because the board_init() starts up the USB host port.

@hathach
Copy link
Member

hathach commented Feb 29, 2024

@jepler I am able to reproduce the issue with my generic low speed usb keyboard. I will try to find an full speed usb to test with as well, just curious if your keyboard is low speed or full speed ? they are handled differently in pio-usb.

@tannewt
Copy link
Member

tannewt commented Feb 29, 2024

I believe my keyboard is low speed as well.

@hathach
Copy link
Member

hathach commented Mar 5, 2024

@FoamyGuy @tannewt would you mind re-testing this with latest (after #8999), it seems that PR also fixes this issue as well when bumping up tinyusb

@FoamyGuy
Copy link
Collaborator Author

FoamyGuy commented Mar 5, 2024

I tested with this firmware version from S3

adafruit-circuitpython-adafruit_feather_rp2040_usb_host-en_US-20240304-main-PR8999-0186d9c.uf2

With a basic code.py file that does basically nothing print(1234)

With this version loaded I still don't seem to be able to interact with the REPL using the keyboard plugged in to the USB A Host port until I unplug / re-plug it.

I wasn't certain if the build that has PR8999 in it's name includes that PR or not for certain, so I also tried what is the absolute newest build listed in S3 at the time of testing which was:

adafruit-circuitpython-adafruit_feather_rp2040_usb_host-en_US-20240305-main-PR9007-3aedd90.uf2

And I see the same behavior with that one. Still unable to interact unless I unplug / re-plug the keyboard.

I did notice with these new versions that while I am spamming buttons on the keyboard to test if they will be recognized occasionally all 3 indicator LEDs on the keyboard light up for about half a second and then turn back off. Which does also occur when you first plug in the keyboard. It appears to me that maybe it's attempting to get connected and it manages to make those lights turn on for a second as if it had connected, but afterward the button presses still have no reaction in the REPL. The timing of those lights turning on when they do doesn't seem consistent, sometimes they turn on within only a few seconds of pressing keys to test, but other times they don't turn on for 30 seconds or longer.

@dhalbert dhalbert modified the milestones: 9.0.0, 9.0.x Mar 7, 2024
@hathach
Copy link
Member

hathach commented Mar 13, 2024

I still couldn't reproduce the issue with my machine, it take a bit of time (several seconds) to enumerate keyboard but seems to work just fine. @FoamyGuy are you testing with rp2040 connected to a macOS machine. If yes, then you maybe give this #9042 a try, it fixes an issue with using with macos.

@FoamyGuy
Copy link
Collaborator Author

All of my testing was performed with a Feather RP2040 USB Host (https://www.adafruit.com/product/5723) and it has been plugged into an Ubuntu PC for power and serial communication during my testing.

@hathach
Copy link
Member

hathach commented Mar 13, 2024

All of my testing was performed with a Feather RP2040 USB Host (https://www.adafruit.com/product/5723) and it has been plugged into an Ubuntu PC for power and serial communication during my testing.

I also tested with both feather usb host + pico (with testbed brain) and a Linux PC. It probably has something to do with keyboard. Can you enable the CFG_TUSB_DEBUG = 2 then getting the tinyusb log from uart to see if there is any problems.

@FoamyGuy
Copy link
Collaborator Author

@hathach I can try but I'm not sure how to do that. Is there documentation for that process somewhere I could reference?

Or if not separately documented somewhere can you tell me where to put CFG_TUSB_DEBUG = 2 is that a build flag that you put on the make command line like circuitpython DEBUG? Or something that goes into one of the board files before you make a build?

Once that is enabled how are they logs accessed? do they just get sent out over the serial line? so if I'm connected to REPL / serial console I will see them? Or I need to connect to some other port or something for those?

@tannewt
Copy link
Member

tannewt commented Mar 18, 2024

We have CIRCUITPY_DEBUG_TINYUSB

// Debug level for TinyUSB. Only outputs over debug UART so it doesn't cause
It outputs to the console UART. I think it needs to be in mpconfigboard.h instead of on the command line. It needs to use the UART instead of USB because logging to USB would trigger more logging. :-)

@FoamyGuy
Copy link
Collaborator Author

FoamyGuy commented Mar 18, 2024

I tried adding this at the end of this file: https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/boards/adafruit_feather_rp2040_usb_host/mpconfigboard.h

#define CIRCUITPY_DEBUG_TINYUSB 1

I was able successfully make a build but as far as I can tell enabling the debugging did not work. When the device connects to the PC there is only 1 serial port and it's the standard serial output / REPL. If I enable the USB Console line with boot.py then it typically appears as /dev/ttyACM1, I'm assuming that is how it would connect for debugging too, but no other ports other than the standard ttyACM0 appear.

I also tried

#define CIRCUITPY_DEBUG_TINYUSB 2

Because @hathach message mentioned CFG_TUSB_DEBUG = 2 but it's unclear to me whether 1 or 2 would be the correct value for CIRCUITPY_DEBUG_TINYUSB. In my case I don't seem to see any difference, with either of them I get the same behavior, successful build but only 1 serial connection and it's the standard one with REPL.

Honestly though I think my local environment or builds might be messed up anyway. I'm noticing that if I build from main and then flash it to my device that USB Host never seems to work. No matter if I un-plug and re-plug the REPL will never recognize the keyboard.

I tried downloading the absolute newest from S3 and on that one I the keyboard does get recognized and works correctly after an un-plug / re-plug (which is same behavior I see with RC1).

I'm not sure why but my local builds seem to have broken USB Host in general beyond the debug not exposing the extra port.

If someone else can make and share a debug build that is known to have working USB Host and debugging enabled I could download it and flash it to my device and share the resulting output.

@tannewt
Copy link
Member

tannewt commented Mar 19, 2024

Here is a build for the rp2040 usb host feather. The debug statements are transmitted out the TX pin.

firmware.uf2.zip

Here is my debug output that shows the same issue. I've marked where I unplugged and replugged the device.

Serial console setup
USBH init on controller 1
sizeof(usbh_device_t) = 184
sizeof(hcd_event_t) = 12
sizeof(_ctrl_xfer) = 24
sizeof(tuh_xfer_t) = 24
sizeof(tu_fifo_t) = 20
sizeof(tu_edpt_stream_t) = 40
HID init
HUB init
Adafruit CircuitPython 9.0.0-rc.0-5-gdeb8ae02fe-dirty on 2024-03-19; Adafruit Feather RP2040 USB Host with rp2040
Board ID:adafruit_feather_rp2040_usb_host
UID:DF6254209F7B3C29
boot.py output:
sizeof(hw_endpoint_t) = 32

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
  Open EP 81 with Size = 64
  Allocated 64 bytes at offset 0x180 (0x0x50100180)
  Open EP 02 with Size = 64
  Allocated 128 bytes at offset 0x1c0 (0x0x501001c0)
  Open EP 82 with Size = 64
  Allocated 128 bytes at offset 0x240 (0x0x50100240)
  Bind EP 81 to driver id 0
  Bind EP 02 to driver id 0
  Bind EP 82 to driver id 0
  Open EP 83 with Size = 64
  Allocated 128 bytes at offset 0x2c0 (0x0x501002c0)
  Open EP 03 with Size = 64
  Allocated 128 bytes at offset 0x340 (0x0x50100340)
  Bind EP 83 to driver id 1
  Bind EP 03 to driver id 1
  Open EP 84 with Size = 64
  Allocated 64 bytes at offset 0x3c0 (0x0x501003c0)
  Open EP 04 with Size = 64
  Allocated 64 bytes at offset 0x400 (0x0x50100400)
  Bind EP 84 to driver id 2
  Bind EP 04 to driver id 2
  Open EP 05 with Size = 64
  Allocated 128 bytes at offset 0x440 (0x0x50100440)
  Open EP 85 with Size = 64
  Allocated 128 bytes at offset 0x4c0 (0x0x501004c0)
  Bind EP 05 to driver id 4
  Bind EP 85 to driver id 4
[1:] USBH DEVICE ATTACH
Low Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Full Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
process_enumeration 1335: ASSERT FAILED
[1:] USBH DEVICE ATTACH
Full Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
[1:0:0] USBH DEVICE REMOVED
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Full Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Low Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Full Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Low Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED
[1:] USBH DEVICE ATTACH
Low Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

[1:0:0] USBH DEVICE REMOVED

// Actually unplugged here

[1:] USBH DEVICE ATTACH
Low Speed
[1:0] Open EP0 with Size = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: FAILED
[1:0] Control FAILED, xferred_bytes = 8
80 06 00 01 00 00 08 00 

Enumeration attempt 1
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
on EP 00 with 8 bytes: OK
on EP 80 with 8 bytes: OK
[1:0] Control data:
  0000:  12 01 10 01 00 00 00 08                          |........|
on EP 00 with 0 bytes: OK

Set Address = 1
[1:0] Set Address: 00 05 01 00 00 00 00 00 
on EP 00 with 8 bytes: OK
on EP 80 with 0 bytes: OK

[1:1] Open EP0 with Size = 8
Get Device Descriptor
[1:1] Get Descriptor: 80 06 00 01 00 00 12 00 
on EP 00 with 8 bytes: OK
on EP 80 with 18 bytes: OK
[1:1] Control data:
  0000:  12 01 10 01 00 00 00 08 D9 04 69 01 10 01 00 02  |..........i.....|
  0010:  00 01                                            |..|
on EP 00 with 0 bytes: OK

Get Configuration[0] Descriptor (9 bytes)
[1:1] Get Descriptor: 80 06 00 02 00 00 09 00 
on EP 00 with 8 bytes: OK
on EP 80 with 9 bytes: OK
[1:1] Control data:
  0000:  09 02 3B 00 02 01 00 A0 32                       |..;.....2|
on EP 00 with 0 bytes: OK

@hathach
Copy link
Member

hathach commented Mar 22, 2024

@tannewt thanks for the log, I will try to find other keyboards to test with, and also look more at the log.

@dhalbert dhalbert modified the milestones: 9.0.x, 9.x.x Apr 5, 2024
@tannewt tannewt removed their assignment Apr 23, 2024
@dhalbert
Copy link
Collaborator

Retest after #9571

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

No branches or pull requests

5 participants