USB (Universal Serial Bus)
USB connects devices in a tree whose root is a host controller. A device describes itself through descriptors: vendor and product ids, then a configuration of one or more interfaces. An interface is one function of the device, with a class, subclass and protocol that say what it is. It talks through endpoints, one-way channels IN to the host or OUT from it, beside the control endpoint 0 every device has. Each endpoint has a transfer type: control for requests, bulk for large data without timing guarantees, interrupt for small reports with bounded latency, isochronous for streams such as audio.
The name of the interrupt type misleads. A USB device has no interrupt line to the CPU and never starts a transfer: the host controller schedules every one. An interrupt IN endpoint is one the controller polls at the interval its descriptor asks for, and a device with nothing new answers that it has no data, all without the CPU. What reaches the CPU is the controller's own interrupt when a transfer completes, so the code that receives a report can run inside that handler, in interrupt context.
Hubs and enumeration are the host's side of the bus. A hub is a device with downstream ports, and the controller's root ports act as one. When a device is plugged in, the host resets its port, assigns it an address, reads its descriptors and selects a configuration, and only then offers its interfaces to class drivers.
A host controller is a PCI function whose class bytes name its programming interface, and four of them have shipped in PCs. OHCI (class 0x0C, subclass 0x03, interface 0x10) is the USB 1.1 host interface of many chipsets, AMD's and NVIDIA's among them: it drives low speed (1.5 Mb/s) and full speed (12 Mb/s) from endpoint and transfer descriptor lists it walks in memory. UHCI (interface 0x00), the USB 1.1 host of Intel and VIA chipsets, is programmed through port I/O and has no driver in Cosmos. EHCI (0x20) is the USB 2.0 host and drives high speed (480 Mb/s) only, so a full- or low-speed device plugged into one of its ports has to go elsewhere, and chipsets solved that in two ways. AMD and NVIDIA paired the EHCI with OHCI companion functions that share its ports: the EHCI gives such a port to the companion through its port owner bit, and the companion enumerates the device as its own. Later Intel chipsets put a rate matching hub, a high-speed hub soldered on the board, between the EHCI and its ports, so the slow device arrives behind that hub and its transactions are carried as split transactions, a start-split and a complete-split addressed to the hub's transaction translator, which runs the slow transaction downstream at the device's speed. xHCI (0x30), the USB 3 host, drives every speed on one controller and needs neither.
The trap is to read the socket off the node path. The port a device is plugged into decides which controller's bus it lands on, not the device: a full-speed keyboard in a USB 2 socket of an AMD board is enumerated by the OHCI companion, not by the EHCI it was plugged into, and the same keyboard sits on a root port on that board and behind the rate matching hub on an Intel one, so usb:2-1:0 on one machine and usb:1-1.3:0 on another can be the same device in the same kind of socket. A class driver sees none of this, which is why enumeration belongs to the host and hub drivers. The controller may also be the one the firmware is still driving to emulate a PS/2 keyboard when the kernel starts (firmware handoff), and every one of them reports connects and disconnects as hot-plug events.
Keyboards and mice belong to the HID (human interface device) class, whose devices normally describe their report layout in a report descriptor that the host must parse, more than a PC's firmware is expected to do. The boot protocol is the fixed alternative: an interface with subclass 1 and protocol 1 (keyboard) or 2 (mouse), once a SET_PROTOCOL request selects it, sends an 8-byte keyboard report (modifiers, a reserved byte, up to six keys held) or a mouse report of buttons, then X and Y movement.
In the driver kit, a USB node is one interface, reached through UsbAccess, whose OpenInterruptPipe hands each report to a UsbReportHandler. The handler runs in interrupt context when the controller signals completions with an interrupt (an MSI-X message on xHCI, the function's legacy line on EHCI and OHCI), and in thread context when it is polled, so it follows the interrupt handler rules either way; XhciDriver, EhciDriver, OhciDriver and UsbHubDriver hand each new device to the kit's enumeration, which a class driver never sees. See The USB access object, The host controller contract and The USB class drivers.