USB Complete

Jan Axelson

Mentioned 6

Computing: general.

More on

Mentioned in questions and answers.

I have been tasked to write a device driver for an embedded device which will communicate with the micro controller via the SPI interface. Eventually, the USB interface will be used to download updated code externally and used during the verification phase.

My question is, does anyone know of a good reference design or documentation or online tutorial which covers the implementation/design of the USB protocol stack/device driver within an embedded system? I am just starting out and reading through the 650 page USB v2.0 spec is a little daunting at the moment.

Just as a FYI, the micro controller that I am using is a Freescale 9S12.


Based upon goldenmean's (-AD) comments I wanted to add the following info:

1) The embedded device uses a custom executive and makes no use of a COTS or RTOS.

2) The device will use interrupts to indicate data is ready to be retrieved from the device.

3) I have read through some of the docs regarding Linux, but since I am not at all familiar with Linux it isn't very helpful at the moment (though I am hoping it will be very quickly).

4) The design approach, for now at least, it to write a device driver for the USB device then a USB protocol layer (I/O) would reside on top of the device driver to interpret the data. I would assume this would be the best approach, though I could be wrong.

Edit - A year later

I just wanted to share a few items before they vanish from my mind in case I never work on a USB device again. I ran into a few obstacles when developing code and getting it up and running for the first.

The first problem I ran into was that when the USB device was connected to the Host (Windows in my case) was the host issues a Reset request. The USB device would reset and clear the interrupt enable flags. I didn't read the literature enough to know this was happening, thus I was never receiving the Set-Up Request Interrupt. It took me quite a while to figure this out.

The second problem I ran into was not handling the Set-Up Request for Set_Configuration properly. I was handling it, but I was not processing the request correctly in that the USB device was not sending an ACK when this Set-Up Request came in. I eventually found this out by using a hardware USB protocol analyzer.

There were other issues that I ran into, but these were the two biggest ones that took me quite a while to figure out. The other issue I had to worry about is big-endian and little-endian, Freescale 9S12 vs USB data format (Intel), respectively.

I ended up building the USB device driver similar to UART device drivers I had done in the past. I have posted the code to this at the following URL.

I tend to use structures a lot, so people may not like them since they are not as portal as using #defines (e.g., MAX3420_SETUP_DATA_AVAIL_INT_REQR 0x20), but I like them since it makes the code more readable for me. If anyone has questions regarding it please feel free to e-mail and I can try to give some insight to it. The book "USB Complete: The Developer's Guide" was helpful, so long as you knew what areas to concentrate on. This was a simple application and only used low-speed USB.

I've used an earlier edition of USB Complete by Jan Axelson. Indeed very complete.

From the editorial review:

Now in its fourth edition, this developer's guide to the Universal Serial Bus (USB) interface covers all aspects of project development, such as hardware design, device firmware, and host application software.

I'm using C++ and libusb-win32 to try and communicate with a commercial USB device ... I don't know much about USB programming, but I want to send some commands to the device that I know from using a sniffer program. Libusb-win32 seemed OK, but it looks like it can only be used on a device that uses the libusb driver for the device. I want to use it on a device with a driver "USB Composite Device" driver provided by windows usbccgp.sys ... is it even possible? If not, how can I do this? I just need to send some Control Transfers

If you want to talk to a commercial device you need to contact the manufacturer and find out if there is an interface to that device that is published through their driver. Most manufacturers won't have a way to interface with generic control requests in a product. There may be an undocumented IOCTL, but again you'll need to work with them to get this information.

If you just want to hook the device and send it a control request then you need to replace the manufacturer's driver with the libusb driver. The problem here is that while you can get at the device it may not function the way you want unless you spoof what the manufacturer does (for example, the device might expect some vendor specific communication to get the device ready to interact with the host). If you do see problems then you can reverse engineer the vendor specific protocol by looking at the USB line through some hardware analyzer.

Read USB Complete, it's a great introduction to the USB protocol and will help you understand more of what's going on between a USB device and your host PC.

When I do a ReadFile/WriteFile on a handle provided by CreateFile(HID_DEVICE_NAME,...), what happens in a terms of HID operations?

Does it issues a direct write/read request to HID device (USB, in my case), or is it transformed somewhere in underlying drivers to read last cached HID report with such ID?

ReadFile call:

syncDevice.OutputReportBuffer[0] = 0;
syncDevice.OutputReportBuffer[1] = reportID;
HANDLE writeHandle = CreateFile(pDevice->DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
HANDLE readHandle = CreateFile(pDevice->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
success = WriteFile(writeHandle, (void*) syncDevice.OutputReportBuffer, syncDevice.Caps.OutputReportByteLength, &bytecnt, 0);
success = ReadFile(readHandle, syncDevice.InputReportBuffer, syncDevice.Caps.InputReportByteLength, &bytecnt, 0);

From USB Complete by Jan Axelson:

The Windows HID driver causes the host controller to request Input reports. The driver stores received reports in a buffer. ReadFile retrieves one or more reports from the buffer. If the buffer is empty, ReadFile waits for a report to arrive. In other words, ReadFile doesn’t cause a device to send a report but just reads reports that the driver has requested.

WriteFile sends an Output report. The function uses an interrupt transfer if the HID has an interrupt OUT endpoint and the operating system is later than Windows 98 Gold. Otherwise, WriteFile uses a control transfer with a Set Report request. If using interrupt transfers, WriteFile will wait if the device NAKs. If using control transfers, WriteFile returns with an error code on failure or a timeout.

I was trying to program a USB2 controller(EHCI) on a bare metal system(No OS,No drivers). Are there any USB tutorial available for an absolute beginner ? The EHCI specs seemed to be too complex for a beginner.

USB Complete is a good book that will give you a start. Hard to find online tutorials.

I am trying to write a software that can control the connected USB 3.0 devices (something like opening file in each devices at some times).

However I have almost zero programming basic in USB, anyone here can suggest a direction or a good start for USB programming? Like example of some USB programming?

Prefer C++.

Thanks in advance. Sorry if I ask noob question.

Jan Axelson's USB Complete is what I learned and how I train anyone I work with on USB. The book explains USB in general (from the device and host side), enumeration, endpoints, class devices and request formats. It's a great, and easy, read. I'd start here - you'll need to know all of this.

Depending on what you are trying to do will dictate what example code you'll need to use. But WinUSB, libusb and HID will probably be the APIs you'll use - the underlying hyperlinks provide documentation on each.

I know this is sort of a "Help me with my code" kind of website, but I could actually use a little help with just methodology.

I am looking to retrieve data from a USB device, this device is a fingerprint scanner. Because I bought it online and wasn't reading carefully enough, drivers and other installation programs weren't included. Send it back? Nah . . .

I want to see if it is possible to retrieve data from this device. To be honest, I don't even know if it's possible, but I would love to give it a whack.

I looked into making INF files and things Microsoft has put out, but I honestly don't know where to start simply because I have absolutely no experience doing this. I have a lot of a program set up to organize the data and such, just need to find a way to actually get it.

What should I research and look into?

I'd recommend starting my reading USB Complete. The first few chapters will give you a good overview of how USB works. This will give you a basic understanding of the protocol, types of transfers, descriptors and general usage of a device. You need this knowledge and terminology so you can understand the rest of the documentation below.

From there you will probably want to use WinUSB or hidapi to interface with the device. If the device is vendor specific then WinUSB is the best bet. If the device enumerates as an HID device then you won't need a kernel driver but you will need to interface with the hidapi to interface with the device. You can discover this by looking at the descriptors through some tool like UVCView.exe, or looking to see if the HID driver is loaded in Device Manager (if it's not you will probably have an unidentified device).