Quantcast
Channel: Zombie Brainz' Juice » coding
Viewing all articles
Browse latest Browse all 10

USB descriptors tutorial [hacking]

$
0
0

This tutorial will explore the USB descriptors. All devices complying with the USB standard should be able to describe itself. This is a key part of the protocol, allowing a smooth user experience. Everything has been codified in hundred of pages of  standard, so the user just plugs the device into a port, and he is instantly ready to play with it. Learning USB descriptors is a good introduction to USB in general.

To make it work, several layers of components should be described in the process, and there is one “descriptor” for each nested level. Therefore several descriptors should be called one after each other. This operation is done by the “host”, which is the master of all connected devices to the same “bus”. When something is plugged into a computer, the host is the computer. A smartphone can also be an host. A USB key can’t. And sometimes there is a battle between to know who will be the host. Just keep in mind that there is one host and only one for this tutorial.

This tutorial can be directly applied to your USB devices. You can use the Linux command lsusb to list and described devices connected to your computer. You can also write a short Python program as I did. I find this last method somehow more engaging and therefore better for learning a technical topic like this one. Check my post on how to install PyUSB on Ubuntu.

HIERARCHY OF DESCRIPTORS

Each level can collect one or several sub-levels. Here are the several layers you will have to address:

  • device
  • configuration
  • interface
  • endpoint

For each level, the description is based on fields, which are described in the USB standard. I will use those field names, as done in PyUSB or libusb. All descriptor fields are available in the functions provided by those package (convenient when your IDE does not give you the full data structure of functions or variables).

BINARY AND HEXADECIMALS

We are dealing with a very technical topic here and very close to the hardware. Therefore, most of the values are expressed in binary in the standard documentation and displayed in a compact  and convenient hexadecimal format in the tutorials, including this one.

DEVICE DESCRIPTOR 

A device is basically a physical device connected to the host. This is the higher level of description. The device is described as a combination of the vendor ID (VID) and product ID (PID).

The very first step in any USB development is to check whether the expected device is recognized by the host. On the other way around, you can list all devices connected to the host. From there, you may need to convert the codes into a text description. To do that, check the text file provided by Linux-USB.org in the resources bellow.

A device class is associated to the device. The class describes the kind of the device. This is a really powerful information, as it can be used to determine which driver should be called to communicate with the device. All devices of the same kind, let’s say a human interface device (HID), should be interchangeable. The list can be found in the standard documentation or on Wikipedia.

The class is also defined at the interface level where it makes more sens (see bellow). A single device can have two interfaces with different classes. If you plug a camera into your computer, you could expect to read the internal storage and to be able to take control of the camera parameters, and to do that, you need two interfaces.

Device descriptor field names mentioned in this section:

  • idVendor (ex. 0x18d1 for Google)
  • idProduct (ex. 0x4ee1 for the Nexus 4)
  • bDeviceSubClass (ex. 0x00h for unspecified class, which is commonly used)

CONFIGURATION DESCRIPTOR

The general idea of the configuration is to explain how to work with the device. A configuration should be explicitly called during the communication setup. Calling this configuration will trigger some action on the device. Technical power information are stored at this level, like self power or max power which will be drained from the bus.

Most of the devices only propose a single descriptor. Some devices have several interfaces, to adapt to several power situations for example. The number of interfaces could be arranged with several configurations also.

There is no usable information in the scope of this tutorial. Just keep in mind that the configurations are here and that they should be called to have a working device.

INTERFACE DESCRIPTOR

An interface is a group of endpoints which will be involved to sustain a single feature of the device. The interfaces are numbered and may propose alternate settings. The alternate settings have the same interface number with an incremental alternate number. Therefore an interface should be defined with the interface number and the alternate setting number.

At this level are also managed the class, subclass and protocol, which are used to describe the feature.

Interface descriptor field names mentioned in this section:

  • bInterfaceNumber (ex. 0 for the first one)
  • bAlternateSetting (ex. 0 typically for an interface without alternate settings)
  • bInterfaceClass (ex. 0×09 for hubs)
  • bInterfaceSubClass (ex. 0×00)
  • bInterfaceProtocol (ex. 0×00 for full speed hub)

ENDPOINT DESCRIPTOR

The endpoints are the lower level of description. They are addresses which will be used to build “pipes”, that means connections between the host and the device.

Endpoints are identified by an address, which indicate the endpoint number AND the direction, in the same value. The type of transfer is described in a specific field. This type could be one of the four USB transfer type (bulk, interrupt, etc.). To be noticed, all devices have an endpoint 0, of type control, used for the configuration of the device itself. This endpoint is usually not listed by PyUSB or libusb, but it is there.

Endpoint descriptor field names mentioned in this section:

  • bEndpointAddress (ex. 0×81 for the endpoint 1, with the direction IN / 0×02 for the enpoint 2 with the direction OUT)
  • bmAttributes (ex. 0×10 for bulk transfer)

CONCLUSION

I hope that you enjoyed this short trip through the USB interface. I would be please to exchange with you in the comments bellow. Tutorials, and this USB descriptors tutorial is not an exception, are living documentation.

RESOURCES

  1. USB.org official standard, “USB 3.0 Specification”, at the time this post has been published (more than 500 pages)
  2. Beyond logic, “USB in a Nutshell, making sens in the USB standard”, a very detailed tutorial which I highly recommend
  3. Wikipedia, “Universal Serial Bus”, of course
  4. PyUSB on SourceForge, “Programming with PyUSB 1.0″, if you read only one, it should be this one
  5. Linux-USB.org, “USB Vendor/Device IDs Database”, for a description of the devices by VID/PID (text file)
USB certified logo TM 1024x360 USB descriptors tutorial [hacking]

USB certified logo (TM)

The post USB descriptors tutorial [hacking] appeared first on Zombie Brainz' Juice.


Viewing all articles
Browse latest Browse all 10

Latest Images

Trending Articles



Latest Images