USB stack - who's done their own, and who ported one?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
thewrongchristian
Member
Member
Posts: 426
Joined: Tue Apr 03, 2018 2:44 am

USB stack - who's done their own, and who ported one?

Post by thewrongchristian »

USB is like the creationists argument about eyes. It seems just like you can't have half an eye, creating a USB stack seems to be all or nothing, you can't have half a USB stack.

Of course, just as the half an eye argument made by creationists is a logical fallacy, so too must be the corresponding half a USB stack argument. I seem to remember Windows 95 OSR2.1 having basic USB, though I don't know how complete it was. Presumably BIOS/UEFI implementations don't implement an entire USB stack either.

I was hoping my half USB stack would provide UHCI and EHCI controllers at least (that combination matches most of the hardware I have access to), and provide directly connected keyboards, mice and thumb drives, with no general hub capabilities. I wasn't going to bother with isochronous transfers at this point.

But even taking things like hubs and isochronous support out, I still have to implement sooo much just to get anything functional, that I'm just considering porting an existing USB stack (or at the least, importing USB defines from NetBSD.)

So the question for me becomes:
  • What have people who have done their own USB stack done as a half way complete implementation? Where do you draw the line in functionality?
  • Has anyone here ported an existing USB stack to their OS? What did you port?
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: USB stack - who's done their own, and who ported one?

Post by bloodline »

I’ve been thinking about writing a USB stack for a while now, as my last machine to have PS2 ports doesn’t seem to have survived my recent house move, so I need to support a more modern keyboard/mouse interface.

I initially only plan to support keyboard and mouse HID devices.
The thing holding me back is the difference in host controllers… UHCI and OHCI, which I think both have to be supported…

I’ll try and get started this weekend I guess (which I think means getting my PCI driver working too) #-o

-edit- I found watching Ben Eater’s videos about what the hardware is actually doing helpful when building my mental model of what is going on!

https://youtu.be/wdgULBpRoXk
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
klange
Member
Member
Posts: 679
Joined: Wed Mar 30, 2011 12:31 am
Libera.chat IRC: klange
Discord: klange

Re: USB stack - who's done their own, and who ported one?

Post by klange »

It has been on my TODO list for a decade now, and I've been poking at an ExpressCard xHCI controller in my laptop recently...
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: USB stack - who's done their own, and who ported one?

Post by rdos »

I built my own in x86 assembly. Or, I first built something that wasn't as good as it should have been and so I redesigned it more or less from scratch. At this point, I think I have something that works, but it was a lot of work to get it up again. I support all USB standards (UHCI, OHCI, EHCI, and XHCI), and USB 2 hubs (on EHCI and XHCI). I have a working HID class (that actually partially is in C), several USB serial drivers, two USB printer drivers, and a USB disc driver. I also have a custom USB driver for a PCB I did myself and another that we designed professionally at work.
nullplan
Member
Member
Posts: 1789
Joined: Wed Aug 30, 2017 8:24 am

Re: USB stack - who's done their own, and who ported one?

Post by nullplan »

Getting the interface right is basically all you need. I looked at seabios, and worked out the following interface:
  • The abstract "usb_pipe" is a data type containing a connection to an endpoint.
  • The host controller driver knows how to initialize the host controller, and further more knows how to send requests to pipes.
  • The hub drivers know how many ports a given hub has, how to reset a port and detect a device on a port, and also how to de-power a port.
Now you only need to implement those for XHCI (I suggest you start with XHCI, it probably being the simplest interface and the most relevant these days), the XHCI root hub, USB hubs 1,2,3, and you are basically done.
Carpe diem!
thewrongchristian
Member
Member
Posts: 426
Joined: Tue Apr 03, 2018 2:44 am

Re: USB stack - who's done their own, and who ported one?

Post by thewrongchristian »

nullplan wrote:Getting the interface right is basically all you need. I looked at seabios, and worked out the following interface:
  • The abstract "usb_pipe" is a data type containing a connection to an endpoint.
  • The host controller driver knows how to initialize the host controller, and further more knows how to send requests to pipes.
  • The hub drivers know how many ports a given hub has, how to reset a port and detect a device on a port, and also how to de-power a port.
Now you only need to implement those for XHCI (I suggest you start with XHCI, it probably being the simplest interface and the most relevant these days), the XHCI root hub, USB hubs 1,2,3, and you are basically done.
Ah, seabios, that's one I hadn't looked at. It is somewhat gratifying that seabios implements an API for hubs in basically the same manner as I currently do. Ie. The root hub is accessed via an virtual function table rather than as a virtual hub via USB requests, as the NetBSD root hubs do. The benefit of the NetBSD approach is that the root hubs act just like a real hub.

Yes, I was converging on an endpoint being the unit of addressing for requests. I've implemented a UHCI driver, on which I'm currently building some generic USB infrastructure, and I can currently enumerate the devices connected to the root hub, and get the configuration/interface/endpoint descriptors, but that's as far as I've got so far.

I have no actual machines with xHCI, so I might give that a swerve for now.
rdos wrote: I built my own in x86 assembly.
...
At this point, I think I have something that works, but it was a lot of work to get it up again. I support all USB standards (UHCI, OHCI, EHCI, and XHCI), and USB 2 hubs (on EHCI and XHCI). I have a working HID class (that actually partially is in C), several USB serial drivers, two USB printer drivers, and a USB disc driver.
I may disagree with how you handle bad sectors, but I've got to admire your effort in implementing a USB stack in predominantly assembly. The thought just gives me the willies!

klange wrote: It has been on my TODO list for a decade now.
Haha, I don't feel so bad now, that something as accomplished as PonyOS^WToaruos can come so far without USB support.

I wanted USB support mainly for the USB storage support it affords me. I want to run on real hardware, which will most likely be old netbooks and laptops, using USB storage as the primary storage medium.
bloodline wrote: I’ll try and get started this weekend...
About this time last year, I went on holiday armed with Ben Lunt's USB book, and vowed to have USB well on the way to being started. In that week, I implemented the start of my UHCI driver, and was able to do some basic port enumeration, but I was no where near anything usable.

A year passes, and I'm again on holiday in the same place, armed with the same book, and some more experience and USB knowledge (I discovered Ben Eater's youtube channel a couple of weeks ago, from which I learned quite a lot in the couple of videos I've looked at.) So far this week, I've found what I think is an optimisation bug in GCC which has been distracting me for weeks, and done some work reading and parsing the configuration descriptor that I can then use to select a driver based on the interface information contained therein, so over the next week, I hope to have at least keyboard/mouse support using boot protocol at least, and perhaps BBB storage support, but at least be in a position to start writing higher level drivers at the USB interface/endpoint level.

It was this latter bit, parsing in the nuts and bolts of descriptors, that made me question how cut down a cut down USB stack can be, but I think I may be on the right (or at least, a reasonable) track.
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: USB stack - who's done their own, and who ported one?

Post by Ethin »

I've got a question about USB stacks (I've considered writing one myself): do you truly need to implement all four HCIs? Wouldn't just xHCI work since, from what I can tell, xHCI can interoperate with EHCI, OHCI and UHCI?
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: USB stack - who's done their own, and who ported one?

Post by nexos »

Ethin wrote:I've got a question about USB stacks (I've considered writing one myself): do you truly need to implement all four HCIs? Wouldn't just xHCI work since, from what I can tell, xHCI can interoperate with EHCI, OHCI and UHCI?
In theory, yes, but you have older hardware you have to deal with that may not support xHCI
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: USB stack - who's done their own, and who ported one?

Post by Octocontrabass »

You can't use an IDE driver with an AHCI controller, but you can use an IDE driver to access a SATA disk plugged into an IDE controller.

In the same way, you can't use an xHCI driver with an EHCI (or OHCI or UHCI) controller, but you can use an xHCI driver to access a USB 2 or USB 1 device plugged into an xHCI controller.
nullplan
Member
Member
Posts: 1789
Joined: Wed Aug 30, 2017 8:24 am

Re: USB stack - who's done their own, and who ported one?

Post by nullplan »

thewrongchristian wrote:Ah, seabios, that's one I hadn't looked at.
Beware when reading seabios code: seabios is operating in non-paged 32-bit mode, and therefore writes only the low 32 bits of 64-bit addresses, and does not differentiate between physical and virtual addresses. Also, it only implements synchronous behavior, while for a multitasking OS you would want asynchronous behavior.
thewrongchristian wrote:The benefit of the NetBSD approach is that the root hubs act just like a real hub.
Exactly my point. This allows you to write a generic "enumerate" function that finds all devices everywhere.
thewrongchristian wrote:I have no actual machines with xHCI, so I might give that a swerve for now.
:shock: :shock: What is this I don't even.... but all PCs sold in the last decade or so have had one.
Ethin wrote:Wouldn't just xHCI work since, from what I can tell, xHCI can interoperate with EHCI, OHCI and UHCI?
No, it cannot. XHCI can interoperate with USB 1 and 2 devices, yes, but not the older host controllers. If the older host controllers are present, you need drivers for those to access the USB.

Gratifyingly, you don't even necessarily need OHCI or UHCI drivers to get EHCI to work. In the later days of USB 2, they realized that it is much easier to connect one USB 2 hub to the root hub, and then have the USB 2 hub handle slower connections. I have a system here that does that: It has exactly one root hub port, and that port is connected internally to a USB 2 hub chip, and all the external ports are connected to the hub chip.
Carpe diem!
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: USB stack - who's done their own, and who ported one?

Post by bloodline »

nullplan wrote:
thewrongchristian wrote:I have no actual machines with xHCI, so I might give that a swerve for now.
:shock: :shock: What is this I don't even.... but all PCs sold in the last decade or so have had one.
As long as QEmu supports an xHCI controller then I have a hope of developing a driver for it :)
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: USB stack - who's done their own, and who ported one?

Post by rdos »

nullplan wrote:Getting the interface right is basically all you need. I looked at seabios, and worked out the following interface:
  • The abstract "usb_pipe" is a data type containing a connection to an endpoint.
  • The host controller driver knows how to initialize the host controller, and further more knows how to send requests to pipes.
  • The hub drivers know how many ports a given hub has, how to reset a port and detect a device on a port, and also how to de-power a port.
Now you only need to implement those for XHCI (I suggest you start with XHCI, it probably being the simplest interface and the most relevant these days), the XHCI root hub, USB hubs 1,2,3, and you are basically done.
Yes, the most important initial decision is how the generic USB interface looks like, and how hubs are viewed. I didn't get this right the first time, and so I felt I needed to redo it, which was a lot of work (not to mention to get all old installations to work again).

Initially, I viewed hubs as a specific type, but in the current implementation, a hub acts like an additional USB host controller, which I think is optimal. In the new API, I have a special control-type API which handles in and out on the control pipe. Initially, I handled this with generic functions, but it makes devices much easier if you can just send the parameters and let the USB API construct the packets. Also note that for XHCI, some control exchanges are done by XHCI itself which you need to do with control transfers for the other host controllers (addressing). For bulk & interupt pipes, I have one interface for reading and another for writing. For reading you typically want to queue a number of packets in a ring, and get a signal when one of them is done. You then read it and reinsert it into the ring. Write is better done with "post" which just queues the request on the transfer ring.

I also think you should decode error conditions for every package, and send error messages to an event handler so the application can see problems with USB devices. A USB reset function also is more or less indispensible, and can be interested into devices when they misbehave. Many USB errors, but particularly stall needs attention. I automatically do USB reset on all USB errors.
User avatar
Quaker763
Posts: 17
Joined: Sun Mar 08, 2015 5:32 am
Location: Straya

Re: USB stack - who's done their own, and who ported one?

Post by Quaker763 »

I wrote the original USB stack (Host Controller Driver and basic USBD) for SerenityOS after doing quite a bit of research. It can currently detect device attach and detach, and handle hub connects to a root UHCI port. I wrote a small `lsusb` clone so that you can see what devices are currently on the bus. Reading the spec helped quite a bit, but it mostly came down to experimentation and not being afraid to mess up. Most people seem to have the misconception that writing a USBD/Host Controller stack is extraordinarily difficult, but imho the biggest hurdle is wrapping your head around how all of the structures mesh together, and how your code should be structured, because the amount of documentation is somewhat astronomical and very technically meaty. The UHCI schedule can be a bit of a brain tickler too, though @BenLunt 's book is a fantastic resource for this.

This website also helped when it came to understanding how the transfers are physically performed "on the wire": https://www.beyondlogic.org/usbnutshell/usb1.shtml

In case you're curious here's the source for it. Feel free to take some inspiration from this if you'd like to write your own :)
https://github.com/SerenityOS/serenity/ ... el/Bus/USB
klange wrote:It has been on my TODO list for a decade now, and I've been poking at an ExpressCard xHCI controller in my laptop recently...
Considering you got SMP working on your lunch-break, I doubt this would present much of a challenge for you ahahaha.
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: USB stack - who's done their own, and who ported one?

Post by nexos »

Quaker763 wrote:Considering you got SMP working on your lunch-break, I doubt this would present much of a challenge for you ahahaha.
I know! My previous 2 OSes ended at SMP. I personally dread that more then I do USB / ACPI. SMP is a pain to get right, and I certainly haven't yet. But I'm doing it again! About USB, that's way far back on my todo list, as I am still early in the bootloader. But, I am going to write my own USB stack, as whats the point of using somebody else's code. I am going to focus on xHCI at first, however, and then work to add UHCI, OHCI, and EHCI. Hubs seem like their going to be a pain, but I am in no rush :)
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: USB stack - who's done their own, and who ported one?

Post by h0bby1 »

I made my own usb drivers, its still has basic support but has HID and usb 1.

https://gitlab.com/h0bby1/micro-kernel/ ... /usb_bus.c
Post Reply