Implemented basic handler for USB GET STATUS requests
I'm currently working with a BTT non-pro Octopus v1.1 with klippy running on my Linux Machine (Ubuntu 24.04, Kernel 6.8.0-45-generic amd64) and experienced erratic USB behavior. The board would connect normally but get kicked off the bus after starting klippy. Any attempt at configuring the serial device would yield the same behavior (e.g. connecting with gtkterm or screen)
dmesg would look like this
[ 9350.139784] usb 1-2: new full-speed USB device number 37 using xhci_hcd
[ 9350.267874] usb 1-2: New USB device found, idVendor=1d50, idProduct=614e, bcdDevice= 1.00
[ 9350.267892] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 9350.267901] usb 1-2: Product: stm32f446xx
[ 9350.267908] usb 1-2: Manufacturer: Klipper
[ 9350.267914] usb 1-2: SerialNumber: 240032000751323438353631
[ 9350.271220] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[ 9355.236947] usb 1-2: reset full-speed USB device number 37 using xhci_hcd
[ 9355.364256] usb 1-2: USB disconnect, device number 37
[ 9355.478658] usb 1-2: new full-speed USB device number 38 using xhci_hcd
[ 9355.606352] usb 1-2: New USB device found, idVendor=1d50, idProduct=614e, bcdDevice= 1.00
[ 9355.606357] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 9355.606359] usb 1-2: Product: stm32f446xx
[ 9355.606361] usb 1-2: Manufacturer: Klipper
[ 9355.606362] usb 1-2: SerialNumber: 240032000751323438353631
[ 9355.608104] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
I've spent some time debugging with Wireshark and usbmon and noticed that the GET STATUS device request was never answered by the device which probably caused it to be kicked off the bus.
In the PR I've implemented a basic handler for GET STATUS which fixed the erratic behavior for me. I've consulted the USB 2.0 spec and tinyusb . The USB Spec allows a host to ask for the status of the device, interface(s), or endpoint(s) via the bRequest field. It will contain some number corresponding to usb_interface_descriptor::bInterfaceNumber or usb_endpoint_descriptor::bEndpointAddress or just a zero for the device. The last part is a guess of mine as the spec. isn't very clear on that. Also, while debugging Linux only ever asked for 0 so :shrug:.
If one would want to implement this fully, requests for interface status are simple, just send a 0; for endpoints however there needs to be some more work done on supporting halting of endpoints. Additionally USB can also request changes of the two device status flags (self-powered and remote-wakeup) via a config request. This isn't implemented either. It could maybe create some problems in the future.
I hope you find this useful. Cheers!
Thank you for submitting a PR. Please be aware you need to sign off, as per point 3 in https://github.com/Klipper3d/klipper/blob/master/docs/CONTRIBUTING.md#what-to-expect-in-a-review
Also, check the commit message format. I think it would be appropriate to use:
usb_cdc: ...
Thanks for the hint @nefelim4ag . I should have read the whole contributing document. It should be in specification now
Please not the instruction in the contributing doc
Comments in code submissions should focus on enhancing code maintenance. Submissions should not contain "commented out code" nor excessive comments describing past implementations. There should not be excessive "todo" comments.
The comments you added are probably better suited for the PR than inside the code.
Thanks James
Please not the instruction in the contributing doc
Comments in code submissions should focus on enhancing code maintenance. Submissions should not contain "commented out code" nor excessive comments describing past implementations. There should not be excessive "todo" comments.
The comments you added are probably better suited for the PR than inside the code.
Thanks James
You're right. I've slimmed down my comments and put them in the PR description
Thanks for working on this. Sorry for the delay in responding.
I'd like to better understand the root issue here. It seems odd that no other users have reported this issue previously (the micro-controller USB code is shared among all boards) - any ideas why that would be? Is it possible you have ModemManager (or similar) software running on your machine? What steps would I run to reproduce this issue on one of my machines (including the logs)? I have an stm32f446 development board I can use for testing.
We can certainly implement the GET_STATUS command, but I'd like to make sure that we aren't working around some other fundamental error. (For example, perhaps the mcu code isn't properly generating a STALL condition.)
-Kevin
I ran some tests locally and I'm unable to reproduce this issue on my stm32f446 development board.
I started the capture with:
sudo apt-get install tcpdump
sudo modprobe usbmon
sudo tcpdump -i usbmon0 -w usblog.pcap
I can force Linux to send a GET_STATUS command by running sudo lsusb -vvv.
I inspected the capture with wireshark (wireshark usblog.pcap). I do see the GET_STATUS request, but the device immediately responds with a STALL and Linux accepts that. For example:
Frame 9427: 64 bytes on wire (512 bits), 64 bytes captured (512 bits)
USB URB
[Source: host]
[Destination: 1.94.0]
URB id: 0x0000000086326a00
URB type: URB_SUBMIT ('S')
URB transfer type: URB_CONTROL (0x02)
Endpoint: 0x80, Direction: IN
Device: 94
URB bus id: 1
Device setup request: relevant ('\0')
Data: not present ('<')
URB sec: 1746290624
URB usec: 299
URB status: Operation now in progress (-EINPROGRESS) (-115)
URB length [bytes]: 2
Data length [bytes]: 0
[Response in: 9428]
Interval: 0
Start frame: 0
Copy of Transfer Flags: 0x00000200, Dir IN
Number of ISO descriptors: 0
Setup Data
Frame 9428: 64 bytes on wire (512 bits), 64 bytes captured (512 bits)
USB URB
[Source: 1.94.0]
[Destination: host]
URB id: 0x0000000086326a00
URB type: URB_COMPLETE ('C')
URB transfer type: URB_CONTROL (0x02)
Endpoint: 0x80, Direction: IN
Device: 94
URB bus id: 1
Device setup request: not relevant ('-')
Data: present ('\0')
URB sec: 1746290624
URB usec: 1764
URB status: Broken pipe (-EPIPE) (-32)
URB length [bytes]: 0
Data length [bytes]: 0
[Request in: 9427]
[Time from request: 0.001465000 seconds]
Unused Setup Header
Interval: 0
Start frame: 0
Copy of Transfer Flags: 0x00000200, Dir IN
Number of ISO descriptors: 0
So, I'm not seeing a problem with the current code. I guess we'll need more information on your setup. Also, it may help if you can upload the USB packet logs when running the pristine code (make sure you have a recent version of the Klipper code on the flash as there were some USB fixes a few months ago).
-Kevin