Commit 2492b740 authored by Jürgen Quade's avatar Jürgen Quade Committed by Greg Kroah-Hartman

[PATCH] USB: writing usb driver documentation update

I noticed, that your documentation of your usb-skeleton driver
is not up to date. So I took the time to rework it slightly.
I append the patch to the version I found in kernel 2.6.0-test3.
parent 20612862
...@@ -202,41 +202,21 @@ MODULE_DEVICE_TABLE (usb, skel_table); ...@@ -202,41 +202,21 @@ MODULE_DEVICE_TABLE (usb, skel_table);
are passed to the function: are passed to the function:
</para> </para>
<programlisting> <programlisting>
static void * skel_probe(struct usb_device *dev, static int skel_probe(struct usb_interface *interface,
unsigned int ifnum, const struct usb_device_id *id) const struct usb_device_id *id)
</programlisting> </programlisting>
<para> <para>
The driver now needs to verify that this device is actually one that it The driver now needs to verify that this device is actually one that it
can accept. If not, or if any error occurs during initialization, a NULL can accept. If so, it returns 0.
value is returned from the probe function. Otherwise a pointer to a If not, or if any error occurs during initialization, an errorcode
private data structure containing the driver's state for this device is (such as <literal>-ENOMEM<literal> or <literal>-ENODEV<literal>)
returned. That pointer is stored in the usb_device structure, and all is returned from the probe function.
callbacks to the driver pass that pointer.
</para> </para>
<para> <para>
In the skeleton driver, we determine what end points are marked as bulk-in In the skeleton driver, we determine what end points are marked as bulk-in
and bulk-out. We create buffers to hold the data that will be sent and and bulk-out. We create buffers to hold the data that will be sent and
received from the device, and a USB urb to write data to the device is received from the device, and a USB urb to write data to the device is
initialized. Also, we register the device with the devfs subsystem, initialized.
allowing users of devfs to access our device. That registration looks like
the following:
</para>
<programlisting>
/* initialize the devfs node for this device and register it */
sprintf(name, &quot;skel%d&quot;, skel->minor);
skel->devfs = devfs_register (usb_devfs_handle,
name,
DEVFS_FL_DEFAULT,
USB_MAJOR,
USB_SKEL_MINOR_BASE + skel->minor,
S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
&amp;skel_fops,
NULL);
</programlisting>
<para>
If the devfs_register function fails, we do not care, as the devfs
subsystem will report this to the user.
</para> </para>
<para> <para>
Conversely, when the device is removed from the USB bus, the disconnect Conversely, when the device is removed from the USB bus, the disconnect
...@@ -254,23 +234,18 @@ devfs_unregister(skel->devfs); ...@@ -254,23 +234,18 @@ devfs_unregister(skel->devfs);
the device, any of the functions in the file_operations structure that the device, any of the functions in the file_operations structure that
were passed to the USB subsystem will be called from a user program trying were passed to the USB subsystem will be called from a user program trying
to talk to the device. The first function called will be open, as the to talk to the device. The first function called will be open, as the
program tries to open the device for I/O. Within the skeleton driver's program tries to open the device for I/O. We increment our private usage
open function we increment the driver's usage count if it is a module with
a call to MODULE_INC_USE_COUNT. With this macro call, if the driver is
compiled as a module, the driver cannot be unloaded until a corresponding
MODULE_DEC_USE_COUNT macro is called. We also increment our private usage
count and save off a pointer to our internal structure in the file count and save off a pointer to our internal structure in the file
structure. This is done so that future calls to file operations will structure. This is done so that future calls to file operations will
enable the driver to determine which device the user is addressing. All of enable the driver to determine which device the user is addressing. All
this is done with the following code: of this is done with the following code:
</para> </para>
<programlisting> <programlisting>
/* increment our usage count for the module */ /* increment our usage count for the module */
MOD_INC_USE_COUNT;
++skel->open_count; ++skel->open_count;
/* save our object in the file's private structure */ /* save our object in the file's private structure */
file->private_data = skel; file->private_data = dev;
</programlisting> </programlisting>
<para> <para>
After the open function is called, the read and write functions are called After the open function is called, the read and write functions are called
...@@ -350,24 +325,11 @@ if (!retval) { ...@@ -350,24 +325,11 @@ if (!retval) {
<para> <para>
When the user program releases the file handle that it has been using to When the user program releases the file handle that it has been using to
talk to the device, the release function in the driver is called. In this talk to the device, the release function in the driver is called. In this
function we decrement the module usage count with a call to function we decrement our private usage count and wait for possible
MOD_DEC_USE_COUNT (to match our previous call to MOD_INC_USE_COUNT). We pending writes:
also determine if there are any other programs that are currently talking
to the device (a device may be opened by more than one program at one
time). If this is the last user of the device, then we shut down any
possible pending writes that might be currently occurring. This is all
done with:
</para>
<programlisting> <programlisting>
/* decrement our usage count for the device */ /* decrement our usage count for the device */
--skel->open_count; --skel->open_count;
if (skel->open_count &lt;= 0) {
/* shutdown any bulk writes that might be going on */
usb_unlink_urb (skel->write_urb);
skel->open_count = 0;
}
/* decrement our usage count for the module */
MOD_DEC_USE_COUNT;
</programlisting> </programlisting>
<para> <para>
One of the more difficult problems that USB drivers must be able to handle One of the more difficult problems that USB drivers must be able to handle
...@@ -375,49 +337,34 @@ MOD_DEC_USE_COUNT; ...@@ -375,49 +337,34 @@ MOD_DEC_USE_COUNT;
any point in time, even if a program is currently talking to it. It needs any point in time, even if a program is currently talking to it. It needs
to be able to shut down any current reads and writes and notify the to be able to shut down any current reads and writes and notify the
user-space programs that the device is no longer there. The following user-space programs that the device is no longer there. The following
code is an example of how to do this: </para> code (function <function>skel_delete</function>)
is an example of how to do this: </para>
<programlisting> <programlisting>
/* if the device is not opened, then we clean right now */ static inline void skel_delete (struct usb_skel *dev)
if (skel->open_count) { {
minor_table[skel->minor] = NULL; if (dev->bulk_in_buffer != NULL)
if (skel->bulk_in_buffer != NULL) kfree (dev->bulk_in_buffer);
kfree (skel->bulk_in_buffer); if (dev->bulk_out_buffer != NULL)
if (skel->bulk_out_buffer != NULL) usb_buffer_free (dev->udev, dev->bulk_out_size,
kfree (skel->bulk_out_buffer); dev->bulk_out_buffer,
if (skel->write_urb != NULL) dev->write_urb->transfer_dma);
usb_free_urb (skel->write_urb); if (dev->write_urb != NULL)
kfree (skel); usb_free_urb (dev->write_urb);
} else { kfree (dev);
skel->dev = NULL;
up (&amp;skel->sem);
} }
</programlisting> </programlisting>
<para> <para>
If a program currently has an open handle to the device, we only null the If a program currently has an open handle to the device, we reset the flag
usb_device structure in our local structure, as it has now gone away. For <literal>device_present</literal>. For
every read, write, release and other functions that expect a device to be every read, write, release and other functions that expect a device to be
present, the driver first checks to see if this usb_device structure is present, the driver first checks this flag to see if the device is
still present. If not, it releases that the device has disappeared, and a still present. If not, it releases that the device has disappeared, and a
-ENODEV error is returned to the user-space program. When the release -ENODEV error is returned to the user-space program. When the release
function is eventually called, it determines if there is no usb_device function is eventually called, it determines if there is no device
structure and if not, it does the cleanup that the skel_disconnect and if not, it does the cleanup that the skel_disconnect
function normally does if there are no open files on the device (see function normally does if there are no open files on the device (see
Listing 5). Listing 5).
</para> </para>
<programlisting>
if (skel->dev == NULL) {
/* the device was unplugged before the file was released */
minor_table[skel->minor] = NULL;
if (skel->bulk_in_buffer != NULL)
kfree (skel->bulk_in_buffer);
if (skel->bulk_out_buffer != NULL)
kfree (skel->bulk_out_buffer);
if (skel->write_urb != NULL)
usb_free_urb (skel->write_urb);
kfree (skel);
goto exit;
}
</programlisting>
</chapter> </chapter>
<chapter id="iso"> <chapter id="iso">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment