Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Jan 2004 16:25:50 +0100
From:      "Daan Vreeken [PA4DAN]" <Danovitsch@Vitsch.net>
To:        Bernd Walter <ticso@cicely.de>
Cc:        FreeBSD-hackers@freebsd.org
Subject:   Re: USB stack / configuration 0
Message-ID:  <200401081625.50446.Danovitsch@Vitsch.net>
In-Reply-To: <20040108060156.GH47728@cicely12.cicely.de>
References:  <3FFA04A8.30601@evilrealms.net> <200401071104.37461.Danovitsch@Vitsch.net> <20040108060156.GH47728@cicely12.cicely.de>

next in thread | previous in thread | raw e-mail | index | archive | help

--------------Boundary-00=_27G6VZGUKWL81X5FUH53
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

On Thursday 08 January 2004 07:01, Bernd wrote:
> Im mostly worried about having more than a single device with address 0=
=2E
> 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 re=
set=20
the device from the ATTACH routine of a driver. This should garantee that=
=20
there is only one device with addr=3D=3D0 , since the probe & attach rout=
ines are=20
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 t=
o
> > tell the USB Stack thee device needs to be re-enumerated. The stack t=
hen
> > 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 a=
nd=20
after that return with USB_ATTACH_NEED_RESET. Since some devices really=20
require a reset to be sent to it and others only need to be re-configured=
,=20
the USB stack doesn't send the reset itself. The ATTACH function is=20
responsible for sending the reset to the device.
After getting the NEED_RESET response, the USB stack assumes the device i=
s=20
ready and listening at addr=3D=3D0 again. The stack re-reads the device=20
descriptor, sets the address again and tries another round of attaching=20
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=20
to ideas :)

grtz,
Daan
--------------Boundary-00=_27G6VZGUKWL81X5FUH53
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="diff-2004-01-08-usb-reset"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="diff-2004-01-08-usb-reset"

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;

--------------Boundary-00=_27G6VZGUKWL81X5FUH53--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401081625.50446.Danovitsch>