Hi!
I've come far enough on my USB driver work that I'd like to
put what I've got into the tree fairly soon (within a month
or two), so I'd really like some feedback. If you are at all
interested please have a look and tell me what you think.
Note that USB is a fairly complicated beast and if you don't
have some basic USB knowledge you can't expect to gain it from
reading my code. :-)
If you want to study the code start at www.carlstedt.se/~augustss/usb.html
Here's an executive summary:
What we have:
* A UHCI (the Intel standard) host controller driver.
+ A OHCI (everyone else's standard) host controller driver.
* A host controller independent framework for handling the
devices. This framework presents a mostly USBDI compliant
interface to the drivers.
+ Support for all kinds of transfers (control, interrupt, bulk,
and isochronous).
* Power budgeting.
+ Bandwidth budgeting.
* A hub driver.
* A mouse driver.
* A keyboard driver for keyboards supporting the boot
protocol.
* A generic HID (Human Interface Device) driver for
those devices that do not have a special driver.
+ A totally generic driver to handle leftover devices.
+ An audio driver.
[The + means work in progress.]
What we don't have:
- Proper handling of devices that are disconnected. NetBSD lacks
the functionality for this.
- Suspend/resume handling. I think this is simply a matter of
sitting down and writing some code.
- A printer class driver.
- A communication class driver.
- Drivers for a lot of proprietary devices.
- Loadable device drivers.
Here's an overview of the code:
The NetBSD USB driver is done in several layers (just like SCSI
and PCMCIA).
The following header files are derived from the USB specs and
are used by kernel and user code.
Source code:
sys/sys/usb.h
sys/sys/usbhid.h
First we have the host controller layer (cf. SCSI controllers and
PCMCIA controllers). The host controller is responsible for
handling the hardware on the host side. There are two standards
OHCI and UHCI and there is support for both of them. This layer
presents a uniform API for the next layer and also emulates the
root hub.
Source code:
sys/dev/usb/ohci.c
sys/dev/usb/uhci.c
The host controller attaches to some bus (most likely PCI) and that
bus attachment is broken out into separate files.
Source code:
sys/dev/pci/ohci_pci.c
sys/dev/pci/uhci_pci.c
Attaching to the host controller is the USB "bus" (cf. scsibus? and
pcmcia?). The devices (you'll probably only have one) called usb?.
This layer handles all kinds of functionality that is common to all
USB devices, e.g., getting various kind of descriptors, power
budgeting, part of bandwidth budgeting ...
The interface to the device layer follows USBDI (which is the
slowly emerging standard for USB device drivers) fairly well.
Source code:
sys/dev/usb/usb.c
sys/dev/usb/usb_quirks.c
sys/dev/usb/usb_subr.c
sys/dev/usb/usbdi.c
sys/dev/usb/usbdi_util.c
Next is the device driver layer (cf. SCSI devices and PCMCIA devices).
It contains code for handling the actual USB devices.
So far there are only a few drivers:
Hub driver. There must always be a hub driver since all USB systems
have at least one hub (the root hub). The hub driver is responsible
for connecting and disconnecting devices and also handles to bus
enumeration and probe/attach. Even though devices physically
attach to a hub the logical attachment is still to `usb?'
sys/dev/usb/uhub.c
Mouse driver. Supports any (reasonable) USB mice.
Not implemented yet: attaching wscons mouse.
sys/dev/usb/ums.c
Keyboard driver. Supports USB keyboard that speak the boot protocol.
Not implemented yet: attaching wscons keyboard.
sys/dev/usb/ukbd.c
Generic HID (Human Interface Device). Handles HID device (mouse,
keyboard, joystick, monitors, LEDs, buttons, game controllers etc.)
that do not have any special driver.
sys/dev/usb/uhid.c
More drivers are on their way.
There are actually two kind of USB devcie driver, device drivers
and interface drivers. A device driver recognizes a USB device as
a whole unit (could be based on product/vendor codes, but could
also just be based on the device class). An interface driver
attaches to a specific interface on a device (of which there may be
many) based on the interface class. The hub driver is a device
driver and the rest are interface drivers. So a physical USB device
which is a keyboard with a built in touch pad would present two
interface and it would get both a keyboard driver and a mouse driver
attached to it.
So this is how the attachment could look
uhci0 at pci0 Host controller
usb0 at uhci0 The "bus"
uhub0 at usb0 Root hub
uhub1 at usb0 Other hub
ums0 at usb0 Mouse
ukbd0 at usb0 Keyboard
uaudio0 at usb0 Speakers
audio0 at uaudio0
uhid0 at usb0 Joystick
uhid1 at usb0 ...
In /dev some new devices are needed:
/dev/usbN The device the usbd demon talks to for
handling connect and disconnect.
/dev/uhidN Generic HID devices, supports reading and
writing to the device as well as ioctl
to get descriptors.
Currently (goes away with wscons) there are also
/dev/umsN
/dev/ukbdN
-- Lennart