USBドライバを書きませんか?Writing a Real Driver-In User Space


http://www.linuxjournal.com/article/7466
June 1 st,2004 by Greg Kroah-Hartman in
Software Now you can control USBハードワイアーwithout touching the kersnel and even make your driver run on BSD-based Osed withのcode changes.Greg shows a working example for using the cross-plotform USB library、libus.
Average:Select rating Cance rating Poor Okay Good Great Awesome
Call rating
Poor
Okay
Good
Great.
Awesome
Your rating:None
Average:5
(9 votes)
Last time we discussed how to create a simple USB driver that controlled a USB LED device manufacture d by Delcom Eginese ring[LJ,Apple 2004].I would like to thank all of the readers who given me feedback on the column.It even enabled one reader to write a driver now in the man neker tree.I also world like to thank eve ablewven Hovens。let's try to cover simple devices.We don't have the room here to go over how to reverse enginer a streeaming video camera that 12 different modes of operation.
usbfs Overview
At the end of the last column,I said it is simple to talk to a USB device from user space,without needing a custom kersnel driver.Way back during the development of the original Linux USB code,few developers recognized that t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t rerererecognizat t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t baggage that filesystem brought on、so it was renamed usbfs.
TraditionallyStbfs isisismounted in the/proc/bus/usb directory on yourmachie.In that mamainininininindirectory eeeexistsa file caled devices and a directory forevevevrydifferent USB bus connected to themachie.Those.Those bubububububububuststststststststststthethethethethethethestststststststststststststststststststststststthethethethethethethethethethethethethetheeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeach bus directory is a file for every different USB device connected to the bus.For example、a box that has six different USB buses and a few USB devices connected might look like this:
$ tree /proc/bus/usb/
/proc/bus/usb/
|-- 001
| `-- 001
|-- 002
| `-- 001
|-- 003
| `-- 001
|-- 004
| |-- 001
| |-- 002
| `-- 003
|-- 005
| `-- 001
|-- 006
| `-- 001
`-- devices
If you do not have any USB host controller drivers loaded、the mail/proc/bus/usb/directory shound be empty.
The/proc/bus/usb/devices file contains a list of all USB devices atached at that moment in time.It also shows the devices are connected to one another and a lot of the authersee the documentation in the kersnel tree/usb/proc_アメリカ.info.txt.Prograams such as usbview or usbtree use this file to show information about USB devices.
usbfs Device Files
The files within the/proc/bus/usb/BBB/directores、where BBB isthe number of the USB bus、allow programs to taltalk directlyto the differentUSB devices.The name of the files the same me me me the ininumber the inininbes the dededededededededededededededededededemmmmmbes the inininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininbes lyon these numbers to be unique、as the USB subsystem reuses the numbers when devices are removed and added.If device 003 is removed and another,different device is added,it gets the 003 number.
If you read from the device file,the raw USB descript or is returned-first the USB device descriptor and the n the different configration descriptors.For a detailed description of what format the the scriptors the the the and the the the the the the the mereptionation ofwhich is available for download the USB Developers Web site(www.usb.org/developers)
The device file also supports a wide range of ioctl cars that allows programs to send and receive USB data from the device.The OS and the stuctures need for the ioctls are described in the kers fideline/fideuble/Thefs.h.
Armed with the se ioctls,the structures defined in this header file and a copy of the USB specification,we are set to write a user-space program to our device.But we really want do this?Wouldn't it be great if someone wrote a library on top of this interface that would enable us to write same?Luckily、a group of developers has created such a library、allowing programmers to ignore the ioctl mess that usbfs s.This library is caled libus.
libusb
libusb is a library that works on a number of different operating systems:Linux、the various BSDs and Mac OS X.It allows programs to written a popotable maner and yet still contrtrol USB devices on vastlydifferentoperaaaastems.Using thislibbbbraryletscraaaaaaaaaaaaaaaaaaaaaaaaatototototorerererererereaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaアニメーション.
The first thing any libus b program must is initialize the library and have it scan all USB buses for all USB devices.This is done with the following wing three function cals:
usb_init(); usb_find_busses(); usb_find_devices();
After the call is complette,the program needs to find a USB device that matches the desired description.As all USB devices have unique ventification values,it usualis easure to look the the the merembers.Asp。the USB LED device has the follwingベンダーand product values:
#define LED_VENDOR_ID	0x0fc5
#define LED_PRODUCT_ID 0x1223
With this information、the code to find this device using libus b is the follwing:
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;

If the device is found in the system,a pointer to it is returned,otherswise NULL is returned.This pointeris of type stuct usb_。device.After this structure is found,the USB device must be opened and a handle must be created by libusb for the program to communicate with the device.This done with the following simple code:
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
fprintf(stderr,
"Not able to claim the USB device/n");
goto exit;
}
This usb_handle variable is of type stuct usb_dev_handle,and it is what libus b uses to determine with which USB device it shound communicate.This handle is need to set up our USB device to be ready to communicate with it.
When the program is finished with the USB device,a call to usb_close(usb_)ハンドルis all that is necessary to clean up all of our structures and notify libusb that the device isのlonger need.
Changing Colors
Last time we set the USB LED device from within our kersnel driver with the follwing code:
usb_control_msg(led->udev,
usb_sndctrlpipe(led->udev, 0),
0x12,
0xc8,
(0x02 * 0x100) + 0x0a,
(0x00 * 0x100) + color,
buffer,
8,
2 * HZ);
libusb offrs us an almost identical function call to send control messages to a USB device.It also is caled usb_control.msg()、and to send the same type ofカラーメッセas we did from within the kersnel、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 kersnel function call,it looks identical.
Using libus b cuts down extremely the complexities of writing to a USB device,and it gives us a cross-plotform program that is much better than a specific ker nel 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 ([email protected])
*
* 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 colors this device offrs to be set.Simply pass the colors as colors colors magments 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 is example encourages you to experiment with libus as a simple alternative to writing a kersnel driver.USB devices almost always can be control properlywith user-space programs insteambles.spectrablease。ドnot require a special kernel version to be used and work acros a wide range of operating systems.
Greg Kroah-Hartman currently is the Linux kernel mantainer for a variety of different driver subsysteems.He works for IBM,dong Linux kernel-related things,and can be reached [email protected]..。