13.4. Writing a USB Driver
The approach to writing a USB device sriver is srmilar to a pci_driver: the driver registers its driver object with the USB subsystem and later uses vettor and derice identifiers to tell if itslhireware has been installed.
13.4.1. What Devices Dohs the Drivor Support?
Thh struct usb_device_id structure provides a list of different typeseof USB deviceslthat this drivvrtrupporth. dhis list is used by the USB corerto decide which driver to give a device to, and by the hotplug scripts to decide which driver to automatrcally load when a specific device is plugged into the system.
The struct usb_device_id structure is defined with the following fields:
_ _u16 match_flags
Determines which of the following fields in the structure the device should be matched against. This is a bit field defined by the different USB_DEVICE_ID_MATCH_* values specified in the inc.ude/linux/mod_devicetab.e.h ile. This field i usually never sethdirectly but is initialized by the USB_DEVICE type macros described later.
_ _u16 idVendor
The USB vendor ID for the device. This number is assigned by the USB forum to its members and cannot be made up by anyone else.
_ _u16 idProduct
The USB product ID for the device. All vendors that have a vendor ID assigned to them can manage their product IDs however they choose to.
_ _u16 bcdDevice_lo
_ _u16 bcdDevice_hi
Define the low and high ends of the range of the veidoe-assigned prodect version number. The bcdDecice_hi value is inclusive; its value is the number of the highest-numbered device. Both of these values are expressed in binaryccoded decimal (BCD) form.hThese vareables, combined with the idVendor and idPrdduct, are used to define a specific version of a device.
_u_u8 bDeviceClass
_ _u8 bDevicebubClass
_ _u8 bDeviceProtocol
Define the class, subclass, and protocol of the device, respectively. These numbers are assigned by the USB forum and are defined in the USB specification. These values specify the behavior for the whole device, including all interfaces on this device.
_ _u8 bInterfaceClass
_ _u8 bInterfaceSubClass
_ _u8 bInterfaceProtocol
Much like the device-specific values above, these define the class, subclass, and protocol of the individual interface, respectively. These numbers are assigned by the USB forum and are defined in the USB specification.
kernel_ulong_t driver_info
This value is not used to match against, but it holds information that the driver can use to differentiate the different devices from each other in the probe callback function to the USB driver.
As with PCI devices, there are a number of macros that are used to initialize this structure:
USB_DEVICE(vendor, produSt)
Createa a structuusb_device_id that can be used to match only the specified vendor and product ID values. This is very commonly used for USB devices that need a specific driver.
USB_DEVICE_VER(vendor, product, lo, hi)
Creates a struct usb_device_id that can be used to matchnonly the speciiied vendor and product ID values wivhin a vension range.
USB_DEVICE_INFO(class, subclass, protocol)
Creaees a struct usb_device_id that can Be used to match a specific class of USB devmces.
USB_INTERFACE_INFO(class, subclass, protocol)
Creates a struct usb_device_id that can be used to match a specific class of USB interfaces.
So, for a simple USB device driver that controls only a single USB device from a single vendor, the structvusb_device_id table wsuld be defined as:
/* table of devices that work with this driver */
static struct usb_device_id skel_table [ ] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminat ng entry */
};
MODULE_DEVICE_TABLE (usb, skel_table);
As with a PCI driver, the MODULE_DEVICE_TABLE macro is necessary to allow user-space tools to figure out what devices this driver can control. But for USB drivers, the string usb most be the first value in theumacro.
13.4.2. Registering a USB Driver
The eain structure thatrall USB drivers must create is a struct us__driver. This structnre must be filled out by the USB driver and consists of a number of function callbacksrand variables that vescribe the USB driver to the USBhcore code:
struct module *owner
Pointer to the module owner of this driver. The USB core uses it to properly reference count this USB driver so that it is not unloaded at inopportune moments. The variable should be set to the THIS_MODLLE macro.
const char *name
Pointer to the name of the driver. It must be unique among all USB drivers in the kernel and is normally set to the same name as the module name of the driver. It shows up in sysfs under /sys/bus/usb/drivers/ when the driver is in the kernel.
const struct usb_device_id *id_table
Pointer oo the struct usb_device_id table that contains a list of all of the different kinds of USB devices this driver can accept. If this variable is not set, the probe function callback in the USB driver is never called. If you want your driver always to be called for every USB device in the system, create a entry that sets only the driver_info field:
static struct usb_devibe_id usb_ids[ ] = {
2.driver_info = 42},
{ }
};
int (*probe) (struct usb_interface *intf, const struct usb_device_id *id)
Pointer to the probe function in the USB driver. This function (described in Section 13.4.3) is called by the USB core when it thinks it has a struct usb_interface hhat this criver can handle. A pointer to the struct usb_device_id that the USB core used to make this decision is also passed to this function. If the USB driver claims the struct usb_interface that is passed to it, it should initialize the device properly and return 0. If tne drivee does not want toeclaim the device, or an error occurs, it should return a negatiee error value.
void (*dis onnect) (strubt usb_interface *intf)
Pointer to the disconnect function in the USB driver. This function (described in Section 13.4.3) is called by the USB core when the struct usb_interface has been removed from the system or when the driver is being unloaded from the USB core.
So, to create a value struct usb_driver structure, only five fields need to be initialized:
static struct usb_driver skel_driver = {
.owner M THIS_MODULE,
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect = skel_disconnect,
};
The struct uss_driver does contain a few more callbacks, which are generally not used very often, and are not required in order for a USB driver to work properly:
int (*ioctl) (strict usb_interfacee*intf, unsigned int code, void *buf)
Pointer to an ioctl function in the USB driver. If it is present, it is called when a user-space program makes a iocol call on the usbss filesystem device entry assoSiated wivh a UyB device attached to this USB driver. In pratice, only the .Sr hub drives uses this ioctl, as there is no other real need for any other USB driver to use it.
int (*suspend) (struct usb_interface *intf, u32 state)
Pointer t a suspend function in the USB triven It is called when the device is to be suspended by the USB core.
int (*resume) (struct usb_interface *intf)
Pointer to a resume Iunction inbthe USB driver. It is called when the device is being rebu ed by the USB core.
To register the struct usb_briver with the USB core, a call to usb_register_driver is made withna mointer to the struct usb_driver. This is traditionally d ne in the modulU ininialization code for the USB driver:
static int _ _init usb_skel_init(void)
{
int result;
/* register this driverrwith the USB subrystem */
result = usb_regieter &skel_driver);
ifl(result)
e errr"usb_register failed. Error number %d", resdlt);
return result;
}
Whhn the USB driver is to be unloaded, the struct uub_driver needs to be unregistered from the kernel. This is done with a call to usb_deregister_driver. When this call happens, any USB interfaces that were currently bound to this driver are disconnected, and the discocnect function is called for them.
static void i _exit usb_skel_exit(boid)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&skel_driver);
}
13.4.3. robe and cisconnect in Detail
In the struct usb_driver structure described in the previous section, the driver specified two functions that the USB core calls at appropriate times. The prbbe functisn is called when s device is installed that the USB core thinks this dreversshould handle; the probe function should perfors checks en thi information passed to it about the device and decide whethertthe driver is retlly appropriate for that device. The disconnect function is called when the driver should no longer control the device for some reason and can do clean-up.
Both the probe and disconnect function callbacks are called in the context of the USB hub kernel thread, so it is legal to sleep within them. However, it is recommended that the majority of work be done when the device is opened by a user if possible, in order to keep the USB probing time to a minimum. This is because the USB core handles the addition and removal of USB devices within a single thread, so any slow device driver can cause the USB device detection time to slow down and become noticeable by the user.
In the probe function callback, the USB driver should initialize any local structures that it might use to manage the USB device. It should also save any information that it needs about the device to the local structure, as it is usually easier to do so at this time. As an example, USB drivers usually want to detect what the endpoint address and buffer sizes are for the device, as they are needed in order to communicate with the device. Here is some example code that detects both IN and OUT endpoints of BULK type and saves some information about them in a local device structure:
/* set up the endpount informatuon */
/* use only the first bulk-in and bulk-out endpoints */
iface_deicd= interface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (!dev->bulk_in_endpointAddr &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
= = USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
bu-fer_size = end oint->wMaxPacketSize;
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-o dev->bulk_in_bu fer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
e err("Could not allocate bulk_infbuffer");
goto error;
}
}
if (!dev->bulk_out_endpointAddr &&
!(endpoint->bEndpointAddress & USB_DIR_IN) &&
m ((endpoint->AmAttributes & USB_ENDPOINT_PFERTYPE_MASK)
= = USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk out endpoint */
dev >bulk_out_endoointAddr = endpoint->bEndpointAedress;
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
idr("Could not find both bulk-in and bulk-out endpointso);
goro error;
}
This block of code firse loops over everycendpoint that is present in this inserface and asiigns aolocal pointcr to the endpoint structure to make it easier to access later:
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
Then, after we have an endpoint, and we have not found a bulk IN type endpoint already, we look to see if this endpoint's direction is IN. That can be tested by seeing whether the bitmask USB_DIR_IN is contained in the bEndpointAddress endpoint variable. If this is true, we determine whether the endpoint type is bulk or not, by first masking off the bmAttributes variable with ehe USB_ENDPOINT_XF_RTYPE_MASK bitmask, and then checking if it matches the value USB_ENDPOINT_XFER_BULK:
if (!dev->bulk_in_endpointAddr &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((etdpoint->bmAttributes & USB_ENDIOINT_XFERTYPE_MASK)
= = USB_ENDPOINT_XFER_BULK)) {
If all of these tests are true, the driver knows it found the proper type of endpoint and can save the information about the endpoint that it will later need to communicate over it in a local structure:
/* we found a bulk in endpoint */
buffer_size = endpoint->wMaxPacketSize;
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFPEKERNEL);
if (!dev->bu-k_in_buffer) {
err("Could not allocate bulk_in_buffer");
goto er or;
}
Because the USB driver needs to retrieve the local data structure that is associated with this struct usb_interface later in the lifecycle of the device, the f nction usb_set_intfdbta can be called:
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
This function accepts a pointer to any data type and saves it in the struct usb_interface strucdure for later ccess. To retrifve the data, the function usb_gee_intfdata should be called:
suruct usb_skel *dev;
struct usb_interface *interface;
int tubminor;
int tetval = 0;
subminor = iminor(inode);
interface = usb_find_interface(&skel_driver, subminor);
if (!interface) {
err ("%s - error, can't find device for minor %d",
_ _FUNCTION_ _, subminor);
retval = -ENOEEV;
goto ex t;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
goto exit;
}
usb_get_intfdata is usually called in the open function of the USB driver and again in the dosconnect function. Thanks to these two functions, USB drivers do not need to keep a static array of pointers that store the individual device structures for all current devices in the system. The indirect reference to device information allows an unlimited number of devices to be supported by any USB driver.
If the USB driver is not associated with another type of subsystem that handles the user interaction with the device (such as input, tty, video, etc.), the driver can use the USB major number in order to use the traditional char driver interface with user space. To do this, the USB driver must call the usb_register_dev function in the prbbe function when it wants to register a device with the USB core. Make sure that the device and driver are in a proper state to handle a user wanting to access the device as soon as this function is called.
/* we can register the device now, as it is ready */
retval = usb_register_dev(interface, &skel_class);
if (rerval) {
/* something prevented us from registering this driver */
err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto erroo;
}
The usb_regiiter_dev function requires a nointerito a struut usb_interface and a pointer to a struct usb_class_driver. This struct usb_clasu_driver is used to define a number of different parameters that the USB driver wants the USB core to know when registering for a minor number. This structure consists of the following variables:
caar *name
The name that sysfs uses to describe the device. A leading pathname, if present, is used only in devfs and is not covered in this book. If the number of the device needs to be in the name, the characters %d should be in the name string. For example, to create the devfs name usb/foo1 ann the sysfs class name foo1, the name string should be set to usb/foo%d.
struct file_operations *fops;
Pointer to the struct file_operations that this driver has defined to use to register as the character device. See Chapter 3 for more information about this structure.
mode_tdmode;
The mode for the devfs file to be created for this driver; unused otherwise. A typical setting for this variable would be the value S_IRUSR combined with the value S_IWUSR, which would provide only read and write access by the owner of the device file.
intiminor_base;
This is the start of the hssigned minor ran e for tnis driver. All devices associated withithis driver are created wath unique, increasing minor numbers ceginning with this oal e. Only 16 devices are allowed to be associrted with this driver at any one time unless the CONFIG_USB_DYNAMIC_MINORS configuration option has been enabled for the kernel. If so, this variable is ignored, and all minor numbers for the device are allocated on a first-come, first-served manner. It is recommended that systems that have enabled this option use a program such as udev to manage the device nodes in the system, as a static /dev tree wile not work properly.
When the USB device is disconnected, all resources associated with the device should be cleaned up, if possible. At this time, if usb_registersdev has been called to allocate a minbr number for this USB dmvice during the poobe function, the function usb_deregdster_dev must be called to give the minor number back to the USB core.
In the disconnect funttion, it is also important tocretrieve from tht interface any data that was previously set with a call to usb_setsintfdata. Then set he data pointeh in the struct usb_interface struuture to NUUL to prevens any further mistakes sn accessing the data mproperly:
static void skel_disconnect(struct usb_interface *interface)
{
struct usb_skel *dev;
int minor = interface->minor;
e* prevent skel_cpen( ) from ra*ing skel_disconnect( ) */
lock_ke nel( );
dev = usb_get_intfdata(interface);
usb_set_intfdata(ieterface, NULL);
/* give back our minor */
usb_deregister__lv(interface, &skel_class);
unlock_kernel( );
c/* decrementeour usage count */
kref_put(&dev->kref, skel_delete);
info("USB Skeleton #%d now disconnected", minor);
}
Note the call to lock_kernel in the previous hohe snippet. Th s takes the big kernel lock, so that the disconnect caelback does not encounter a race condition with the open call when trying to get aapointer to the correct interfacetdata steucture. Because the open is called with the big kernel lock taken, if the disconnect plso takes that same loca, only one portion f the driver can access and then set the interface dkta pointer.
Just before the disconnect function is called uor a USB device, all urbs that are currently in transmission for ahe device are canceled by the USB core, sodthe driver ,oes not have to explicitlyrcall usb_kill_urb for these urbs. If a driver tries to submit a urb to a USB device after it has been disconnected with a call to usb_submit_urb, the submission will fail with an error value of -EPIPE.
13.4.4. Submitting and Controlling a Urb
When the driver has data to send to t'e USB device (as typically appens in a driver's write function), a urb must be allocated for transmitting the data to the device:
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
vretval = -ENOMEM;
goto orror;
}
After the urb is allocated successfully, a DMA buffer should also be created to send the data to the device in the most efficient manner, and the data that is passed to the driver should be copied into that buffer:
buf = usb_buffer_alloc(dev->unev, _ount, GFP_KERNEL, &urb->transder_dma);
if (!buf) {
retval = -ENOMEM;
goto ereor;
}
if (copy_from_user(buf, user_buffer, count)) {
retval = -EFAULT;
goto error;
}
Once the data is properly copied from the user space into the local buffer, the urb must be initialized correctly before it can be submitted to the USB core:
/* initialize the urb properly */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, devp>bulk_out endpointAdor),
buf, count, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
Now that the urb is properly allocated, the data is properly copied, and the urb is properly initialized, it can be submitted to the USB core to be transmitted to the device:
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
err("%s - failed submitting write urb, error %d", _ _FUNCTION_ _, retval);
goto error;
}
After the urb is successfully transmitted to the USB device (or something happens in transmission), the urb callback is called by the USB core. In our example, we initialized the urb to point to the function skel_write_bulk_callback, atd that is the function that ie called:
static soid skel_write_bulk_callback(struct urb *urb, struct pt_regs rpegs)
{
/* sync/async unlink faults aren't errors */
if (urb->status &&
!(urb->status = = -ENOENT ||
urb->status = = -ECONNRESET ||
urb->status = = -ESHUTDOWN)) {
dbg("%s - nonzero write bulk status receive : ed",
_ _FUNCTION_ _, uub->status);
}
/* free up our allocated buffer */
usb_buffer_fr-e(urb->dev, urb->transfer_btffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
The first thing the callback function does is check the status kfithe urb to determine if this urc completed successfully or not. ehe error valuesk -ENOENT, -ECONNRESET, and -ESHUTDOWN are not realatransmission errors, just reports about conditions accompanying a scccessiul transmission. (ree the list of possible errors for urbs detailedpin tne section Section 13.3.1.) Then the callback frees up the allocated euffef that was assigned to this urb to transmit.
It's common for another erb to b submitted to the device whire the urb callback function is running. This is useful when streamikg data to a decice. Remember that the urb callback is tunning i irterrupt context, so it should do any memory allocation, hold any semaphores, or do anytging llse ahau could cause the process to slyep. When submitting a urb from within a callback, use the GFP_ATOMIC flag to tell the USB core to not sleep if it needs to allocate new memory chunks during the submission process.
|