# USB subsystem

Dusk OS has support for the Universal Serial Bus which was initially ported
from Plan 9. It lives in [drv/usb].

The broad idea of USB is that there's a host that communicates with devices
through one or more port. A device can be a hub which itself has more ports,
each of which being able to have an attached device.

When a device is connected, it's being given an address by the host. An address
is a simple number between 1 and 127 (address 0 is special and cannot be
assigned).

Each device can have up to 16 endpoints, which are channels through which the
host can communicate with the device. Endpoint 0 is special and is the
"control" endpoint. Every USB device has a 0 endpoint and it's through this
endpoint that initial configuration of each device is done.

A computer system can have more than one host. Theoretically, each host could
have its own addressing space, but we don't do that in Dusk. The address space
is shared through all USB hosts of the system.

## Loading the drivers

The USB drivers come in three broad parts. First, there's the host driver. This
driver is specific to each chipset implementing a USB host. For example,
[drv/usb/dwc.fs] contains the driver for the DWC USB host.

Then, there're the generic host driver. Different USB hosts all have their
specificities, but they all adhere to the USB specifications, which makes them
behave in the same manner in many regards. For example, enumeration logic works
the same with all USB host. This logic is implemented in [drv/usb/usb.fs].

Lastly, there's USB device drivers. USB devices can have many different behavior
and one needs a particular driver for each type of behavior. For example, if you
want to drive a USB keyboard, you'll use [drv/usb/kbd.fs].

In a typical system, the first thing you'll want to load the driver for your
USB host first, which will typically auto-load the generic part of the USB
mechanism.

Once your host is initialized, you can do attachment detection and enumeration
with `usbwork`. This checks each port of each hub for the "present and changed"
flags and do device initialization for each newly connected device.

If you want to see USB status, you can call `lsusb`.

Then, the rest if open ended and depends on the kind of device you want to use.

## Keyboards

The keyboard driver lives at [drv/usb/kbd.fs]. This unit supplies two important
words. `usbkbd$ ( -- )` iterates through attached devices until it finds a
keyboard (class 1, subclass 3) and initialize the device as a keyboard.

Then, there's the "USBKeyboard" struct which is created through
":new ( -- kbd )" and conforms to [doc/sys/kbd]. Therefore, once you've
initialized the USB keyboard driver with "usbkbd$", you can bind it to the
system keyboard with a line that looks like:

  USBKeyboard :new rebind' keyboard
