Page 1 of 1

USB Keyboard Input?

Posted: Fri Feb 19, 2021 4:35 pm
by Peemard
Hi! Right Now I am around 3 days into my OS framework, and have all of the basics, including (but not limited to :P )

--

- A basic kernel
- A Global Descriptor Table
- Hardware Interrupts
- PIC Communication
- Interface Drivers (only Ps/2 keyboard at the moment)

--

I am trying to get USB keyboard input configured with it and was hoping somebody could direct me towards resources for doing this in C++.
My assumptions are that I'll have to write some form of HID Driver for generic USB communication, and then build off of that so I can actually read & use the input.
Any help would be immensely appreciated!!

Re: USB Keyboard Input?

Posted: Sat Feb 20, 2021 7:39 pm
by Octocontrabass
To start out, you need to enumerate the PCI bus to find the USB host controllers. You might also want to find the ACPI MCFG table so you can use the PCIe memory-mapped configuration space, if it exists.

I've heard that XHCI is the most reasonable of the four USB host controller standards, so if you can find a VM that emulates it, that's probably the best starting point. (Yes, there are four different types of host controller. You'll need to implement drivers for all four if you want complete USB support.)

Since you're new here, you might also want to take a look at this post.

Re: USB Keyboard Input?

Posted: Sat Feb 20, 2021 8:34 pm
by thewrongchristian
Peemard wrote:Hi! Right Now I am around 3 days into my OS framework, and have all of the basics, including (but not limited to :P )

--

- A basic kernel
- A Global Descriptor Table
- Hardware Interrupts
- PIC Communication
- Interface Drivers (only Ps/2 keyboard at the moment)

--

I am trying to get USB keyboard input configured with it and was hoping somebody could direct me towards resources for doing this in C++.
My assumptions are that I'll have to write some form of HID Driver for generic USB communication, and then build off of that so I can actually read & use the input.
Any help would be immensely appreciated!!
Not a subject anyone could reasonably cover in a forum post.

USB is a huge topic, and you first have to write a device driver to talk to the host controller interface, which is no mean feat in itself. Then you have to build on top of that your generic USB functionality, then on top of that you layer your HUD driver, then you get to your keyboard driver.

The author of this book frequents these forums. I can recommend this book, I've not yet found a web based source that matches it in detail.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 5:52 am
by rdos
Octocontrabass wrote:To start out, you need to enumerate the PCI bus to find the USB host controllers. You might also want to find the ACPI MCFG table so you can use the PCIe memory-mapped configuration space, if it exists.

I've heard that XHCI is the most reasonable of the four USB host controller standards, so if you can find a VM that emulates it, that's probably the best starting point. (Yes, there are four different types of host controller. You'll need to implement drivers for all four if you want complete USB support.)
There are USB hubs too, sometimes built into the PC. :-)

I wouldn't say that XHCI is the most reasonable of the four USB controllers for a newbie. XHCI is by far the most complex USB controller. If I had a choice, I'd use OHCI or UHCI instead. These specifications are far easier to read & implement.

When it comes to HID, selecting the boot protocol makes the most sense for a newbie, and doesn't require a full-blown implementation of HID, which is super-complex too.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 8:38 am
by iansjack
TBH, I wouldn't put USB support as a priority for an OS that is 3 days old. Like networking it is rather an advanced topic and there are a host of easier, interesting things to implement first. Multiple processes and scheduling, user processes, disk access and file systems, etc.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 1:02 pm
by Peemard
iansjack wrote:TBH, I wouldn't put USB support as a priority for an OS that is 3 days old. Like networking it is rather an advanced topic and there are a host of easier, interesting things to implement first. Multiple processes and scheduling, user processes, disk access and file systems, etc.
True, and I 100% agree with that, but I really want to be able to occasionally test my operating system off of actual hardware instead of a VM, and I don't really have any ps/2 keyboards lying around and my pc mb doesn't have ports for it.so even if I wanted to I couldn't do it.

I guess I wouldn't be entirely opposed to just using a VM for now though.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 1:06 pm
by BenLunt
Hi guys,

Peemard, first, don't be discouraged by the comments that you might not wish to start so early in to USB. Though I agree with the comments of it being difficult and probably not something a three day old should be starting with, I will tell you that the USB was my most enjoyable part of the whole project. Therefore, if you wish to start USB now, for the joy of it, this would be a perfect time to do so, though keep in mind that a successful implementation will need other parts of the OS system already implemented.

As for which controller to start with, I have mixed feelings about this. The UHCI and OHCI were released first, nearly 30 years ago though. OHCI in September of 1995 and UHCI two months later. Though most modern emulators will still support these two controllers, most hardware will not. xHCI, announced in September of 2007, is still 15 years old, though USB version 3.2 which takes advantage of xHCI, is more recent, only 5 years ago.

To decided which controller you would like to start with, ask yourself one question: Will I be testing my code on real hardware or using emulation exclusively?

If your answer is emulation, I suggest the UHCI and OHCI as your beginning. One controller was built to use the hardware with little software intervention, while the other was completely the opposite. It would be a good learning experience to code for both of them to learn the difference. Also, the Bochs emulator, which I'm glad to have had a big part of during that time, will produce a nice debug log file, which is quite helpful in the beginning of your development.

Next, in my humble opinion, completely skip the EHCI. Again, IMHO, it was a hodge-podge piece of hardware put together to allow higher speed devices, but still be backward compatible with UHCI and OHCI. Other than reading over the subject, getting an idea of what it does, I would completely skip the EHCI.

xHCI, in my opinion, finally got the interface correct. xHCI will support all speeds using this one interface. However, to do so, unlike the UHCI and OHIC where there was a single bit indicating the different speed, xHCI needs quite a bit of setup before allowing that specific speed.

As mentioned before, you also have to watch out for hubs, both external and "internal", the internal more commonly known as RMHs, or Rate Matching Hubs.

A note about these RMHs: The EHCI only handles High Speed devices. The EHCI will *not* communicate with a Full or Low speed device. Therefore, the EHCI's card was designed to have companion controllers, either OHCI or UHCI, to pass on the Full- and Low-speed device traffic. Therefore, each EHCI adapter card had all of the EHCI components *and* at least one, though usually more than one OHCI or UHCI component. These got a little expensive. Now, since an External Hub can have any speed device plugged in to it, the Hub has to handle the speed difference. Therefore, if you plug a High-Speed Hub into an EHCI and then plug all other devices into the HUB, the EHCI adapter card no longer needs the added UHCI or OHCI components. Even better, if you place the external hub directly on the EHCI adapter card, this guarantees that the lower speed controllers are no longer needed. This dramatically decreased the cost as well as the circuity of the EHCI adapter card. The drawback for you and I, as the developer, it is now a requirement that we have a HUB driver in our USB tool box. We can't even get to the Low-speed mouse without it. Another reason to completely skip the EHCI.

As mentioned before, you will also need to have a working PCI parser, to even find the USB controller, let alone know what to do with it. This means you need to study the PCI as well.

With thanks, and as mentioned, my book covers this from the beginning. It starts by describing the PCI enough to find the USB controllers, determine which type it is, and how to find other information about the controller. The next section shows how to setup and use each of the four controllers, each part independent of another. The next section shows how to enumerate different devices in general while the next section goes into detail about types of devices, such as Mice, Keyboards, MSDs (Mass Storage Devices) such as thumb drives, External Hubs, Printers, etc.

Again, I believe the USB was/is the most enjoyable part of this hobby of ours and highly recommend that you put it high on your TODO list.

Though, lately I have been quite busy with other things, I do try to frequent this forum at least once a day and give help when needed. There are others here with substantial knowledge of the USB, that can help as well. Feel free to post your questions.

Thank you and above all, enjoy the process of this hobby we have.
Ben
- http://www.fysnet.net/the_universal_serial_bus.htm

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 1:55 pm
by rdos
BenLunt wrote: Peemard, first, don't be discouraged by the comments that you might not wish to start so early in to USB. Though I agree with the comments of it being difficult and probably not something a three day old should be starting with, I will tell you that the USB was my most enjoyable part of the whole project. Therefore, if you wish to start USB now, for the joy of it, this would be a perfect time to do so, though keep in mind that a successful implementation will need other parts of the OS system already implemented.
Perhaps the most important thing to think about before you design an USB stack is to define a common interface that will work with all the USB standards and HUBs. Without that, it would be a bit like skipping the virtual file system layer and staring to use FAT (or other FS) directly in your file & directory interface.

This is not a simple as it might sound, and I actually had to do a complete rewrite to make this optimal and stable. The specifications simply are not clear anough about what is used and how. For instance, it's not described that SETUP and STATUS messages are only used in a very specific context on the control pipe, and that it is better to define a specific function for this than to allow the use of these in a more general context.

Also, I've failed to use the OHCI completed list twice now, and I start to suspect that the Windows drivers isn't using it either, and that it actually will not work on many OHCI implementations. The best method to verify completion of commands appears to be to check the schedule links, and make sure everything completed with OK status. Stall is also a bit of a problem. If it happens on the control pipe you can just ignore it, while if it happens somewhere else, it's a fatal error that needs a USB reset. On XHCI, it's a lot more complex on the control pipe since you need to restart the pipe.

The OHCI & UHCI standards also have problems with IRQs. For XHCI (and EHCI) you can usually use MSI or MSI-X, while this often is not supported on OHCI and UHCI. To find the IRQ numbers requires ACPI, and on some even this isn't enough to get the IRQs to work. Another possible strategy is to create a 1 ms timer instead and use that to check the schedules for completion.
BenLunt wrote: Thank you and above all, enjoy the process of this hobby we have.
Ben
- http://www.fysnet.net/the_universal_serial_bus.htm
Even if I know USB quite extensively by now, I probably should buy & read you book. :-)

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 2:05 pm
by Octocontrabass
Peemard wrote:I really want to be able to occasionally test my operating system off of actual hardware instead of a VM, and I don't really have any ps/2 keyboards lying around and my pc mb doesn't have ports for it.
Try it anyway! Most PC hardware emulates a PS/2 keyboard (very poorly), so it might work.

You can always come back and do proper USB drivers later.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 2:15 pm
by rdos
Octocontrabass wrote:
Peemard wrote:I really want to be able to occasionally test my operating system off of actual hardware instead of a VM, and I don't really have any ps/2 keyboards lying around and my pc mb doesn't have ports for it.
Try it anyway! Most PC hardware emulates a PS/2 keyboard (very poorly), so it might work.

You can always come back and do proper USB drivers later.
Exactly. If you don't try to access the USB hardware, chances are the PS/2 emulations might work. Sometimes there are BIOS settings that allows for turning it on or off.

Sometimes this can be a problem too. If the BIOS handoff is not done properly for the USB chip, chances are the PS/2 emulations are still active and your USB setup is not.

When I buy new hardware I always try to get a motherboard that has a physical PS/2 connector. This makes sure that I can boot it and get the keyboard to work. With only USB keyboards, the USB driver might fail and then I have no easy way to debug why the USB stack doesn't work.

Also, many portable PCs have internal PS/2 connectors, and so might be a better alternative than a motherboard without a PS/2 connector. Although, many portable PCs also lack a network card with an Ethernet connector, and only have WiFi, and few WiFi chips have public documentation. This means that when you want to do the network part, you will need to use USB network adaptors, which are also poorly documented and complex.

Re: USB Keyboard Input?

Posted: Sun Feb 21, 2021 3:37 pm
by BenLunt
rdos wrote:Perhaps the most important thing to think about before you design an USB stack is to define a common interface that will work with all the USB standards and HUBs. Without that, it would be a bit like skipping the virtual file system layer and staring to use FAT (or other FS) directly in your file & directory interface.

This is not a simple as it might sound, and I actually had to do a complete rewrite to make this optimal and stable. The specifications simply are not clear [e]nough about what is used and how. For instance, it's not described that SETUP and STATUS messages are only used in a very specific context on the control pipe, and that it is better to define a specific function for this than to allow the use of these in a more general context.
I totally agree. Within the device layer of my system, a device can be of any type and still be used exactly the same. For example, a block device can be sent the READ_SECTOR command and it will read a count of sectors, returning a buffer filled with data. The caller has no idea what type of device it called, other than it is a block device. The actual determination that it is a USB device is determined in a lower layer. This is a good point.
rdos wrote:Also, I've failed to use the OHCI completed list twice now, and I start to suspect that the Windows drivers isn't using it either, and that it actually will not work on many OHCI implementations. The best method to verify completion of commands appears to be to check the schedule links, and make sure everything completed with OK status.
I don't use the completion list either. I do pretty much as you describe here. However, I cannot confirm or deny that the completion list is buggy in either case. It has been a while since I did anything with the OHCI though, so I cannot remember if I had problems with it or not.
rdos wrote:Stall is also a bit of a problem. If it happens on the control pipe you can just ignore it, while if it happens somewhere else, it's a fatal error that needs a USB reset. On XHCI, it's a lot more complex on the control pipe since you need to restart the pipe.
This is not exactly the case. If the stall is on the Control Pipe, you don't necessarily ignore it. The stall remains until the next SETUP packet is found. Since the Control Pipe uses SETUP packets almost exclusively, then an ignore of the stall is almost correct. However, if the stall happens during an IN or OUT packet, you still need to remove the remaining scheduled packets before you sent the next SETUP packet.

As for a USB reset on other pipes, this is not the case. A stall on a BULK Pipe simply needs a CLEAR_STALL sent on the Control Pipe, informing the device that you have received the stall indication and have reset the Toggle bit status for the next bulk transfer. This is not considered a fatal error and a USB reset is not required. In fact, all other Bulk Pipes can continue to send and receive data during this process, though usually some Bulk transfers rely on other Bulk transfers, namely BBB transfers.
rdos wrote:The OHCI & UHCI standards also have problems with IRQs. For XHCI (and EHCI) you can usually use MSI or MSI-X, while this often is not supported on OHCI and UHCI. To find the IRQ numbers requires ACPI, and on some even this isn't enough to get the IRQs to work. Another possible strategy is to create a 1 ms timer instead and use that to check the schedules for completion.
This is agreed. I have one test machine that even after using ACPI to retrieve the IRQ number, it still does not use the correct IRQ. Either I am missing something or it is a special case and I need a special, hardware specific, technique to retrieve the correct IRQ.

Interesting to know, though, I have yet to implement MSI and MSI-X interrupt in my system. This is something on my TODO list, but have yet to do it. :-)
BenLunt wrote:Even if I know USB quite extensively by now, I probably should buy & read you book. :-)
From a (long time?) fellow coder, I would be honored to receive your feedback.

Thank you,
Ben