ref: 215b67ff3d630c56418026dda7ae68f23111c4a5
parent: d46099e3afa9681a4f98e0d2574c2ad65820ed7e
author: cinap_lenrek <[email protected]>
date: Sun Jul 30 23:19:24 EDT 2017
nusb/usbd: create endpoint files for conf #1, usb3 preparation
--- a/sys/src/cmd/nusb/lib/parse.c
+++ b/sys/src/cmd/nusb/lib/parse.c
@@ -27,7 +27,12 @@
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)
--- a/sys/src/cmd/nusb/lib/usb.h
+++ b/sys/src/cmd/nusb/lib/usb.h
@@ -36,7 +36,7 @@
Rep = 2, /* endpoint */
Rother = 3,
- /* standard requests */
+ /* standard requests (USB2.0) */
Rgetstatus = 0,
Rclearfeature = 1,
Rsetfeature = 3,
@@ -49,6 +49,10 @@
Rsetiface = 11,
Rsynchframe = 12,
+ /* standard requests (USB3.0) */
+ Rsethubdepth = 12,
+ Rgetporterrcnt = 13,
+
Rgetcur = 0x81,
Rgetmin = 0x82,
Rgetmax = 0x83,
@@ -169,6 +173,7 @@
int id; /* usb id for device or ep. number */
int dfd; /* descriptor for the data file */
int cfd; /* descriptor for the control file */
+ int isusb3; /* this is a usb3 device */
int maxpkt; /* cached from usb description */
Ref nerrs; /* number of errors in requests */
Usbdev* usb; /* USB description */
@@ -182,6 +187,7 @@
*/
struct Usbdev
{
+ int ver; /* usb version */
ulong csp; /* USB class/subclass/proto */
int vid; /* vendor id */
int did; /* product (device) id */
--- a/sys/src/cmd/nusb/usbd/dat.h
+++ b/sys/src/cmd/nusb/usbd/dat.h
@@ -50,9 +50,7 @@
Pconfiged,
/* Delays, timeouts (ms) */
-// Spawndelay = 1000, /* how often may we re-spawn a driver */
Spawndelay = 250, /* how often may we re-spawn a driver */
-// Connectdelay = 1000, /* how much to wait after a connect */
Connectdelay = 500, /* how much to wait after a connect */
Resetdelay = 20, /* how much to wait after a reset */
Enabledelay = 20, /* how much to wait after an enable */
@@ -82,6 +80,7 @@
Port *port;
int failed; /* I/O error while enumerating */
int isroot; /* set if root hub */
+ int depth; /* hub depth */
Dev *dev; /* for this hub */
Hub *next; /* in list of hubs */
};
@@ -89,13 +88,11 @@
struct Port
{
int state; /* state of the device */
- int sts; /* old port status */
+ u32int sts; /* old port status */
uchar removable;
uchar pwrctl;
Dev *dev; /* attached device (if non-nil) */
Hub *hub; /* non-nil if hub attached */
- int devnb; /* device number */
- uvlong *devmaskp; /* ptr to dev mask */
};
/* USB HUB descriptor */
--- a/sys/src/cmd/nusb/usbd/fns.h
+++ b/sys/src/cmd/nusb/usbd/fns.h
@@ -1,6 +1,6 @@
-int attachdev(Port*);
-void detachdev(Port*);
+int attachdev(Hub*, Port*);
+void detachdev(Hub*, Port*);
void work(void);
-Hub* newhub(char *, Dev *);
+Hub* newhub(char *, Dev*, Hub*);
void hname(char *);
void checkidle(void);
--- a/sys/src/cmd/nusb/usbd/hub.c
+++ b/sys/src/cmd/nusb/usbd/hub.c
@@ -10,35 +10,9 @@
static int nhubs;
static int mustdump;
static int pollms = Pollms;
-static Lock masklck;
static char *dsname[] = { "disabled", "attached", "configed" };
-int
-getdevnb(uvlong *maskp)
-{
- int i;
-
- lock(&masklck);
- for(i = 0; i < 8 * sizeof *maskp; i++)
- if((*maskp & (1ULL<<i)) == 0){
- *maskp |= 1ULL<<i;
- unlock(&masklck);
- return i;
- }
- unlock(&masklck);
- return -1;
-}
-
-void
-putdevnb(uvlong *maskp, int id)
-{
- lock(&masklck);
- if(id >= 0)
- *maskp &= ~(1ULL<<id);
- unlock(&masklck);
-}
-
static int
hubfeature(Hub *h, int port, int f, int on)
{
@@ -51,25 +25,6 @@
return usbcmd(h->dev, Rh2d|Rclass|Rother, cmd, f, port, nil, 0);
}
-/*
- * This may be used to detect overcurrent on the hub
- */
-static void
-checkhubstatus(Hub *h)
-{
- uchar buf[4];
- int sts;
-
- if(h->isroot) /* not for root hubs */
- return;
- if(usbcmd(h->dev, Rd2h|Rclass|Rdev, Rgetstatus, 0, 0, buf, 4) < 0){
- dprint(2, "%s: get hub status: %r\n", h->dev->dir);
- return;
- }
- sts = GET2(buf);
- dprint(2, "hub %s: status %#ux\n", h->dev->dir, sts);
-}
-
static int
confighub(Hub *h)
{
@@ -124,6 +79,10 @@
pp->removable = (dd->DeviceRemovable[offset] & mask) != 0;
pp->pwrctl = (PortPwrCtrlMask[offset] & mask) != 0;
}
+ if(h->dev->isusb3){
+ type = Rh2d|Rclass|Rdev;
+ usbcmd(h->dev, type, Rsethubdepth, h->depth, 0, nil, 0);
+ }
return 0;
}
@@ -143,7 +102,7 @@
if(nr < 0)
goto Done;
buf[nr] = 0;
-
+ d->isusb3 = strstr(buf, "speed super") != nil;
p = strstr(buf, "ports ");
if(p == nil)
fprint(2, "%s: %s: no port information\n", argv0, d->dir);
@@ -160,7 +119,7 @@
}
Hub*
-newhub(char *fn, Dev *d)
+newhub(char *fn, Dev *d, Hub *ph)
{
Hub *h;
int i;
@@ -169,17 +128,20 @@
h = emallocz(sizeof(Hub), 1);
h->isroot = (d == nil);
if(h->isroot){
+ h->depth = -1;
h->dev = opendev(fn);
if(h->dev == nil){
fprint(2, "%s: opendev: %s: %r", argv0, fn);
goto Fail;
}
+ configroothub(h); /* never fails */
if(opendevdata(h->dev, ORDWR) < 0){
fprint(2, "%s: opendevdata: %s: %r\n", argv0, fn);
+ closedev(h->dev);
goto Fail;
}
- configroothub(h); /* never fails */
}else{
+ h->depth = ph->depth+1;
h->dev = d;
if(confighub(h) < 0){
fprint(2, "%s: %s: config: %r\n", argv0, fn);
@@ -186,10 +148,6 @@
goto Fail;
}
}
- if(h->dev == nil){
- fprint(2, "%s: opendev: %s: %r\n", argv0, fn);
- goto Fail;
- }
devctl(h->dev, "hub");
ud = h->dev->usb;
if(h->isroot)
@@ -265,13 +223,13 @@
free(h);
}
-static int
+static u32int
portstatus(Hub *h, int p)
{
Dev *d;
uchar buf[4];
+ u32int sts;
int t;
- int sts;
int dbg;
dbg = usbdebug;
@@ -282,34 +240,38 @@
if(usbcmd(d, t, Rgetstatus, 0, p, buf, sizeof(buf)) < 0)
sts = -1;
else
- sts = GET2(buf);
+ sts = GET4(buf);
usbdebug = dbg;
return sts;
}
static char*
-stsstr(int sts)
+stsstr(int sts, int isusb3)
{
static char s[80];
char *e;
e = s;
- if(sts&PSsuspend)
- *e++ = 'z';
- if(sts&PSreset)
- *e++ = 'r';
- if(sts&PSslow)
- *e++ = 'l';
- if(sts&PShigh)
- *e++ = 'h';
- if(sts&PSchange)
- *e++ = 'c';
- if(sts&PSenable)
- *e++ = 'e';
- if(sts&PSstatuschg)
- *e++ = 's';
if(sts&PSpresent)
*e++ = 'p';
+ if(sts&PSenable)
+ *e++ = 'e';
+ if(sts&PSovercurrent)
+ *e++ = 'o';
+ if(sts&PSreset)
+ *e++ = 'r';
+ if(!isusb3){
+ if(sts&PSslow)
+ *e++ = 'l';
+ if(sts&PShigh)
+ *e++ = 'h';
+ if(sts&PSchange)
+ *e++ = 'c';
+ if(sts&PSstatuschg)
+ *e++ = 's';
+ if(sts&PSsuspend)
+ *e++ = 'z';
+ }
if(e == s)
*e++ = '-';
*e = 0;
@@ -322,6 +284,8 @@
uchar buf[64]; /* More room to try to get device-specific descriptors */
DDev *dd;
+ if(d->isusb3)
+ return 512;
dd = (DDev*)buf;
if(islow)
dd->bMaxPacketSize0 = 8;
@@ -336,7 +300,7 @@
* BUG: does not consider max. power avail.
*/
static Dev*
-portattach(Hub *h, int p, int sts)
+portattach(Hub *h, int p, u32int sts)
{
Dev *d;
Port *pp;
@@ -352,31 +316,43 @@
nd = nil;
pp->state = Pattached;
dprint(2, "%s: %s: port %d attach sts %#ux\n", argv0, d->dir, p, sts);
- sleep(Connectdelay);
- if(hubfeature(h, p, Fportenable, 1) < 0)
- dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
- sleep(Enabledelay);
- if(hubfeature(h, p, Fportreset, 1) < 0){
- dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
- goto Fail;
- }
- sleep(Resetdelay);
- sts = portstatus(h, p);
- if(sts < 0)
- goto Fail;
- if((sts & PSenable) == 0){
- dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
- hubfeature(h, p, Fportenable, 1);
+ if(h->dev->isusb3){
+ sleep(Connectdelay);
sts = portstatus(h, p);
- if((sts & PSenable) == 0)
+ if(sts == -1)
goto Fail;
+ if((sts & PSenable) == 0){
+ dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+ goto Fail;
+ }
+ sp = "super";
+ } else {
+ sleep(Connectdelay);
+ if(hubfeature(h, p, Fportenable, 1) < 0)
+ dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
+ sleep(Enabledelay);
+ if(hubfeature(h, p, Fportreset, 1) < 0){
+ dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
+ goto Fail;
+ }
+ sleep(Resetdelay);
+ sts = portstatus(h, p);
+ if(sts == -1)
+ goto Fail;
+ if((sts & PSenable) == 0){
+ dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+ hubfeature(h, p, Fportenable, 1);
+ sts = portstatus(h, p);
+ if((sts & PSenable) == 0)
+ goto Fail;
+ }
+ sp = "full";
+ if(sts & PSslow)
+ sp = "low";
+ if(sts & PShigh)
+ sp = "high";
}
- sp = "full";
- if(sts & PSslow)
- sp = "low";
- if(sts & PShigh)
- sp = "high";
- dprint(2, "%s: %s: port %d: attached status %#ux\n", argv0, d->dir, p, sts);
+ dprint(2, "%s: %s: port %d: attached status %#ux, speed %s\n", argv0, d->dir, p, sts, sp);
if(devctl(d, "newdev %s %d", sp, p) < 0){
fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p);
@@ -413,7 +389,7 @@
dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p);
goto Fail;
}
-
+ nd->isusb3 = h->dev->isusb3;
mp=getmaxpkt(nd, strcmp(sp, "low") == 0);
if(mp < 0){
dprint(2, "%s: %s: port %d: getmaxpkt: %r\n", argv0, d->dir, p);
@@ -422,9 +398,6 @@
dprint(2, "%s; %s: port %d: maxpkt %d\n", argv0, d->dir, p, mp);
devctl(nd, "maxpkt %d", mp);
}
- if((sts & PSslow) != 0 && strcmp(sp, "full") == 0)
- dprint(2, "%s: %s: port %d: %s is full speed when port is low\n",
- argv0, d->dir, p, nd->dir);
if(configdev(nd) < 0){
dprint(2, "%s: %s: port %d: configdev: %r\n", argv0, d->dir, p);
goto Fail;
@@ -446,7 +419,8 @@
pp->sts = 0;
if(pp->hub != nil)
pp->hub = nil; /* hub closed by enumhub */
- hubfeature(h, p, Fportenable, 0);
+ if(!h->dev->isusb3)
+ hubfeature(h, p, Fportenable, 0);
if(nd != nil)
devctl(nd, "detach");
closedev(nd);
@@ -475,11 +449,8 @@
closehub(pp->hub);
pp->hub = nil;
}
- if(pp->devmaskp != nil)
- putdevnb(pp->devmaskp, pp->devnb);
- pp->devmaskp = nil;
if(pp->dev != nil){
- detachdev(pp);
+ detachdev(h, pp);
devctl(pp->dev, "detach");
closedev(pp->dev);
@@ -523,7 +494,7 @@
static void
portreset(Hub *h, int p)
{
- int sts;
+ u32int sts;
Dev *d, *nd;
Port *pp;
@@ -537,10 +508,12 @@
}
sleep(Resetdelay);
sts = portstatus(h, p);
- if(sts < 0)
+ if(sts == -1)
goto Fail;
if((sts & PSenable) == 0){
dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+ if(h->dev->isusb3)
+ goto Fail;
hubfeature(h, p, Fportenable, 1);
sts = portstatus(h, p);
if((sts & PSenable) == 0)
@@ -572,7 +545,8 @@
pp->sts = 0;
if(pp->hub != nil)
pp->hub = nil; /* hub closed by enumhub */
- hubfeature(h, p, Fportenable, 0);
+ if(!h->dev->isusb3)
+ hubfeature(h, p, Fportenable, 0);
if(nd != nil)
devctl(nd, "detach");
closedev(nd);
@@ -579,9 +553,9 @@
}
static int
-portgone(Port *pp, int sts)
+portgone(Port *pp, u32int sts)
{
- if(sts < 0)
+ if(sts == -1)
return 1;
/*
* If it was enabled and it's not now then it may be reconnect.
@@ -595,7 +569,7 @@
static int
enumhub(Hub *h, int p)
{
- int sts;
+ u32int sts;
Dev *d;
Port *pp;
int onhubs;
@@ -607,22 +581,24 @@
fprint(2, "%s: %s: port %d enumhub\n", argv0, d->dir, p);
sts = portstatus(h, p);
- if(sts < 0){
+ if(sts == -1){
hubfail(h); /* avoid delays on detachment */
return -1;
}
pp = &h->port[p];
onhubs = nhubs;
- if((sts & PSsuspend) != 0){
- if(hubfeature(h, p, Fportenable, 1) < 0)
- dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
- sleep(Enabledelay);
- sts = portstatus(h, p);
- fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts);
+ if(!h->dev->isusb3){
+ if((sts & PSsuspend) != 0){
+ if(hubfeature(h, p, Fportenable, 1) < 0)
+ dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
+ sleep(Enabledelay);
+ sts = portstatus(h, p);
+ fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts);
+ }
}
if((pp->sts & PSpresent) == 0 && (sts & PSpresent) != 0){
if(portattach(h, p, sts) != nil)
- if(attachdev(pp) < 0)
+ if(attachdev(h, pp) < 0)
portdetach(h, p);
}else if(portgone(pp, sts)){
portdetach(h, p);
@@ -629,9 +605,9 @@
}else if(portresetwanted(h, p))
portreset(h, p);
else if(pp->sts != sts){
- dprint(2, "%s: %s port %d: sts %s %#x ->",
- argv0, d->dir, p, stsstr(pp->sts), pp->sts);
- dprint(2, " %s %#x\n",stsstr(sts), sts);
+ dprint(2, "%s: %s port %d: sts %s %#ux ->",
+ argv0, d->dir, p, stsstr(pp->sts, h->dev->isusb3), pp->sts);
+ dprint(2, " %s %#ux\n",stsstr(sts, h->dev->isusb3), sts);
}
pp->sts = sts;
if(onhubs != nhubs)
@@ -663,7 +639,7 @@
hubs = nil;
while((fn = rendezvous(work, nil)) != nil){
dprint(2, "%s: %s starting\n", argv0, fn);
- h = newhub(fn, nil);
+ h = newhub(fn, nil, nil);
if(h == nil)
fprint(2, "%s: %s: newhub failed: %r\n", argv0, fn);
free(fn);
--- a/sys/src/cmd/nusb/usbd/usbd.c
+++ b/sys/src/cmd/nusb/usbd/usbd.c
@@ -373,9 +373,10 @@
}
int
-attachdev(Port *p)
+attachdev(Hub *h, Port *p)
{
Dev *d = p->dev;
+ int id;
if(d->usb->class == Clhub){
/*
@@ -384,11 +385,21 @@
* has the config address in use.
* We cancel kernel debug for these eps. too chatty.
*/
- if((p->hub = newhub(d->dir, d)) == nil)
+ if((p->hub = newhub(d->dir, d, h)) == nil)
return -1;
return 0;
}
+ /* create all endpoint files for default conf #1 */
+ for(id=1; id<nelem(d->usb->ep); id++){
+ Ep *ep = d->usb->ep[id];
+ if(ep != nil && ep->conf != nil && ep->conf->cval == 1){
+ Dev *epd = openep(d, id);
+ if(epd != nil)
+ closedev(epd);
+ }
+ }
+
/* close control endpoint so driver can open it */
close(d->dfd);
d->dfd = -1;
@@ -406,7 +417,7 @@
}
void
-detachdev(Port *p)
+detachdev(Hub *, Port *p)
{
Dev *d = p->dev;