LWN.net Logo

[RFC] USB driver conversion to "struct device_driver" for 2.5.32

From:  Greg KH <greg@kroah.com>
To:  linux-usb-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org
Subject:  [linux-usb-devel] [RFC] USB driver conversion to "struct device_driver" for 2.5.32
Date:  Thu, 29 Aug 2002 15:13:39 -0700
Cc:  Patrick Mochel <mochel@osdl.org>

Yet another updated version of this patch :)

For those who do not remember (probably everyone, who really cares about
this stuff anyway...) this patch add support to the USB core to use
"struct device_driver" instead of keeping it's own list of devices.  The
patch is against 2.5.32, and includes the following changes since the
last one:
	- cleaned up the usb device names a bit, so the driverfs tree
	  looks a lot better.
	- devices now attach to the hub above itself main device, not
	  the hub interface of the device.
	- when disconnecting devices, any children devices are removed
	  before the device is.
	- lots of little cleanups.
	- many more USB drivers are converted to the new code.
	- now there is only one probe() and disconnect() function in the
	  usb_driver structure.  So if your favorite driver gives the
	  following error when building:
	  	warning: initialization from incompatible pointer type
	  it is not converted yet, and will probably oops badly if you
	  try to use it.  You have been warned :)
	- much more code was removed from the USB core.
	- I think I got the driver binding and removal working a bit
	  better for usbfs, but am not positive.  Any help in this area
	  would be appreciated.

In short, the patch is looking a lot better (with the exception of an
occasional oops in the core driver code when some devices are removed),
and will probably be sent to Linus soon.

Comments appreciated.

thanks,

greg k-h


diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/class/audio.c	Thu Aug 29 14:56:00 2002
@@ -2740,9 +2740,9 @@
 
 /* --------------------------------------------------------------------- */
 
-static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
-			      const struct usb_device_id *id);
-static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
+static int usb_audio_probe(struct usb_interface *iface,
+			   const struct usb_device_id *id);
+static void usb_audio_disconnect(struct usb_interface *iface);
 
 static struct usb_device_id usb_audio_ids [] = {
     { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
@@ -2756,7 +2756,6 @@
 	.name =		"audio",
 	.probe =	usb_audio_probe,
 	.disconnect =	usb_audio_disconnect,
-	.driver_list =	LIST_HEAD_INIT(usb_audio_driver.driver_list), 
 	.id_table =	usb_audio_ids,
 };
 
@@ -3643,7 +3642,7 @@
 	list_add_tail(&ms->list, &s->mixerlist);
 }
 
-static void *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
+static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
 {
 	struct usb_audio_state *s;
 	struct usb_config_descriptor *config = dev->actconfig;
@@ -3766,10 +3765,12 @@
 
 /* we only care for the currently active configuration */
 
-static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
-			     const struct usb_device_id *id)
+static int usb_audio_probe(struct usb_interface *iface,
+			   const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev (iface);
 	struct usb_config_descriptor *config = dev->actconfig;	
+	struct usb_audio_state *s;
 	unsigned char *buffer;
 	unsigned char buf[8];
 	unsigned int i, buflen;
@@ -3789,39 +3790,47 @@
 
 	if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
 		printk(KERN_ERR "usbaudio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);
-		return NULL;
+		return -EIO;
 	}
 	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
 	if (ret < 0) {
 		printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return NULL;
+		return -EIO;
 	}
 	if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
 		printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum);
-		return NULL;
+		return -EIO;
 	}
 	buflen = buf[2] | (buf[3] << 8);
 	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
-		return NULL;
+		return -ENOMEM;
 	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
 	if (ret < 0) {
 		kfree(buffer);
 		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return NULL;
+		return -EIO;
 	}
-	return usb_audio_parsecontrol(dev, buffer, buflen, ifnum);
+	s = usb_audio_parsecontrol(dev, buffer, buflen, usb_if_to_ifnum(iface));
+	if (s) {
+		iface->dev.driver_data = s;
+		return 0;
+	}
+	return -ENODEV;
 }
 
 
 /* a revoke facility would make things simpler */
 
-static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
+static void usb_audio_disconnect(struct usb_interface *iface)
 {
-	struct usb_audio_state *s = (struct usb_audio_state *)ptr;
+	struct usb_audio_state *s = (struct usb_audio_state *)iface->dev.driver_data;
 	struct list_head *list;
 	struct usb_audiodev *as;
 	struct usb_mixerdev *ms;
 
+	if (!s)
+		return;
+
 	/* we get called with -1 for every audiostreaming interface registered */
 	if (s == (struct usb_audio_state *)-1) {
 		dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with -1\n"));
@@ -3835,6 +3844,8 @@
 	list_del(&s->audiodev);
 	INIT_LIST_HEAD(&s->audiodev);
 	s->usbdev = NULL;
+	iface->dev.driver_data = NULL;
+
 	/* deregister all audio and mixer devices, so no new processes can open this device */
 	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
 		as = list_entry(list, struct usb_audiodev, list);
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/class/bluetty.c	Thu Aug 29 14:56:01 2002
@@ -221,9 +221,9 @@
 static void bluetooth_read_bulk_callback	(struct urb *urb);
 static void bluetooth_write_bulk_callback	(struct urb *urb);
 
-static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
-			 	  const struct usb_device_id *id);
-static void usb_bluetooth_disconnect	(struct usb_device *dev, void *ptr);
+static int usb_bluetooth_probe (struct usb_interface *intf, 
+				const struct usb_device_id *id);
+static void usb_bluetooth_disconnect	(struct usb_interface *intf);
 
 
 static struct usb_device_id usb_bluetooth_ids [] = {
@@ -1033,9 +1033,10 @@
 }
 
 
-static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
-			 	  const struct usb_device_id *id)
+static int usb_bluetooth_probe (struct usb_interface *iface, 
+				const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev (iface);
 	struct usb_bluetooth *bluetooth = NULL;
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
@@ -1051,7 +1052,7 @@
 	int num_bulk_in = 0;
 	int num_bulk_out = 0;
 
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	interface = &iface->altsetting[0];
 	control_out_endpoint = interface->bInterfaceNumber;
 
 	/* find the endpoints that we need */
@@ -1088,7 +1089,7 @@
 	    (num_bulk_out != 1) ||
 	    (num_interrupt_in != 1)) {
 		dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound.");
-		return NULL;
+		return -EIO;
 	}
 
 	MOD_INC_USE_COUNT;
@@ -1099,13 +1100,13 @@
 	if (bluetooth_table[minor]) {
 		err("No more free Bluetooth devices");
 		MOD_DEC_USE_COUNT;
-		return NULL;
+		return -ENODEV;
 	}
 
 	if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
 		err("Out of memory");
 		MOD_DEC_USE_COUNT;
-		return NULL;
+		return -ENOMEM;
 	}
 
 	memset(bluetooth, 0, sizeof(struct usb_bluetooth));
@@ -1191,7 +1192,9 @@
 
 	bluetooth_table[minor] = bluetooth;
 
-	return bluetooth; /* success */
+	/* success */
+	iface->dev.driver_data = bluetooth;
+	return 0;
 
 probe_error:
 	if (bluetooth->read_urb)
@@ -1220,13 +1223,13 @@
 	/* free up any memory that we allocated */
 	kfree (bluetooth);
 	MOD_DEC_USE_COUNT;
-	return NULL;
+	return -EIO;
 }
 
 
-static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr)
+static void usb_bluetooth_disconnect(struct usb_interface *iface)
 {
-	struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr;
+	struct usb_bluetooth *bluetooth = iface->dev.driver_data;
 	int i;
 
 	if (bluetooth) {
@@ -1274,7 +1277,7 @@
 
 		/* free up any memory that we allocated */
 		kfree (bluetooth);
-
+		iface->dev.driver_data = NULL;
 	} else {
 		info("device disconnected");
 	}
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/class/cdc-acm.c	Thu Aug 29 14:56:01 2002
@@ -507,9 +507,10 @@
  * USB probe and disconnect routines.
  */
 
-static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
-		       const struct usb_device_id *id)
+static int acm_probe (struct usb_interface *iface,
+		      const struct usb_device_id *id)
 {
+	struct usb_device *dev;
 	struct acm *acm;
 	struct usb_config_descriptor *cfacm;
 	struct usb_interface_descriptor *ifcom, *ifdata;
@@ -517,6 +518,7 @@
 	int readsize, ctrlsize, minor, i;
 	unsigned char *buf;
 
+	dev = interface_to_usbdev (iface);
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 
 		cfacm = dev->config + i;
@@ -561,12 +563,12 @@
 		for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
 		if (acm_table[minor]) {
 			err("no more free acm devices");
-			return NULL;
+			return -ENODEV;
 		}
 
 		if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
 			err("out of memory");
-			return NULL;
+			return -ENOMEM;
 		}
 		memset(acm, 0, sizeof(struct acm));
 
@@ -583,21 +585,21 @@
 		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
 			err("out of memory");
 			kfree(acm);
-			return NULL;
+			return -ENOMEM;
 		}
 
 		acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!acm->ctrlurb) {
 			err("out of memory");
 			kfree(acm);
-			return NULL;
+			return -ENOMEM;
 		}
 		acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!acm->readurb) {
 			err("out of memory");
 			usb_free_urb(acm->ctrlurb);
 			kfree(acm);
-			return NULL;
+			return -ENOMEM;
 		}
 		acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!acm->writeurb) {
@@ -605,7 +607,7 @@
 			usb_free_urb(acm->readurb);
 			usb_free_urb(acm->ctrlurb);
 			kfree(acm);
-			return NULL;
+			return -ENOMEM;
 		}
 
 		usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
@@ -631,15 +633,18 @@
 		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
 
 		tty_register_devfs(&acm_tty_driver, 0, minor);
-		return acm_table[minor] = acm;
+
+		acm_table[minor] = acm;
+		iface->dev.driver_data = acm;
+		return 0;
 	}
 
-	return NULL;
+	return -EIO;
 }
 
-static void acm_disconnect(struct usb_device *dev, void *ptr)
+static void acm_disconnect(struct usb_interface *iface)
 {
-	struct acm *acm = ptr;
+	struct acm *acm = iface->dev.driver_data;
 
 	if (!acm || !acm->dev) {
 		dbg("disconnect on nonexisting interface");
@@ -647,6 +652,7 @@
 	}
 
 	acm->dev = NULL;
+	iface->dev.driver_data = NULL;
 
 	usb_unlink_urb(acm->ctrlurb);
 	usb_unlink_urb(acm->readurb);
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/class/usb-midi.c	Thu Aug 29 14:56:00 2002
@@ -2020,13 +2020,16 @@
 
 /* ------------------------------------------------------------------------- */
 
-static void *usb_midi_probe(struct usb_device *dev, unsigned int ifnum,
-			    const struct usb_device_id *id)
+static int usb_midi_probe(struct usb_interface *iface, 
+			  const struct usb_device_id *id)
 {
 	struct usb_midi_state *s;
+	struct usb_device *dev = interface_to_usbdev(iface);
+	int ifnum = usb_if_to_ifnum(iface);
 
 	s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL);
-	if ( !s ) { return NULL; }
+	if ( !s )
+		return -ENOMEM;
 
 	memset( s, 0, sizeof(struct usb_midi_state) );
 	INIT_LIST_HEAD(&s->midiDevList);
@@ -2042,7 +2045,7 @@
 		detect_vendor_specific_device( dev, ifnum, s ) &&
 		detect_yamaha_device( dev, ifnum, s) ) {
 		kfree(s);
-		return NULL;
+		return -EIO;
 	}
 
 	down(&open_sem);
@@ -2053,16 +2056,20 @@
 	MOD_INC_USE_COUNT;
 #endif
 
-	return s;
+	iface->dev.driver_data = s;
+	return 0;
 }
 
 
-static void usb_midi_disconnect(struct usb_device *dev, void *ptr)
+static void usb_midi_disconnect(struct usb_interface *iface)
 {
-	struct usb_midi_state *s = (struct usb_midi_state *)ptr;
+	struct usb_midi_state *s = (struct usb_midi_state *)iface->dev.driver_data;
 	struct list_head      *list;
 	struct usb_mididev    *m;
 
+	if ( !s )
+		return;
+
 	if ( s == (struct usb_midi_state *)-1 ) {
 		return;
 	}
@@ -2073,6 +2080,7 @@
 	list_del(&s->mididev);
 	INIT_LIST_HEAD(&s->mididev);
 	s->usbdev = NULL;
+	iface->dev.driver_data = NULL;
 
 	for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) {
 		m = list_entry(list, struct usb_mididev, list);
@@ -2092,14 +2100,17 @@
 	return;
 }
 
-
+/* we want to look at all devices by hand */
+static struct usb_device_id id_table[] = {
+	{.driver_info = 42},
+	{}
+};
 
 static struct usb_driver usb_midi_driver = {
-	.name = "midi",
-	.probe = usb_midi_probe,
-	.disconnect = usb_midi_disconnect,
-	.id_table =	NULL, 			/* check all devices */
-	.driver_list = LIST_HEAD_INIT(usb_midi_driver.driver_list)
+	.name =		"midi",
+	.probe =	usb_midi_probe,
+	.disconnect =	usb_midi_disconnect,
+	.id_table =	id_table,
 };
 
 /* ------------------------------------------------------------------------- */
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/class/usblp.c	Thu Aug 29 14:56:00 2002
@@ -795,9 +795,10 @@
 	.release =	usblp_release,
 };
 
-static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
-			 const struct usb_device_id *id)
+static int usblp_probe(struct usb_interface *iface,
+		       const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev (iface);
 	struct usblp *usblp = 0;
 	int protocol;
 	int retval;
@@ -813,7 +814,7 @@
 	usblp->dev = dev;
 	init_MUTEX (&usblp->sem);
 	init_waitqueue_head(&usblp->wait);
-	usblp->ifnum = ifnum;
+	usblp->ifnum = usb_if_to_ifnum (iface);
 
 	retval = usb_register_dev(&usblp_fops, USBLP_MINOR_BASE, 1, &usblp->minor);
 	if (retval) {
@@ -886,12 +887,14 @@
 
 	info("usblp%d: USB %sdirectional printer dev %d "
 		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
-		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
+		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
+		usblp->ifnum,
 		usblp->protocol[usblp->current_protocol].alt_setting,
 		usblp->current_protocol, usblp->dev->descriptor.idVendor,
 		usblp->dev->descriptor.idProduct);
 
-	return usblp;
+	iface->dev.driver_data = usblp;
+	return 0;
 
 abort_minor:
 	usb_deregister_dev (1, usblp->minor);
@@ -903,7 +906,7 @@
 		if (usblp->device_id_string) kfree(usblp->device_id_string);
 		kfree(usblp);
 	}
-	return NULL;
+	return -EIO;
 }
 
 /*
@@ -1065,9 +1068,9 @@
 	return length;
 }
 
-static void usblp_disconnect(struct usb_device *dev, void *ptr)
+static void usblp_disconnect(struct usb_interface *iface)
 {
-	struct usblp *usblp = ptr;
+	struct usblp *usblp = iface->dev.driver_data;
 
 	if (!usblp || !usblp->dev) {
 		err("bogus disconnect");
@@ -1077,6 +1080,7 @@
 	down (&usblp->sem);
 	lock_kernel();
 	usblp->dev = NULL;
+	iface->dev.driver_data = NULL;
 
 	usblp_unlink_urbs(usblp);
 
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/core/config.c	Thu Aug 29 14:56:00 2002
@@ -89,7 +89,8 @@
 	return parsed;
 }
 
-static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
+static int usb_parse_interface (struct usb_interface *interface,
+				unsigned char *buffer, int size)
 {
 	int i, len, numskipped, retval, parsed = 0;
 	struct usb_descriptor_header *header;
@@ -240,7 +241,8 @@
 	return parsed;
 }
 
-int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
+static int usb_parse_configuration (struct usb_config_descriptor *config,
+				    char *buffer)
 {
 	int i, retval, size;
 	struct usb_descriptor_header *header;
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/core/devices.c	Thu Aug 29 14:56:01 2002
@@ -111,7 +111,6 @@
 
 /*
  * Need access to the driver and USB bus lists.
- * extern struct list_head usb_driver_list;
  * extern struct list_head usb_bus_list;
  * However, these will come from functions that return ptrs to each of them.
  */
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/core/devio.c	Thu Aug 29 14:56:00 2002
@@ -298,15 +298,15 @@
  * they're also undone when devices disconnect.
  */
 
-static void *driver_probe(struct usb_device *dev, unsigned int intf,
-			  const struct usb_device_id *id)
+static int driver_probe (struct usb_interface *intf,
+			 const struct usb_device_id *id)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static void driver_disconnect(struct usb_device *dev, void *context)
+static void driver_disconnect(struct usb_interface *intf)
 {
-	struct dev_state *ps = (struct dev_state *)context;
+	struct dev_state *ps = (struct dev_state *)intf->dev.driver_data;
 
 	if (!ps)
 		return;
@@ -317,6 +317,7 @@
 	/* prevent new I/O requests */
 	ps->dev = 0;
 	ps->ifclaimed = 0;
+	intf->dev.driver_data = NULL;
 
 	/* force async requests to complete */
 	destroy_all_async (ps);
@@ -427,30 +428,6 @@
 	return -ENOENT; 
 }
 
-extern struct list_head usb_driver_list;
-
-#if 0
-static int finddriver(struct usb_driver **driver, char *name)
-{
-	struct list_head *tmp;
-
-	tmp = usb_driver_list.next;
-	while (tmp != &usb_driver_list) {
-		struct usb_driver *d = list_entry(tmp, struct usb_driver,
-							driver_list);
-
-		if (!strcmp(d->name, name)) {
-			*driver = d;
-			return 0;
-		}
-
-		tmp = tmp->next;
-	}
-
-	return -EINVAL;
-}
-#endif
-
 static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
 {
 	int ret;
@@ -723,11 +700,10 @@
 		if (test_bit(i, &ps->ifclaimed))
 			continue;
 
-		lock_kernel();
+		err ("%s - this function is broken", __FUNCTION__);
 		if (intf->driver && ps->dev) {
-			usb_bind_driver (intf->driver, intf);
+			usb_device_probe (&intf->dev);
 		}
-		unlock_kernel();
 	}
 
 	return 0;
@@ -1090,22 +1066,19 @@
 
        /* disconnect kernel driver from interface, leaving it unbound.  */
        case USBDEVFS_DISCONNECT:
-       	/* this function is voodoo. without locking it is a maybe thing */
-		lock_kernel();
-               driver = ifp->driver;
-               if (driver) {
-                       dbg ("disconnect '%s' from dev %d interface %d",
-                               driver->name, ps->dev->devnum, ctrl.ifno);
-		       usb_unbind_driver(ps->dev, ifp);
-                       usb_driver_release_interface (driver, ifp);
-               } else
+		/* this function is voodoo. */
+		driver = ifp->driver;
+		if (driver) {
+			dbg ("disconnect '%s' from dev %d interface %d",
+			     driver->name, ps->dev->devnum, ctrl.ifno);
+			usb_device_remove(&ifp->dev);
+		} else
 			retval = -EINVAL;
-		unlock_kernel();
-               break;
+		break;
 
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
-		usb_find_interface_driver (ps->dev, ifp);
+		retval = usb_device_probe (&ifp->dev);
 		break;
 
        /* talk directly to the interface's driver */
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/core/hcd.c	Thu Aug 29 14:56:01 2002
@@ -722,13 +722,16 @@
 {
 	int retval;
 
-	usb_dev->dev.parent = parent_dev;
-	strcpy (&usb_dev->dev.name[0], "usb_name");
-	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
-	retval = usb_new_device (usb_dev);
+//	usb_dev->dev.parent = parent_dev;
+//	strcpy (&usb_dev->dev.name[0], "usb_name");
+//	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
+	sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum);
+	retval = usb_new_device (usb_dev, parent_dev);
 	if (retval)
-		put_device (&usb_dev->dev);
+		err("%s - usb_new_device failed with value %d", __FUNCTION__, retval);
+//		put_device (&usb_dev->dev);
 	return retval;
+//	return usb_new_device (usb_dev, parent_dev);
 }
 EXPORT_SYMBOL (usb_register_root_hub);
 
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/core/hcd.h	Thu Aug 29 14:56:01 2002
@@ -255,7 +255,7 @@
 /* -------------------------------------------------------------------------- */
 
 /* Enumeration is only for the hub driver, or HCD virtual root hubs */
-extern int usb_new_device(struct usb_device *dev);
+extern int usb_new_device(struct usb_device *dev, struct device *parent);
 extern void usb_connect(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
 
@@ -380,12 +380,6 @@
 #define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
 
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
-
-/* for probe/disconnect with correct module usage counting */
-void *usb_bind_driver(struct usb_driver *driver, struct usb_interface *intf);
-void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf);
-
-extern struct list_head usb_driver_list;
 
 /*
  * USB device fs stuff
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/core/hub.c	Thu Aug 29 14:56:01 2002
@@ -175,6 +175,7 @@
 	while (!list_empty (&hub->tt.clear_list)) {
 		struct list_head	*temp;
 		struct usb_tt_clear	*clear;
+		struct usb_device	*dev;
 		int			status;
 
 		temp = hub->tt.clear_list.next;
@@ -183,13 +184,13 @@
 
 		/* drop lock so HCD can concurrently report other TT errors */
 		spin_unlock_irqrestore (&hub->tt.lock, flags);
-		status = hub_clear_tt_buffer (hub->dev,
-				clear->devinfo, clear->tt);
+		dev = interface_to_usbdev (hub->intf);
+		status = hub_clear_tt_buffer (dev, clear->devinfo, clear->tt);
 		spin_lock_irqsave (&hub->tt.lock, flags);
 
 		if (status)
 			err ("usb-%s-%s clear tt %d (%04x) error %d",
-				hub->dev->bus->bus_name, hub->dev->devpath,
+				dev->bus->bus_name, dev->devpath,
 				clear->tt, clear->devinfo, status);
 		kfree (clear);
 	}
@@ -245,12 +246,14 @@
 
 static void usb_hub_power_on(struct usb_hub *hub)
 {
+	struct usb_device *dev;
 	int i;
 
 	/* Enable power to the ports */
 	dbg("enabling power on all ports");
+	dev = interface_to_usbdev(hub->intf);
 	for (i = 0; i < hub->descriptor->bNbrPorts; i++)
-		usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER);
+		usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
 
 	/* Wait for power to be enabled */
 	wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
@@ -259,7 +262,7 @@
 static int usb_hub_configure(struct usb_hub *hub,
 	struct usb_endpoint_descriptor *endpoint)
 {
-	struct usb_device *dev = hub->dev;
+	struct usb_device *dev = interface_to_usbdev (hub->intf);
 	struct usb_hub_status hubstatus;
 	unsigned int pipe;
 	int maxp, ret;
@@ -425,39 +428,81 @@
 	return 0;
 }
 
-static void *hub_probe(struct usb_device *dev, unsigned int i,
-		       const struct usb_device_id *id)
+static void hub_disconnect(struct usb_interface *intf)
 {
-	struct usb_interface_descriptor *interface;
+	struct usb_hub *hub = (struct usb_hub *)intf->dev.driver_data;
+	unsigned long flags;
+
+	if (!hub)
+		return;
+
+	spin_lock_irqsave(&hub_event_lock, flags);
+
+	/* Delete it and then reset it */
+	list_del(&hub->event_list);
+	INIT_LIST_HEAD(&hub->event_list);
+	list_del(&hub->hub_list);
+	INIT_LIST_HEAD(&hub->hub_list);
+
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+
+	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
+	up(&hub->khubd_sem);
+
+	/* assuming we used keventd, it must quiesce too */
+	if (hub->tt.hub)
+		flush_scheduled_tasks ();
+
+	if (hub->urb) {
+		usb_unlink_urb(hub->urb);
+		usb_free_urb(hub->urb);
+		hub->urb = NULL;
+	}
+
+	if (hub->descriptor) {
+		kfree(hub->descriptor);
+		hub->descriptor = NULL;
+	}
+
+	/* Free the memory */
+	kfree(hub);
+	intf->dev.driver_data = NULL;
+}
+
+static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *desc;
 	struct usb_endpoint_descriptor *endpoint;
+	struct usb_device *dev;
 	struct usb_hub *hub;
 	unsigned long flags;
 
-	interface = &dev->actconfig->interface[i].altsetting[0];
+	desc = intf->altsetting + intf->act_altsetting;
+	dev = interface_to_usbdev(intf);
 
 	/* Some hubs have a subclass of 1, which AFAICT according to the */
 	/*  specs is not defined, but it works */
-	if ((interface->bInterfaceSubClass != 0) &&
-	    (interface->bInterfaceSubClass != 1)) {
+	if ((desc->bInterfaceSubClass != 0) &&
+	    (desc->bInterfaceSubClass != 1)) {
 		err("invalid subclass (%d) for USB hub device #%d",
-			interface->bInterfaceSubClass, dev->devnum);
-		return NULL;
+			desc->bInterfaceSubClass, dev->devnum);
+		return -EIO;
 	}
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
-	if (interface->bNumEndpoints != 1) {
+	if (desc->bNumEndpoints != 1) {
 		err("invalid bNumEndpoints (%d) for USB hub device #%d",
-			interface->bNumEndpoints, dev->devnum);
-		return NULL;
+			desc->bNumEndpoints, dev->devnum);
+		return -EIO;
 	}
 
-	endpoint = &interface->endpoint[0];
+	endpoint = &desc->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
 		err("Device #%d is hub class, but has output endpoint?",
 			dev->devnum);
-		return NULL;
+		return -EIO;
 	}
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
@@ -465,7 +510,7 @@
 			!= USB_ENDPOINT_XFER_INT) {
 		err("Device #%d is hub class, but endpoint is not interrupt?",
 			dev->devnum);
-		return NULL;
+		return -EIO;
 	}
 
 	/* We found a hub */
@@ -474,13 +519,13 @@
 	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
 	if (!hub) {
 		err("couldn't kmalloc hub struct");
-		return NULL;
+		return -ENOMEM;
 	}
 
 	memset(hub, 0, sizeof(*hub));
 
 	INIT_LIST_HEAD(&hub->event_list);
-	hub->dev = dev;
+	hub->intf = intf;
 	init_MUTEX(&hub->khubd_sem);
 
 	/* Record the new hub's existence */
@@ -489,14 +534,18 @@
 	list_add(&hub->hub_list, &hub_list);
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
+	intf->dev.driver_data = hub;
+
 	if (usb_hub_configure(hub, endpoint) >= 0) {
-		strcpy (dev->actconfig->interface[i].dev.name,
-			"Hub/Port Status Changes");
-		return hub;
+		strcpy (intf->dev.name, "Hub/Port Status Changes");
+		return 0;
 	}
 
 	err("hub configuration failed for device at %s", dev->devpath);
 
+	hub_disconnect (intf);
+	return -ENODEV;
+#if 0
 	/* free hub, but first clean up its list. */
 	spin_lock_irqsave(&hub_event_lock, flags);
 
@@ -511,43 +560,7 @@
 	kfree(hub);
 
 	return NULL;
-}
-
-static void hub_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_hub *hub = (struct usb_hub *)ptr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hub_event_lock, flags);
-
-	/* Delete it and then reset it */
-	list_del(&hub->event_list);
-	INIT_LIST_HEAD(&hub->event_list);
-	list_del(&hub->hub_list);
-	INIT_LIST_HEAD(&hub->hub_list);
-
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
-	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
-	up(&hub->khubd_sem);
-
-	/* assuming we used keventd, it must quiesce too */
-	if (hub->tt.hub)
-		flush_scheduled_tasks ();
-
-	if (hub->urb) {
-		usb_unlink_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
-
-	if (hub->descriptor) {
-		kfree(hub->descriptor);
-		hub->descriptor = NULL;
-	}
-
-	/* Free the memory */
-	kfree(hub);
+#endif
 }
 
 static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
@@ -584,7 +597,7 @@
 
 static int usb_hub_reset(struct usb_hub *hub)
 {
-	struct usb_device *dev = hub->dev;
+	struct usb_device *dev = interface_to_usbdev(hub->intf);
 	int i;
 
 	/* Disconnect any attached devices */
@@ -796,7 +809,7 @@
 static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
 					u16 portstatus, u16 portchange)
 {
-	struct usb_device *hub = hubstate->dev;
+	struct usb_device *hub = interface_to_usbdev(hubstate->intf);
 	struct usb_device *dev;
 	unsigned int delay = HUB_SHORT_RESET_TIME;
 	int i;
@@ -891,11 +904,15 @@
 		/* put the device in the global device tree. the hub port
 		 * is the "bus_id"; hubs show in hierarchy like bridges
 		 */
-		dev->dev.parent = &dev->parent->dev;
-		sprintf (&dev->dev.bus_id[0], "%d", port + 1);
+//		dev->dev.parent = &dev->parent->dev;
+//		if (dev->parent->dev.parent)
+			dev->dev.parent = dev->parent->dev.parent->parent;
+//		else
+//			dev->dev.parent = &dev->parent->dev;
+//		sprintf (&dev->dev.bus_id[0], "%d", port + 1);
 
 		/* Run it through the hoops (find a driver, etc) */
-		if (!usb_new_device(dev))
+		if (!usb_new_device(dev, &hub->dev))
 			goto done;
 
 		/* Free the configuration if there was an error */
@@ -940,7 +957,7 @@
 		tmp = hub_event_list.next;
 
 		hub = list_entry(tmp, struct usb_hub, event_list);
-		dev = hub->dev;
+		dev = interface_to_usbdev(hub->intf);
 
 		list_del(tmp);
 		INIT_LIST_HEAD(tmp);
@@ -1081,8 +1098,8 @@
 static struct usb_driver hub_driver = {
 	.name =		"hub",
 	.probe =	hub_probe,
-	.ioctl =	hub_ioctl,
 	.disconnect =	hub_disconnect,
+	.ioctl =	hub_ioctl,
 	.id_table =	hub_id_table,
 };
 
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/core/hub.h	Thu Aug 29 14:56:00 2002
@@ -170,7 +170,8 @@
 extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
 
 struct usb_hub {
-	struct usb_device	*dev;		/* the "real" device */
+//	struct usb_device	*dev;		/* the "real" device */
+	struct usb_interface	*intf;		/* the "real" device */
 	struct urb		*urb;		/* for interrupt polling pipe */
 
 	/* buffer for urb ... 1 bit each for hub and children, rounded up */
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/core/usb.c	Thu Aug 29 14:56:01 2002
@@ -48,225 +48,131 @@
 extern int usb_major_init(void);
 extern void usb_major_cleanup(void);
 
-/*
- * Prototypes for the device driver probing/loading functions
- */
-static void usb_find_drivers(struct usb_device *);
-static void usb_check_support(struct usb_device *);
-
-/*
- * We have a per-interface "registered driver" list.
- */
-LIST_HEAD(usb_driver_list);
 
 
-/**
- * usb_register - register a USB driver
- * @new_driver: USB operations for the driver
- *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
- * Returns a negative error code on failure and 0 on success.
- * 
- * NOTE: if you want your driver to use the USB major number, you must call
- * usb_register_dev() to enable that functionality.  This function no longer
- * takes care of that.
- */
-int usb_register(struct usb_driver *new_driver)
+static int generic_probe (struct device *dev)
 {
-	int retval = 0;
-
-	info("registered new driver %s", new_driver->name);
-
-	init_MUTEX(&new_driver->serialize);
-
-	/* Add it to the list of known drivers */
-	list_add_tail(&new_driver->driver_list, &usb_driver_list);
-
-	usb_scan_devices();
-
-	usbfs_update_special();
-
-	return retval;
+	return 0;
 }
-
-
-/**
- *	usb_scan_devices - scans all unclaimed USB interfaces
- *	Context: !in_interrupt ()
- *
- *	Goes through all unclaimed USB interfaces, and offers them to all
- *	registered USB drivers through the 'probe' function.
- *	This will automatically be called after usb_register is called.
- *	It is called by some of the subsystems layered over USB
- *	after one of their subdrivers are registered.
- */
-void usb_scan_devices(void)
+static int generic_remove (struct device *dev)
+{
+	return 0;
+}
+static void generic_release (struct device_driver * drv)
 {
-	struct list_head *tmp;
-
-	down (&usb_bus_list_lock);
-	tmp = usb_bus_list.next;
-	while (tmp != &usb_bus_list) {
-		struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
-
-		tmp = tmp->next;
-		usb_check_support(bus->root_hub);
-	}
-	up (&usb_bus_list_lock);
 }
 
-/**
- *	usb_unbind_driver - disconnects a driver from a device (usbcore-internal)
- *	@device: usb device to be disconnected
- *	@intf: interface of the device to be disconnected
- *	Context: BKL held
- *
- *	Handles module usage count correctly
- */
+static struct device_driver usb_generic_driver = {
+	.name =	"generic usb driver",
+	.probe = generic_probe,
+	.remove = generic_remove,
+	.release = generic_release,
+};
+	
 
-void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf)
+int usb_device_probe(struct device *dev)
 {
-	struct usb_driver *driver;
-	void *priv;
+	struct usb_interface * intf = to_usb_interface(dev);
+	struct usb_driver * driver = to_usb_driver(dev->driver);
+	const struct usb_device_id *id;
+	int error = -ENODEV;
 	int m;
-	
 
-	driver = intf->driver;
-	priv = intf->private_data;
-	
-	if (!driver || !driver->disconnect)
-		return;
+	dbg("%s", __FUNCTION__);
+
+	if (!driver->probe)
+		return error;
 
-	/* as soon as we increase the module use count we drop the BKL
-	   before that we must not sleep */
 	if (driver->owner) {
 		m = try_inc_mod_count(driver->owner);
-		if (m == 0) {
-			err("Dieing driver still bound to device.\n");
-			return;
-		}
-		unlock_kernel();
+		if (m == 0)
+			return error;
 	}
-	down(&driver->serialize); 	/* if we sleep here on an umanaged driver
-					   the holder of the lock guards against
-					   module unload */
 
-	driver->disconnect(device, priv);
+	id = usb_match_id (intf, driver->id_table);
+	if (id) {
+		dbg ("%s - got id", __FUNCTION__);
+		down (&driver->serialize);
+		error = driver->probe (intf, id);
+		up (&driver->serialize);
+	}
+	if (!error)
+		intf->driver = driver;
 
-	up(&driver->serialize);
-	if (driver->owner) {
-		lock_kernel();
+	if (driver->owner)
 		__MOD_DEC_USE_COUNT(driver->owner);
-	}
+
+	return error;
 }
 
-/**
- *	usb_bind_driver - connect a driver to a device's interface (usbcore-internal)
- *	@driver: device driver to be bound to interface
- *	@interface: interface that the driver will be using
- *	Context: BKL held
- *
- *	Does a safe binding of a driver to one of a device's interfaces.
- *	Returns the driver's data for the binding, or null indicating
- *	that the driver did not bind to this interface.
- *
- *	This differs from usb_driver_claim_interface(), which is called from
- *	drivers and neither calls the driver's probe() entry nor does any
- *	locking to guard against removing driver modules.
- */
-void *
-usb_bind_driver (struct usb_driver *driver, struct usb_interface *interface)
+int usb_device_remove(struct device *dev)
 {
-	int i,m;
-	void *private = NULL;
-	const struct usb_device_id *id;
-	struct usb_device *dev = interface_to_usbdev (interface);
-	int ifnum;
+	struct usb_interface *intf = list_entry(dev,struct usb_interface,dev);
+	struct usb_driver *driver = to_usb_driver(dev->driver);
+	int m;
 
 	if (driver->owner) {
 		m = try_inc_mod_count(driver->owner);
-		if (m == 0)
-			return NULL; /* this horse is dead - don't ride*/
-		unlock_kernel();
+		if (m == 0) {
+			err("Dieing driver still bound to device.\n");
+			return -EIO;
+		}
 	}
 
-	// START TEMPORARY
-	// driver->probe() hasn't yet changed to take interface not dev+ifnum,
-	// so we still need ifnum here.
-	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++)
-		if (&dev->actconfig->interface [ifnum] == interface)
-			break;
-	BUG_ON (ifnum == dev->actconfig->bNumInterfaces);
-	// END TEMPORARY
-
-	id = driver->id_table;
-	/* new style driver? */
-	if (id) {
-		for (i = 0; i < interface->num_altsetting; i++) {
-		  	interface->act_altsetting = i;
-			id = usb_match_id(interface, id);
-			if (id) {
-				down(&driver->serialize);
-				private = driver->probe(dev,ifnum,id);
-				up(&driver->serialize);
-				if (private != NULL)
-					break;
-			}
-		}
+	/* if we sleep here on an umanaged driver 
+	 * the holder of the lock guards against 
+	 * module unload */
+	down(&driver->serialize);
+
+	if (intf->driver && intf->driver->disconnect)
+		intf->driver->disconnect(intf);
+
+	/* if driver->disconnect didn't release the interface */
+	if (intf->driver)
+		usb_driver_release_interface(driver, intf);
 
-		/* if driver not bound, leave defaults unchanged */
-		if (private == NULL)
-			interface->act_altsetting = 0;
-	} else { /* "old style" driver */
-		down(&driver->serialize);
-		private = driver->probe(dev, ifnum, NULL);
-		up(&driver->serialize);
-	}
+	up(&driver->serialize);
 	if (driver->owner) {
-		lock_kernel();
 		__MOD_DEC_USE_COUNT(driver->owner);
 	}
-
-	return private;
+	return 0;
 }
 
-/*
- * This function is part of a depth-first search down the device tree,
- * removing any instances of a device driver.
+/**
+ * usb_register - register a USB driver
+ * @new_driver: USB operations for the driver
+ *
+ * Registers a USB driver with the USB core.  The list of unattached
+ * interfaces will be rescanned whenever a new driver is added, allowing
+ * the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ * 
+ * NOTE: if you want your driver to use the USB major number, you must call
+ * usb_register_dev() to enable that functionality.  This function no longer
+ * takes care of that.
  */
-static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
+int usb_register(struct usb_driver *new_driver)
 {
-	int i;
-
-	if (!dev) {
-		err("null device being purged!!!");
-		return;
-	}
+	int retval = 0;
 
-	for (i=0; i<USB_MAXCHILDREN; i++)
-		if (dev->children[i])
-			usb_drivers_purge(driver, dev->children[i]);
+	new_driver->driver.name = (char *)new_driver->name;
+	new_driver->driver.bus = &usb_bus_type;
+	new_driver->driver.probe = usb_device_probe;
+	new_driver->driver.remove = usb_device_remove;
 
-	if (!dev->actconfig)
-		return;
+	init_MUTEX(&new_driver->serialize);
 
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface *interface = &dev->actconfig->interface[i];
+	retval = driver_register(&new_driver->driver);
 
-		if (interface->driver == driver) {
-			usb_unbind_driver(dev, interface);
-			/* if driver->disconnect didn't release the interface */
-			if (interface->driver)
-				usb_driver_release_interface(driver, interface);
-			/*
-			 * This will go through the list looking for another
-			 * driver that can handle the device
-			 */
-			usb_find_interface_driver(dev, interface);
-		}
+	if (!retval) {
+		info("registered new driver %s", new_driver->name);
+		usbfs_update_special();
+	} else {
+		err("problem %d when registering driver %s",
+			retval, new_driver->name);
 	}
+
+	return retval;
 }
 
 /**
@@ -282,25 +188,9 @@
  */
 void usb_deregister(struct usb_driver *driver)
 {
-	struct list_head *tmp;
-
 	info("deregistering driver %s", driver->name);
 
-	/*
-	 * first we remove the driver, to be sure it doesn't get used by
-	 * another thread while we are stepping through removing entries
-	 */
-	list_del(&driver->driver_list);
-
-	down (&usb_bus_list_lock);
-	tmp = usb_bus_list.next;
-	while (tmp != &usb_bus_list) {
-		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
-
-		tmp = tmp->next;
-		usb_drivers_purge(driver, bus->root_hub);
-	}
-	up (&usb_bus_list_lock);
+	remove_driver (&driver->driver);
 
 	usbfs_update_special();
 }
@@ -333,6 +223,32 @@
 }
 
 /**
+ * usb_if_to_ifnum - get the interface number for a given interface
+ * @iface: the interface to determine the ifnum of
+ *
+ * This walks the device descriptor for the currently active configuration
+ * and returns the interface number of this specific interface, or -ENODEV.
+ *
+ * Note that configuration descriptors are not required to assign interface
+ * numbers sequentially, so that it would be incorrect to assume that
+ * the first interface in that descriptor corresponds to interface zero.
+ * This routine helps device drivers avoid such mistakes.
+ * However, you should make sure that you do the right thing with any
+ * alternate settings available for this interfaces.
+ */
+int usb_if_to_ifnum(struct usb_interface *iface)
+{
+	struct usb_device *dev = interface_to_usbdev(iface);
+	int i;
+
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+		if (iface == &dev->actconfig->interface[i])
+			return dev->actconfig->interface[i].altsetting[0].bInterfaceNumber;
+
+	return -ENODEV;
+}
+
+/**
  * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
  * @dev: the device whose current configuration is considered
  * @epnum: the desired endpoint
@@ -359,34 +275,6 @@
 	return NULL;
 }
 
-/*
- * This function is for doing a depth-first search for devices which
- * have support, for dynamic loading of driver modules.
- */
-static void usb_check_support(struct usb_device *dev)
-{
-	int i;
-
-	if (!dev) {
-		err("null device being checked!!!");
-		return;
-	}
-
-	for (i=0; i<USB_MAXCHILDREN; i++)
-		if (dev->children[i])
-			usb_check_support(dev->children[i]);
-
-	if (!dev->actconfig)
-		return;
-
-	/* now we check this device */
-	if (dev->devnum > 0)
-		for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
-			usb_find_interface_driver (dev,
-				dev->actconfig->interface + i);
-}
-
-
 /**
  * usb_driver_claim_interface - bind a driver to an interface
  * @driver: the driver to be bound
@@ -595,72 +483,25 @@
 	return NULL;
 }
 
-/*
- * This entrypoint gets called for unclaimed interfaces.
- *
- * 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. 
- *
- * Returns: 0 if a driver accepted the interface, -1 otherwise
- */
-int usb_find_interface_driver (
-	struct usb_device *dev,
-	struct usb_interface *interface
-)
+static int usb_device_match (struct device *dev, struct device_driver *drv)
 {
-	struct list_head *tmp;
-	void *private;
-	struct usb_driver *driver;
-	int ifnum;
-	
-	down(&dev->serialize);
-
-	/* FIXME It's just luck that for some devices with drivers that set
-	 * configuration in probe(), the interface numbers still make sense.
-	 * That's one of several unsafe assumptions involved in configuring
-	 * devices, and in binding drivers to their interfaces.
-	 */
-	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++)
-		if (&dev->actconfig->interface [ifnum] == interface)
-			break;
-	BUG_ON (ifnum == dev->actconfig->bNumInterfaces);
+	struct usb_interface *intf;
+	struct usb_driver *usb_drv;
+	const struct usb_device_id *id;
 
-	if (usb_interface_claimed(interface))
-		goto out_err;
+	intf = to_usb_interface(dev);
 
-	private = NULL;
-	lock_kernel();
-	for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
-		driver = list_entry(tmp, struct usb_driver, driver_list);
-		tmp = tmp->next;
-
-		private = usb_bind_driver(driver, interface);
-
-		/* probe() may have changed the config on us */
-		interface = dev->actconfig->interface + ifnum;
-
-		if (private) {
-			usb_driver_claim_interface(driver, interface, private);
-			up(&dev->serialize);
-			unlock_kernel();
-			return 0;
-		}
-	}
-	unlock_kernel();
+	usb_drv = to_usb_driver(drv);
+	id = usb_drv->id_table;
+	
+	id = usb_match_id (intf, usb_drv->id_table);
+	if (id)
+		return 1;
 
-out_err:
-	up(&dev->serialize);
-	return -1;
+	return 0;
 }
 
+
 #ifdef	CONFIG_HOTPLUG
 
 /*
@@ -890,71 +731,6 @@
 }
 static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
 
-/*
- * This entrypoint gets called for each new device.
- *
- * All interfaces are scanned for matching drivers.
- */
-static void usb_find_drivers(struct usb_device *dev)
-{
-	unsigned ifnum;
-	unsigned rejected = 0;
-	unsigned claimed = 0;
-
-	/* FIXME should get called for each new configuration not just the
-	 * first one for a device. switching configs (or altsettings) should
-	 * undo driverfs and HCD state for the previous interfaces.
-	 */
-	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
-		struct usb_interface *interface = &dev->actconfig->interface[ifnum];
-		struct usb_interface_descriptor *desc = interface->altsetting;
-
-		/* register this interface with driverfs */
-		interface->dev.parent = &dev->dev;
-		interface->dev.bus = &usb_bus_type;
-		sprintf (&interface->dev.bus_id[0], "%s-%s:%d",
-			 dev->bus->bus_name, dev->devpath,
-			 interface->altsetting->bInterfaceNumber);
-		if (!desc->iInterface
-				|| usb_string (dev, desc->iInterface,
-					interface->dev.name,
-					sizeof interface->dev.name) <= 0) {
-			/* typically devices won't bother with interface
-			 * descriptions; this is the normal case.  an
-			 * interface's driver might describe it better.
-			 * (also: iInterface is per-altsetting ...)
-			 */
-			sprintf (&interface->dev.name[0],
-				"usb-%s-%s interface %d",
-				dev->bus->bus_name, dev->devpath,
-				interface->altsetting->bInterfaceNumber);
-		}
-		device_register (&interface->dev);
-		device_create_file (&interface->dev, &dev_attr_altsetting);
-
-		/* if this interface hasn't already been claimed */
-		if (!usb_interface_claimed(interface)) {
-			if (usb_find_interface_driver(dev, interface))
-				rejected++;
-			else
-				claimed++;
-		}
-	}
- 
-	if (rejected)
-		dbg("unhandled interfaces on device");
-
-	if (!claimed) {
-		warn("USB device %d (vend/prod 0x%x/0x%x) is not claimed by any active driver.",
-			dev->devnum,
-			dev->descriptor.idVendor,
-			dev->descriptor.idProduct);
-#ifdef DEBUG
-		usb_show_device(dev);
-#endif
-	}
-}
-
 /**
  * usb_alloc_dev - allocate a usb device structure (usbcore-internal)
  * @parent: hub to which device is connected
@@ -1109,32 +885,21 @@
 
 	info("USB disconnect on device %d", dev->devnum);
 
-	lock_kernel();
-	if (dev->actconfig) {
-		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-			struct usb_interface *interface = &dev->actconfig->interface[i];
-			struct usb_driver *driver = interface->driver;
-			if (driver) {
-				usb_unbind_driver(dev, interface);
-				/* if driver->disconnect didn't release the interface */
-				if (interface->driver)
-					usb_driver_release_interface(driver, interface);
-			}
-			/* remove our device node for this interface */
-			put_device(&interface->dev);
-		}
-	}
-	unlock_kernel();
-
-	/* Free up all the children.. */
+	/* Free up all the children before we remove this device */
 	for (i = 0; i < USB_MAXCHILDREN; i++) {
 		struct usb_device **child = dev->children + i;
 		if (*child)
 			usb_disconnect(child);
 	}
 
-	/* Let policy agent unload modules etc */
-	call_policy ("remove", dev);
+	if (dev->actconfig) {
+		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+			struct usb_interface *interface = &dev->actconfig->interface[i];
+
+			/* remove this interface */
+			put_device(&interface->dev);
+		}
+	}
 
 	/* Free the device number and remove the /proc/bus/usb entry */
 	if (dev->devnum > 0) {
@@ -1146,6 +911,9 @@
 	/* Decrement the reference count, it'll auto free everything when */
 	/* it hits 0 which could very well be now */
 	usb_put_dev(dev);
+
+	/* Let policy agent unload modules etc */
+	call_policy ("remove", dev);
 }
 
 /**
@@ -1271,7 +1039,7 @@
  */
 #define NEW_DEVICE_RETRYS	2
 #define SET_ADDRESS_RETRYS	2
-int usb_new_device(struct usb_device *dev)
+int usb_new_device(struct usb_device *dev, struct device *parent)
 {
 	int err = 0;
 	int i;
@@ -1361,10 +1129,25 @@
 		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
-	/* register this device in the driverfs tree */
+	/*
+	 * Set the driver for the usb device to point to the "generic" driver.
+	 * This prevents the main usb device from being sent to the usb bus
+	 * probe function.  Yes, it's a hack, but a nice one :)
+	 */
+	usb_generic_driver.bus = &usb_bus_type;
+	dev->dev.parent = parent;
+	dev->dev.driver = &usb_generic_driver;
+	dev->dev.bus = &usb_bus_type;
+//	sprintf (&dev->dev.bus_id[0], "%s-%s",
+//		 dev->bus->bus_name, dev->devpath);
+	if (dev->dev.bus_id[0] == 0)
+		sprintf (&dev->dev.bus_id[0], "%d-%s",
+			 dev->bus->busnum, dev->devpath);
 	err = device_register (&dev->dev);
 	if (err)
 		return err;
+
+	/* add the USB device specific driverfs files */
 	device_create_file (&dev->dev, &dev_attr_configuration);
 	if (dev->descriptor.iManufacturer)
 		device_create_file (&dev->dev, &dev_attr_manufacturer);
@@ -1373,11 +1156,41 @@
 	if (dev->descriptor.iSerialNumber)
 		device_create_file (&dev->dev, &dev_attr_serial);
 
-	/* now that the basic setup is over, add a /proc/bus/usb entry */
-	usbfs_add_device(dev);
+	/* Register all of the interfaces for this device with the driver core.
+	 * Remember, interfaces get bound to drivers, not devices. */
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *interface = &dev->actconfig->interface[i];
+		struct usb_interface_descriptor *desc = interface->altsetting;
 
-	/* find drivers willing to handle this device */
-	usb_find_drivers(dev);
+		interface->dev.parent = &dev->dev;
+		interface->dev.bus = &usb_bus_type;
+//		sprintf (&interface->dev.bus_id[0], "%s-%s:%d",
+//			 dev->bus->bus_name, dev->devpath,
+//			 interface->altsetting->bInterfaceNumber);
+		sprintf (&interface->dev.bus_id[0], "%d-%s:%d",
+			 dev->bus->busnum, dev->devpath,
+			 interface->altsetting->bInterfaceNumber);
+		if (!desc->iInterface
+				|| usb_string (dev, desc->iInterface,
+					interface->dev.name,
+					sizeof interface->dev.name) <= 0) {
+			/* typically devices won't bother with interface
+			 * descriptions; this is the normal case.  an
+			 * interface's driver might describe it better.
+			 * (also: iInterface is per-altsetting ...)
+			 */
+			sprintf (&interface->dev.name[0],
+				"usb-%s-%s interface %d",
+				dev->bus->bus_name, dev->devpath,
+				interface->altsetting->bInterfaceNumber);
+		}
+		dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
+		device_register (&interface->dev);
+		device_create_file (&interface->dev, &dev_attr_altsetting);
+	}
+
+	/* add a /proc/bus/usb entry */
+	usbfs_add_device(dev);
 
 	/* userspace may load modules and/or configure further */
 	call_policy ("add", dev);
@@ -1385,7 +1198,6 @@
 	return 0;
 }
 
-
 /**
  * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP
  * @dev: device the buffer will be used with
@@ -1532,20 +1344,9 @@
 				: USB_DIR_OUT);
 }
 
-#ifdef CONFIG_PROC_FS
-struct list_head *usb_driver_get_list(void)
-{
-	return &usb_driver_list;
-}
-
-struct list_head *usb_bus_get_list(void)
-{
-	return &usb_bus_list;
-}
-#endif
-
 struct bus_type usb_bus_type = {
-	.name =	"usb",
+	.name =		"usb",
+	.match =	usb_device_match,
 };
 
 /*
@@ -1584,7 +1385,11 @@
 
 EXPORT_SYMBOL(usb_register);
 EXPORT_SYMBOL(usb_deregister);
-EXPORT_SYMBOL(usb_scan_devices);
+
+EXPORT_SYMBOL(usb_device_probe);
+EXPORT_SYMBOL(usb_device_remove);
+
+EXPORT_SYMBOL(usb_if_to_ifnum);
 
 EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_free_dev);
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/input/hid-core.c	Thu Aug 29 14:56:00 2002
@@ -1338,9 +1338,10 @@
 	{ 0, 0 }
 };
 
-static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
+static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
-	struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
+	struct usb_interface_descriptor *interface = intf->altsetting + intf->act_altsetting;
+	struct usb_device *dev = interface_to_usbdev (intf);
 	struct hid_descriptor *hdesc;
 	struct hid_device *hid;
 	unsigned quirks = 0, rsize = 0;
@@ -1450,7 +1451,7 @@
 		snprintf(hid->name, 128, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
 
 	usb_make_path(dev, buf, 64);
-	snprintf(hid->phys, 64, "%s/input%d", buf, ifnum);
+	snprintf(hid->phys, 64, "%s/input%d", buf, intf->altsetting[0].bInterfaceNumber);
 
 	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
 		hid->uniq[0] = 0;
@@ -1472,9 +1473,12 @@
 	return NULL;
 }
 
-static void hid_disconnect(struct usb_device *dev, void *ptr)
+static void hid_disconnect(struct usb_interface *intf)
 {
-	struct hid_device *hid = ptr;
+	struct hid_device *hid = intf->dev.driver_data;
+
+	if (!hid)
+		return;
 
 	usb_unlink_urb(hid->urbin);
 	usb_unlink_urb(hid->urbout);
@@ -1491,20 +1495,20 @@
 		usb_free_urb(hid->urbout);
 
 	hid_free_device(hid);
+	intf->dev.driver_data = NULL;
 }
 
-static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
-		       const struct usb_device_id *id)
+static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct hid_device *hid;
 	char path[64];
 	int i;
 	char *c;
 
-	dbg("HID probe called for ifnum %d", ifnum);
+	dbg("HID probe called for ifnum %d", intf->ifnum);
 
-	if (!(hid = usb_hid_configure(dev, ifnum)))
-		return NULL;
+	if (!(hid = usb_hid_configure(intf)))
+		return -EIO;
 
 	hid_init_reports(hid);
 	hid_dump_device(hid);
@@ -1516,9 +1520,11 @@
 	if (!hiddev_connect(hid))
 		hid->claimed |= HID_CLAIMED_HIDDEV;
 
+	intf->dev.driver_data = hid;
+
 	if (!hid->claimed) {
-		hid_disconnect(dev, hid);
-		return NULL;
+		hid_disconnect(intf);
+		return -EIO;
 	}
 
 	printk(KERN_INFO);
@@ -1540,12 +1546,12 @@
 		}
 	}
 
-	usb_make_path(dev, path, 63);
+	usb_make_path(interface_to_usbdev(intf), path, 63);
 
 	printk(": USB HID v%x.%02x %s [%s] on %s\n",
 		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
 
-	return hid;
+	return 0;
 }
 
 static struct usb_device_id hid_usb_ids [] = {
diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
--- a/drivers/usb/input/usbmouse.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/input/usbmouse.c	Thu Aug 29 14:56:00 2002
@@ -98,10 +98,9 @@
 		usb_unlink_urb(mouse->irq);
 }
 
-static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
-			     const struct usb_device_id *id)
+static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
 {
-	struct usb_interface *iface;
+	struct usb_device * dev = interface_to_usbdev(intf);
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_mouse *mouse;
@@ -109,25 +108,28 @@
 	char path[64];
 	char *buf;
 
-	iface = &dev->actconfig->interface[ifnum];
-	interface = &iface->altsetting[iface->act_altsetting];
+	interface = &intf->altsetting[intf->act_altsetting];
 
-	if (interface->bNumEndpoints != 1) return NULL;
+	if (interface->bNumEndpoints != 1) 
+		return -ENODEV;
 
 	endpoint = interface->endpoint + 0;
-	if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
-	if ((endpoint->bmAttributes & 3) != 3) return NULL;
+	if (!(endpoint->bEndpointAddress & 0x80)) 
+		return -ENODEV;
+	if ((endpoint->bmAttributes & 3) != 3) 
+		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
+	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) 
+		return -ENOMEM;
 	memset(mouse, 0, sizeof(struct usb_mouse));
 
 	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!mouse->irq) {
 		kfree(mouse);
-		return NULL;
+		return -ENODEV;
 	}
 
 	mouse->usbdev = dev;
@@ -154,7 +156,7 @@
 
 	if (!(buf = kmalloc(63, GFP_KERNEL))) {
 		kfree(mouse);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	if (dev->descriptor.iManufacturer &&
@@ -174,19 +176,23 @@
 		usb_mouse_irq, mouse, endpoint->bInterval);
 
 	input_register_device(&mouse->dev);
-
 	printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
 
-	return mouse;
+	intf->dev.driver_data = mouse;
+	return 0;
 }
 
-static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
+static void usb_mouse_disconnect(struct usb_interface * intf)
 {
-	struct usb_mouse *mouse = ptr;
-	usb_unlink_urb(mouse->irq);
-	input_unregister_device(&mouse->dev);
-	usb_free_urb(mouse->irq);
-	kfree(mouse);
+	struct usb_mouse *mouse = intf->dev.driver_data;
+	intf->dev.driver_data = NULL;
+
+	if (mouse) {
+		usb_unlink_urb(mouse->irq);
+		input_unregister_device(&mouse->dev);
+		usb_free_urb(mouse->irq);
+		kfree(mouse);
+	}
 }
 
 static struct usb_device_id usb_mouse_id_table [] = {
@@ -197,10 +203,10 @@
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
 
 static struct usb_driver usb_mouse_driver = {
-	.name =		"usb_mouse",
-	.probe =	usb_mouse_probe,
-	.disconnect =	usb_mouse_disconnect,
-	.id_table =	usb_mouse_id_table,
+	.name		= "usb_mouse",
+	.probe		= usb_mouse_probe,
+	.disconnect	= usb_mouse_disconnect,
+	.id_table	= usb_mouse_id_table,
 };
 
 static int __init usb_mouse_init(void)
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/belkin_sa.c	Thu Aug 29 14:56:01 2002
@@ -114,6 +114,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver belkin_driver = {
+	.name =		"belkin",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
 /* All of the device info needed for the serial converters */
 static struct usb_serial_device_type belkin_device = {
 	.owner =		THIS_MODULE,
@@ -526,6 +533,7 @@
 static int __init belkin_sa_init (void)
 {
 	usb_serial_register (&belkin_device);
+	usb_register (&belkin_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -533,6 +541,7 @@
 
 static void __exit belkin_sa_exit (void)
 {
+	usb_deregister (&belkin_driver);
 	usb_serial_deregister (&belkin_device);
 }
 
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/cyberjack.c	Thu Aug 29 14:56:00 2002
@@ -73,6 +73,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver cyberjack_driver = {
+	.name =		"cyberjack",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
 static struct usb_serial_device_type cyberjack_device = {
 	.owner =		THIS_MODULE,
 	.name =			"Reiner SCT Cyberjack USB card reader",
@@ -461,6 +468,7 @@
 static int __init cyberjack_init (void)
 {
 	usb_serial_register (&cyberjack_device);
+	usb_register (&cyberjack_driver);
 
 	info(DRIVER_VERSION " " DRIVER_AUTHOR);
 	info(DRIVER_DESC);
@@ -470,6 +478,7 @@
 
 static void __exit cyberjack_exit (void)
 {
+	usb_deregister (&cyberjack_driver);
 	usb_serial_deregister (&cyberjack_device);
 }
 
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/digi_acceleport.c	Thu Aug 29 14:56:01 2002
@@ -477,7 +477,7 @@
 
 /* Statics */
 
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
 	{ }						/* Terminating entry */
@@ -495,6 +495,14 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver digi_driver = {
+	.name =		"digi_acceleport",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
+
 /* device info needed for the Digi serial converter */
 
 static struct usb_serial_device_type digi_acceleport_2_device = {
@@ -2026,6 +2034,7 @@
 {
 	usb_serial_register (&digi_acceleport_2_device);
 	usb_serial_register (&digi_acceleport_4_device);
+	usb_register (&digi_driver);
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 	return 0;
 }
@@ -2033,6 +2042,7 @@
 
 static void __exit digi_exit (void)
 {
+	usb_deregister (&digi_driver);
 	usb_serial_deregister (&digi_acceleport_2_device);
 	usb_serial_deregister (&digi_acceleport_4_device);
 }
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/empeg.c	Thu Aug 29 14:56:01 2002
@@ -110,6 +110,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver empeg_driver = {
+	.name =		"empeg",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
 static struct usb_serial_device_type empeg_device = {
 	.owner =		THIS_MODULE,
 	.name =			"Empeg",
@@ -550,8 +557,6 @@
 	struct urb *urb;
 	int i;
 
-	usb_serial_register (&empeg_device);
-
 	/* create our write urb pool and transfer buffers */ 
 	spin_lock_init (&write_urb_pool_lock);
 	for (i = 0; i < NUM_URBS; ++i) {
@@ -570,10 +575,12 @@
 		}
 	}
 
+	usb_serial_register (&empeg_device);
+	usb_register (&empeg_driver);
+
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 
 	return 0;
-
 }
 
 
@@ -582,6 +589,7 @@
 	int i;
 	unsigned long flags;
 
+	usb_register (&empeg_driver);
 	usb_serial_deregister (&empeg_device);
 
 	spin_lock_irqsave (&write_urb_pool_lock, flags);
@@ -599,7 +607,6 @@
 	}
 
 	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
 }
 
 
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/ftdi_sio.c	Thu Aug 29 14:56:00 2002
@@ -140,7 +140,7 @@
 };
 
 
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
@@ -149,6 +149,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver ftdi_driver = {
+	.name =		"ftdi_sio",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
 
 struct ftdi_private {
 	enum ftdi_type ftdi_type;
@@ -944,6 +951,7 @@
 	dbg(__FUNCTION__);
 	usb_serial_register (&ftdi_sio_device);
 	usb_serial_register (&ftdi_8U232AM_device);
+	usb_register (&ftdi_driver);
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 	return 0;
 }
@@ -952,6 +960,7 @@
 static void __exit ftdi_sio_exit (void)
 {
 	dbg(__FUNCTION__);
+	usb_deregister (&ftdi_driver);
 	usb_serial_deregister (&ftdi_sio_device);
 	usb_serial_deregister (&ftdi_8U232AM_device);
 }
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/io_edgeport.c	Thu Aug 29 14:56:01 2002
@@ -457,6 +457,12 @@
 
 #include "io_tables.h"	/* all of the devices that this driver supports */
 
+static struct usb_driver io_driver = {
+	.name =		"io_edgeport",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
 
 /* function prototypes for all of our local functions */
 static int  process_rcvd_data		(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
@@ -3049,6 +3055,7 @@
 	usb_serial_register (&edgeport_2port_device);
 	usb_serial_register (&edgeport_4port_device);
 	usb_serial_register (&edgeport_8port_device);
+	usb_register (&io_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -3061,6 +3068,7 @@
  ****************************************************************************/
 void __exit edgeport_exit (void)
 {
+	usb_deregister (&io_driver);
 	usb_serial_deregister (&edgeport_1port_device);
 	usb_serial_deregister (&edgeport_2port_device);
 	usb_serial_deregister (&edgeport_4port_device);
diff -Nru a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
--- a/drivers/usb/serial/io_tables.h	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/io_tables.h	Thu Aug 29 14:56:00 2002
@@ -61,7 +61,7 @@
 };
 
 /* Devices that this driver supports */
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_RAPIDPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4T) },
diff -Nru a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
--- a/drivers/usb/serial/io_ti.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/io_ti.c	Thu Aug 29 14:56:00 2002
@@ -142,7 +142,7 @@
 };
 
 /* Devices that this driver supports */
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
@@ -161,6 +161,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver io_driver = {
+	.name =		"io_ti",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
 
 static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion;
 
@@ -2658,12 +2665,14 @@
 {
 	usb_serial_register (&edgeport_1port_device);
 	usb_serial_register (&edgeport_2port_device);
+	usb_register (&io_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
 
 static void __exit edgeport_exit (void)
 {
+	usb_deregister (&io_driver);
 	usb_serial_deregister (&edgeport_1port_device);
 	usb_serial_deregister (&edgeport_2port_device);
 }
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/ipaq.c	Thu Aug 29 14:56:01 2002
@@ -94,6 +94,14 @@
 
 MODULE_DEVICE_TABLE (usb, ipaq_id_table);
 
+static struct usb_driver ipaq_driver = {
+	.name =		"ipaq",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	ipaq_id_table,
+};
+
+
 /* All of the device info needed for the Compaq iPAQ */
 struct usb_serial_device_type ipaq_device = {
 	.owner =		THIS_MODULE,
@@ -130,13 +138,13 @@
 		return -ENODEV;
 	}
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	bytes_in = 0;
 	bytes_out = 0;
 	priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
 	if (priv == NULL) {
-		err(__FUNCTION__ " - Out of memory");
+		err("%s - Out of memory", __FUNCTION__);
 		return -ENOMEM;
 	}
 	port->private = (void *)priv;
@@ -198,7 +206,7 @@
 		      ipaq_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
-		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 		goto error;
 	}
 
@@ -218,12 +226,12 @@
 			return 0;
 		}
 	}
-	err(__FUNCTION__ " - failed doing control urb, error %d", result);
+	err("%s - failed doing control urb, error %d", __FUNCTION__, result);
 	goto error;
 
 enomem:
 	result = -ENOMEM;
-	err(__FUNCTION__ " - Out of memory");
+	err("%s - Out of memory", __FUNCTION__);
 error:
 	ipaq_destroy_lists(port);
 	kfree(priv);
@@ -240,7 +248,7 @@
 		return; 
 	}
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 			 
 	serial = get_usb_serial(port, __FUNCTION__);
 	if (!serial)
@@ -271,15 +279,15 @@
 	if (port_paranoia_check(port, __FUNCTION__))
 		return;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
@@ -306,7 +314,7 @@
 		      ipaq_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 	return;
 }
 
@@ -317,7 +325,7 @@
 	int			bytes_sent = 0;
 	int			transfer_size;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	usb_serial_debug_data(__FILE__, __FUNCTION__, count, buf);
 	
@@ -344,7 +352,7 @@
 	unsigned long		flags;
 
 	if (priv->free_len <= 0) {
-		dbg(__FUNCTION__ " - we're stuffed");
+		dbg("%s - we're stuffed", __FUNCTION__);
 		return -EAGAIN;
 	}
 
@@ -356,7 +364,7 @@
 	}
 	spin_unlock_irqrestore(&write_list_lock, flags);
 	if (pkt == NULL) {
-		dbg(__FUNCTION__ " - we're stuffed");
+		dbg("%s - we're stuffed", __FUNCTION__);
 		return -EAGAIN;
 	}
 
@@ -379,7 +387,7 @@
 		spin_unlock_irqrestore(&write_list_lock, flags);
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 		}
 	} else {
 		spin_unlock_irqrestore(&write_list_lock, flags);
@@ -398,7 +406,7 @@
 
 	if (urb->status == -EINPROGRESS) {
 		/* Should never happen */
-		err(__FUNCTION__ " - flushing while urb is active !");
+		err("%s - flushing while urb is active !", __FUNCTION__);
 		return;
 	}
 	room = URBDATA_SIZE;
@@ -439,10 +447,10 @@
 		return;
 	}
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 	}
 
 	spin_lock_irqsave(&write_list_lock, flags);
@@ -451,7 +459,7 @@
 		spin_unlock_irqrestore(&write_list_lock, flags);
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 		}
 	} else {
 		priv->active = 0;
@@ -467,7 +475,7 @@
 {
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 
-	dbg(__FUNCTION__ " - freelen %d", priv->free_len);
+	dbg("%s - freelen %d", __FUNCTION__, priv->free_len);
 	return priv->free_len;
 }
 
@@ -475,7 +483,7 @@
 {
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 
-	dbg(__FUNCTION__ " - queuelen %d", priv->queue_len);
+	dbg("%s - queuelen %d", __FUNCTION__, priv->queue_len);
 	return priv->queue_len;
 }
 
@@ -503,19 +511,20 @@
 
 static int ipaq_startup(struct usb_serial *serial)
 {
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 	usb_set_configuration(serial->dev, 1);
 	return 0;
 }
 
 static void ipaq_shutdown(struct usb_serial *serial)
 {
-	dbg (__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 }
 
 static int __init ipaq_init(void)
 {
 	usb_serial_register(&ipaq_device);
+	usb_register(&ipaq_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 
 	return 0;
@@ -524,6 +533,7 @@
 
 static void __exit ipaq_exit(void)
 {
+	usb_deregister(&ipaq_driver);
 	usb_serial_deregister(&ipaq_device);
 }
 
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/ir-usb.c	Thu Aug 29 14:56:00 2002
@@ -129,6 +129,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver ir_driver = {
+	.name =		"ir-usb",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
 
 struct usb_serial_device_type ir_device = {
 	.owner =		THIS_MODULE,
@@ -606,6 +613,7 @@
 static int __init ir_init (void)
 {
 	usb_serial_register (&ir_device);
+	usb_register (&ir_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -613,6 +621,7 @@
 
 static void __exit ir_exit (void)
 {
+	usb_deregister (&ir_driver);
 	usb_serial_deregister (&ir_device);
 }
 
diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/keyspan.c	Thu Aug 29 14:56:01 2002
@@ -183,6 +183,7 @@
 	usb_serial_register (&keyspan_1port_device);
 	usb_serial_register (&keyspan_2port_device);
 	usb_serial_register (&keyspan_4port_device);
+	usb_register (&keyspan_driver);
 
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 
@@ -191,6 +192,7 @@
 
 static void __exit keyspan_exit (void)
 {
+	usb_deregister (&keyspan_driver);
 	usb_serial_deregister (&keyspan_pre_device);
 	usb_serial_deregister (&keyspan_1port_device);
 	usb_serial_deregister (&keyspan_2port_device);
diff -Nru a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
--- a/drivers/usb/serial/keyspan.h	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/keyspan.h	Thu Aug 29 14:56:00 2002
@@ -408,7 +408,7 @@
 	NULL,
 };
 
-static __devinitdata struct usb_device_id keyspan_ids_combined[] = {
+static struct usb_device_id keyspan_ids_combined[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
@@ -433,6 +433,13 @@
 };
 
 MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
+
+static struct usb_driver keyspan_driver = {
+	.name =		"keyspan",                
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	keyspan_ids_combined,
+};
 
 /* usb_device_id table for the pre-firmware download keyspan devices */
 static struct usb_device_id keyspan_pre_ids[] = {
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/keyspan_pda.c	Thu Aug 29 14:56:00 2002
@@ -140,7 +140,7 @@
 #define ENTREGRA_VENDOR_ID		0x1645
 #define ENTREGRA_FAKE_ID		0x8093
 
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 #ifdef KEYSPAN
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) },
 #endif
@@ -154,6 +154,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver keyspan_pda_driver = {
+	.name =		"keyspan_pda",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
 static struct usb_device_id id_table_std [] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) },
 	{ }						/* Terminating entry */
@@ -862,6 +869,7 @@
 #ifdef XIRCOM
 	usb_serial_register (&xircom_pgs_fake_device);
 #endif
+	usb_register (&keyspan_pda_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -869,6 +877,7 @@
 
 static void __exit keyspan_pda_exit (void)
 {
+	usb_deregister (&keyspan_pda_driver);
 	usb_serial_deregister (&keyspan_pda_device);
 #ifdef KEYSPAN
 	usb_serial_deregister (&keyspan_pda_fake_device);
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/kl5kusb105.c	Thu Aug 29 14:56:00 2002
@@ -117,6 +117,12 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver kl5kusb105d_driver = {
+	.name =		"kl5kusb105d",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
 
 static struct usb_serial_device_type kl5kusb105d_device = {
 	.owner =             THIS_MODULE,
@@ -1013,6 +1019,7 @@
 static int __init klsi_105_init (void)
 {
 	usb_serial_register (&kl5kusb105d_device);
+	usb_register (&kl5kusb105d_driver);
 
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
@@ -1021,6 +1028,7 @@
 
 static void __exit klsi_105_exit (void)
 {
+	usb_deregister (&kl5kusb105d_driver);
 	usb_serial_deregister (&kl5kusb105d_device);
 }
 
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/mct_u232.c	Thu Aug 29 14:56:01 2002
@@ -139,6 +139,12 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver mct_u232_driver = {
+	.name =		"mct_u232",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
 
 static struct usb_serial_device_type mct_u232_device = {
 	.owner =	     THIS_MODULE,
@@ -783,6 +789,7 @@
 static int __init mct_u232_init (void)
 {
 	usb_serial_register (&mct_u232_device);
+	usb_register (&mct_u232_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -790,6 +797,7 @@
 
 static void __exit mct_u232_exit (void)
 {
+	usb_deregister (&mct_u232_driver);
 	usb_serial_deregister (&mct_u232_device);
 }
 
diff -Nru a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
--- a/drivers/usb/serial/omninet.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/omninet.c	Thu Aug 29 14:56:00 2002
@@ -83,6 +83,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver omninet_driver = {
+	.name =		"omninet",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
 
 static struct usb_serial_device_type zyxel_omninet_device = {
 	.owner =		THIS_MODULE,
@@ -370,6 +377,7 @@
 static int __init omninet_init (void)
 {
 	usb_serial_register (&zyxel_omninet_device);
+	usb_register (&omninet_driver);
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 	return 0;
 }
@@ -377,6 +385,7 @@
 
 static void __exit omninet_exit (void)
 {
+	usb_deregister (&omninet_driver);
 	usb_serial_deregister (&zyxel_omninet_device);
 }
 
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/pl2303.c	Thu Aug 29 14:56:00 2002
@@ -72,11 +72,18 @@
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
 	{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver pl2303_driver = {
+	.name =		"pl2303",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
 
 #define SET_LINE_REQUEST_TYPE		0x21
 #define SET_LINE_REQUEST		0x20
@@ -708,6 +715,7 @@
 static int __init pl2303_init (void)
 {
 	usb_serial_register (&pl2303_device);
+	usb_register (&pl2303_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -715,6 +723,7 @@
 
 static void __exit pl2303_exit (void)
 {
+	usb_deregister (&pl2303_driver);
 	usb_serial_deregister (&pl2303_device);
 }
 
diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
--- a/drivers/usb/serial/pl2303.h	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/pl2303.h	Thu Aug 29 14:56:00 2002
@@ -22,3 +22,6 @@
 
 #define ITEGNO_VENDOR_ID	0x0eba
 #define ITEGNO_PRODUCT_ID	0x1080
+
+#define MA620_VENDOR_ID		0x0df7
+#define MA620_PRODUCT_ID	0x0620
diff -Nru a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
--- a/drivers/usb/serial/safe_serial.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/safe_serial.c	Thu Aug 29 14:56:01 2002
@@ -161,6 +161,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
+static struct usb_driver safe_driver = {
+	.name =		"safe_serial",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
 static __u16 crc10_table[256] = {
 	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
 	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
@@ -434,12 +441,14 @@
 	}
 
 	usb_serial_register (&safe_device);
+	usb_register (&safe_driver);
 
 	return 0;
 }
 
 static void __exit safe_exit (void)
 {
+	usb_deregister (&safe_driver);
 	usb_serial_deregister (&safe_device);
 }
 
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/usb-serial.h	Thu Aug 29 14:56:00 2002
@@ -233,6 +233,9 @@
 extern int  usb_serial_register(struct usb_serial_device_type *new_device);
 extern void usb_serial_deregister(struct usb_serial_device_type *device);
 
+extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
+extern void usb_serial_disconnect(struct usb_interface *iface);
+
 /* determine if we should include the EzUSB loader functions */
 #undef USES_EZUSB_FUNCTIONS
 #if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE)
diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/usbserial.c	Thu Aug 29 14:56:01 2002
@@ -5,10 +5,9 @@
  * Copyright (c) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com)
  *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
  *
  * This driver was originally based on the ACM driver by Armin Fuerst (which was 
  * based on a driver by Brad Keryan)
@@ -380,30 +379,23 @@
 	.num_ports =		1,
 	.shutdown =		generic_shutdown,
 };
-#endif
-
 
-/* local function prototypes */
-static int  serial_open (struct tty_struct *tty, struct file * filp);
-static void serial_close (struct tty_struct *tty, struct file * filp);
-static int  serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static int  serial_write_room (struct tty_struct *tty);
-static int  serial_chars_in_buffer (struct tty_struct *tty);
-static void serial_throttle (struct tty_struct * tty);
-static void serial_unthrottle (struct tty_struct * tty);
-static int  serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-static void serial_set_termios (struct tty_struct *tty, struct termios * old);
-static void serial_shutdown (struct usb_serial *serial);
-
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
-			       const struct usb_device_id *id);
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
+/* we want to look at all devices, as the vendor/product id can change
+ * depending on the command line argument */
+static struct usb_device_id generic_serial_ids[] = {
+	{.driver_info = 42},
+	{}
+};
+#endif
 
+/* Driver structure we register with the USB core */
 static struct usb_driver usb_serial_driver = {
 	.name =		"serial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
-	.id_table =	NULL, 			/* check all devices */
+#ifdef CONFIG_USB_SERIAL_GENERIC
+	.id_table =	generic_serial_ids,
+#endif
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -413,7 +405,6 @@
    drivers depend on it.
 */
 
-
 static int			serial_refcount;
 static struct tty_driver	serial_tty_driver;
 static struct tty_struct *	serial_tty[SERIAL_TTY_MINORS];
@@ -443,7 +434,7 @@
 	unsigned int i, j;
 	int good_spot;
 
-	dbg(__FUNCTION__ " %d", num_ports);
+	dbg("%s %d", __FUNCTION__, num_ports);
 
 	*minor = 0;
 	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
@@ -462,7 +453,7 @@
 			
 		serial->magic = USB_SERIAL_MAGIC;
 		*minor = i;
-		dbg(__FUNCTION__ " - minor base = %d", *minor);
+		dbg("%s - minor base = %d", __FUNCTION__, *minor);
 		for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
 			serial_table[i] = serial;
 		return serial;
@@ -474,7 +465,7 @@
 {
 	int i;
 
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	if (serial == NULL)
 		return;
@@ -497,13 +488,13 @@
 
 	/* dbg("ezusb_writememory %x, %d", address, length); */
 	if (!serial->dev) {
-		dbg(__FUNCTION__ " - no physical device present, failing.");
+		dbg("%s - no physical device present, failing.", __FUNCTION__);
 		return -ENODEV;
 	}
 
 	transfer_buffer =  kmalloc (length, GFP_KERNEL);
 	if (!transfer_buffer) {
-		err(__FUNCTION__ " - kmalloc(%d) failed.", length);
+		err("%s - kmalloc(%d) failed.", __FUNCTION__, length);
 		return -ENOMEM;
 	}
 	memcpy (transfer_buffer, data, length);
@@ -515,10 +506,10 @@
 int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
 {
 	int	response;
-	dbg(__FUNCTION__ " - %d", reset_bit);
+	dbg("%s - %d", __FUNCTION__, reset_bit);
 	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
 	if (response < 0) {
-		err(__FUNCTION__ "- %d failed", reset_bit);
+		err("%s- %d failed", __FUNCTION__, reset_bit);
 	}
 	return response;
 }
@@ -535,7 +526,7 @@
 	unsigned int portNumber;
 	int retval = 0;
 	
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	/* initialize the pointer incase something fails */
 	tty->driver_data = NULL;
@@ -610,7 +601,7 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* if disconnect beat us to the punch here, there's nothing to do */
 	if (tty->driver_data) {
@@ -631,10 +622,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
+	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not opened");
+		dbg("%s - port not opened", __FUNCTION__);
 		goto exit;
 	}
 
@@ -660,10 +651,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -689,10 +680,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s = port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -717,7 +708,7 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
@@ -742,10 +733,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -768,10 +759,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg ("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -796,10 +787,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -821,10 +812,10 @@
 
 	down (&port->sem);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not open");
+		dbg("%s - port not open", __FUNCTION__);
 		goto exit;
 	}
 
@@ -838,7 +829,7 @@
 
 static void serial_shutdown (struct usb_serial *serial)
 {
-	dbg(__FUNCTION__);
+	dbg ("%s", __FUNCTION__);
 
 	if (serial->type->shutdown)
 		serial->type->shutdown(serial);
@@ -854,7 +845,7 @@
 	off_t begin = 0;
 	char tmp[40];
 
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 	length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
 	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
 		serial = get_serial_by_minor(i);
@@ -899,7 +890,7 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return -ENODEV;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* force low_latency on so that our tty_push actually forces the data through, 
 	   otherwise it is scheduled, and with high data rates (like with OHCI) data
@@ -920,7 +911,7 @@
 				   port);
 		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
-			err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 	}
 
 	return result;
@@ -930,7 +921,7 @@
 {
 	struct usb_serial *serial = port->serial;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (serial->dev) {
 		/* shutdown any bulk reads that might be going on */
@@ -943,7 +934,7 @@
 
 static void generic_close (struct usb_serial_port *port, struct file * filp)
 {
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	generic_cleanup (port);
 }
 
@@ -952,17 +943,17 @@
 	struct usb_serial *serial = port->serial;
 	int result;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (count == 0) {
-		dbg(__FUNCTION__ " - write request of 0 bytes");
+		dbg("%s - write request of 0 bytes", __FUNCTION__);
 		return (0);
 	}
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
 		if (port->write_urb->status == -EINPROGRESS) {
-			dbg (__FUNCTION__ " - already writing");
+			dbg("%s - already writing", __FUNCTION__);
 			return (0);
 		}
 
@@ -990,7 +981,7 @@
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result)
-			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 		else
 			result = count;
 
@@ -1006,14 +997,14 @@
 	struct usb_serial *serial = port->serial;
 	int room = 0;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (serial->num_bulk_out) {
 		if (port->write_urb->status != -EINPROGRESS)
 			room = port->bulk_out_size;
 	}
 
-	dbg(__FUNCTION__ " - returns %d", room);
+	dbg("%s - returns %d", __FUNCTION__, room);
 	return (room);
 }
 
@@ -1022,14 +1013,14 @@
 	struct usb_serial *serial = port->serial;
 	int chars = 0;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (serial->num_bulk_out) {
 		if (port->write_urb->status == -EINPROGRESS)
 			chars = port->write_urb->transfer_buffer_length;
 	}
 
-	dbg (__FUNCTION__ " - returns %d", chars);
+	dbg("%s - returns %d", __FUNCTION__, chars);
 	return (chars);
 }
 
@@ -1042,15 +1033,15 @@
 	int i;
 	int result;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
@@ -1080,7 +1071,7 @@
 			     generic_read_bulk_callback), port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 }
 
 static void generic_write_bulk_callback (struct urb *urb)
@@ -1088,15 +1079,15 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
@@ -1110,7 +1101,7 @@
 {
 	int i;
 
-	dbg (__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
@@ -1124,7 +1115,7 @@
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	struct tty_struct *tty;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (!serial)
 		return;
@@ -1134,7 +1125,7 @@
 		return;
 
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg(__FUNCTION__ " - write wakeup call.");
+		dbg("%s - write wakeup call.", __FUNCTION__);
 		(tty->ldisc.write_wakeup)(tty);
 	}
 
@@ -1162,12 +1153,12 @@
 	return serial;
 }
 
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
+int usb_serial_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev (interface);
 	struct usb_serial *serial = NULL;
 	struct usb_serial_port *port;
-	struct usb_interface *interface;
 	struct usb_interface_descriptor *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
@@ -1190,7 +1181,6 @@
 	/* loop through our list of known serial converters, and see if this
 	   device matches. */
 	found = 0;
-	interface = &dev->actconfig->interface[ifnum];
 	list_for_each (tmp, &usb_serial_driver_list) {
 		type = list_entry(tmp, struct usb_serial_device_type, driver_list);
 		id_pattern = usb_match_id(interface, type->id_table);
@@ -1203,13 +1193,13 @@
 	if (!found) {
 		/* no match */
 		dbg("none matched");
-		return(NULL);
+		return -ENODEV;
 	}
 
 	serial = create_serial (dev, interface, type);
 	if (!serial) {
 		err ("%s - out of memory", __FUNCTION__);
-		return NULL;
+		return -ENODEV;
 	}
 
 	/* if this device type has a probe function, call it */
@@ -1223,7 +1213,7 @@
 		if (retval < 0) {
 			dbg ("sub driver rejected device");
 			kfree (serial);
-			return NULL;
+			return -ENODEV;
 		}
 	}
 
@@ -1259,6 +1249,7 @@
 	}
 
 #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
+#if 0
 	/* BEGIN HORRIBLE HACK FOR PL2303 */ 
 	/* this is needed due to the looney way its endpoints are set up */
 	if (ifnum == 1) {
@@ -1283,6 +1274,7 @@
 	}
 	/* END HORRIBLE HACK FOR PL2303 */
 #endif
+#endif
 
 	/* found all that we need */
 	info("%s converter detected", type->name);
@@ -1293,7 +1285,7 @@
 		if (num_ports == 0) {
 			err("Generic device with no bulk out, not allowed.");
 			kfree (serial);
-			return NULL;
+			return -EIO;
 		}
 	}
 #endif
@@ -1313,7 +1305,7 @@
 	if (get_free_serial (serial, num_ports, &minor) == NULL) {
 		err("No more free serial devices");
 		kfree (serial);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	serial->minor = minor;
@@ -1402,7 +1394,7 @@
 	max_endpoints = max(num_bulk_in, num_bulk_out);
 	max_endpoints = max(max_endpoints, num_interrupt_in);
 	max_endpoints = max(max_endpoints, (int)serial->num_ports);
-	dbg (__FUNCTION__ " - setting up %d port structures for this device", max_endpoints);
+	dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
 	for (i = 0; i < max_endpoints; ++i) {
 		port = &serial->port[i];
 		port->number = i + serial->minor;
@@ -1425,7 +1417,8 @@
 		if (retval > 0) {
 			/* quietly accept this device, but don't bind to a serial port
 			 * as it's about to disappear */
-			return serial;
+			interface->dev.driver_data = serial;
+			return 0;
 		}
 	}
 
@@ -1456,7 +1449,9 @@
 	}
 #endif
 
-	return serial; /* success */
+	/* success */
+	interface->dev.driver_data = serial;
+	return 0;
 
 
 probe_error:
@@ -1487,16 +1482,18 @@
 
 	/* free up any memory that we allocated */
 	kfree (serial);
-	return NULL;
+	return -EIO;
 }
 
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
+void usb_serial_disconnect(struct usb_interface *interface)
 {
-	struct usb_serial *serial = (struct usb_serial *) ptr;
+	struct usb_serial *serial = (struct usb_serial *)interface->dev.driver_data;
 	struct usb_serial_port *port;
 	int i;
 
-	dbg(__FUNCTION__);
+	dbg ("%s", __FUNCTION__);
+
+	interface->dev.driver_data = NULL;
 	if (serial) {
 		/* fail all future close/read/write/ioctl/etc calls */
 		for (i = 0; i < serial->num_ports; ++i) {
@@ -1555,10 +1552,8 @@
 
 		/* free up any memory that we allocated */
 		kfree (serial);
-
-	} else {
-		info("device disconnected");
 	}
+	info("device disconnected");
 
 }
 
@@ -1566,7 +1561,11 @@
 static struct tty_driver serial_tty_driver = {
 	.magic =		TTY_DRIVER_MAGIC,
 	.driver_name =		"usb-serial",
+#ifndef CONFIG_DEVFS_FS
+	.name =			"ttyUSB",
+#else
 	.name =			"usb/tts/%d",
+#endif
 	.major =		SERIAL_TTY_MAJOR,
 	.minor_start =		0,
 	.num =			SERIAL_TTY_MINORS,
@@ -1607,7 +1606,7 @@
 	serial_tty_driver.init_termios          = tty_std_termios;
 	serial_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	if (tty_register_driver (&serial_tty_driver)) {
-		err(__FUNCTION__ " - failed to register tty driver");
+		err("%s - failed to register tty driver", __FUNCTION__);
 		return -1;
 	}
 
@@ -1660,8 +1659,6 @@
 
 	info ("USB Serial support registered for %s", new_device->name);
 
-	usb_scan_devices();
-
 	return 0;
 }
 
@@ -1678,7 +1675,7 @@
 		serial = serial_table[i];
 		if ((serial != NULL) && (serial->type == device)) {
 			usb_driver_release_interface (&usb_serial_driver, serial->interface);
-			usb_serial_disconnect (NULL, serial);
+			usb_serial_disconnect (serial->interface);
 		}
 	}
 
@@ -1691,6 +1688,8 @@
    need these symbols to load properly as modules. */
 EXPORT_SYMBOL(usb_serial_register);
 EXPORT_SYMBOL(usb_serial_deregister);
+EXPORT_SYMBOL(usb_serial_probe);
+EXPORT_SYMBOL(usb_serial_disconnect);
 #ifdef USES_EZUSB_FUNCTIONS
 	EXPORT_SYMBOL(ezusb_writememory);
 	EXPORT_SYMBOL(ezusb_set_reset);
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/serial/visor.c	Thu Aug 29 14:56:00 2002
@@ -197,7 +197,7 @@
 	{ }					/* Terminating entry */
 };
 
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
@@ -214,7 +214,12 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-
+static struct usb_driver visor_driver = {
+	.name =		"visor",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
 static struct usb_serial_device_type handspring_device = {
@@ -280,7 +285,7 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return -ENODEV;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->read_urb) {
 		/* this is needed for some brain dead Sony devices */
@@ -298,7 +303,7 @@
 	 */
 	if (port->tty)
 		port->tty->low_latency = 1;
-	
+
 	/* Start reading from the device */
 	usb_fill_bulk_urb (port->read_urb, serial->dev,
 			   usb_rcvbulkpipe (serial->dev, 
@@ -308,7 +313,7 @@
 			   visor_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
-		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 	
 	return result;
 }
@@ -322,7 +327,7 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 			 
 	serial = get_usb_serial (port, __FUNCTION__);
 	if (!serial)
@@ -333,7 +338,7 @@
 		 * device is still here */
 		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
 		if (!transfer_buffer) {
-			err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+			err("%s - kmalloc(%d) failed.", __FUNCTION__, 0x12);
 		} else {
 			/* send a shutdown message to the device */
 			usb_control_msg (serial->dev,
@@ -358,7 +363,7 @@
 	unsigned char *buffer;
 	int status;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	buffer = kmalloc (count, GFP_ATOMIC);
 	if (!buffer) {
@@ -410,7 +415,7 @@
 
 static int visor_write_room (struct usb_serial_port *port)
 {
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/*
 	 * We really can take anything the user throws at us
@@ -423,7 +428,7 @@
 
 static int visor_chars_in_buffer (struct usb_serial_port *port)
 {
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* 
 	 * We can't really account for how much data we
@@ -442,10 +447,10 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
@@ -471,15 +476,15 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
@@ -508,14 +513,14 @@
 			   visor_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 	return;
 }
 
 
 static void visor_throttle (struct usb_serial_port *port)
 {
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	usb_unlink_urb (port->read_urb);
 }
 
@@ -524,12 +529,12 @@
 {
 	int result;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	port->read_urb->dev = port->serial->dev;
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 }
 
 static int visor_probe (struct usb_serial *serial)
@@ -540,20 +545,20 @@
 	unsigned char *transfer_buffer =  kmalloc (256, GFP_KERNEL);
 
 	if (!transfer_buffer) {
-		err(__FUNCTION__ " - kmalloc(%d) failed.", 256);
+		err("%s - kmalloc(%d) failed.", __FUNCTION__, 256);
 		return -ENOMEM;
 	}
 
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
-	dbg(__FUNCTION__ " - Set config to 1");
+	dbg("%s - Set config to 1", __FUNCTION__);
 	usb_set_configuration (serial->dev, 1);
 
 	/* send a get connection info request */
 	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
 					0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
 	if (response < 0) {
-		err(__FUNCTION__ " - error getting connection information");
+		err("%s - error getting connection information", __FUNCTION__);
 	} else {
 		struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
 		char *string;
@@ -598,7 +603,7 @@
 					    0xc2, 0x0000, 0x0000, transfer_buffer, 
 					    0x14, 300);
 		if (response < 0) {
-			err(__FUNCTION__ " - error getting first unknown palm command");
+			err("%s - error getting first unknown palm command", __FUNCTION__);
 		} else {
 			usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
 		}
@@ -607,7 +612,7 @@
 					    0xc2, 0x0000, 0x0000, transfer_buffer, 
 					    0x14, 300);
 		if (response < 0) {
-			err(__FUNCTION__ " - error getting second unknown palm command");
+			err("%s - error getting second unknown palm command", __FUNCTION__);
 		} else {
 			usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
 		}
@@ -617,7 +622,7 @@
 	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
 					0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
 	if (response < 0) {
-		err(__FUNCTION__ " - error getting bytes available request");
+		err("%s - error getting bytes available request", __FUNCTION__);
 	}
 
 	kfree (transfer_buffer);
@@ -642,7 +647,7 @@
 	int result;
 	u8 data;
 
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	/*
 	 * Note that PEG-300 series devices expect the following two calls.
@@ -653,11 +658,11 @@
 				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
 				  0, 0, &data, 1, HZ * 3);
 	if (result < 0) {
-		err(__FUNCTION__ ": get config number failed: %d", result);
+		err("%s: get config number failed: %d", __FUNCTION__, result);
 		return result;
 	}
 	if (result != 1) {
-		err(__FUNCTION__ ": get config number bad return length: %d", result);
+		err("%s: get config number bad return length: %d", __FUNCTION__, result);
 		return -EIO;
 	}
 
@@ -667,11 +672,11 @@
 				  USB_DIR_IN | USB_DT_DEVICE,
 				  0, 0, &data, 1, HZ * 3);
 	if (result < 0) {
-		err(__FUNCTION__ ": get interface number failed: %d", result);
+		err("%s: get interface number failed: %d", __FUNCTION__, result);
 		return result;
 	}
 	if (result != 1) {
-		err(__FUNCTION__ ": get interface number bad return length: %d", result);
+		err("%s: get interface number bad return length: %d", __FUNCTION__, result);
 		return -EIO;
 	}
 
@@ -680,12 +685,12 @@
 
 static void visor_shutdown (struct usb_serial *serial)
 {
-	dbg (__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 }
 
 static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
-	dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
 	return -ENOIOCTLCMD;
 }
@@ -696,10 +701,10 @@
 {
 	unsigned int cflag;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if ((!port->tty) || (!port->tty->termios)) {
-		dbg(__FUNCTION__" - no tty structures");
+		dbg("%s - no tty structures", __FUNCTION__);
 		return;
 	}
 
@@ -708,39 +713,39 @@
 	if (old_termios) {
 		if ((cflag == old_termios->c_cflag) &&
 		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg(__FUNCTION__ " - nothing to change...");
+			dbg("%s - nothing to change...", __FUNCTION__);
 			return;
 		}
 	}
 
 	/* get the byte size */
 	switch (cflag & CSIZE) {
-		case CS5:	dbg(__FUNCTION__ " - data bits = 5");   break;
-		case CS6:	dbg(__FUNCTION__ " - data bits = 6");   break;
-		case CS7:	dbg(__FUNCTION__ " - data bits = 7");   break;
+		case CS5:	dbg("%s - data bits = 5", __FUNCTION__);   break;
+		case CS6:	dbg("%s - data bits = 6", __FUNCTION__);   break;
+		case CS7:	dbg("%s - data bits = 7", __FUNCTION__);   break;
 		default:
-		case CS8:	dbg(__FUNCTION__ " - data bits = 8");   break;
+		case CS8:	dbg("%s - data bits = 8", __FUNCTION__);   break;
 	}
 	
 	/* determine the parity */
 	if (cflag & PARENB)
 		if (cflag & PARODD)
-			dbg(__FUNCTION__ " - parity = odd");
+			dbg("%s - parity = odd", __FUNCTION__);
 		else
-			dbg(__FUNCTION__ " - parity = even");
+			dbg("%s - parity = even", __FUNCTION__);
 	else
-		dbg(__FUNCTION__ " - parity = none");
+		dbg("%s - parity = none", __FUNCTION__);
 
 	/* figure out the stop bits requested */
 	if (cflag & CSTOPB)
-		dbg(__FUNCTION__ " - stop bits = 2");
+		dbg("%s - stop bits = 2", __FUNCTION__);
 	else
-		dbg(__FUNCTION__ " - stop bits = 1");
+		dbg("%s - stop bits = 1", __FUNCTION__);
 
 	
 	/* figure out the flow control settings */
 	if (cflag & CRTSCTS)
-		dbg(__FUNCTION__ " - RTS/CTS is enabled");
+		dbg("%s - RTS/CTS is enabled", __FUNCTION__);
 	else
 		dbg(__FUNCTION__ " - RTS/CTS is disabled");
 	
@@ -761,6 +766,7 @@
 {
 	usb_serial_register (&handspring_device);
 	usb_serial_register (&clie_3_5_device);
+	usb_register (&visor_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 
 	return 0;
@@ -769,6 +775,7 @@
 
 static void __exit visor_exit (void)
 {
+	usb_deregister (&visor_driver);
 	usb_serial_deregister (&handspring_device);
 	usb_serial_deregister (&clie_3_5_device);
 }
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/serial/whiteheat.c	Thu Aug 29 14:56:01 2002
@@ -110,7 +110,7 @@
 	{ }						/* Terminating entry */
 };
 
-static __devinitdata struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },
 	{ }						/* Terminating entry */
@@ -118,6 +118,13 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
+static struct usb_driver whiteheat_driver = {
+	.name =		"whiteheat",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table_combined,
+};
+
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_open		(struct usb_serial_port *port, struct file *filp);
 static void whiteheat_close		(struct usb_serial_port *port, struct file *filp);
@@ -179,7 +186,7 @@
  *****************************************************************************/
 static void command_port_write_callback (struct urb *urb)
 {
-	dbg (__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	if (urb->status) {
 		dbg ("nonzero urb status: %d", urb->status);
@@ -200,15 +207,15 @@
 	unsigned char *data = urb->transfer_buffer;
 	int result;
 
-	dbg (__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	if (urb->status) {
-		dbg (__FUNCTION__ " - nonzero urb status: %d", urb->status);
+		dbg("%s - nonzero urb status: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 	
@@ -216,7 +223,7 @@
 
 	info = (struct whiteheat_private *)port->private;
 	if (!info) {
-		dbg (__FUNCTION__ " - info is NULL, exiting.");
+		dbg("%s - info is NULL, exiting.", __FUNCTION__);
 		return;
 	}
 
@@ -239,7 +246,7 @@
 		      command_port_read_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+		dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 }
 
 
@@ -251,7 +258,7 @@
 	__u8 *transfer_buffer;
 	int retval = 0;
 
-	dbg(__FUNCTION__" - command %d", command);
+	dbg("%s - command %d", __FUNCTION__, command);
 
 	port = &serial->port[COMMAND_PORT];
 	info = (struct whiteheat_private *)port->private;
@@ -264,7 +271,7 @@
 	port->write_urb->dev = serial->dev;
 	retval = usb_submit_urb (port->write_urb, GFP_KERNEL);
 	if (retval) {
-		dbg (__FUNCTION__" - submit urb failed");
+		dbg("%s - submit urb failed", __FUNCTION__);
 		goto exit;
 	}
 
@@ -275,19 +282,19 @@
 	}
 
 	if (info->command_finished == FALSE) {
-		dbg (__FUNCTION__ " - command timed out.");
+		dbg("%s - command timed out.", __FUNCTION__);
 		retval = -ETIMEDOUT;
 		goto exit;
 	}
 
 	if (info->command_finished == WHITEHEAT_CMD_FAILURE) {
-		dbg (__FUNCTION__ " - command failed.");
+		dbg("%s - command failed.", __FUNCTION__);
 		retval = -EIO;
 		goto exit;
 	}
 
 	if (info->command_finished == WHITEHEAT_CMD_COMPLETE)
-		dbg (__FUNCTION__ " - command completed.");
+		dbg("%s - command completed.", __FUNCTION__);
 
 exit:
 	return retval;
@@ -301,14 +308,14 @@
 	struct whiteheat_private	*info;
 	int				retval = 0;
 
-	dbg(__FUNCTION__" - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* set up some stuff for our command port */
 	command_port = &port->serial->port[COMMAND_PORT];
 	if (command_port->private == NULL) {
 		info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL);
 		if (info == NULL) {
-			err(__FUNCTION__ " - out of memory");
+			err("%s - out of memory", __FUNCTION__);
 			retval = -ENOMEM;
 			goto exit;
 		}
@@ -321,7 +328,7 @@
 		command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */
 		retval = usb_submit_urb (command_port->read_urb, GFP_KERNEL);
 		if (retval) {
-			err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
+			err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
 			goto exit;
 		}
 	}
@@ -330,7 +337,7 @@
 	port->read_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (retval) {
-		err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
 		goto exit;
 	}
 
@@ -345,7 +352,7 @@
 	/* FIXME!!! */
 
 exit:
-	dbg(__FUNCTION__ " - exit, retval = %d", retval);
+	dbg("%s - exit, retval = %d", __FUNCTION__, retval);
 	return retval;
 }
 
@@ -354,7 +361,7 @@
 {
 	struct whiteheat_min_set	close_command;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	/* send a close command to the port */
 	/* firmware uses 1 based port numbering */
@@ -372,7 +379,7 @@
 
 static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
-	dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
 	return -ENOIOCTLCMD;
 }
@@ -383,10 +390,10 @@
 	unsigned int cflag;
 	struct whiteheat_port_settings port_settings;
 
-	dbg(__FUNCTION__ " -port %d", port->number);
+	dbg("%s -port %d", __FUNCTION__, port->number);
 
 	if ((!port->tty) || (!port->tty->termios)) {
-		dbg(__FUNCTION__" - no tty structures");
+		dbg("%s - no tty structures", __FUNCTION__);
 		goto exit;
 	}
 	
@@ -395,7 +402,7 @@
 	if (old_termios) {
 		if ((cflag == old_termios->c_cflag) &&
 		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg(__FUNCTION__ " - nothing to change...");
+			dbg("%s - nothing to change...", __FUNCTION__);
 			goto exit;
 		}
 	}
@@ -412,7 +419,7 @@
 		default:
 		case CS8:	port_settings.bits = 8;   break;
 	}
-	dbg(__FUNCTION__ " - data bits = %d", port_settings.bits);
+	dbg("%s - data bits = %d", __FUNCTION__, port_settings.bits);
 	
 	/* determine the parity */
 	if (cflag & PARENB)
@@ -422,14 +429,14 @@
 			port_settings.parity = 'e';
 	else
 		port_settings.parity = 'n';
-	dbg(__FUNCTION__ " - parity = %c", port_settings.parity);
+	dbg("%s - parity = %c", __FUNCTION__, port_settings.parity);
 
 	/* figure out the stop bits requested */
 	if (cflag & CSTOPB)
 		port_settings.stop = 2;
 	else
 		port_settings.stop = 1;
-	dbg(__FUNCTION__ " - stop bits = %d", port_settings.stop);
+	dbg("%s - stop bits = %d", __FUNCTION__, port_settings.stop);
 
 	
 	/* figure out the flow control settings */
@@ -437,7 +444,7 @@
 		port_settings.hflow = (WHITEHEAT_CTS_FLOW | WHITEHEAT_RTS_FLOW);
 	else
 		port_settings.hflow = 0;
-	dbg(__FUNCTION__ " - hardware flow control = %s %s %s %s",
+	dbg("%s - hardware flow control = %s %s %s %s", __FUNCTION__,
 	    (port_settings.hflow & WHITEHEAT_CTS_FLOW) ? "CTS" : "",
 	    (port_settings.hflow & WHITEHEAT_RTS_FLOW) ? "RTS" : "",
 	    (port_settings.hflow & WHITEHEAT_DSR_FLOW) ? "DSR" : "",
@@ -448,15 +455,15 @@
 		port_settings.sflow = 'b';
 	else
 		port_settings.sflow = 'n';
-	dbg(__FUNCTION__ " - software flow control = %c", port_settings.sflow);
+	dbg("%s - software flow control = %c", __FUNCTION__, port_settings.sflow);
 	
 	port_settings.xon = START_CHAR(port->tty);
 	port_settings.xoff = STOP_CHAR(port->tty);
-	dbg(__FUNCTION__ " - XON = %2x, XOFF = %2x", port_settings.xon, port_settings.xoff);
+	dbg("%s - XON = %2x, XOFF = %2x", __FUNCTION__, port_settings.xon, port_settings.xoff);
 
 	/* get the baud rate wanted */
 	port_settings.baud = tty_get_baud_rate(port->tty);
-	dbg(__FUNCTION__ " - baud rate = %d", port_settings.baud);
+	dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);
 
 	/* handle any settings that aren't specified in the tty structure */
 	port_settings.lloop = 0;
@@ -471,7 +478,7 @@
 
 static void whiteheat_throttle (struct usb_serial_port *port)
 {
-	dbg(__FUNCTION__" - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -482,7 +489,7 @@
 
 static void whiteheat_unthrottle (struct usb_serial_port *port)
 {
-	dbg(__FUNCTION__" - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -509,7 +516,7 @@
 	int response;
 	const struct whiteheat_hex_record *record;
 	
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 	
 	response = ezusb_set_reset (serial, 1);
 
@@ -626,7 +633,7 @@
 {
 	struct usb_serial_port *command_port;
 
-	dbg(__FUNCTION__);
+	dbg("%s", __FUNCTION__);
 
 	/* free up our private data for our command port */
 	command_port = &serial->port[COMMAND_PORT];
@@ -639,8 +646,6 @@
 }
 
 
-
-
 static void set_command (struct usb_serial_port *port, unsigned char state, unsigned char command)
 {
 	struct whiteheat_rdb_set rdb_command;
@@ -676,6 +681,7 @@
 {
 	usb_serial_register (&whiteheat_fake_device);
 	usb_serial_register (&whiteheat_device);
+	usb_register (&whiteheat_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -683,6 +689,7 @@
 
 static void __exit whiteheat_exit (void)
 {
+	usb_deregister (&whiteheat_driver);
 	usb_serial_deregister (&whiteheat_fake_device);
 	usb_serial_deregister (&whiteheat_device);
 }
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Thu Aug 29 14:56:00 2002
+++ b/drivers/usb/storage/scsiglue.c	Thu Aug 29 14:56:00 2002
@@ -252,7 +252,6 @@
 	for (i = 0; i < pusb_dev_save->actconfig->bNumInterfaces; i++) {
  		struct usb_interface *intf =
 			&pusb_dev_save->actconfig->interface[i];
-		const struct usb_device_id *id;
 
 		/* if this is an unclaimed interface, skip it */
 		if (!intf->driver) {
@@ -263,11 +262,8 @@
 
 		/* simulate a disconnect and reconnect for all interfaces */
 		US_DEBUGPX("simulating disconnect/reconnect.\n");
-		down(&intf->driver->serialize);
-		intf->driver->disconnect(pusb_dev_save, intf->private_data);
-		id = usb_match_id(intf, intf->driver->id_table);
-		intf->driver->probe(pusb_dev_save, i, id);
-		up(&intf->driver->serialize);
+		usb_device_remove (&intf->dev);
+		usb_device_probe (&intf->dev);
 	}
 	US_DEBUGP("bus_reset() complete\n");
 	scsi_lock(srb->host);
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Thu Aug 29 14:56:01 2002
+++ b/drivers/usb/storage/usb.c	Thu Aug 29 14:56:01 2002
@@ -103,10 +103,10 @@
 struct us_data *us_list;
 struct semaphore us_list_semaphore;
 
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
-			    const struct usb_device_id *id);
+static int storage_probe(struct usb_interface *iface,
+			 const struct usb_device_id *id);
 
-static void storage_disconnect(struct usb_device *dev, void *ptr);
+static void storage_disconnect(struct usb_interface *iface);
 
 /* The entries in this table, except for final ones here
  * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
@@ -618,9 +618,11 @@
 }
 
 /* Probe to see if a new device is actually a SCSI device */
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
-			    const struct usb_device_id *id)
+static int storage_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev(intf);
+	int ifnum = usb_if_to_ifnum(intf);
 	int i;
 	const int id_index = id - storage_usb_ids; 
 	char mf[USB_STOR_STRING_LEN];		     /* manufacturer */
@@ -645,7 +647,6 @@
 	/* the altsetting on the interface we're probing that matched our
 	 * usb_match_id table
 	 */
-	struct usb_interface *intf = dev->actconfig->interface;
 	struct usb_interface_descriptor *altsetting =
 		intf[ifnum].altsetting + intf[ifnum].act_altsetting;
 	US_DEBUGP("act_altsetting is %d\n", intf[ifnum].act_altsetting);
@@ -675,7 +676,7 @@
 			US_DEBUGP("Product: %s\n", unusual_dev->productName);
 	} else
 		/* no, we can't support it */
-		return NULL;
+		return -EIO;
 
 	/* At this point, we know we've got a live one */
 	US_DEBUGP("USB Mass Storage device detected\n");
@@ -724,7 +725,7 @@
 		} else if (result != 0) {
 			/* it's not a stall, but another error -- time to bail */
 			US_DEBUGP("-- Unknown error.  Rejecting device\n");
-			return NULL;
+			return -EIO;
 		}
 	}
 #endif
@@ -732,7 +733,7 @@
 	/* Do some basic sanity checks, and bail if we find a problem */
 	if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
-		return NULL;
+		return -EIO;
 	}
 
 	/* At this point, we've decided to try to use the device */
@@ -811,7 +812,7 @@
 						    GFP_KERNEL)) == NULL) {
 			printk(KERN_WARNING USB_STORAGE "Out of memory\n");
 			usb_put_dev(dev);
-			return NULL;
+			return -ENOMEM;
 		}
 		memset(ss, 0, sizeof(struct us_data));
 		new_device = 1;
@@ -1088,8 +1089,9 @@
 	printk(KERN_DEBUG 
 	       "USB Mass Storage device found at %d\n", dev->devnum);
 
-	/* return a pointer for the disconnect function */
-	return ss;
+	/* save a pointer to our structure */
+	intf->dev.driver_data = ss;
+	return 0;
 
 	/* we come here if there are any problems */
 	/* ss->dev_semaphore must be locked */
@@ -1099,15 +1101,17 @@
 	up(&ss->dev_semaphore);
 	if (new_device)
 		kfree(ss);
-	return NULL;
+	return -EIO;
 }
 
 /* Handle a disconnect event from the USB core */
-static void storage_disconnect(struct usb_device *dev, void *ptr)
+static void storage_disconnect(struct usb_interface *intf)
 {
-	struct us_data *ss = ptr;
+	struct us_data *ss = intf->dev.driver_data;
 
 	US_DEBUGP("storage_disconnect() called\n");
+
+	intf->dev.driver_data = NULL;
 
 	/* this is the odd case -- we disconnected but weren't using it */
 	if (!ss) {
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Thu Aug 29 14:56:01 2002
+++ b/include/linux/usb.h	Thu Aug 29 14:56:01 2002
@@ -227,7 +227,7 @@
 	int act_altsetting;		/* active alternate setting */
 	int num_altsetting;		/* number of alternate settings */
 	int max_altsetting;		/* total memory allocated */
- 
+
 	struct usb_driver *driver;	/* driver */
 	struct device dev;		/* interface specific device info */
 	void *private_data;
@@ -291,6 +291,8 @@
 	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
 		type,(void**)ptr)
 
+extern int usb_if_to_ifnum(struct usb_interface *iface);
+	
 /* -------------------------------------------------------------------------- */
 
 /* Host Controller Driver (HCD) support */
@@ -399,9 +401,6 @@
 extern void usb_free_dev(struct usb_device *);
 #define usb_put_dev usb_free_dev
 
-/* for when layers above USB add new non-USB drivers */
-extern void usb_scan_devices(void);
-
 /* mostly for devices emulating SCSI over USB */
 extern int usb_reset_device(struct usb_device *dev);
 
@@ -623,10 +622,10 @@
  *	expose information to user space regardless of where they
  *	do (or don't) show up otherwise in the filesystem.
  * @id_table: USB drivers use ID table to support hotplugging.
- *	Export this with MODULE_DEVICE_TABLE(usb,...), or use NULL to
- *	say that probe() should be called for any unclaimed interfce.
+ *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
+ *	or your driver's probe function will never get called. 
  *
- * USB drivers should provide a name, probe() and disconnect() methods,
+ * USB drivers must provide a name, probe() and disconnect() methods,
  * and an id_table.  Other driver fields are optional.
  *
  * The id_table is used in hotplugging.  It holds a set of descriptors,
@@ -643,32 +642,23 @@
  */
 struct usb_driver {
 	struct module *owner;
+
 	const char *name;
 
-	void *(*probe)(
-	    struct usb_device *dev,		/* the device */
-	    unsigned intf,			/* what interface */
-	    const struct usb_device_id *id	/* from id_table */
-	    );
-	void (*disconnect)(
-	    struct usb_device *dev,		/* the device */
-	    void *handle			/* as returned by probe() */
-	    );
+	int (*probe) (struct usb_interface *intf,
+		      const struct usb_device_id *id);
 
-	struct list_head driver_list;
-	struct semaphore serialize;
+	void (*disconnect) (struct usb_interface *intf);
 
-	/* ioctl -- userspace apps can talk to drivers through usbfs */
-	int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
+	int (*ioctl) (struct usb_device *dev, unsigned int code, void *buf);
 
-	/* support for "new-style" USB hotplugging */
 	const struct usb_device_id *id_table;
 
-	/* suspend before the bus suspends;
-	 * disconnect or resume when the bus resumes */
-	/* void (*suspend)(struct usb_device *dev); */
-	/* void (*resume)(struct usb_device *dev); */
+	struct device_driver driver;
+
+	struct semaphore serialize;
 };
+#define	to_usb_driver(d) container_of(d, struct usb_driver, driver)
 
 extern struct bus_type usb_bus_type;
 
@@ -681,6 +671,9 @@
 
 extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor);
 extern void usb_deregister_dev(int num_minors, int start_minor);
+
+extern int usb_device_probe(struct device *dev);
+extern int usb_device_remove(struct device *dev);
 
 /* -------------------------------------------------------------------------- */
 


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Copyright © 2002, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds