Friday, August 8, 2008

Using Python and XML for parsing USB descriptor structures to C

This project consists of a Python script that parses an XML description of USB descriptors and generates C code structures that can be included in a C firmware program for a USB device. This tool is primarily intended for developers of USB devices on embedded platforms. The XML representation of the descriptors gives a good view of the structure and the Python parser generates correct bDescriptorType values, bLength values and calculates total lengths. For elements with a variable number of child elements, such as bNumEndpoints in the Interface descriptor, the correct value is inferred from the XML structure. Most elements have a default value that is inserted in the generated C data structure. Symbolic values can be used for field values through XML entities defined in a DTD.

Related work

This project is part of a set of tools written in Python to simplify work with embedded development and USB. Most of the development work is done under Linux. Other components in this effort are:
  • usbmodule: A Python module that wraps libusb and gives raw access to USB devices, with experimental thread code to download and buffer incoming data before the application requests it, this works (for me) but it is unstructured, uncleaned and probable a bit buggy. This is similar to PyUSB , I have not had time to really check out this project, perhaps we should merge ....
  • A python GUI application for firmware downloads to embedded systems, first written to program Parallax Javelin systems from Linux, then extended to talk to serial monitors on LPC2xxx and AT91SAM7 arm processors. Today it is mostly used for SPI flashing of Atmel AVR8 processors using an FT232 interface in bitbang mode (this is where the USB from Python is used)


An example XML representation of a device dsecriptor
<USB_Device_Descriptor name="devDescriptor" bcdUSB="0110" bDeviceClass="0" bDeviceSubclass="0" bDeviceProtocol="0" idVendor="EB03" idProduct="2463" bcdDevice="0000" iManufacturer="1" iProduct="2" iSerialNumber="3" bNumConfigs="1"/>
and the output in C code format that is generated
const char devDescriptor [] = {
// Device Descriptor
/* 0 */ 0x12, //bLength
/* 1 */ 0x1, //bDescriptorType
/* 2 */ 0x10,
/* 2 */ 0x1,
/* 4 */ 0x0,
/* 5 */ 0x0,
/* 6 */ 0x0, //bDeviceProtocol
/* 7 */ 0x8,
/* 8 */ 0x3,
/* 8 */ 0xeb,
/* 10 */ 0x63,
/* 10 */ 0x24,
/* 12 */ 0x0,
/* 12 */ 0x0,
/* 14 */ 0x1,
/* 15 */ 0x2, //iProduct
/* 16 */ 0x3,
/* 17 */ 0x1


Currently the tool can generate what looks as correct C code structures, with examples from USB specification. The output has not been tested and used as descriptor structures in actual USB firmware. The Python code can be run as a simple command line tool. There is a lack of documentation for the XML tags and attributes used. Future work devoted to this will depend on the testing and also interest from third parties-

Future work

Use the output from this tool as descriptors for a MIDI interface implemented on an AT91SAM7S development board. Use the output from this tool as descriptors for a HID device implemented on an AT91SAM7S development board connected to . This document/page will also be updated and made more complete depending on external feedback.


Magnus Lundin If you are interested in this project contact me at: lundin at mlu dot mine dot nu

No comments: