Martin wrote:

panic()
destroy_dev()
ugen_destroy_devnodes()
ugen_set_config()

Could you try the attached patch, to see if it fixes the panic on the second run of your program?


--
Cheers,
Jay

http://www.evilrealms.net/ - Systems Administrator & Developer
http://www.imperial.ac.uk/ - 3rd year CS student
Index: sys/dev/usb/ugen.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.81
diff -u -3 -p -r1.81 ugen.c
--- sys/dev/usb/ugen.c  9 Nov 2003 09:17:22 -0000       1.81
+++ sys/dev/usb/ugen.c  27 Nov 2003 14:06:25 -0000
@@ -1014,8 +1014,8 @@ ugen_set_interface(struct ugen_softc *sc
        usbd_interface_handle iface;
        usb_endpoint_descriptor_t *ed;
        usbd_status err;
-       struct ugen_endpoint *sce;
-       u_int8_t niface, nendpt, endptno, endpt;
+       struct ugen_endpoint *sce, **sce_cache;
+       u_int8_t niface, nendpt, nendpt_cache, endptno, endpt;
        int dir;
 
        DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
@@ -1033,30 +1033,47 @@ ugen_set_interface(struct ugen_softc *sc
        if (err)
                return (err);
 
-#if defined(__FreeBSD__)
-       /* destroy the existing devices, we remake the new ones in a moment */
-       ugen_destroy_devnodes(sc);
-#endif
+       /* store an array of endpoint descriptors to destroy if the interface
+        * change succeeds - these aren't available afterwards */
+       sce_cache = malloc(sizeof(struct ugen_endpoint *) * nendpt, M_TEMP,
+               M_WAITOK);
+       nendpt_cache = nendpt;
 
-       /* XXX should only do this after setting new altno has succeeded */
        for (endptno = 0; endptno < nendpt; endptno++) {
                ed = usbd_interface2endpoint_descriptor(iface,endptno);
                endpt = ed->bEndpointAddress;
                dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
-               sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
-               sce->sc = 0;
-               sce->edesc = 0;
-               sce->iface = 0;
+               sce_cache[endptno] = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
        }
 
        /* change setting */
        err = usbd_set_interface(iface, altno);
-       if (err)
+       if (err) {
+               free(sce_cache, M_TEMP);
                return (err);
+       }
 
        err = usbd_endpoint_count(iface, &nendpt);
-       if (err)
+       if (err) {
+               free(sce_cache, M_TEMP);
                return (err);
+       }
+
+#if defined(__FreeBSD__)
+       /* destroy the existing devices, we remake the new ones in a moment */
+       ugen_destroy_devnodes(sc);
+#endif
+
+       /* now we can clear the old interface's ugen_endpoints */
+       for (endptno = 0; endptno < nendpt_cache; endptno++) {
+               sce = sce_cache[endptno];
+               sce->sc = 0;
+               sce->edesc = 0;
+               sce->iface = 0;
+       }
+       free(sce_cache, M_TEMP);
+
+       /* set the new interface's ugen_endpoints */
        for (endptno = 0; endptno < nendpt; endptno++) {
                ed = usbd_interface2endpoint_descriptor(iface,endptno);
                endpt = ed->bEndpointAddress;
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to