On Thursday 08 January 2004 07:01, Bernd wrote:
> Im mostly worried about having more than a single device with address 0.
> You can't do this as long as another device gets initialized.
> Therefor I thought disabling/enabling the port would be better, but I'm
> wrong as the result is be the same.
With the changes I have made, it is only possible to let the USB stack reset 
the device from the ATTACH routine of a driver. This should garantee that 
there is only one device with addr==0 , since the probe & attach routines are 
only called from one process.

> > For my device driver I have made a small change to the USB Stack and I
> > have introduced the return code "USB_ATTACH_NEED_RESET" for drivers to
> > tell the USB Stack thee device needs to be re-enumerated. The stack then
> > automatically re-assigns the device it's address, and re-probes for
> > drivers. This way even two seperate drivers could be made : one with the
> > firmware and one with the real driver.
> > Is anyone interrested in a patch maybe?
> Sounds interesting.
Have a look at the patch attached to this mail.

My idea is to let a driver upload the firmware from it's ATTACH routine and 
after that return with USB_ATTACH_NEED_RESET. Since some devices really 
require a reset to be sent to it and others only need to be re-configured, 
the USB stack doesn't send the reset itself. The ATTACH function is 
responsible for sending the reset to the device.
After getting the NEED_RESET response, the USB stack assumes the device is 
ready and listening at addr==0 again. The stack re-reads the device 
descriptor, sets the address again and tries another round of attaching 
drivers. We give up after 5 rounds of NEED_RESET.

If anyone knows a more elegant way to achieve the same functionality, I'm open 
to ideas :)

grtz,
Daan
diff -ur usb.org/usb_port.h usb/usb_port.h
--- usb.org/usb_port.h	Wed Oct  2 09:44:20 2002
+++ usb/usb_port.h	Wed Jan  7 20:26:55 2004
@@ -435,6 +435,7 @@
 /* Returns from attach */
 #define USB_ATTACH_ERROR_RETURN	return ENXIO
 #define USB_ATTACH_SUCCESS_RETURN	return 0
+#define USB_ATTACH_NEED_RESET		return EAGAIN
 
 #define USB_ATTACH_SETUP \
 	sc->sc_dev = self; \
diff -ur usb.org/usb_subr.c usb/usb_subr.c
--- usb.org/usb_subr.c	Wed Jan 15 00:07:43 2003
+++ usb/usb_subr.c	Wed Jan  7 22:50:20 2004
@@ -86,6 +86,9 @@
 Static int usbd_print(void *aux, const char *pnp);
 Static int usbd_submatch(device_ptr_t, void *, void *);
 #endif
+Static usbd_status usbd_new_device2(device_ptr_t parent, usbd_bus_handle bus,
+		 		int depth, int speed, int port,
+		 		struct usbd_port *up);
 Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
 Static void usbd_kill_pipe(usbd_pipe_handle);
 Static usbd_status usbd_probe_and_attach(device_ptr_t parent,
@@ -131,6 +134,7 @@
 	"SHORT_XFER",
 	"STALLED",
 	"INTERRUPTED",
+	"NEED_RESET",
 	"XXX",
 };
 
@@ -888,6 +892,14 @@
 			uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
 			dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
 					   usbd_submatch);
+
+			if (dev->address == USB_START_ADDR) {
+#if defined(__FreeBSD__)
+				device_delete_child(parent, bdev);
+#endif
+				return (USBD_NEED_RESET);
+			}
+			
 			if (dv != NULL) {
 				dev->subdevs[found++] = dv;
 				dev->subdevs[found] = 0;
@@ -958,7 +970,7 @@
  * and attach a driver.
  */
 usbd_status
-usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
+usbd_new_device2(device_ptr_t parent, usbd_bus_handle bus, int depth,
 		int speed, int port, struct usbd_port *up)
 {
 	usbd_device_handle dev;
@@ -1099,6 +1111,12 @@
 
 	err = usbd_probe_and_attach(parent, dev, port, addr);
 	if (err) {
+		if (err == USBD_NEED_RESET) {
+			DPRINTFN(1,("usbd_new_device: device needs reset\n"));
+			/* must set address back to what it was */
+			dev->address = addr;
+		}
+	
 		usbd_remove_device(dev, up);
 		return (err);
   	}
@@ -1106,6 +1124,27 @@
 	usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
   
   	return (USBD_NORMAL_COMPLETION);
+}
+
+usbd_status
+usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
+		int speed, int ports, struct usbd_port *up)
+{
+	int		retry = 0;
+	usbd_status	err;
+	
+	err = usbd_new_device2(parent, bus, depth, speed, ports, up);
+	while ((err == USBD_NEED_RESET) && (retry++ < 5)) {
+		DPRINTFN(1,("usb_new_device: re-enumerating device\n"));
+		err = usbd_new_device2(parent, bus, depth, speed, ports, up);
+	}
+	
+	if (retry == 5) {
+		DPRINTFN(1,("usb_new_device: giving up after 5 tries...\n"));
+		return (USBD_NOT_CONFIGURED);
+	}
+	
+	return err;
 }
 
 usbd_status
diff -ur usb.org/usbdi.h usb/usbdi.h
--- usb.org/usbdi.h	Mon May  6 20:23:36 2002
+++ usb/usbdi.h	Wed Jan  7 21:45:11 2004
@@ -66,6 +66,7 @@
 	USBD_SHORT_XFER,	/* 16 */
 	USBD_STALLED,		/* 17 */
 	USBD_INTERRUPTED,	/* 18 */
+	USBD_NEED_RESET,	/* 19 */
 
 	USBD_ERROR_MAX		/* must be last */
 } usbd_status;
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to