USB enumeration is a bit complicated so I thought it'd be good to document a few of the packets...
I'm working on a stm32 USB driver in Zig (for my little Zuric project) and well it's turned out to be quite a learning process. This is on linux, I'm not sure if windows does anything differently.
When a "full speed" device is first plugged in and connected (by enabling the pulling up) linux will send a setup packet requesting the device descriptor to determine the max endpoint size.
The device needs to reply with the first part of the device descriptor.
Instead of reading the whole thing the host will send back an empty ack and then force a bus reset.
Then a it'll reset.
A few ms after the reset it will send another setup packet to set the device address.
The device then needs to send an ack response while still un addressed so the response is to addr still 0.
After the ack status is pulled the firmware needs to update the address. All future requests will be to the address it set.
The host will do another request with the new address to pull the device descriptor.
Note: When the first and second bytes are
0x80
and0x06
the 4th byte is the descriptor type (eg0x01
). See the references for the setup packet layout.
This time it will do multiple requests (as needed) to pull the entire descriptor. For full speed it will be 3 packets.
Next the host will request the device qualifier (if any). I'm not sure if this always occurs or is only based on the configuration being used.
In my case there is none so the response is a "Stall". (There happens to be a SOF packet in this screenshot, that can be ignored).
The host may retry a few times.
After that it'll the host will pull the configuration.
It needs 2 packets.
Zig is awesome at catching programming errors.
Breakpoint 1, panic (err=..., stack=<optimized out>) at startup.zig:72
72 pub fn panic(err: []const u8, stack: ?*std.builtin.StackTrace) noreturn {
(gdb) p err
$3 = {ptr = 0x8003f68 <__unnamed_98> "index out of bounds", len = 19}
(gdb) bt
#0 panic (err=..., stack=<optimized out>) at startup.zig:72
#1 0x0800245e in usb.Device.irqHandler (self=<optimized out>) at <omitted>/usb.zig:432
#2 <omitted>
#3 USB_LP_IRQHandler () at startup.zig:239
#4 <signal handler called>
...