patch-2.4.0-test10 linux/drivers/usb/usb.c
Next file: linux/drivers/usb/usbmouse.c
Previous file: linux/drivers/usb/usb-uhci.c
Back to the patch index
Back to the overall index
- Lines: 162
- Date:
Tue Oct 31 12:24:04 2000
- Orig file:
v2.4.0-test9/linux/drivers/usb/usb.c
- Orig date:
Sun Oct 8 10:50:31 2000
diff -u --recursive --new-file v2.4.0-test9/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
@@ -26,6 +26,7 @@
#include <linux/malloc.h>
#include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/kmod.h>
+#include <linux/init.h>
#ifdef CONFIG_USB_DEBUG
@@ -47,6 +48,9 @@
0;
#endif
+extern int usb_hub_init(void);
+extern void usb_hub_cleanup(void);
+
/*
* Prototypes for the device driver probing/loading functions
*/
@@ -462,6 +466,10 @@
* We now walk the list of registered USB drivers,
* looking for one that will accept this interface.
*
+ * "New Style" drivers use a table describing the devices and interfaces
+ * they handle. Those tables are available to user mode tools deciding
+ * whether to load driver modules for a new device.
+ *
* The probe return value is changed to be a private pointer. This way
* the drivers don't have to dig around in our structures to set the
* private pointer if they only need one interface.
@@ -490,7 +498,70 @@
tmp = tmp->next;
down(&driver->serialize);
- private = driver->probe(dev, ifnum);
+
+ /* new style driver? */
+ if (driver->bind) {
+ const struct usb_device_id *id = driver->id_table;
+
+ if (id) {
+ /* scan device ids for a match */
+ for (;; id++) {
+ struct usb_interface_descriptor *intf = 0;
+
+ /* done? */
+ if (!id->idVendor && !id->bDeviceClass && !id->bInterfaceClass) {
+ id = 0;
+ break;
+ }
+
+ /* Vendor match, possibly product-specific? */
+ if (id->idVendor && id->idVendor == dev->descriptor.idVendor) {
+ if (id->idProduct && id->idProduct != dev->descriptor.idProduct)
+ continue;
+ break;
+ }
+
+ /* Device class match? */
+ if (id->bDeviceClass
+ && id->bDeviceClass == dev->descriptor.bDeviceClass) {
+ if (id->bDeviceSubClass && id->bDeviceSubClass
+ != dev->descriptor.bDeviceClass)
+ continue;
+ if (id->bDeviceProtocol && id->bDeviceProtocol
+ != dev->descriptor.bDeviceProtocol)
+ continue;
+ break;
+ }
+
+ /* Interface class match? */
+ if (!interface->altsetting || interface->num_altsetting < 1)
+ continue;
+ intf = &interface->altsetting [0];
+ if (id->bInterfaceClass
+ && id->bInterfaceClass == intf->bInterfaceClass) {
+ if (id->bInterfaceSubClass && id->bInterfaceSubClass
+ != intf->bInterfaceClass)
+ continue;
+ if (id->bInterfaceProtocol && id->bInterfaceProtocol
+ != intf->bInterfaceProtocol)
+ continue;
+ break;
+ }
+ }
+
+ /* is this driver interested in this interface? */
+ if (id)
+ private = driver->bind(dev, ifnum, id);
+ else
+ private = 0;
+ } else {
+ /* "old style" driver, but using new interface */
+ private = driver->bind(dev, ifnum, 0);
+ }
+
+ /* "old style" driver */
+ } else
+ private = driver->probe(dev, ifnum);
up(&driver->serialize);
if (!private)
continue;
@@ -758,6 +829,7 @@
{
atomic_inc(&dev->refcnt);
}
+
/* -------------------------------------------------------------------------------------
* New USB Core Functions
* -------------------------------------------------------------------------------------*/
@@ -836,7 +908,6 @@
int status;
awd.wakeup = &wqh;
- awd.handler = 0;
init_waitqueue_head(&wqh);
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&wqh, &wait);
@@ -1518,9 +1589,9 @@
while (i--) {
if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) >= 0 ||
+ (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) > 0 ||
result == -EPIPE)
- break;
+ break; /* retry if the returned length was 0; flaky device */
}
return result;
}
@@ -2028,6 +2099,32 @@
return &usb_bus_list;
}
#endif
+
+
+/*
+ * Init
+ */
+static int __init usb_init(void)
+{
+ usb_major_init();
+ usbdevfs_init();
+ usb_hub_init();
+
+ return 0;
+}
+
+/*
+ * Cleanup
+ */
+static void __exit usb_exit(void)
+{
+ usb_major_cleanup();
+ usbdevfs_cleanup();
+ usb_hub_cleanup();
+}
+
+module_init(usb_init);
+module_exit(usb_exit);
/*
* USB may be built into the kernel or be built as modules.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)