]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/nusb/lib/parse.c
nusb: don't create rw iso endpoints (by Michael Forney)
[plan9front.git] / sys / src / cmd / nusb / lib / parse.c
index 642c427a237513a63a7ad543ee1145953ff77fc1..916da0b3ee6ddde79eddd960a9be6f9a84b3331f 100644 (file)
@@ -1,7 +1,6 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
-#include <bio.h>
 #include "usb.h"
 
 int
@@ -28,7 +27,12 @@ parsedev(Dev *xd, uchar *b, int n)
                return -1;
        }
        d->csp = CSP(dd->bDevClass, dd->bDevSubClass, dd->bDevProtocol);
-       d->ep[0]->maxpkt = xd->maxpkt = dd->bMaxPacketSize0;
+       d->ver = GET2(dd->bcdUSB);
+       xd->isusb3 = (d->ver >= 0x0300);
+       if(xd->isusb3)
+               d->ep[0]->maxpkt = xd->maxpkt = 1<<dd->bMaxPacketSize0;
+       else
+               d->ep[0]->maxpkt = xd->maxpkt = dd->bMaxPacketSize0;
        d->class = dd->bDevClass;
        d->nconf = dd->bNumConfigurations;
        if(d->nconf == 0)
@@ -71,6 +75,8 @@ parseiface(Usbdev *d, Conf *c, uchar *b, int n, Iface **ipp, Altc **app)
        subclass = dip->bInterfaceSubClass;
        proto = dip->bInterfaceProtocol;
        ip->csp = CSP(class, subclass, proto);
+       if(ip->csp == 0)
+               ip->csp = d->csp;
        if(d->csp == 0)                         /* use csp from 1st iface */
                d->csp = ip->csp;               /* if device has none */
        if(d->class == 0)
@@ -95,7 +101,7 @@ extern Ep* mkep(Usbdev *, int);
 static int
 parseendpt(Usbdev *d, Conf *c, Iface *ip, Altc *altc, uchar *b, int n, Ep **epp)
 {
-       int i, dir, epid;
+       int i, dir, epid, type, addr;
        Ep *ep;
        DEp *dep;
 
@@ -108,23 +114,41 @@ parseendpt(Usbdev *d, Conf *c, Iface *ip, Altc *altc, uchar *b, int n, Ep **epp)
        altc->attrib = dep->bmAttributes;       /* here? */
        altc->interval = dep->bInterval;
 
-       epid = dep->bEndpointAddress & 0xF;
-       assert(epid < nelem(d->ep));
-       if(dep->bEndpointAddress & 0x80)
+       type = dep->bmAttributes & 0x03;
+       addr = dep->bEndpointAddress;
+       if(addr & 0x80)
                dir = Ein;
        else
                dir = Eout;
+       epid = addr & 0xF;      /* default map to 0..15 */
+       assert(epid < nelem(d->ep));
        ep = d->ep[epid];
        if(ep == nil){
                ep = mkep(d, epid);
                ep->dir = dir;
-       }else if((ep->addr & 0x80) != (dep->bEndpointAddress & 0x80))
-               ep->dir = Eboth;
+       }else if((ep->addr & 0x80) != (addr & 0x80)){
+               if(ep->type == type && type != Eiso)
+                       ep->dir = Eboth;
+               else {
+                       /*
+                        * resolve conflict when same endpoint number
+                        * is used for different input and output types.
+                        * map input endpoint to 16..31 and output to 0..15.
+                        */
+                       ep->id = ((ep->addr & 0x80) != 0)<<4 | (ep->addr & 0xF);
+                       d->ep[ep->id] = ep;
+                       epid = ep->id ^ 0x10;
+                       ep = mkep(d, epid);
+                       ep->dir = dir;
+               }
+       }
        ep->maxpkt = GET2(dep->wMaxPacketSize);
        ep->ntds = 1 + ((ep->maxpkt >> 11) & 3);
        ep->maxpkt &= 0x7FF;
-       ep->addr = dep->bEndpointAddress;
-       ep->type = dep->bmAttributes & 0x03;
+       altc->maxpkt = ep->maxpkt;
+       altc->ntds = ep->ntds;
+       ep->addr = addr;
+       ep->type = type;
        ep->isotype = (dep->bmAttributes>>2) & 0x03;
        ep->conf = c;
        ep->iface = ip;