Writing a Real Driver—In User Space
Last time we set the color of the USB LED device from within our kernel driver with the following code:
usb_control_msg(led->udev,
usb_sndctrlpipe(led->udev, 0),
0x12,
0xc8,
(0x02 * 0x100) + 0x0a,
(0x00 * 0x100) + color,
buffer,
8,
2 * HZ);
libusb offers us an almost identical function call to send control messages to a USB device. It also is called usb_control_msg(), and to send the same type of color message as we did from within the kernel, our user-space program does it like this:
usb_control_msg(handle,
0xc8,
0x12,
(0x02 * 0x100) + 0x0a,
(0c00 * 0x100) + color,
buffer,
8,
5000);
Other than the request type and request variables being reversed from the kernel function call, it looks identical.
Using libusb cuts down extremely the complexities of writing to a USB device, and it gives us a cross-platform program that is much better than a specific kernel driver for most devices.
Listing 1. Controlling a USB LED Device
/*
* Set LED - program to control a USB LED device
* from user space using libusb
*
* Copyright (C) 2004
* Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can
* redistribute it and/or modify it under the terms
* of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the
* License.
*
*/
#include <stdio.h>
#include <string.h>
#include <usb.h>
#define NONE 0x00
#define BLUE 0x04
#define RED 0x02
#define GREEN 0x01
#define LED_VENDOR_ID 0x0fc5
#define LED_PRODUCT_ID 0x1223
static void change_color
(struct usb_dev_handle *handle,
unsigned char color)
{
char *dummy;
usb_control_msg(handle,
0x000000c8,
0x00000012,
(0x02 * 0x100) + 0x0a,
0xff & (~color),
dummy,
0x00000008,
5000);
}
static struct usb_device *device_init(void)
{
struct usb_bus *usb_bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (usb_bus = usb_busses;
usb_bus;
usb_bus = usb_bus->next) {
for (dev = usb_bus->devices;
dev;
dev = dev->next) {
if ((dev->descriptor.idVendor
== LED_VENDOR_ID) &&
(dev->descriptor.idProduct
== LED_PRODUCT_ID))
return dev;
}
}
return NULL;
}
int main(int argc, char **argv)
{
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
int retval = 1;
int i;
unsigned char color = NONE;
usb_dev = device_init();
if (usb_dev == NULL) {
fprintf(stderr, "Device not foundn\n");
goto exit;
}
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
fprintf(stderr,
goto exit;
}
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
fprintf(stderr,
"Not able to claim the USB device\n");
goto exit;
}
if (argc == 1) {
fprintf(stderr,
"specify at least 1 color\n");
goto exit;
}
for (i = 1; i < argc; ++i) {
if (strcasecmp(argv[i], "red") == 0)
color |= RED;
if (strcasecmp(argv[i], "blue") == 0)
color |= BLUE;
if (strcasecmp(argv[i], "green") == 0)
color |= GREEN;
if (strcasecmp(argv[i], "none") == 0)
color = NONE;
}
change_color(usb_handle, color);
retval = 0;
exit:
usb_close(usb_handle);
return retval;
}
Listing 1 allows any mixture of the three possible colors this device offers to be set. Simply pass the colors as command-line arguments to make changes:
To set the red led:
set_led red
To set the green and blue led:
set_led green blue
To turn off all leds:
set_led none
I hope that this example encourages you to experiment with libusb as a simple alternative to writing a kernel driver. USB devices almost always can be controlled properly with user-space programs instead of specialized kernel drivers. User-space programs using libusb are much easier to debug, do not require a special kernel version to be used and work across a wide range of operating systems.
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.
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?
- One Hand Slapping
- Home, My Backup Data Center
- What's the tweeting protocol?
- RSS Feeds
- Readers' Choice Awards 2011
- Trying to Tame the Tablet
- Reply to comment | Linux Journal
4 hours 38 min ago - Reply to comment | Linux Journal
7 hours 11 min ago - Reply to comment | Linux Journal
8 hours 28 min ago - great post
9 hours 3 min ago - Google Docs
9 hours 25 min ago - Reply to comment | Linux Journal
14 hours 14 min ago - Reply to comment | Linux Journal
15 hours 1 min ago - Web Hosting IQ
16 hours 34 min ago - Thanks for taking the time to
18 hours 11 min ago - Linux is good
20 hours 9 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 create device entry under /dev in rootfs
Hi,
I am facing a issue, while creating /dev entry for LCD backlight driver.
I am using following functions for doing the same.
1) alloc_chrdev_region(&bl->bdev, 0, 1, BIHP_BL_DEVICE_NAME);
2) cdev_init(&bl->cdev, &bl_fops);
3) cdev_add(&bl->cdev, bl->bdev, 1);
Compilation is done properly, If I check /dev entry for backlight there it is showing nothing.
Please let me know, Am I doing any thing wrong?
Kind Regards,
Santhosh Reddy.P
Check /proc/devices
The device name (BIHP_BL_DEVICE_NAME) you specify in alloc_chrdev_region() puts an entry in /proc/devices not /dev. You create the /dev file with mknod.
Mitch Frazier is an Associate Editor for Linux Journal.
/proc/bus/usb deprecated
Just FYI /proc/bus/usb has been deprecated for a while and in fact is no longer mounted by default on recent Linux distros. The new location is /dev/bus/usb.
libusb-1.0.2
I've been trying to figure out how to do an isochronous read but I'm not having any luck. Could you please outline the sequence of steps to accomplish this. I'm using libusb_fill_iso_transfer () followed by libusb_submit_transfer () but this hangs up inside libusb. I'm suspicious that libusb is incomplete since I don't see any way of specifying the interval.
Also, I need to get at the manufacturers name string, but all I can find is an index (iManufacturer) in the device descriptor. There should be an access function.
So far I've been able to open this device, detach the kernel driver and claim the interface.
The device has a vendorId=18f5 and a productId=1000 (yes, it's in the Linux list). The device contains 2 joysticks and 16 switches (it's not a gaming device), I need to read the raw data so that I can extract the individual components. I have the memory map. Using usbviewer I found one endpoint at 0x81, the transfer size is 12 bytes and the interval is 5ms.
Hurst
access data from USB using c++
how can i access data from USB using c++ code, libusb1.0, in linux.
Some questions.
Hello, it's a very nice posting and great help for newbie like me.
I'm trying to implement a usb driver that enables a programmer can write a program to communicate with a usb device. But your advice seems not working for me because our device has API that communicate with the device and I just want the api can initialize the device and programmers don't have to care about it.
Could you give me any advice on that?
Also, I'm confused about the header file you included in the program. It has usb.h instead of libusb.h. is it something different from the libusb.h or you just wrote another header that refers libusb.h?
Thanks,
USBFS IOCTLS
Hi ,
This is a very interesting article . Is the documentation for using USBFS IOCTL's documented .
I wanted to issue basic USB String Descriptor to a device .
Help is appreciated
Thanks
What are the usb_control_msg values?
Hi Greg -
Thanks for the great article. It's been a big help in writing a program to talk to a little communications board that I'm working with.
I have a question about the usb_control_msg() function, and I can't find any documentation on it (no man page, even on the Google?).
What are requesttype, request, value, and index for, exactly? Your program has requesttype 0x000000c8 (not sure where this is defined/how you chose it), request 0x00000012 (again, not sure how you decided this was the option to use), value (0x02 * 0x100) + 0x0a, index 0xff & (~color). It seems a little odd to me, wouldn't the request type/etc simply be part of the usb packet header and the data would be which pins you're setting? Probably my device is a little more complicated :).
I've been using SnoopyPro to sniff my device (i have a program for windows that interfaces with it correctly) and all the communication with the device is using Function "BULK_OR_INTERRUPT_TRANSFER" (0x09), so I'm guessing this would be my request_type? or my request? My device receives data via the buffer variable, so buffer and length are a no brainer (I know what these values need to be), I'm just not sure about these header-y things. If you have any idea or know a good place for documentation, toss it my way.
Thanks a ton,
Reid
yeah! What are the usb_control_msg values?
Somebody can you tell us?
According SnoopyPro for my device i got something like this:
-----------
URB Header (length: 80)
SequenceNumber: 10
Function: 001b (CLASS_INTERFACE)
PipeHandle: 00000000
SetupPacket:
0000: 22 01 00 03 00 00 00 00
bmRequestType: 22
DIR: Host-To-Device
TYPE: Class
RECIPIENT: Endpoint
bRequest: 01
No TransferBuffer
-----------
I guess that bmRequestType:22 is the 2nd parameter, bRequest:01 is the 3rd. But, what about the 'value' and 'index' parameters?
If you read the line-> 0000: 22 01 00 03 00 00 00 00 it's the command sent to the device .. but how can i put this into the usb_control_msg function?
Thanks!
PS: I don't speak english ... sorry
Errors while compilling
Anybody could help me?
I found some errors wihle I tried do compile this example:
g++ -c -o usb.o usb.cc
usb.cc: In function ‘void change_color(usb_dev_handle*, unsigned char)’:
usb.cc:24: error: ‘usb_control_msg’ was not declared in this scope
usb.cc: In function ‘usb_device* device_init()’:
usb.cc:30: error: ‘usb_init’ was not declared in this scope
usb.cc:31: error: ‘usb_find_busses’ was not declared in this scope
usb.cc:32: error: ‘usb_find_devices’ was not declared in this scope
usb.cc:33: error: ‘usb_busses’ was not declared in this scope
usb.cc:35: error: invalid use of undefined type ‘struct usb_bus’
usb.cc:28: error: forward declaration of ‘struct usb_bus’
usb.cc:36: error: invalid use of undefined type ‘struct usb_bus’
usb.cc:28: error: forward declaration of ‘struct usb_bus’
usb.cc:38: error: invalid use of undefined type ‘struct usb_device’
usb.cc:26: error: forward declaration of ‘struct usb_device’
usb.cc:39: error: invalid use of undefined type ‘struct usb_device’
usb.cc:26: error: forward declaration of ‘struct usb_device’
usb.cc:41: error: invalid use of undefined type ‘struct usb_device’
usb.cc:26: error: forward declaration of ‘struct usb_device’
usb.cc: In function ‘int main(int, char**)’:
usb.cc:60: error: ‘usb_open’ was not declared in this scope
usb.cc:63: error: expected primary-expression before ‘goto’
usb.cc:89: error: ‘usb_close’ was not declared in this scope
expected primary-expression before "goto"
Same problem when I try to use goto in the place like these
if(goto location);
OR
i!=j?goto location:exit;
If you know the solution or why is this happening plz mail me.
Thnks,
Daniel
Errors while compilling
Hi Felipe,
Try this:
locate libusb
/usr/lib/libusbhid.a
/usr/lib/libusbhid.so.3.0
/usr/lib/libusbhid_p.a
/usr/lib/libusbhid_pic.a
/usr/local/bin/libusb-config
/usr/local/lib/libusb.a
/usr/local/lib/libusb.so.8.2
/usr/local/lib/libusbpp.a
/usr/local/lib/libusbpp.so.9.0
/var/db/pkg/libusb-0.1.10ap1
/var/db/pkg/libusb-0.1.10ap1/+CONTENTS
/var/db/pkg/libusb-0.1.10ap1/+DESC
/var/db/pkg/libusb-0.1.10ap1/+REQUIRED_BY
gcc -o driver driver.c -L/usr/local/lib -lusb
It compiles without problems on OpenBSD 4.1, just remember to force library path to libusb to compile.
HELP ME ???
Hi,
I wanted to write just a simple driver for my usb-mass-storage (memory stick).
All I want to do is to flash (On/Off) the led on the device. It is only one led, I changed the LED_VENDOR_ID and LED_PRODUCT_ID Everything works fine, except that this usb_control_msg() doesnt work for this device :(!
Can someone help me with this? All I want is to switch this Led On and Off! Nothing more :).
Do I have to use another function? Is there a function that can manage to do this(put this only Led on)?
I hope u can help me with this.
Thank you
Little mistake in the code
In the program code appears:
if (usb_handle == NULL) {
fprintf(stderr,
goto exit;
}
I think this is a block that can be deleted because the error check is also done in the next block.
¡Nice article!
Bad code...
Hmm, goto's are bad anywhere.
Also doesn't your control message write 8 bytes to a random location (dummy isn't initialised)?
And you don't use usb_claim_interface() anywhere. The doc's say this "Must be called!" I'm not entirely sure what an interface is yet though. libusb has terrible documentation. It is also the best example of why C++ is better than C that I've ever seen.
Re: Writing a Real Driver
hello,
I just want to ask for some links to more information about USB in general, how to implement USB in Self build devices,
An overview, how USB (and pehaps also the serial and parallel interface) are implemented in Gnu/Linux and also BSD-Unix.
I'm an Engineer and it was easy to send some bytes to a device in the Dos Area - continued in Win9x. How can I do it - as easy as possible in Linux, especialy if new computers only have USB - this is the Future if we believe Intel
Greatings
D. Schneider
Re: Writing a Real Driver
hello,
this is in your example code:
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
fprintf(stderr,
goto exit;
}
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
fprintf(stderr,
"Not able to claim the USB device
");
goto exit;
}
Sorry for the request but the libusb developer manual say to call usb_init() and usb_claim_device() (for claim), before any operation with USB device...
There are step by step example to respect correct order?
Greatings
R.LOBERTO
ioctl for massive storage device
Hi,
I want to access the massive storage device (memory stick) using ioctl instead of libusb. Can you recommend a reference for this purpose?
I tried to do the work but was not successful. The sequence of actions I did is as following:
/*open the device*/
fd = open(file, O_RDWR);
/*reset the device*/
ioctl(fd, USBDEVFS_RESET, NULL);
close(fd);
fd = open(file, O_RDWR);
/*configure the device*/
ioctl(fd, USBDEVFS_SETCONFIGURATION, &configuration);
/*claim the interface*/
ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
/*read data via the bulk endpoint*/
ioctl(fd, USBDEVFS_BULK, &bulk);
All steps successed until it failed at the last step.
Regards,
Jing