Exploring USB at the Hardware/Software Interface
Instructor:
Allan Cruse
contact: cruse@usfca.edu
Synopsis:
This website documents our development of some classroom materials
intended
to support a future course for advanced students in
Computer Science
which will
investigate hardware-level programming of the UHCI and
EHCI Universal Serial
Bus Host Controllers commonly found in today's
Intel-based personal computers.
We also explore programming of an OHCI USB Host Controller,
made available
as an 'add-in' to our Intel-based PCs.
Familiarity with the Linux operating system and the GNU development tools,
and
with the x86-CPU architecture and instruction-set, will be assumed
here. See our
lecture-slides and demo-programs from courses
CS 630 and CS 635
for relevant
details regarding these prerequisite topics.
Initial topics:
- How to program the EHCI Hi-Speed USB 2.0 Debug Port
- Programming of Intel's EHCI and UHCI Host Controllers
- Programming an add-in card's OHCI USB Host Controller
- Exploring the eXtensible Host Controller (xHCI) for USB 3.0
     
This page is under continuing construction
Resources
- Industry document:
USB2 Debug Device: A Functional Device Specification, Revision 0.9
- Product description:
NET20DC-USB Hi-Speed USB 2.0 Host-to-Host Debug Device
- Industry document:
Enhanced Host Controller Interface Specification for Universal Serial Bus
- Industry document:
Enhanced Host Controller Interface (EHCI) Programmer's Reference Manual
- Industry document:
Intel I/O Controller Hub 9 (ICH9) Family Datasheet
- Industry document:
Universal Host Controller Interface (UHCI) Design Guide
- Industry document:
Open Host Controller Interface (OHCI) Specification for USB
- Industry document: "Section 2:
Overview of the Open Host Controller Interface (OpenHCI) Specification",
in "SH7760 Group USB Host Module Application Note", Renesas Electronics
(rev 1.00), October 2003
- Product description:
Sonnet Allegro Express 5-port USB 2.0 PCIe Adapter Card
- Product description:
Delcom Products, Inc. USB HID Visual Signal Indicator
- Product description:
Foresight Systems LLC Pertelian x2040 LCD Display
- Product description:
TotalPhase, Inc. Beagle USB 480 Protocol Analyzer
- Industry document:
Extensible Host Controller Interface (xHCI)for USB 3.0
- Product description:
Buffalo Technology, Inc. USB 3.0 PCI Express Interface Card
- Product description:
ADATA Nobility Series N005 USB 3.0 Flash Drive
- Industry document:
USB Mass Storage Class: Bulk-Only Transport Specification
(Rev 1.0, 1999)
- Product Description:
Logitech Stereo USB Laptop Speaker Z205
- Industry Document:
USB Device Class Specification for Audio Devices ( Rev 1.0, 1998)
- Product description:
Logitech, Inc. Webcam C200
- MathPages article:
Cyclic Redundancy Checks, by Kevin Brown
- Professor Ralf Brown's Interrupt List online at
http://www.ctyme.com/rbrown.htm
- Quick reference to
USB Keyboard Scancodes
(from The Linux Keyboard HOWTO, by Andries Brouwer)
Readings
Systems Software
- Utility program: mmake.cpp
(a tool for compiling our own Linux 2.6 kernel modules)
- Utility program: newproc.cpp
builds the skeleton for an LKM that creates a '/proc' file
- Utility program: fileview.cpp
(a navigation tool for viewing the contents of binary files)
- Utility program: dynaview.cpp
offers a 'dynamic' view of volatile text in a pseudo-file
- Linker script: ldscript
allows the GNU linker 'ld' to produce a 'binary-format' executable
- Boot loader: usfcsipl.s
loads demos we write for the 'Pre-boot eXecution Environment'
Handouts
- Kernel module: ajay.c
a character-mode driver for the 'NET20DC' Debug Cable by Ajays Technology
             
             
             
             
             
- HowTo advice: Identifying your Debug Port
using our 'ajay.c' driver and our 'dynaview.cpp' application
- Demo program: ajayinit.cpp
shows how a program uses our 'ajay.c' module to access the Debug Port
- Demo program: ajayxfer.cpp
lets a user send a message via the Debug Port, then shows the response
- Demo program: ajayecho.cpp
waits to receive a message sent from the link partner, then sends it back
- Demo remarks: author's commentary
regarding our 'ajayxfer.cpp' and 'ajayecho.cpp' programs (above)
- Demo program: ajayseek.cpp
shows how to discover our Debug Peripheral's current 'device-address'
- Demo program: uhciboot.s
allows us to see the contents of each UHCI controller's registers at 'startup'
- Demo program: ehciboot.s
allows us to see the contents of each EHCI controller's registers at 'startup'
-- revised on 7/29/2010
- Kernel module: ehci.c
a character-mode driver supporting user-mode EHCI programming experiments
-- revised on 12/29/2010
- Demo program: dev2desc.cpp
illustrates programming of the EHCI controller to do a 'control transfer'
-- correction on 3/29/2010
- Demo program: findajay.cpp
reports the NET20DC Debug Peripheral's assigned USB device-address
-- revised on 4/02/2010
- Utility output: USB descriptors for NET20DC device
produced by Linux's 'root# /sbin/lsusb -v' command
- Demo programs: ajayxmit.cpp
and ajayrecv.cpp
illustrates transfer of textfiles via the 'NET20DC' cable
-- revised on 4/29/2010
- Kernel module: iopl.c
for showing how we transparently grant I/O-port access to user-mode programs
- Demo program: openuhci.cpp
illustrates the modification of IOPL upon opening '/dev/uhci' device-file
- Kernel module: uhci.c
a character-mode driver supporting user-mode UHCI programming experiments
-- revised on 10/07/2011
- Demo program: tryioctl.cpp
a test-program to show how an application learns UCHI i/o-port addresses
- Demo program: tryuhci.cpp
illustrates programming of a UHCI controller to perform a 'control transfer'
-- revised on 4/06/2010
NOTE: Remote login is recommended when testing this demo
on a system that uses a USB keyboard
             
             
             
             
- Demo program: usbkeybd.cpp
illustrating UHCI 'Interrupt Transactions' for operating a USB keyboard
- Demo program: usbmouse.cpp
illustrates UHCI programming to operate a Dynex USB optical mouse
             
             
             
         
       
- Demo program: usbswipe.cpp
uses UHCI to operate a Swipe Card Reader with 'keyboard emulation'
- Demo program: ajlocate.cpp
finds the 'NET20DC' peripheral's device-address using UHCI controllers
- Demo programs: ajayfstx.cpp
and ajayfsrx.cpp to transfer textfiles
over 'NET20DC' cable using UHCIs
- Kernel module: ajfschar.c
this 'character-mode' device-driver supports transfers of text at 'Full-Speed'
-- experimental version
- Demo programs: xmitajay.cpp and
recvajay.cpp were useful for testing
text-transfers with 'ajfschar.c'
- Kernel module: ohci.c
a character-mode driver supporting user-mode OHCI programming experiments
-- revised on 10/07/2011
   
             
             
- Demo program: ohciblue.cpp
to illustrate direct hardware-level programming of a USB OHCI controller
-- revised on 8/15/2011
- Demo program: ohcipert.cpp
showing the steps needed to send some text to the Pertelian x2040 LCD
- Demo program: ohciboot.s
allows us to see the contents of each OHCI controller's registers at 'startup'
- Demo program: usleep.s
tests a 'boot-time' procedure that executes a delay of microseconds duration
             
             
             
           
- kernel module: buffalo.c
a character-mode driver which acquaints us with most major xHCI registers
-- revised on 9/30/2010
- Demo program: xhciboot.s
allows us to view the contents of most XHCI controller registers at 'startup'
- Kernel module: usb3.c
a character-mode driver supporting user-mode XHCI programming experiments
- Demo program: xhcidemo.cpp
shows XHCI programming that turns on/off our Delcom Visual Indicator
-- revised on 12/3/2010
- Demo program: redlight.s
shows 'boot-time' XHCI programming needed to operate our Delcom device
             
             
             
           
- Demo program: tryadata.cpp
shows programming of a USB Mass Storage Class 'INQUIRY' command
- Demo program: usbcrc16.cpp
showing the steps for computing a USB Data-Packet's 16-bit CRC-field
- Demo program: tokencrc.cpp
showing detailed steps for calculating a USB token-packet's 5-bit CRC
- Sample output: tokencrc.out
lets users view an example of the output produced by our 'tokencrc' utility
             
             
             
             
     
- Demo program: ohcitone.cpp
illustrates programming of OHCI isochronous transfers to sound a tone
             
             
             
           
Announcements
- We believe that our
'ajayxmit.cpp' and
'ajayrecv.cpp' demo-programs
should serve to demonstrate that
the 'NET20DC' High-Speed USB 2.0
Debug Cable (from Ajays Technology LLC) is able to function as
a
general-purpose (albeit half-duplex) data-transfer facility, and thus is
not merely a tool for debugging.
We hope this work dispels an
apparent misconception, evident from comments by several developers
posted online, that the 'NET20DC' peripheral has to be used in conjunction
with the EHCI controller's
'Debug Port' -- and hence must be attached
only to a particular USB outlet, and can only transfer data
in
small-size packets that each carry a maximum of 8 data-bytes. As
our example shows, one can use
the standard-size high-speed bulk-transfer
packets (512 data-bytes per packet) and can conveniently
do transfers
no matter which outlets the cable is plugged into.
                 
-- Allan Cruse, 11 April 2010.
- We added the 'Clear_Feature(ENDPOINT_HALT)' transaction to our
'ajayxmit.cpp' and 'ajayrecv.cpp'
demo-programs in order to effect
a reset of the relevant EndPoint's data-toggle each time these demos
are reexecuted -- after discovering that the data-toggle bits were
evidently in an 'unsynchronized' state
for subsequent executions
after textfiles of certain sizes had been successfully transferred,
resulting in
omission of initial file data on the next transfer
attempt.
               
             
-- Allan Cruse, 26 April 2010.
- Previous authors have published examples of programming the Delcom
USB Visual Signal Indicator
which rely on the device-driver software
in commercial and open-source operating systems, thereby
obscuring
details of the underlying USB communication protocol, but we have not found
other work
in which the USB Host Controller is directly programmed
at the hardware-level to control the Delcom
device, and
thereby to expose details of the USB hardware/software interface, which
is what we seek
to accomplish by pursuing these educational
explorations.
       
             
-- Allan Cruse, 23 June 2010.
             
             
             
             
- An advantage of writing custom code to control a USB peripheral
device through direct hardware-level
programming of the USB host
controller, rather than relying on generic device-drivers packaged with
a
commercial operating system whose internal algorithms are not
made known, can be seen quite starkly
when working with a
Pertelian x2040 LCD display device (from Foresight Systems LLC) and a
Protocol
Analyzer, such as the Beagle USB 480 (from from TotalPhase, Inc.)
pictured above. For example,
our
'ohcipert.cpp' demo-program displayed the same 'Welcome'
message as Windows 7 did during startup,
but without persistently
redrawing that message, multiple times per second, to no perceptible
effect or
benefit, yet consuming unnecessarily an immense amount
of USB bandwith. Ordinary users probably
would not be aware of what
potentially is causing a slowdown in other competing bus traffic, but when
systems programming students are armed with these hardware-level
insights, they will readily think of
ways the device-driver software
might be redesigned to allow greater overall system efficiency.
                     
                     
                     
                     
                     
                   
-- Allan Cruse, 8 July 2010.
- We have found that the Linux 'ehci-hcd' device-driver interferes
with some of our own programming
explorations of the EHCI hardware, in
that its 'interrupt-handler' and 'watchdog-timer' routines seize
control and perform modifications to registers and data-structures at
unexpected times. Hence, as a
workaround for that problem, we
decided to recompile our kernel without the 'ehci-hcd' driver built in,
but as a 'module' which could be removed when desired.
However, removing the 'ehci-hcd' module
has the undesirable side-effect
of clearing the BME-bit (bit 2: Bus Master Enable) in the command-
word (at offset 4) of the EHCI controller's PCI Configuration Space (as
can be observed by viewing
the '/proc/pci' pseudo-file created in our
'ehci.c' or 'ajay.c' kernel-modules). Without its Bus Master
capability
being enabled, of course, the EHCI hardware cannot fetch descriptors or
transfer data. So
we have revised our 'ehci.c' module to include
an 'open()' driver-method containing code that insures
the
BME-bit will get set to 1 during any use of our driver by an
application-program.
                     
                     
                     
                     
                     
         
-- Allan Cruse, 12 August 2010.
- Regarding 'backward compatibility' of USB 3.0, we wondered whether
our Beagle USB 480 Protocol
Analyzer (from Total Phase, Inc) would
continue to work with USB 2.0 devices when we attached its
cable to
a port on our Buffalo USB 3.0 PCI-e adapter-card. Yes, it worked
just fine when we tried this
today, and allowed us to observe the
usual USB 2.0 'Set_Address' command being sent by the xHCI
controller
to a Low-Speed device when our driver triggered the USB 3.0
'Address Device' command,
and to observe as well that this 'side-effect'
gets inhibited when we set the command-TRB's BSR-bit.
                     
                     
                     
                     
                     
         
-- Allan Cruse, 4 October 2010.
- Today we discovered that the newest release of the Linux kernel
(version 2.6.36) includes a change,
after nearly 20 years, to the
'ioctl()' interface utilized by character device-drivers (such as
our 'uhci.c',
'ehci.h' and 'ohci.c' modules). All drivers which
implemented their own 'ioctl()' method will now need
revisions
in order to be successfully compiled for kernel 2.6.36. The
'struct file_operations' data-type
now includes a 'unlocked_ioctl()'
method which uses fewer arguments and an alternative return-value
type,
but which otherwise appears to be a suitable substitute for the former
'ioctl()' method. (But see
also the 'compat_ioctl()' method.)
                     
                     
               
-- Allan Cruse, 26 October 2010.
- While implementing some experimental programming of our Sonnet
OHCI Add-In Adapter Card, we
observed a deviation from the USB Open
Host Controller Interface Specification (version 1.0a dated
9/14/1999)
which states, in Section 4.3.3.1 (on page 33): "In no case does the
Host Controller set the
Halted bit in the ED for an Isochronous TD."
In fact our Sonnet OHCI controller DID set the Halted bit
in a pair
of EDs for Isochronous TDs.
(See our experimental program anomaly1.cpp.)
When we later
tried executing this same
experimental code on a Laptop system with an ATI OHCI controller
built-in,
we did not observe this deviation from the OHCI
specification.
At this point we have no reason to think
that this Sonnet anomaly
would adversely impact any 'normal' device-driver code; however, it is
likely
to puzzle any students who expect that actual OHCI hardware will
conform to the official specification.
                     
                     
                     
                     
                     
                     
                 
-- Allan Cruse, 18 October 2011.
Last updated on 10/19/2011