Linux Device Drivers (3rd Edition) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Linux Device Drivers (3rd Edition) [Electronic resources] - نسخه متنی

Jonathan Corbet, Greg Kroah-Hartman, Alessandro Rubini

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








13.4. Writing a USB Driver


The approach to writing a USB
device driver is similar to a
pci_driver: the driver registers its driver object
with the USB subsystem and later uses vendor and device identifiers
to tell if its hardware has been installed.


13.4.1. What Devices Does the Driver Support?


The struct usb_device_id structure provides a list
of different types of USB devices that this driver supports. This
list is used by the USB core to decide which driver to give a device
to, and by the hotplug scripts to decide which driver to
automatically 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 include/linux/mod_devicetable.h file.
This field is usually never set directly 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 vendor-assigned
product version number. The bcdDevice_hi value is
inclusive; its value is the number of the highest-numbered device.
Both of these values are expressed in
binary-coded decimal (BCD) form. These
variables, combined with the idVendor and
idProduct, are used to define a specific version
of a device.


_ _u8 bDeviceClass

_ _u8 bDeviceSubClass

_ _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, product)


Creates a struct usb_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
match only the specified vendor and product ID values within a
version range.


USB_DEVICE_INFO(class, subclass, protocol)


Creates a struct usb_device_id that can be used to
match a specific class of USB devices.


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 struct
usb_device_id
table would 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) },
{ } /* Terminating 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 must be the first value in the macro.


13.4.2. Registering a USB Driver


The main structure that all USB
drivers must create is a
struct usb_driver. This
structure must be filled out by the USB driver and consists of a
number of function callbacks and variables that describe the USB
driver to the USB core 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_MODULE 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 to 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_device_id usb_ids[  ] = {
{.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 that this driver 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
the driver does not want to claim the device, or an error occurs, it
should return a negative error value.


void (*disconnect) (struct 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 = THIS_MODULE,
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect = skel_disconnect,
};

The struct usb_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) (struct usb_interface *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
ioctl call on the usbfs
filesystem device entry associated with a USB device attached to this
USB driver. In pratice, only the USB hub driver 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 to a suspend function in the USB driver. It is called when
the device is to be suspended by the USB core.


int (*resume) (struct usb_interface *intf)


Pointer to a resume function in the USB driver. It is called when the
device is being resumed by the USB core.



To register the
struct
usb_driver with
the USB core, a call to usb_register_driver is
made with a pointer to the struct
usb_driver. This is traditionally done in the
module initialization code for the USB driver:

static int _ _init usb_skel_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&skel_driver);
if (result)
err("usb_register failed. Error number %d", result);
return result;
}

When the USB driver is to
be unloaded, the struct
usb_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
disconnect
function is called for them.

static void _ _exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&skel_driver);
}


13.4.3. probe and disconnect 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 probe
function is called when a device is installed that the USB core
thinks this driver should handle; the probe
function should perform checks on the information passed to it about
the device and decide whether the driver is really 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 endpoint information */
/* use only the first bulk-in and bulk-out endpoints */
iface_desc = 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 */
buffer_size = endpoint->wMaxPacketSize;
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
err("Could not allocate bulk_in_buffer");
goto error;
}
}
if (!dev->bulk_out_endpointAddr &&
!(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
= = USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk out endpoint */
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
err("Could not find both bulk-in and bulk-out endpoints");
goto error;
}

This block of code first loops over every endpoint that is present in
this interface and assigns a local pointer 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 the
USB_ENDPOINT_XFERTYPE_MASK bitmask, and then
checking if it matches the value
USB_ENDPOINT_XFER_BULK:

if (!dev->bulk_in_endpointAddr &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_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, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
err("Could not allocate bulk_in_buffer");
goto error;
}

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 function

usb_set_intfdata
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 structure for later access. To
retrieve the data, the function usb_get_intfdata
should be called:

struct usb_skel *dev;
struct usb_interface *interface;
int subminor;
int retval = 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 = -ENODEV;
goto exit;
}
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
disconnect 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
probe 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 (retval) {
/* something prevented us from registering this driver */
err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}

The
usb_register_dev
function requires a pointer to a struct
usb_interface and a pointer to a
struct usb_class_driver. This
struct usb_class_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:

char *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 and 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_t mode;


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.


int minor_base;


This is the start of the assigned minor range for this driver. All
devices associated with this driver are created with unique,
increasing minor numbers beginning with this value. Only 16 devices
are allowed to be associated 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 will 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_register_dev has been called to allocate a
minor number for this USB device during the
probe function, the function
usb_deregister_dev must be called to give the
minor number back to the USB core.

In the disconnect
function, it is also important to
retrieve from the interface any data that was previously set with a
call to usb_set_intfdata. Then set the data
pointer in the struct
usb_interface structure to NULL
to prevent any further mistakes in accessing the data improperly:

static void skel_disconnect(struct usb_interface *interface)
{
struct usb_skel *dev;
int minor = interface->minor;
/* prevent skel_open( ) from racing skel_disconnect( ) */
lock_kernel( );
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &skel_class);
unlock_kernel( );
/* decrement our usage count */
kref_put(&dev->kref, skel_delete);
info("USB Skeleton #%d now disconnected", minor);
}

Note the call to lock_kernel in the previous
code snippet. This takes the big kernel lock, so that the
disconnect callback does not encounter a race
condition with the open call when trying to get a pointer to the
correct interface data structure. Because the
open is called with the big kernel lock taken,
if the disconnect also takes that same lock,
only one portion of the driver can access and then set the interface
data pointer.

Just before the disconnect function is called
for a USB device, all urbs that are currently in transmission for the
device are canceled by the USB core, so the driver does not have to
explicitly call 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 the USB device (as typically happens
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) {
retval = -ENOMEM;
goto error;
}

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->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}
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, dev->bulk_out_endpointAddr),
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, and that is
the function that is called:

static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
/* 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 received: %d",
_ _FUNCTION_ _, urb->status);
}
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}

The first thing the callback function does is check the status of the
urb to determine if this urb completed successfully or not. The error
values, -ENOENT, -ECONNRESET,
and -ESHUTDOWN are not real transmission errors,
just reports about conditions accompanying a successful transmission.
(See the list of possible errors for urbs detailed in the section
Section 13.3.1.) Then the callback frees up the allocated
buffer that was assigned to this urb to transmit.

It's common for another urb to be submitted to the
device while the urb callback function is running. This is useful
when streaming data to a device. Remember that the urb callback is
running in interrupt context, so it should do any memory allocation,
hold any semaphores, or do anything else that could cause the process
to sleep. 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.


    / 202