Subject: usb: want to switch interfaceprotocol.
To: Lennart Augustsson <lennart@augustsson.net>
From: Alfred Perlstein <bright@mu.org>
List: tech-kern
Date: 02/26/2002 01:57:28
My printer reports:

> >   INTERFACE descriptor index 0, alt index 0:
> >   bLength=9 bDescriptorType=4 bInterfaceNumber=0 bAlternateSetting=0
> >   bNumEndpoints=3 bInterfaceClass=7 bInterfaceSubClass=1
> >   bInterfaceProtocol=3 iInterface=0
> ...
> >   INTERFACE descriptor index 0, alt index 1:
> >   bLength=9 bDescriptorType=4 bInterfaceNumber=0 bAlternateSetting=1
> >   bNumEndpoints=2 bInterfaceClass=7 bInterfaceSubClass=1
> >   bInterfaceProtocol=2 iInterface=0
> ...
> >   INTERFACE descriptor index 0, alt index 2:
> >   bLength=9 bDescriptorType=4 bInterfaceNumber=0 bAlternateSetting=2
> >   bNumEndpoints=1 bInterfaceClass=7 bInterfaceSubClass=1
> >   bInterfaceProtocol=1 iInterface=0

Assuming the device is open (ulptopen has been called) will this code
sequence work?  Or do I need to tear down pipes and such?  Any clues
on how to do this?  If you want a better idea of what I want to do
it's to implement most of the stuff on this wishlist:
  http://hpoj.sourceforge.net/doc/ioctl_requests.html
specifically changing the protocol.

                error = ulpt_getdescriptbyproto(dev, *(int *)data, &id, &altno);
                if (error)
                        break;
                error = usbd_set_interface(sc->sc_iface, altno);
                if (error)
                        break;
                sc->sc_ifaceno = id->bInterfaceNumber;

Where ulpt_getdescriptbyproto is:
int
ulpt_getdescriptbyproto(dev, proto, idret, altnoret)
        dev_t dev;
        int proto;
        usb_interface_descriptor_t **idret;
        int *altnoret;
{
        struct ulpt_softc *sc;
        usb_config_descriptor_t *cdesc;
        usb_interface_descriptor_t *id, *ifcd, *iend;

        USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
        ifcd = usbd_get_interface_descriptor(sc_iface);
        cdesc = usbd_get_config_descriptor(sc->sc_udev);
        iend = (usb_interface_descriptor_t *)
            ((char *)cdesc + UGETW(cdesc->wTotalLength));

        for (id = ifcd, altno = 0;
             id < iend;
             id = (void *)((char *)id + id->bLength)) {
                if (id->bDescriptorType == UDESC_INTERFACE &&
                    id->bInterfaceNumber == ifcd->bInterfaceNumber) {
                        if (id->bInterfaceClass == UICLASS_PRINTER &&
                            id->bInterfaceSubClass == UISUBCLASS_PRINTER &&
                            id->bInterfaceProtocol == proto)
                                goto found;
                        altno++;
                }
        }
        return (ENOENT);
found:
        *altnoret = altno;
        *idret = id;
        return (0);
}

thanks,
-- 
-Alfred Perlstein [alfred@freebsd.org]
'Instead of asking why a piece of software is using "1970s technology,"
 start asking why software is ignoring 30 years of accumulated wisdom.'
Tax deductible donations for FreeBSD: http://www.freebsdfoundation.org/