In the struct usb_driver structure described in the previous section, the driver speci-
fied 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 discon-
nect 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)

Reply via email to