Writing a Simple USB Driver
This function starts out by setting all bits in the variable color to 1. Then, if any LEDs are to be enabled, it turns off only that specific bit. We then send a USB control message to the device to write that color value to the device.
It first seems odd that the tiny buffer variable, which is only 8-bytes long, is created with a call to kmalloc. Why not simply declare it on the stack and skip the overhead of dynamically allocating and then destroying it? This is done because some architectures that run Linux cannot send USB data created on the kernel stack, so all data that is to be sent to a USB device must be created dynamically.
With this kernel driver created, built and loaded, when the USB lamp device is plugged in, the driver is bound to it. All USB devices bound to this driver can be found in the sysfs directory for the driver:
$ tree /sys/bus/usb/drivers/usbled/ /sys/bus/usb/drivers/usbled/ `-- 4-1.4:1.0 -> ../../../../devices/pci0000:00/0000:00:0d.0/usb4/4-1/4-1.4/4-1.4:1.0
The file in that directory is a symlink back to the real location in the sysfs tree for that USB device. If we look into that directory we can see the files the driver has created for the LEDs:
$ tree /sys/bus/usb/drivers/usbled/4-1.4:1.0/ /sys/bus/usb/drivers/usbled/4-1.4:1.0/ |-- bAlternateSetting |-- bInterfaceClass |-- bInterfaceNumber |-- bInterfaceProtocol |-- bInterfaceSubClass |-- bNumEndpoints |-- blue |-- detach_state |-- green |-- iInterface |-- power | `-- state `-- red
Then, by writing either 0 or 1 to the blue, green and red files in that directory, the LEDs change color:
$ cd /sys/bus/usb/drivers/usbled/4-1.4:1.0/ $ cat green red blue 0 0 0 $ echo 1 > red [greg@duel 4-1.4:1.0]$ echo 1 > blue [greg@duel 4-1.4:1.0]$ cat green red blue 0 1 1
Now that we have created a simple kernel driver for this device, which can be seen in the 2.6 kernel tree at drivers/usb/misc/usbled.c or on the Linux Journal FTP site at (ftp.linuxjournal.com/pub/lj/listings/issue120/7353.tgz), is this really the best way to talk to the device? What about using something like usbfs or libusb to control the device from user space without any special device drivers? In my next column, I will show how to do this and provide some shell scripts to control the USB lamp devices plugged in to the system easily.
If you would like to see kernel drivers written for any other types of devices, within reason—I'm not going to try to write an NVIDIA video card driver from scratch—please let me know.
Thanks to Don Marti for bugging me to get this device working on Linux. Without his prodding it would have never gotten finished.
Greg Kroah-Hartman currently is the Linux kernel maintainer for a variety of different driver subsystems. He works for IBM, doing Linux kernel-related things, and can be reached at email@example.com.
Webinar: 8 Signs You’re Beyond Cron
11am CDT, April 29th
Join Linux Journal and Pat Cameron, Director of Automation Technology at HelpSystems, as they discuss the eight primary advantages of moving beyond cron job scheduling. In this webinar, you’ll learn about integrating cron with an enterprise scheduler.Join us!
|Android Candy: Intercoms||Apr 23, 2015|
|"No Reboot" Kernel Patching - And Why You Should Care||Apr 22, 2015|
|Return of the Mac||Apr 20, 2015|
|DevOps: Better Than the Sum of Its Parts||Apr 20, 2015|
|Play for Me, Jarvis||Apr 16, 2015|
|Drupageddon: SQL Injection, Database Abstraction and Hundreds of Thousands of Web Sites||Apr 15, 2015|
- Tips for Optimizing Linux Memory Usage
- "No Reboot" Kernel Patching - And Why You Should Care
- DevOps: Better Than the Sum of Its Parts
- Return of the Mac
- Android Candy: Intercoms
- Drupageddon: SQL Injection, Database Abstraction and Hundreds of Thousands of Web Sites
- Non-Linux FOSS: .NET?
- Designing Foils with XFLR5
- Play for Me, Jarvis