Writing a Simple USB Driver

Give your Linux box a multicolored light you can see from across the room, and learn how to write a simple driver for the next piece of hardware you want to hook up.

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.

LEDs in Action

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

This produces the color shown in Figure 3.

Figure 3. The Device with the Red and Blue LEDs On

Is There a Better Way?

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 greg@kroah.com.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

How To Get Port Values and the Resulting LED Patterns ???

Black Spider's picture

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

techieguy22's picture

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

Anonymous's picture

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

Anonymous's picture

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

Anonymous's picture

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!

Ajay Abraham's picture

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

Anonymous's picture

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

Ajay2's picture

The command I gave was : echo 1 > blue

Solved

Anonymous's picture

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

abhinavabcd's picture

Awsome tutorial . very very inspiring .Great job ,I helped me put courage into me to write a device driver..

A driver suggestion

Toby's picture

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

Anonymous's picture

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

Devajyoti Barman's picture

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

Eloi's picture

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

Bhanu's picture

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

Anonymous's picture

You should do a Linux device driver for the USB Rocket Launcher:
http://www.thinkgeek.com/geektoys/warfare/8a0f/

USB dirver

Anonymous's picture

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...

Vadivelu N's picture

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

Sid's picture

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

Renderman's picture

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

Peyman's picture

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

syed's picture

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

Anonymous's picture

I get the same write error. Did you find a resolution?

try passing it without the

Anonymous's picture

try passing it without the '' like echo 1 > blue

Help needed

hssiddhu's picture

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

Anonymous's picture

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

Markus Rechberger's picture

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?

Anonymous's picture

Looks like their latest products allow setting brightness per color?

Also looks like they cost around eighty bucks?!?

Re: Writing a Simple USB Driver

phonghtn's picture

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

Anonymous's picture

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

Anonymous's picture

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

mchirico's picture

Here's the code if interested
code

Regards,

Mike Chirico

Re: Writing a Simple USB Driver

Anonymous's picture

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

Anonymous's picture

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

Anonymous's picture

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.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

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.

Learn More

Sponsored by Storix