surban / usb-gadget

Expose standard or fully custom USB peripherals (gadgets) through a USB device controller (UDC) on Linux using Rust.
https://crates.io/crates/usb-gadget
Apache License 2.0
55 stars 5 forks source link

How to implement a WinUSB device #6

Closed zh522130 closed 2 months ago

zh522130 commented 3 months ago

Hello, I would like to ask how to implement a WinUSB device. I am looking to implement the CMSIS-DAP V2 interface, but after reviewing the API, I still don't know how to proceed. Could you provide some guidance or helpful information?

Reference: CMSIS-DAP Configure USB peripheral

surban commented 3 months ago

Check out the custom_interface examples. The host-side example should work on Windows and uses WinUSB. There is no need for any INF files provided that you are using Windows 10 or later.

zh522130 commented 3 months ago

Check out the custom_interface examples. The host-side example should work on Windows and uses WinUSB. There is no need for any INF files provided that you are using Windows 10 or later.查看 custom_interface 示例。主机端示例应在 Windows 上运行并使用 WinUSB。如果您使用的是 Windows 10 或更高版本,则不需要任何 INF 文件。

thank you,I am using the following code to generate a WinUSB composite device.

usb_gadget::remove_all().expect("cannot remove all gadgets");

// WinUSB
let (mut ep1_rx, ep1_dir) = EndpointDirection::host_to_device();
let (mut ep2_tx, ep2_dir) = EndpointDirection::device_to_host();
let winusb_guid = uuid!("CDB3B5AD-293B-4663-AA36-1AAE46463776");
let (mut custom_winusb, winusb_handle) = Custom::builder()
    // WinUSB
    .with_interface(
        Interface::new(Class::vendor_specific(0x00, 0x00), "Gadget CMSIS-DAP V2")
            .with_os_ext_compat(OsExtCompat::winusb())
            .with_os_ext_prop(OsExtProp::new("DeviceInterfaceGUIDs", OsRegValue::MultiSz(vec![winusb_guid.to_string()])))
            .with_endpoint(Endpoint::bulk(ep1_dir))
            .with_endpoint(Endpoint::bulk(ep2_dir)),
    )
    .build();

// CDC
let (serial,serial_handle) = Serial::new(SerialClass::Acm);

let udc = default_udc().expect("cannot get UDC");
let reg = Gadget::new(
    Class::new(0xEF, 0x02, 0x01),
    Id::new(0x0ADE, 0xEDA0),
    Strings::new("manufacturer", "Gadget CMSIS-DAP", "12345678"),
)
.with_config(Config::new("CMSIS-DAP")
            .with_function(winusb_handle)
            .with_function(serial_handle)
        )
.with_os_descriptor(OsDescriptor::microsoft())
.bind(&udc)
.expect("cannot bind to UDC");`

When running the code, I receive the following prompt:

Custom function at /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0

ep1 unclaimed: Err(Os { code: 95, kind: Uncategorized, message: "Operation not supported" }) ep1 real address: 255 ep1 descriptor: EndpointDesc { endpoint_address: 2, attributes: 2, max_packet_size: 512, interval: 1, audio: None }

ep2 unclaimed: Err(Os { code: 95, kind: Uncategorized, message: "Operation not supported" }) ep2 real address: 255 ep2 descriptor: EndpointDesc { endpoint_address: 130, attributes: 2, max_packet_size: 512, interval: 0, audio: None }`

Windows recognizes the serial port and WinUSB, but when communicating via rust nusb, it throws an error:

"could not claim interface: Custom { kind: Unsupported, error: "Could not find DeviceInterfaceGUIDs in registry. WinUSB driver may not be correctly installed for this interface." }".

I have reviewed the code, and it seems the os_ext_props is not being used. I am not sure where the problem lies.

zh522130 commented 3 months ago

I don't know how to add WinUSB Microsoft OS 2.0 descriptor

surban commented 3 months ago

Please verify first that the examples work on your system.

zh522130 commented 3 months ago

Please verify first that the examples work on your system.请首先验证这些示例是否适用于您的系统。

I am also unable to get the code from custom_interface_device.rs to work properly. The Windows Device Manager displays it as an unrecognized device. unknow driver

The Linux-side log is as follows:

[DEBUG] removing gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [DEBUG] unmounting functionfs usb-gadget0-0 from /dev/ffs-usb-gadget0-0 [DEBUG] removed gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [DEBUG] registering gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [WARN] WebUSB descriptor is unsupported by kernel [DEBUG] creating function at /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0 [DEBUG] creating functionfs directory /dev/ffs-usb-gadget0-0 [DEBUG] mounting functionfs into /dev/ffs-usb-gadget0-0 using options MountOptions { no_disconnect: false, rmode: None, fmode: None, mode: None, uid: None, gid: None } [DEBUG] writing functionfs descriptors to /dev/ffs-usb-gadget0-0/ep0 [DEBUG] writing functionfs strings to /dev/ffs-usb-gadget0-0/ep0 [DEBUG] functionfs initialized [DEBUG] opening endpoint file /dev/ffs-usb-gadget0-0/ep1 with queue length 16 [DEBUG] opening endpoint file /dev/ffs-usb-gadget0-0/ep2 with queue length 16 [DEBUG] creating config at /sys/kernel/config/usb_gadget/usb-gadget0/configs/c.1 [DEBUG] adding function /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0 [DEBUG] gadget at /sys/kernel/config/usb_gadget/usb-gadget0 registered [DEBUG] binding gadget RegGadget { name: "usb-gadget0", is_attached: true } to Some(Udc { name: "4100000.udc-controller" }) Custom function at /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0

ep1 unclaimed: Err(Os { code: 95, kind: Uncategorized, message: "Operation not supported" }) ep1 real address: 255 ep1 descriptor: EndpointDesc { endpoint_address: 1, attributes: 2, max_packet_size: 512, interval: 1, audio: None }

ep2 unclaimed: Err(Os { code: 95, kind: Uncategorized, message: "Operation not supported" }) ep2 real address: 255 ep2 descriptor: EndpointDesc { endpoint_address: 129, attributes: 2, max_packet_size: 512, interval: 0, audio: None }

Event: Enable receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty receive empty sent data 0 of size 512 bytes sent data 1 of size 512 bytes sent data 2 of size 512 bytes sent data 3 of size 512 bytes sent data 4 of size 512 bytes sent data 5 of size 512 bytes sent data 6 of size 512 bytes sent data 7 of size 512 bytes sent data 8 of size 512 bytes sent data 9 of size 512 bytes sent data 10 of size 512 bytes sent data 11 of size 512 bytes sent data 12 of size 512 bytes sent data 13 of size 512 bytes sent data 14 of size 512 bytes sent data 15 of size 512 bytes sent data 16 of size 512 bytes sent data 17 of size 512 bytes no event receive empty send timeout

After installing the libusb-win32 driver with zadig-2.8, I encounter the following error message when using nusb:

could not claim interface: Custom { kind: Unsupported, error: "Device driver is \"libusb0\", not WinUSB" }

image

I have built an embedded Linux system using buildroot,Kernel Version is linux-5.4 and the USB device is an OTG device. I have added all the kernel configurations mentioned in the documentation.

zh522130 commented 3 months ago

I modified the Linux code according to gadget: add WebUSB, and now there is no "[WARN] WebUSB descriptor is unsupported by kernel" message being printed. The log is as follows:

[DEBUG] removing gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [DEBUG] unmounting functionfs usb-gadget0-0 from /dev/ffs-usb-gadget0-0 [DEBUG] removed gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [DEBUG] registering gadget at /sys/kernel/config/usb_gadget/usb-gadget0 [DEBUG] creating function at /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0 [DEBUG] creating functionfs directory /dev/ffs-usb-gadget0-0 [DEBUG] mounting functionfs into /dev/ffs-usb-gadget0-0 using options MountOptions { no_disconnect: false, rmode: None, fmode: None, mode: None, uid: None, gid: None } [DEBUG] writing functionfs descriptors to /dev/ffs-usb-gadget0-0/ep0 [DEBUG] writing functionfs strings to /dev/ffs-usb-gadget0-0/ep0 [DEBUG] functionfs initialized [DEBUG] opening endpoint file /dev/ffs-usb-gadget0-0/ep1 with queue length 16 [DEBUG] opening endpoint file /dev/ffs-usb-gadget0-0/ep2 with queue length 16 [DEBUG] creating config at /sys/kernel/config/usb_gadget/usb-gadget0/configs/c.1 [DEBUG] adding function /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0 [DEBUG] gadget at /sys/kernel/config/usb_gadget/usb-gadget0 registered [DEBUG] binding gadget RegGadget { name: "usb-gadget0", is_attached: true } to Some(Udc { name: "4100000.udc-controller" }) Custom function at /sys/kernel/config/usb_gadget/usb-gadget0/functions/ffs.usb-gadget0-0

However, Windows is still unable to recognize the device created by custom_interface_device.rs.

surban commented 3 months ago

Could you test with a Raspberry Pi 4 using Ubuntu 23.10 as the operating system and see if the problem occurs there as well?

zh522130 commented 3 months ago

I'm very sorry, I don't have a Raspberry Pi 4 development board. If you need any more detailed information, you can tell me the steps, and I can perform some tests. I am using an Allwinner T113-S3.

surban commented 3 months ago

I cannot help with direct debugging. However, I have verified the software using the system described above. So I suggest the best way to figure out what is wrong, is to start with a known good configuration.

zh522130 commented 3 months ago

Thank you, I will learn how to directly use the gadget to simulate the device I need later, to see if there is a problem with the hardware itself. If there are any new developments, I will reply here.