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>