diff --git a/sys/src/9/port/devusb.c b/sys/src/9/port/devusb.c index 35da994a0..0eb8db37a 100644 --- a/sys/src/9/port/devusb.c +++ b/sys/src/9/port/devusb.c @@ -1084,18 +1084,12 @@ usbread(Chan *c, void *a, long n, vlong offset) return n; } -static long -pow2(int n) -{ - return 1 << n; -} - static void setmaxpkt(Ep *ep, char* s) { - long spp; /* samples per packet */ + long spp, max; /* samples per packet */ - if(ep->dev->speed == Highspeed) + if(ep->dev->speed == Highspeed || ep->dev->speed == Superspeed) spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000; else spp = (ep->hz * ep->pollival + 999) / 1000; @@ -1104,9 +1098,24 @@ setmaxpkt(Ep *ep, char* s) " ntds %d %s speed -> spp %ld maxpkt %ld\n", s, ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed], spp, ep->maxpkt); - if(ep->maxpkt > 1024){ - print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt); - ep->maxpkt = 1024; + + switch(ep->dev->speed){ + case Fullspeed: + max = 1024; + break; + case Highspeed: + max = 3*1024; + break; + case Superspeed: + max = 48*1024; + break; + default: + return; + } + if(ep->maxpkt*ep->ntds > max){ + print("usb: %s: maxpkt %ld > %ld for %s, truncating\n", + s, ep->maxpkt*ep->ntds, max, spname[ep->dev->speed]); + ep->maxpkt = max/ep->ntds; } } @@ -1164,7 +1173,7 @@ epctl(Ep *ep, Chan *c, void *a, long n) error("speed must be full|low|high"); nep = newdev(ep->hp, 0, 0); nep->dev->speed = l; - if(nep->dev->speed != Lowspeed) + if(nep->dev->speed != Lowspeed) nep->maxpkt = 64; /* assume full speed */ nep->dev->hub = d->addr; nep->dev->port = atoi(cb->f[2]); @@ -1214,14 +1223,14 @@ epctl(Ep *ep, Chan *c, void *a, long n) error("not an intr or iso endpoint"); l = strtoul(cb->f[1], nil, 0); deprint("usb epctl %s %d\n", cb->f[0], l); - if(ep->ttype == Tiso || - (ep->ttype == Tintr && ep->dev->speed == Highspeed)){ + if(ep->dev->speed == Highspeed || ep->dev->speed == Superspeed){ if(l < 1 || l > 16) error("pollival power not in [1:16]"); - l = pow2(l-1); - }else + l = 1 << l-1; + } else { if(l < 1 || l > 255) error("pollival not in [1:255]"); + } qlock(ep); ep->pollival = l; if(ep->ttype == Tiso) diff --git a/sys/src/9/port/usb.h b/sys/src/9/port/usb.h index 2853513e1..655ee4f4f 100644 --- a/sys/src/9/port/usb.h +++ b/sys/src/9/port/usb.h @@ -162,11 +162,11 @@ struct Ep char* info; /* for humans to read */ long maxpkt; /* maximum packet size */ int ttype; /* tranfer type */ - ulong load; /* in µs, for a fransfer of maxpkt bytes */ + ulong load; /* in µs, for a transfer of maxpkt bytes */ void* aux; /* for controller specific info */ int rhrepl; /* fake root hub replies */ int toggle[2]; /* saved toggles (while ep is not in use) */ - long pollival; /* poll interval ([µ]frames; intr/iso) */ + long pollival; /* poll interval ([µ]frames; intr/iso) */ long hz; /* poll frequency (iso) */ long samplesz; /* sample size (iso) */ int ntds; /* nb. of Tds per µframe */ diff --git a/sys/src/cmd/nusb/lib/dev.c b/sys/src/cmd/nusb/lib/dev.c index cd9d15a38..f7bcc04ae 100644 --- a/sys/src/cmd/nusb/lib/dev.c +++ b/sys/src/cmd/nusb/lib/dev.c @@ -45,11 +45,6 @@ openep(Dev *d, int id) return nil; } ep = ud->ep[id]; - mode = "rw"; - if(ep->dir == Ein) - mode = "r"; - if(ep->dir == Eout) - mode = "w"; snprint(name, sizeof(name), "/dev/usb/ep%d.%d", d->id, id); if(access(name, AEXIST) == 0){ dprint(2, "%s: %s already exists; trying to open\n", argv0, name); @@ -60,6 +55,11 @@ openep(Dev *d, int id) } return epd; } + mode = "rw"; + if(ep->dir == Ein) + mode = "r"; + if(ep->dir == Eout) + mode = "w"; if(devctl(d, "new %d %d %s", id, ep->type, mode) < 0){ dprint(2, "%s: %s: new: %r\n", argv0, d->dir); return nil; @@ -79,13 +79,6 @@ openep(Dev *d, int id) else dprint(2, "%s: %s: ntds %d\n", argv0, epd->dir, ep->ntds); - /* - * For iso endpoints and high speed interrupt endpoints the pollival is - * actually 2ⁿ and not n. - * The kernel usb driver must take that into account. - * It's simpler this way. - */ - if(ac != nil && (ep->type == Eintr || ep->type == Eiso) && ac->interval != 0) if(devctl(epd, "pollival %d", ac->interval) < 0) fprint(2, "%s: %s: openep: pollival: %r\n", argv0, epd->dir);