6.8 About USB Device Drivers

As with other bus-based subsystems in Oracle Linux, a USB device driver registers its driver object with the USB subsystem. It can then use vendor and device identifiers to determine if the USB hardware is present.

The implementation of USB device drivers is likely to differ in many respects between Linux and UNIX operating systems, with most differences arising from the functions that the driver uses to handle USB requests, the structures that are used to represent USB driver methods and to define the properties of USB devices, and the kernel interface routines for communicating with the USB infrastructure.

The usb_driver and usb_device_id structures, defined in <linux/usb.h>, describe the USB driver and the USB device types that it supports. The usb_driver defines a number of methods that the USB core can use with the device:

struct usb_driver {
        const char *name;

        int (*probe) (struct usb_interface *intf,
                      const struct usb_device_id *id);

        void (*disconnect) (struct usb_interface *intf);

        int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
                        void *buf);

        int (*suspend) (struct usb_interface *intf, pm_message_t message);
        int (*resume) (struct usb_interface *intf);
        int (*reset_resume)(struct usb_interface *intf);

        int (*pre_reset)(struct usb_interface *intf);
        int (*post_reset)(struct usb_interface *intf);

        const struct usb_device_id *id_table;

        struct usb_dynids dynids;
        struct usbdrv_wrap drvwrap;
        unsigned int no_dynamic_id:1;
        unsigned int supports_autosuspend:1;
        unsigned int soft_unbind:1;

A driver should define probe() and disconnect() methods to support initialization and cleanup when a device is plugged in or removed from the system. The driver should call usb_register() and usb_deregister() to register the driver with the USB core and to unregister it.

The urb structure defines a USB request block that the kernel uses to send data to a USB device. To send data to a device, the driver's write() method should use usb_alloc_urb() to allocate an urb, usb_buffer_alloc() to allocate a buffer for the data, copy_from_user() to write the data into the buffer, usb_fill_bulk_urb() to fill in the details of the urb, and usb_submit_urb() to submit the urb to the USB core. The USB core invokes the driver's callback() method to report the status of the transaction. The driver should use usb_buffer_free() to free the allocated buffer.

To read data from a device, the driver's read() method can use usb_bulk_msg().

The driver should use usb_control_msg() to send USB control messages.

Other useful helper functions include usb_get_descriptor() and usb_get_string() to retrieve device descriptor information or a string about a USB device.