Writing a Simple USB Driver
Since this column began, it has discussed how a Linux driver writer can create various types of kernel drivers, by explaining the different kernel driver interfaces including TTY, serial, I2C and the driver core. It is time to move on now and focus on writing real drivers for real hardware. We start by explaining how to determine what kind of kernel driver interface to use, tricks to help figure out how the hardware actually works and a lot of other real-world knowledge.
Let's begin with a goal of making a simple USB lamp device work well with Linux. Editor Don Marti pointed out a neat device, the USB Visual Signal Indicator, manufactured by Delcom Engineering and shown in Figure 1. I have no relationship with this company; I just think they make nice products. This device can be ordered on-line from the Delcom Web site, www.delcom-eng.com. Don challenged me to get the device working on Linux, and this article explains how I did it.
The first goal in trying to write a driver for a device is to determine how to control the device. Delcom Engineering is nice enough to ship the entire USB protocol specification their devices use with the product, and it also is available on-line for free. This documentation shows what commands the USB controller chip accepts and how to use them. They also provide a Microsoft Windows DLL to help users of other operating systems write code to control the device.
The documentation for this device is only the documentation for the USB controller in the lamp. It does not explicitly say how to turn on the different color LEDs. For this, we have to do a bit of research.
No Docs? Reverse Engineer It!
If the USB protocol for this device had not been documented or available to me, I would have had to reverse engineer this information from the device itself. A handy tool for this kind of work is a free program called USB Snoopy, www.wingmanteam.com/usbsnoopy; another version of it is SnoopyPro, usbsnoop.sourceforge.net. These programs are both Windows programs that allow users to capture the USB data that is sent to and received from any USB device on a Windows system. All a developer needs to do is find a Windows machine, install the Windows driver provided by the manufacturer for the device and run the snoop program. The data is captured to a file to be analyzed later. Perl scripts can help filter some of the extra noise in the output of these snoop programs into an easier format to understand.
Another method a few people have used to reverse engineer the USB protocol of a device is to run a Windows instance using VMware on top of Linux. VMware enables the Windows instance to talk to all of the USB devices plugged in to the Linux machine by sending data to Linux though the usbfs. A simple modification to the usbfs causes all data flowing though it to be logged to the kernel log. Using this, the full USB traffic stream can be captured and later analyzed.
After opening up the lamp device, making sure not to lose the spring that easily pops out when unscrewing the device, the circuit board can be inspected (Figure 2). Using an ohmmeter, or any kind of device for detecting a closed circuit, it was determined that the three different LEDs are connected to the first three pins of port 1 on the main controller chip.
In reading the documentation, the USB command to control the levels of the port 1 pins is Major 10, Minor 2, Length 0. The command writes the least significant byte of the USB command packet to port 1, and port 1 is defaulted high after reset. So, that is the USB command we need to send to the device to change the different LEDs.
Now that we know the command to enable a port pin, we need to determine which LED color is connected to which pin. This is easy to do with a simple program that runs through all possible combinations of different values for the three port pins and then sends the value to the device. This program enabled me to create a table of values and LED colors (Table 1).
Table 1. Port Values and the Resulting LED Patterns
|Port value in hex||Port value in binary||LEDs on|
|0x00||000||Red, Green, Blue|
|0x07||111||No LEDs on|
So, if all pins on the port are enabled (a value of 0x07 hex), no LEDs are on. This matches up with the note in the data sheet that stated, “Port 1 is defaulted high after reset.” It would make sense not to have any LEDs enabled when the device is first plugged in. This means we need to turn port pins low (off) in order to turn on the LED for that pin. Using the table, we can determine that the blue LED is controlled by pin 2, the red LED by pin 1 and the green LED by pin 0.
|Designing Electronics with Linux||May 22, 2013|
|Dynamic DNS—an Object Lesson in Problem Solving||May 21, 2013|
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
- RSS Feeds
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- A Topic for Discussion - Open Source Feature-Richness?
- Designing Electronics with Linux
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Validate an E-Mail Address with PHP, the Right Way
- What's the tweeting protocol?
- Kernel Problem
2 hours 37 min ago
- BASH script to log IPs on public web server
7 hours 4 min ago
10 hours 40 min ago
- Reply to comment | Linux Journal
11 hours 12 min ago
- All the articles you talked
13 hours 36 min ago
- All the articles you talked
13 hours 39 min ago
- All the articles you talked
13 hours 40 min ago
18 hours 5 min ago
- Keeping track of IP address
19 hours 56 min ago
- Roll your own dynamic dns
1 day 1 hour ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi
It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?