Octocontrabass wrote: ↑Fri Aug 29, 2025 3:57 pm
I haven't implemented USB yet myself, but I have to wonder if the difficulty comes from jumping directly to USB after only implementing drivers for simple things like PS/2 or IDE. It doesn't sound like it should be that much more difficult than something like NVMe or a recent Intel NIC.
It really depends on how extravagant you are going to get. As with any hardware, you can keep it a simple synchronous (single) workload or spend more effort for an asynchronous workload.
If you choose the synchronous type, it can be fairly simple. Only allow communication with one USB device at a time, though allowing multiple devices.
However, this slows things down considerably. Therefore, it is best to do an asynchronous schedule, using URBs (USB Request Blocks) in a virtual space, allowing tasks to insert and remove at will, letting the USB drivers (multiple) and layers (multiple) insert and remove at will also. This gets a lot more difficult, but is a better system.
Another thing, what controller are you going to support? UHCI, OHCI, EHCI, or xHCI, or a combination of. For learning purposes, I do recommend the UHCI and OHCI. One is designed with the software as the work horse, while the other is designed with the hardware as the work horse. IMHO, skip the EHCI altogether, and then create an xHCI driver.
The xHCI uses multiple rings, similar to some NICs, where you insert items at the beginning and the controller removes from the end, and visa-versa. In the xHCI world, this is called the Producer and the Consumer.
After you have written one or more controller drivers, you have to write another layer, one being, to keep on subject here, the HID layer. Within this layer, you have multiple sub-layers. You need to parse the HID descriptors to create a Report descriptor, as well as other items.
As you spoke of, if you have written a driver for the NVMe, with a little study time before hand, I would be confident that you could write a driver for any one of these USB controllers.
As with all hardware, the USB has its own quirks. For example, in the early years, most devices were tested with a well known commercial operating system and if it worked there, they assumed it would work everywhere. However, this particular system, no matter the device, would request the first eight bytes of the Device Descriptor (getting the max packet length for the control pipe) and then reset the device before doing it again. Some, a minute percentage, but still some devices relied upon this and wouldn't work without it.
Anyway, with much bias (so to speak), I really enjoy the USB and have done quite a bit of work with it. If you have not done much, at first, it may be anything but simple.
If you are going to build a USB system, I would suggest you get familiar with Bochs so that once you get something up and going, you can use its debugging capabilities. With all debugging set to on, it will log all interaction with the controller as well as any "attached" device.
- Ben
https://www.fysnet.net/the_universal_serial_bus.htm