rust-embedded-community / usb-device

Experimental device-side USB framework for microcontrollers in Rust.
MIT License
449 stars 76 forks source link

USB Gadget implementation #12

Open nickray opened 5 years ago

nickray commented 5 years ago

Would be great to wrap the USB Gadget API for Linux for testing purposes. Maybe more a request for the eventual USB Class crates.

mvirkkunen commented 5 years ago

I actually took a look at the USB gadget API (especially gadgetfs since that doesn't require an extra kernel driver) some time ago to see if it would be possible to make a driver for it. It seems to be slightly "higher level" than what this crate expects, but it may be possible to make it behave like a lower level driver with some hacks. I don't currently have any hardware that supports the gadget API to test on, so I haven't looked into it in a lot of detail though.

At the very least it would be a good data point to see how universal the UsbBus trait is.

mvirkkunen commented 5 years ago

Judging just by this example gadgetfs is a bit of a mess:

http://www.linux-usb.org/gadget/usb.c

Seems like none of the drivers agree about the device names, endpoint names or endpoint addresses. I want to know who thought of this API...

nickray commented 5 years ago

I think the current buzzword is configfs, https://elinux.org/images/e/ef/USB_Gadget_Configfs_API_0.pdf

Besides, the worse the API, the more of an improvement a nice Rust API can make :)

mvirkkunen commented 4 years ago

https://patchwork.kernel.org/patch/11332299/

Looks like Linux might be getting a new "USB Raw Gadget" system in the future, primarily meant for debugging/fuzzing apparently, but this looks like something that would be reasonable to implement for usb-device.

mvirkkunen commented 4 years ago

I wonder if something like a Raspberry Pi Zero or something else commonly available would support this. Would be interesting to try the "USB raw gadget" system. Have to get around to buying the hardware though I suppose...

mvirkkunen commented 4 years ago

Found myself some hardware so I'll take a look at these gadget APIs when I have some time!

ryan-summers commented 2 years ago

I actually poked around at the raw gadget API recently and was trying to wire usb-device up to it to get integration testing running via CI, but I similarly hit some issues where even raw-gadget is somewhat higher level than this driver. Sending data in packets seems to confuse raw-gadget, as it expects the full descriptor reads, etc.

ianrrees commented 2 years ago

Is the thinking that the gadget API might be used on one VM to host the usb-device implementation, and tested from another VM? That would be cool - I'd love a way to verify that a USB device passes tests against a Windows host for example.

I wonder if it might be worth looking at QEMU's USB implementation.

ryan-summers commented 2 years ago

I was looking into using raw-gadget as a way to emulate a USB device (running usb-device) to have it enumerate under linux. I had it mostly implemented, but I ran into trouble because raw-gadget is still a higher level interface than what we're interested in. Specifically, I believe that raw-gadget expected to be provided entire descriptors when polling the bus, but in the current implementation of usb-device, we send the MTU size of data, and a descriptor may be spread across many MTUs. This caused hangups in raw-gadget because it expected the full descriptor and would error out otherwise.

ianrrees commented 2 years ago

Ah, so that sounds like implementing a usb-device gadget probably doesn't make sense at the moment. I haven't really studied the endpoint trait branch, wonder if the situation might be different over there.

Is the idea that the gadget implementation would be in a virtual machine or real hardware (something like a Raspberry Pi)? If there's a way to make a VM provide a USB device like that, it could be very useful for testing.

ryan-summers commented 2 years ago

The idea was that the gadget would not be hardware (it would be a software module that talks through some /dev/raw-gadget file descriptor, but I wouldn't call it a virtual machine). The intent here is to make tests runable on any machine without hardware I believe.

mvirkkunen commented 2 years ago

But then again the gadget could also be hardware, and you could implement your own USB devices on Linux! Two birds with one stone.

ianrrees commented 2 years ago

Yeah, I think a Linux Gadget driver would be great, for sure. And, I think with there being such cheap, small, powerful embedded systems, there could be a lot of interesting use cases for one.

But, I don't quite understand how a usb-device Gadget driver would facilitate testing usb-device without any hardware. My understanding is that Gadget is a Linux framework that makes a USB controller present a USB device, rather than the typical USB host. Is there some way to loopback USB in a Linux system? I guess if you had a machine with multiple USB controllers, a Gadget driver could manage one of them, and a cable could be plugged between it and a regular host controller (I've got loads of recent work experience with A-A cables if that's helpful ;) ).

Edit to add: an implicit assumption in my question is that the hardwareless test would need to run on a stock Linux, so it could be used in a typical CI environment.

mbyzhang commented 1 year ago

Yeah, I think a Linux Gadget driver would be great, for sure. And, I think with there being such cheap, small, powerful embedded systems, there could be a lot of interesting use cases for one.

But, I don't quite understand how a usb-device Gadget driver would facilitate testing usb-device without any hardware. My understanding is that Gadget is a Linux framework that makes a USB controller present a USB device, rather than the typical USB host. Is there some way to loopback USB in a Linux system? I guess if you had a machine with multiple USB controllers, a Gadget driver could manage one of them, and a cable could be plugged between it and a regular host controller (I've got loads of recent work experience with A-A cables if that's helpful ;) ).

Edit to add: an implicit assumption in my question is that the hardwareless test would need to run on a stock Linux, so it could be used in a typical CI environment.

Check this: https://www.collabora.com/news-and-blog/blog/2019/06/24/using-dummy-hcd/

ianrrees commented 1 year ago

Thanks @mbyzhang - that dummy_hcd driver looks very useful indeed!

I came to this thread initially through work on iscochronous support, and see this in the current dummy_hcd driver * Note: The emulation does not include isochronous transfers!.