picture home | pixelblog | qt_tools

omino code blog

We need code. Lots of code.
David Van Brink // Mon 2008.03.3 22:36 // {wbl weird blinking lights}

Retro USB MIDI Device II

USB in Three Longish Paragraphs

Universal Serial Bus is a specification for an inexpensive medium-bandwidth wired communication system between a host and several devices. The direction of communication is always host-centric: “Out” means data from the host to a device, and “In” means data going to the host from a device.

Each device is organized in terms of configurations, interfaces, and endpoints. A device is identified by its name, and vendor and product IDs (VID and PID). You can buy a VID from usb.org. The device may offer one more configurations; if there’s more than one, the host will tell it which to use. Each configuration is composed of several interfaces. An interface declares its name, and its class and subclass, for example, Audio/MIDI. Each interface is then composed of some number of endpoints. An endpoint is a communications channel within the bus, between the host and a device, much akin to port numbers on an IP stack.

When the host notices a new device, by a clever system of electrical sensing and pulldown resistors and such, it sends a few query packets to endpoint zero, which is always reserved for this “enumeration” query process. The queries are all requests for descriptors, either a device descriptor or a configuration descriptor (which contains interface and endpoint descriptors within), and so on. Quite often these descriptors are slugs of ROM data on the device. If it recognizes the class and subclass of one of the interfaces, the host might send additional class-specific setup commands. Also, the host may engage in more intimate communication, such as allowing the device to control the on-screen cursor, or offering it to the user as an available printer. Some interface classes are “well known” and have drivers built into the host. Speakers and keyboards are both supported intrinsically by desktop computer hosts. More obscure devices, however, require a special driver to be installed.

Commentary

It feels a bit ornate, but it does have plenty of flexibility.

Apparently, neither Windows nor Mac OS X provides a fully general-purpose USB API, but, rather, requires customized drivers for each device class. Oh, a few are built in, like “human interface device” for mouse and keyboard and others. But it would be straightforward to provide truly generic API like:

   void ReadUsbEndpoint(EndpointHandle, char *buffer, int bufferSize, int *bytesGot);
   void WriteUsbEndpoint(EndpointHandle, char *buffer, int bytesToWrite);

Obviously, one would be well-advised to understand the device before conversing with it. But at present, one is required to write low-level drivers for, clearly, high level data manipulation.

Fortunately, my project is to create a MIDI controller. The MIDI class and subclass (01/03) is well-supported intrinsically on Mac OS X and Windows. It’ll “just work”.

USB References

http://www.usb.org/developers/docs/ has the spec. Chapter 9 documents the standard descriptors. This is the main chapter of interest to a software developer.

http://www.usb.org/developers/devclass_docs/ has some of the class-specific specs, including the Streaming MIDI spec.

http://www.colinkraft.com/macusbhid/macusbhid.php contains the laments of another lost would-be usb developer, and some tips for Mac OS X API’s.

Next up, Microchip’s reference implementation for USB.

3 comments
Aaron // Tue 2008.03.4 10:4910:49 am

Very nice! Keep it coming!

Universal Life Church // Thu 2008.03.6 12:0912:09 pm

“Obviously, one would be well-advised to understand the device before conversing with it. But at present, one is required to write low-level drivers for, clearly, high level data manipulation.”

I’m not sure I follow. Don’t you need to know the config of a device before writing code for it?

David Van Brink // Thu 2008.03.6 15:473:47 pm

“Don’t you need to know the config of a device before writing code for it?”

Definitely!

It’s just that the communication *could* be done from user-level API rather than driver-level. I wish Mac and Win provided such an API.

Today, if you have a vertical application with some custom USB hardware, you will likely need to write a custom driver in addition to your custom application, just to talk to your widget.

(Unless you piggyback on serial, or HID, or some other existing protocol.)

oh, i dont know. what do you think?



(c) 2003-2011 omino.com / contact poly@omino.com