Linux Kernel & Device Driver Programming

Ch 13 - USB Drivers

This file uses the W3C HTML Slidy format. The "a" key toggles between one-slide-at-a-time and single-page mode, and the "c" key toggles on and off the table of contents. The ← and → keys can be used to page forward and backward. For more help on controls see the "help?" link at the bottom.

Image quoted for classroom teaching purposes from http://peterahn.wordpress.com/2009/06/27/sushi-buffet-in-portland/

Universal Serial Bus (USB)

  • Connects hsot computer to peripheral devices
  • Created to replace a collection of slower interfaces (parallel, serial, keyboard)
  • Can support up to 480Mbit/sec in theory

Image quoted for classroom teaching purposes from http://media.photobucket.com/image/cereal%20bus/dpihl/USB.png?o=4

USB Topology

Image quoted for classroom teaching purposes from http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html

USB Basics

Protocol Standards

Two Kinds of Linux USB Drivers

Linux USB Core

  • USB core hides most of the complexity that is not already hidden by the hardware.

Image adapted from http://lwn.net/Kernel/LDD3/

Frames

Image quoted for classroom teaching purposes from http://www2.renesas.com/usb/en/about_usb/USB1_3.html

Packets

USB Endpoints

  • Can carry data in just one direction
    • IN endpoint
    • OUT endpoint
  • 4 types describe how data is transmitted:
    • CONTROL
    • INTERRUPT
    • BULK
    • ISOCHRONOUS

Image quoted for classroom teaching purposes from http://www.answers.com/topic/universal-serial-bus

Control Endpoint

Image quoted for classroom teaching purposes from http://www2.renesas.com/usb/en/about_usb/USB1_3.html

"Interrupt" Endpoint

Image quoted for classroom teaching purposes from http://www2.renesas.com/usb/en/about_usb/USB1_3.html

Bulk Endpoint

  • Large amounts of data
  • Guaranteed delivery
  • No delivery time guarantee
  • Similar structure to interrupt packet
  • Large packets may be split
  • Asynchronous
  • Typical uses: printers, storage devices, network interfaces

Image quoted for classroom teaching purposes from http://www.flickr.com/photos/nitib/1308406683/

Isochronous Endpoint

Image quoted for classroom teaching purposes from http://www2.renesas.com/usb/en/about_usb/USB1_3.html

Linux USB Endpoint Structures

struct usb_host_endpoint {
   struct usb_endpoint_descriptor  desc;
   struct list_head                urb_list;
   void                            *hcpriv;   ...
}
struct usb_endpoint_descriptor {
   __u8  bLength;
   __u8  bDescriptorType;
   __u8  bEndpointAddress; /* see USB_ENDPOINT_DIR mask */ 
   __u8  bmAttributes; /* see USB_ENDPOINT_XFERTYPE_MASK */
   __le16 wMaxPacketSize; /* larger transfers will be split */
   __u8  bInterval; /* ms between interrupts sent to endpoint */ 
   __u8  bRefresh;
   __u8  bSynchAddress;
} __attribute__ ((packed));
#define USB_ENDPOINT_NUMBER_MASK        0x0f    /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK           0x80    /* in bEndpointAddress */
#define USB_DIR_OUT                     0       /* to device */
#define USB_DIR_IN                      0x80    /* to host */
#define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
#define USB_ENDPOINT_XFER_CONTROL       0
#define USB_ENDPOINT_XFER_ISOC          1
#define USB_ENDPOINT_XFER_BULK          2
#define USB_ENDPOINT_XFER_INT           3

This slide has additional "handout" notes. You need to use the 'a' key to toggle into handout mode, in order to see them.

Note the use of yet another gcc feature, the attribute "packed", to force these fields to be laid out exactly as specified, with no alignment gaps.

USB Interfaces

  • Interface = a bundle of endpoints
  • Device may have multiple interfaces
  • Each corresponds to a different logical connection: e.g., audio vs. video stream
  • Each interface may have multiple alternate settings
    • e.g., to reserve different amounts of bandwidth for the defvice

Image quoted for classroom teaching purposes from http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html

Linux USB Device Interfaces

Image adapted from http://lwn.net/Kernel/LDD3/

  • Described by
    struct usb_interface

Linux USB Interface Structures

struct usb_interface {
    /* array of alternate settings for this interface, in no particular order */
    struct usb_host_interface *altsetting;
    struct usb_host_interface *cur_altsetting;
    /* points to currently active alternate setting, in altsetting[] */
    unsigned num_altsetting; /* number of alternate settings */
    int minor;
    /* minor number this interface is bound to, set by usb_register_dev() */
    enum usb_interface_condition condition; /* state of binding */
    struct device dev; /* interface specific device info */
    struct device *usb_dev;
    ...
};
struct usb_host_interface {
    struct usb_interface_descriptor desc;
    struct usb_host_endpoint *endpoint;
    /* array of desc.bNumEndpoint endpoints associated with this
     * interface setting, in no particular order. */
    ...
};

USB Configurations

  • Configuration = a bundle of interfaces
  • A device may have multiple configurations, and be reconfigured to change set of interfaces
  • Described by struct usb_host_config
    embedded within struct usb_device

Image quoted for classroom teaching purposes from http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html

Linux USB Configuration Structures

struct usb_host_config {
    struct usb_config_descriptor    desc;
    struct usb_interface *interface[USB_MAXINTERFACES];
    /* the interfaces associated with this configuration, stored in no particular order */
    struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
    /* interface information available even when this is not the active configuration */
    ...
};
struct usb_config_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
    __le16 wTotalLength;
    __u8  bNumInterfaces;
    __u8  bConfigurationValue;
    __u8  iConfiguration;
    __u8  bmAttributes;
    __u8  bMaxPower;
} __attribute__ ((packed));
struct usb_device {
    int             devnum;          /* Address on USB bus */
    char            devpath [16];    /* Use in messages: /port/port/... */
    enum usb_device_state   state;   /* configured, not attached, etc */
    enum usb_device_speed   speed;   /* high/full/low (or error) */
    struct usb_tt   *tt;             /* low/full speed dev, highspeed hub */
    int             ttport;          /* device port on that tt hub */
    unsigned int toggle[2];          /* none bit for each endpoint ([0] = IN, [1] = OUT) */
    struct usb_device *parent;       /* our hub, unless we're the root */
    struct usb_bus *bus;             /* Bus we're part of */
    struct usb_host_endpoint ep0;
    struct device dev;               /* Generic device interface */
    struct usb_device_descriptor descriptor; /* Descriptor */
    struct usb_host_config *config;  /* All of the configs */
    struct usb_host_config *actconfig; /* the active configuration */
    struct usb_host_endpoint *ep_in[16];
    struct usb_host_endpoint *ep_out[16];
    char **rawdescriptors;           /* Raw descriptors for each config */
    int have_langid;                 /* whether string_langid is valid yet */
    int string_langid;               /* language ID for strings */
    struct list_head filelist;
    struct device *usb_classdev;
    struct dentry *usbfs_dentry;     /* usbfs dentry entry for the device */
    /* Child devices - these can be either new devices
     * (if this is a hub device), or different instances of this same device.
     * Each instance needs its own set of data structures. */
    int maxchild;                   /* Number of ports if hub */
    struct usb_device *children[USB_MAXCHILDREN];
    ...
}

Review

  • A USB device has one or more configurations
  • A configuration has one or more interfaces
  • An interface has
    • one or more settings
    • zero or more endpoints

Image quoted for classroom teaching purposes from http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html

sysfs Representation of USB Devices

Interface naming scheme: root_hub(-hub_port)*:config.interface, e.g., 1-2:1.0.

Sample sysfs Output

For a Microsoft 3-Button Mouse on usb-0000:00:0f.2-2, we have.

/sys/devices/pci0000:00/0000:00:0f.2/usb1/1-2/1-2:1.0:
  bAlternateSetting
  bInterfaceClass
  bInterfaceNumber
  bInterfaceProtocol
  bInterfaceSubClass
  bNumEndpoints
  detach_state
  driver
  power
/sys/class/input/event2:
  device -> ../../../devices/pci0000:00/0000:00:0f.2/usb1/1-2/1-2:1.0
/sys/class/input/mouse1:
  device -> ../../../devices/pci0000:00/0000:00:0f.2/usb1/1-2/1-2:1.0
/sys/bus/usb/devices:
  1-2:1.0 -> ../../../devices/pci0000:00/0000:00:0f.2/usb1/1-2/1-2:1.0
/sys/bus/usb/drivers/usbhid:
  1-2:1.0 -> ../../../../devices/pci0000:00/0000:00:0f.2/usb1/1-2/1-2:1.0

This slide has additional "handout" notes. You need to use the 'a' key to toggle into handout mode, in order to see them.

Take note of the multiple links to this mouse, classified as an event-generator and a mouse.

The driver seems to be classified as both a USB driver and a human interface device driver.

I originally hoped to use this as an in-class example of how sysfs works, but gave up after spending 2 hrs. trying to make sense out of the USB-related /sys entries for a system with just one USB device (a mouse). It is far too complicated to try to walk through in class. In fact, one wonders whether all the complexity of sysfs is justified by real value.

Of course, the nominal purpose of these directories is to allow user-space prograsm to communicate directly with the USB devices.

/proc/bus/usb/devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 4
B:  Alloc= 11/900 us ( 1%), #Int=  1, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0000 ProdID=0000 Rev= 2.06
S:  Manufacturer=Linux 2.6.11.9 ohci_hcd
S:  Product=ServerWorks OSB4/CSB5 OHCI USB Controller
S:  SerialNumber=0000:00:0f.2
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=045e ProdID=0040 Rev= 3.00
S:  Manufacturer=Microsoft
S:  Product=Microsoft 3-Button Mouse with IntelliEye(TM)
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=10ms

USB Request Blocks (Urbs)

Urb Utility Functions

An Example of a USB Driver

For a very simple example, take a look at the usbled driver.

For an example of a more useful and more complicated device, take a look at the Konica webcam driver.

Other USB Data Functions

int usb_get_descriptor(struct usb_device *dev, unsigned char type, 
                        unsigned char index, void *buf, int size);

int usb_get_string(struct usb_device *dev, unsigned short langid,
                   unsigned char index, void *buf, int size);