USB Defined Class Codes

I had a mental list of things to do this afternoon, but as usual my mind’s gone blank and I’ve forgotten it all. It’s been over a week since my last post, so I’m probably due to write more garbage here anyway.

I’ve now been playing with the AVR ONE! for a couple of days, and on the whole I like it – it’s fast (once the FPGA has loaded the requested target interface binary) and it’s got a few neat things like automatic physical protocol detection for the XMEGAs (JTAG and PDI) which just makes life a little easier. I’m not about to throw away my JTAG-MKII yet however, as it’s a little buggy. As far as I can tell the latest firmware has an issue with breakpoints – they aren’t disabled on the chip once created until the debugging session is reset. That’s annoying when you set one breakpoint as a test, remove it and move it elsewhere, since you get a bunch of phantom breakpoints until you reload the target. Hopefully it’ll be fixed for the next service pack/release of AVRStudio.

Right, now to my rant of today. This is a follow up to my previous grumpy rant about USB VIDs and PIDs and is on a related topic; Defined Class Codes.

The goal of USB is to make communication between peripherals and hosts cheap, easy to implement, reliable, but also generic. By standardizing the transport, logical channel differentiation and other mechanisms, the USB-IF aimed to create an interface which allows any host to talk to any device of a particular function, without regard for who exactly made it. That’s why you can stick any old mouse or keyboard into your laptop today and have (most) of its functions work out of the box, because they all implement the functions in the same manner as defined in the relevant USB class specifications.

The USB-IF saw the need to define standards for a small set of devices, which would be common enough for people to have a reasonable expectation that they would work across all devices without proprietary drivers. These are the “Approved Class Documents” you can download and read from the USB-IF website today. This is a good thing; while some of the USB-IF’s class standards have some serious flaws and poor design, they at least exist in a form which engineers can develop from. Imagine going back to the early days of USB, where every USB flash drive (back when they were new) required a separate vendor driver to work. Imagine trying to get your new USB mouse and keyboard combo running on a PC if you have to install drivers for them, without being able to use said keyboard and mouse at all while doing it. Utter madness.

However, as usual, the USBIF’s solution to the problem was half baked and screws out a lot of people. To determine what type of device has been inserted, the USB host will take a look at the Class, Subclass and Protocol values of the device’s descriptors. These are then matched against known USBIF sanctioned values, and if they match, the host can use its internal compatible driver for that class. There are many defined values for these, covering input devices (Mouse, Keyboards and Joysticks), CDC serial devices, Mass Storage devices, and plenty more. By matching against the interface’s Class, Subclass and Protocol values the host can use a single driver for the entire family of devices, rather than requiring a different vendor for each unique product (specified by the VID and PID value covered previously).

Does anyone else see the fatal flaw here?

What happens is that this mechanism fails for when people create custom USB devices, which adhere to a standard not endorsed by the USB-IF. The USB-IF have specified that the Class/Subclass/Protocol values of all 0xFF indicate a device which does not use a USB-IF endorsed standard, but they haven’t given any granularity more than that – you’re either a USB-IF class, or you’re “something non-standard”. This means there is no way for the host to easily determine *what* one of theseย  non-standard-class devices actually is, requiring it to fall back on the matching against the VID/PID and, of course, requiring separate vendor drivers.

How is this important? It screws out engineers who just want to make their own USB class specification up and have it work in the same fool-proof manner as the endorsed classes. Take Microsoft’s underused “SideShow” USB devices which they touted during the Windows Vista marketing phase. The SideShow platform was supposed to allow for devices to connect to a PC and have notifications pushed out to them for display to the user – for example, a set of computer speakers with a display to show the currently playing song. While the SideShow devices all adhered to the transport specifications set out by Microsoft, there isn’t any standard method for a class-less device to announce what non-standard protocol it supports.

If the USB-IF had switched to a GUID system for the device classes, we wouldn’t have this mess either. The USB-IF could define a few GUIDs to use for the standardized classes, and left the rest of the vast keyspace over to the engineers to the world, so that they could design and specify their own class. Sure, it would take the host a few extra compares to see if the class GUID is equal to a known USB-IF class, but it would allow for engineers to build new specifications as needed easily without resorting to ugly hacks.


Comments: 2

Leave a reply »


Hi Dean,

I haven’t written in a while, and this post tied in so well with something I’ve been meaning to say to you that I thought I’d comment.

You’ve inspired a little rant I’m afraid, but I get back to the technical bit at the end, so skip ahead if you like ๐Ÿ˜Ž

The situation you discribe is exactly what led to the widespread phenomenon of open and free software based on open and free standards.

These are standards, and the software implimenting them, with a primary objective of technical excellence. One might think that all standards and software have this as their number one priority, but as you find with the usb standard, it’s not the case.

Organizations, with billions of $$$ dependent on the outcome, are often the hosts of standards committees and populate the decision making bodies. The standards are then formulated to provide competative advantage to these organizations. Many people would say, “This is how it should be”, and for the legions of the worlds marketing twits, it is.

But for those of us who focus on making the magick inside the box, instead of holding the mirrors and blowing the smoke, there’s a need for technical excellence.

This has lead technical people around the world to agregate their efforts, and form working libraries, implimenting the conceptial abstractions that are the building blocks of complex products.

Probably the most widespread example of this is the C runtime library. It provides a standard interface on platforms from super-computers to 8 bit microcontrollers.

The one that addresses the issue of just how screwed up USB really is: libusb.

Now for the good stuff ๐Ÿ˜Ž

Is it possible to impliment the libusb API on top of the host side LUFA library?

This seems the approach that would most integrate the target AVR environment and the desktop development host environment, where the software is written.

An approach analogous to the avr-libc.

Host side applications could, in principle, be debugged on a desktop host (with the helpful ability of linux’s debugfs to trace usb transactions via libpcap and wireshark) and then deployed on the AVR.

Some existing libusb based applications could be ported to avr host platforms.

I’ve never seen anything of the like, but it seems a device side companion library to libusb could also ease development of custom usb peripherals and the accompaying host side drivers.

avr-libusb could allow LUFA to support the custom cases that the standard host classes don’t.

Glad to hear you’re having fun down there Dean.

Keep up the great work!



Interesting idea John – I’ll have to look into the libusb APIs and see how well they would translate to the USB AVRs — I confess, I haven’t played with libusb myself yet. I’d worry a tad about the performance of trying to shoehorn the AVR’s controller mechanisms into an API designed for desktop USB chipsets, but perhaps it will work out. I’ll whack it on my TODO list for future things to look into.

– Dean


Leave a Reply

(will not be published)


Vital Stats

  • 32 Years Old
  • Australian
  • Lover of embedded systems
  • Firmware engineer
  • Self-Proclaimed Geek

Latest Blog Posts