Writing a Simple USB Driver
Armed with our new-found information, we set off to whip up a quick kernel driver. It should be a USB driver, but what kind of interface to user space should we use? A block device does not make sense, as this device does not need to store filesystem data, but a character device would work. If we use a character device driver, however, a major and minor number needs to be reserved for it. And how many minor numbers would we need for this driver? What if someone wanted to plug 100 different USB lamp devices in to this system? To anticipate this, we would need to reserve at least 100 minor numbers, which would be a total waste if all anyone ever used was one device at a time. If we make a character driver, we also would need to invent some way to tell the driver to turn on and off the different colors individually. Traditionally, that could be done using different ioctl commands on the character driver, but we know much better than ever to create a new ioctl command in the kernel.
As all USB devices show up in their own directory in the sysfs tree, so why not use sysfs and create three files in the USB device directory, blue, red and green? This would allow any user-space program, be it a C program or a shell script, to change the colors on our LED device. This also would keep us from having to write a character driver and beg for a chunk of minor numbers for our device.
To start out our USB driver, we need to provide the USB subsystem with five things:
A pointer to the module owner of this driver: this allows the USB core to control the module reference count of the driver properly.
The name of the USB driver.
A list of the USB IDs this driver should provide: this table is used by the USB core to determine which driver should be matched up to which device; the hot-plug user-space scripts use it to load that driver automatically when a device is plugged in to the system.
A probe() function called by the USB core when a device is found that matches the USB ID table.
A disconnect() function called when the device is removed from the system.
The driver retrieves this information with the following bit of code:
static struct usb_driver led_driver = {
.owner = THIS_MODULE,
.name = "usbled",
.probe = led_probe,
.disconnect = led_disconnect,
.id_table = id_table,
};
The id_table variable is defined as:
static struct usb_device_id id_table [] = {
{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
{ },
};
MODULE_DEVICE_TABLE (usb, id_table);
The led_probe() and led_disconnect() functions are described later.
When the driver module is loaded, this led_driver structure must be registered with the USB core. This is accomplished with a single call to the usb_register() function:
retval = usb_register(&led_driver);
if (retval)
err("usb_register failed. "
"Error number %d", retval);
Likewise, when the driver is unloaded from the system, it must unregister itself from the USB core:
usb_deregister(&led_driver);
The led_probe() function is called when the USB core has found our USB lamp device. All it needs to do is initialize the device and create the three sysfs files, in the proper location. This is done with the following code:
/* Initialize our local device structure */
dev = kmalloc(sizeof(struct usb_led), GFP_KERNEL);
memset (dev, 0x00, sizeof (*dev));
dev->udev = usb_get_dev(udev);
usb_set_intfdata (interface, dev);
/* Create our three sysfs files in the USB
* device directory */
device_create_file(&interface->dev, &dev_attr_blue);
device_create_file(&interface->dev, &dev_attr_red);
device_create_file(&interface->dev, &dev_attr_green);
dev_info(&interface->dev,
"USB LED device now attached\n");
return 0;
The led_disconnect() function is equally as simple, as we need only to free our allocated memory and remove the sysfs files:
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_blue);
device_remove_file(&interface->dev, &dev_attr_red);
device_remove_file(&interface->dev, &dev_attr_green);
usb_put_dev(dev->udev);
kfree(dev);
dev_info(&interface->dev,
"USB LED now disconnected\n");
When the sysfs files are read from, we want to show the current value of that LED; when it is written to, we want to set that specific LED. To do this, the following macro creates two functions for each color LED and declares a sysfs device attribute file:
#define show_set(value) \
static ssize_t \
show_##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = \
to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", led->value); \
} \
\
static ssize_t \
set_##value(struct device *dev, const char *buf, \
size_t count) \
{ \
struct usb_interface *intf = \
to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
int temp = simple_strtoul(buf, NULL, 10); \
\
led->value = temp; \
change_color(led); \
return count; \
} \
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO,
show_##value, set_##value);
show_set(blue);
show_set(red);
show_set(green);
This creates six functions, show_blue(), set_blue(), show_red(), set_red(), show_green() and set_green(); and three attribute structures, dev_attr_blue, dev_attr_red and dev_attr_green. Due to the simple nature of the sysfs file callbacks and the fact that we need to do the same thing for every different value (blue, red and green), a macro was used to reduce typing. This is a common occurrence for sysfs file functions; an example of this in the kernel source tree is the I2C chip drivers in drivers/i2c/chips.
So, to enable the red LED, a user writes a 1 to the red file in sysfs, which calls the set_red() function in the driver, which calls the change_color() function. The change_color() function looks like:
#define BLUE 0x04
#define RED 0x02
#define GREEN 0x01
buffer = kmalloc(8, GFP_KERNEL);
color = 0x07;
if (led->blue)
color &= ~(BLUE);
if (led->red)
color &= ~(RED);
if (led->green)
color &= ~(GREEN);
retval =
usb_control_msg(led->udev,
usb_sndctrlpipe(led->udev, 0),
0x12,
0xc8,
(0x02 * 0x100) + 0x0a,
(0x00 * 0x100) + color,
buffer,
8,
2 * HZ);
kfree(buffer);
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| 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 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- RSS Feeds
- Home, My Backup Data Center
- What's the tweeting protocol?
- Readers' Choice Awards 2011
- Linux on Azure—a Strange Place to Find a Penguin
- Developer Poll
- Reply to comment | Linux Journal
4 hours 17 min ago - Reply to comment | Linux Journal
6 hours 49 min ago - Reply to comment | Linux Journal
8 hours 7 min ago - great post
8 hours 41 min ago - Google Docs
9 hours 4 min ago - Reply to comment | Linux Journal
13 hours 52 min ago - Reply to comment | Linux Journal
14 hours 39 min ago - Web Hosting IQ
16 hours 13 min ago - Thanks for taking the time to
17 hours 50 min ago - Linux is good
19 hours 47 min ago
Enter to Win an Adafruit Prototyping Pi Plate 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 Prototyping Pi Plate 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
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




Comments
How To Get Port Values and the Resulting LED Patterns ???
Hi
Thanks For this guide but I want to know how to get Port Values and the Resulting LED Patterns without documents of the device ???
Souce
I was actually trying to write a kernel driver for usb and was hooked up reading this article only to find out it's been around for 6 years! Even so I've learned alot from this article. This is a great tutorial to make usb drivers, however I'm quite stucked on the process of compiling the source.
Delphi Hid get path
The first time I use SetupDiGetDeviceInterfaceDetailA
It returns GetLastError = ERROR_INSUFFICIENT_BUFFER or 78
and a byesreturned is a good expected number
DevData ( is the record below)
TSPDevInfoData = packed record
Size: DWORD;
ClassGuid: TGUID;
DevInst: DWORD;
Reserved: DWord;
end;
with TSPDevInfoData.ClassGuid = the Registry USB controller GUID
When I call SetupDiGetDeviceInterfaceDetailA a second time it hates me
real bad. I'm not sure how to convert BytesReturned into my DevData.size or
TSPDeviceInterfaceDetailDataA.size correctly.
I have checked my Structures through and through
The new structure being:-
TSPDeviceInterfaceDetailDataA = record
Size: DWord;
DevicePath: Array [0..255] of AnsiChar;
end;
//*********************************************************
LastSuccess := SetupDiGetDeviceInterfaceDetailA(IsDevPtr, DevData, nil, 0, @BytesReturned, nil);
if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER{ 122 }) then
begin
ADWord := BytesReturned + Sizeof(TSPDeviceInterfaceDetailDataA) + 6; // Sizeof(TSPDeviceInterfaceDetailDataA)is one size in delphi
Str.Size := ADWord; // this is a memory block
DevIntfcDetailDataA := Str.Memory;
//this makes a structure be in the memory block
LastSuccess := SetupDiGetDeviceInterfaceDetailA(IsDevPtr,
DevData,
DevIntfcDetailDataA,
BytesReturned,
@ADWord,
nil);
// lastsuccess is always and error
can you suggest anything I have forgotten
lexdeanair at Hotmail.com
writing protcol cool disk
Hello
i want save data(with txt format) on cool disk by microcontroller AVR.
For this i use cinvertor USRT to USB.
my question is : what is protcol cool disk for writing data on it?
HELLO
hello plz i need help urgently !
i atached my motorola netmon phone to my USB , and it didnt present in the dev/ttyUSB1 directory ...
second think , in c++ how do i write a fucntion that send command to the usb modem ( watever it is )
thx a lot plz help !
USB Lamp writer error!
Hello Greg,
Nice article, I bought the lamp
and I tried it out on Windows and Linux.
I get the following error:
bash: echo: writer error: Success
My system is Ubuntu Jaunty Jackrabbit (9.04)
kernel 2.6.28-15
I've got my usb files in the following directory:
/sys/bus/usb/drivers/usbled/2-2:1.0
|-- bAlternateSetting
|-- bInterfaceClass
|-- bInterfaceNumber
|-- bInterfaceProtocol
|-- bInterfaceSubClass
|-- bNumEndpoints
|-- blue
|-- driver -> ../../../../../../bus/usb/drivers/usbled
|-- green
|-- modalias
|-- power
| `-- wakeup
|-- red
|-- subsystem -> ../../../../../../bus/usb
|-- supports_autosuspend
`-- uevent
Scratching my head... any ideas appreciated...
Thanks
USB lamp enquiry
Hello Ajay Abraham,
This is Nagesh A from India.
I have gone through this artical, and found interested.
As I have seen your comment on this, I would like to ask you, how can I buy this product, thinking you might be aware of buying this product.
Please give some detail, if you know.
thank you,
-Nagesh A
USB Lamp writer error
The command I gave was : echo 1 > blue
Solved
System : slax
kernel :2.6.27.27
Hardware : Lenovo Thinkpad R60
echo 1 > blue
echo 1 > red
echo 1 >green
I didnt even have to write the driver
I just used usbfs mounted on sys/bus/usb/devices
Simply amazing
Awsome tutorial . very very inspiring .Great job ,I helped me put courage into me to write a device driver..
A driver suggestion
How about a driver for the Wireless PC Lock
http://www.gadgets.co.uk/item/USBLOCK/USB-Wireless-PC-Lock.html
The bundled software for windows is godawful and I think someone already did a tutorial on writing new software for the device to enable locking of the system etc. Would be nice if I could get this device working under Linux so I could look into writing some software to secure the system when I step away!
~T
Some question
Hi! Is the way to read messages from usb mouse? I went to /dev/ folder. What I should to do? I only need to send/receive data via usb interface.
Re
I never thought that device driver writing could be this straightforward. Wow! Superb tutorial and very very inspiring. I simply love it.
Problem when compilling
Hi !
Thank you for this tutorial which allow easly to develop my own driver.
However, I have a problem when I'm compiling your file. Normally I have all the libraries (libusb, libusb-dev). I just replace config.h by autoconf.h because ubuntu use this file rather than config.h
My error is:
driverUSB_HID.c:154: error: unknown field ‘owner’ specified in initializer
So could you please help me ?
BR
Eloi
Mr Greg , I m
Mr Greg ,
I m writing a driver for usb device in linux 2.4 version ,how i can get get minor no dynamically from usb core , how to create node in the /dev with using major and minor no without devfs .
Thank you
with regards
Bhanu
ThinkGeek USB Rocket Launcher
You should do a Linux device driver for the USB Rocket Launcher:
http://www.thinkgeek.com/geektoys/warfare/8a0f/
USB dirver
Hey was wondering which would be the best method for writing a USB game control driver e.g. Would you make the driver listen for when a button is pressed or would you write the driver and then a program in say C to retrieve the current state of the button?
im wrting a driver programm..Help me...
Im writing a driver program for transfering data's between PC and my SWITCH(Its an telcom equipment)in Linux platform.Getting cofused in "how to program for send and receive data's b/w PC and my switch.Please help me to get clear idea about that.
USB driver for MPEG 4
Hi I want to write a driver for USB streaming of MPEG 4 Video. I am not sure how and where to start. I have MPEG 4 video capture and the video is saved as a file onto the system. How should I start writing the driver for streaming the video instead of saving it in the system?
Doing it
Their are a few ways to do this. The hardest way,would be to write a "pure driver". To do that, you would have to first know how to the USB HID's Subclass and the exact paramters on using it. Also, if you told it to save the data to the device, and then later retrive it, it would deffinitly reduc bottlenecks. There is lots more and the hardest part would have to do with the audio. The easiest way to do it,is with Java. Get the Windows Media SDK, use Java to interface with the device. If you look at some documentation for the WMSDK, it should tell you all the video paramters and how to set it up. There should be a HID protocol for streaming data between devices maybe MTP, I am not fully sure on the semantics,but that should help you.
USB cable to work as a communication medium
How can I write a driver for a simple two headed USB cable that enables it to work as a communication medium? The only thing I want it to do is to be able to send and receive data from one machine to/from another, and they're connected to each other using this USB cable. /*the cable is a wire, with two USB plugs on both ends*/I appreciate any pointer to a reference or help.
error when i passs command line argument
hi,
when i pass this argument then this error appear.
plz help me.
[root@localhost 4-1:1.0]# echo '1' > blue
bash: echo: write error: Success
thnx
Write Error
I get the same write error. Did you find a resolution?
try passing it without the
try passing it without the '' like echo 1 > blue
Help needed
Hi Greg,
I saw your posts, its very nice and i got a lot of knowledge from them. Can you do me a favour? I'm writing a host side USB driver for ucos. Can you help me how to start....
It should be like it should check for the vendor id and for product id then it should load the driver. It should also have routines for endpoint creations. If you have any idea on this just mail to the below address
hssiddhu@yahoo.com
Thanks in advance
Siddhu
i'm writing a kernel driver for usb on arm linux-2.6.20
Hai
I'm pavan. I'm writing the kernel driver for usb.All the code is available on the kernel and i enabled the relavent features in the menuconfig .when i insert the following modules ,usbcore.ko,hid.ko,usbhid.ko,usb-stotage.ko and ohci-hcd.ko.Its giving the messages that
insmod usbcore.ko
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
insmod usbhid.ko
usbcore: registered new interface driver usbhid
drivers/usb/input/hid-core.c: v2.6:USB HID core driver
insmod usb-storage.ko
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
insmod ohci-hcd.ko
probe in platform.c is working<7>In ohci_hcd_pxa27x_drv_probe
in last module i.e ohci-hcd.ko ,its terminating by -ENODEV this i got by printk. i hope the usb is not detecting the devices ,inorder to detect devices what changes i have to made in the kenel.
i'm struck from 3days to debug this problem ,please if anyone have idea about this please share with me.
with regards
pavan
usbreplay
http://linuxtv.org/v4lwiki/index.php/USBVideo
please have a look at usbreplay and co. these tools might ease up everything quite alot
Now Delcom has variable intensity LED lights?
Looks like their latest products allow setting brightness per color?
Also looks like they cost around eighty bucks?!?
Re: Writing a Simple USB Driver
Hi there,
I am planing to write a virtual device which use USB port to talk with the computer. So, my idea is I want to developt a virtual device connect with the PC through USB port. I mean, if you have an usb lamp and you begin write a drive for it. You have a specification of the lamp. And you plug the lamp to the pc. In my case, i want to build my lamp by the software with all properties like a real lamp. So, my first problem is i don't know how to write a virtual device run on both Linux and Windows. So any idea help me now.
Thanks a lot.
Phong
Re: Writing a Simple USB Driver
Greg:
Excellent article. I went with the Delcom "USB Numeric Display", which is a numeric counter.
I noticed something on my system. When I create device files under the /sys/bus/usb/drivers/mydevice directory, and send data to it with the echo command, I can hear the disk access on my computer... It's really getting hit with a lot of data; Perl script that writes lots of changing data to the USB device. Is this normal? I'm making changes in my program so that data goes to the device from a "/proc/mydevice/entries" instead, since "/proc" seems to be mounted in ram vs. /sys on the hard drive.
I'm running 2.6.4 and /sys was mounted with "sysfs /sys sysfs defaults 0 0" in my /etc/fstab. Here's a link to how I setup 2.6
http://osdn.dl.sourceforge.net/sourceforge/souptonuts/README_26.txt
Its seems problematic if new directory trees created under /sys/bus... for input will require disk reads and writes. Maybe I'm overlooking something?
Regards,
Mike Chirico
Re: Writing a Simple USB Driver
I stand corrected.... I had the debug commands "dev_dbg" writing to the log files. Ok, good. I'm on my way.
Regards,
Mike Chirico
Re: Writing a Simple USB Driver
Here's the code if interested
code
Regards,
Mike Chirico
Re: Writing a Simple USB Driver
Great article. I'd like see an article on creating your own USB device and then creating a kernel driver for it.
Re: Writing a Simple USB Driver
Very good article, in this case, you writing a simple driver for a Led lamp. But I am researching now a virtual program simulate a led lamp and I am not found any document for this.
Re: Writing a Simple USB Driver
Looks very cool -- thanks for the article, Greg. I've ordered one of these already to set up a weather-forcast indicator to be installed by my front door.
It looks from the documentation that the device has a programmable flash rate -- it'd be cool to see support for that in the driver. And maybe the buzzer, although I don't think I have a use for that.