ref: b1d4e860642d13805e47ee5cf9f373d8c97d0bc4
parent: b4c1cf2ea1220698c00fa2692477505e20431bb0
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jul 31 10:38:39 EDT 2017
nusb/usbd: support for usb3 hubs
--- a/sys/src/cmd/nusb/usbd/dat.h
+++ b/sys/src/cmd/nusb/usbd/dat.h
@@ -1,5 +1,6 @@
typedef struct Hub Hub;
typedef struct DHub DHub;
+typedef struct DSSHub DSSHub;
typedef struct Port Port;
enum
@@ -6,9 +7,12 @@
{
Stack = 32*1024,
- Dhub = 0x29, /* hub descriptor type */
- Dhublen = 9, /* hub descriptor length */
+ Dhub = 0x29, /* hub descriptor type */
+ Dhublen = 9, /* hub descriptor length */
+ Dsshub = 0x2A, /* superspeed hub descriptor type */
+ Dsshublen = 12, /* superspeed hub descriptor length */
+
/* hub class feature selectors */
Fhublocalpower = 0,
Fhubovercurrent = 1,
@@ -104,5 +108,19 @@
uchar wHubCharacteristics[2];
uchar bPwrOn2PwrGood;
uchar bHubContrCurrent;
+ uchar DeviceRemovable[1]; /* variable length */
+};
+
+/* Superspeed HUB descriptor */
+struct DSSHub
+{
+ uchar bLength;
+ uchar bDescriptorType;
+ uchar bNbrPorts;
+ uchar wHubCharacteristics[2];
+ uchar bPwrOn2PwrGood;
+ uchar bHubContrCurrent;
+ uchar bHubHdrDecLat;
+ uchar wHubDelay[2];
uchar DeviceRemovable[1]; /* variable length */
};
--- a/sys/src/cmd/nusb/usbd/hub.c
+++ b/sys/src/cmd/nusb/usbd/hub.c
@@ -26,37 +26,12 @@
}
static int
-confighub(Hub *h)
+configusb2hub(Hub *h, DHub *dd, int nr)
{
- int type;
- uchar buf[128]; /* room for extra descriptors */
- int i;
- Usbdev *d;
- DHub *dd;
- Port *pp;
- int nr;
- int nmap;
uchar *PortPwrCtrlMask;
- int offset;
- int mask;
+ int i, offset, mask, nmap;
+ Port *pp;
- d = h->dev->usb;
- for(i = 0; i < nelem(d->ddesc); i++)
- if(d->ddesc[i] == nil)
- break;
- else if(d->ddesc[i]->data.bDescriptorType == Dhub){
- dd = (DHub*)&d->ddesc[i]->data;
- nr = Dhublen;
- goto Config;
- }
- type = Rd2h|Rclass|Rdev;
- nr = usbcmd(h->dev, type, Rgetdesc, Dhub<<8|0, 0, buf, sizeof buf);
- if(nr < Dhublen){
- dprint(2, "%s: %s: getdesc hub: %r\n", argv0, h->dev->dir);
- return -1;
- }
- dd = (DHub*)buf;
-Config:
h->nport = dd->bNbrPorts;
nmap = 1 + h->nport/8;
if(nr < 7 + 2*nmap){
@@ -79,11 +54,77 @@
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;
+}
+
+static int
+configusb3hub(Hub *h, DSSHub *dd, int nr)
+{
+ int i, offset, mask, nmap;
+ Port *pp;
+
+ h->nport = dd->bNbrPorts;
+ nmap = 1 + h->nport/8;
+ if(nr < 10 + nmap){
+ fprint(2, "%s: %s: descr. too small\n", argv0, h->dev->dir);
+ return -1;
}
+ h->port = emallocz((h->nport+1)*sizeof(Port), 1);
+ h->pwrms = dd->bPwrOn2PwrGood*2;
+ if(h->pwrms < Powerdelay)
+ h->pwrms = Powerdelay;
+ h->maxcurrent = dd->bHubContrCurrent;
+ h->pwrmode = dd->wHubCharacteristics[0] & 3;
+ h->compound = (dd->wHubCharacteristics[0] & (1<<2))!=0;
+ h->leds = (dd->wHubCharacteristics[0] & (1<<7)) != 0;
+ for(i = 1; i <= h->nport; i++){
+ pp = &h->port[i];
+ offset = i/8;
+ mask = 1<<(i%8);
+ pp->removable = (dd->DeviceRemovable[offset] & mask) != 0;
+ }
+ if(usbcmd(h->dev, Rh2d|Rclass|Rdev, Rsethubdepth, h->depth, 0, nil, 0) < 0){
+ fprint(2, "%s: %s: sethubdepth: %r\n", argv0, h->dev->dir);
+ return -1;
+ }
return 0;
+}
+
+static int
+confighub(Hub *h)
+{
+ uchar buf[128]; /* room for extra descriptors */
+ int i, dt, dl, nr;
+ Usbdev *d;
+ void *dd;
+
+ d = h->dev->usb;
+ if(h->dev->isusb3){
+ dt = Dsshub;
+ dl = Dsshublen;
+ } else {
+ dt = Dhub;
+ dl = Dhublen;
+ }
+ for(i = 0; i < nelem(d->ddesc); i++)
+ if(d->ddesc[i] == nil)
+ break;
+ else if(d->ddesc[i]->data.bDescriptorType == dt){
+ dd = &d->ddesc[i]->data;
+ nr = dl;
+ goto Config;
+ }
+ nr = usbcmd(h->dev, Rd2h|Rclass|Rdev, Rgetdesc, dt<<8|0, 0, buf, sizeof buf);
+ if(nr < dl){
+ fprint(2, "%s: %s: getdesc hub: %r\n", argv0, h->dev->dir);
+ return -1;
+ }
+ dd = buf;
+Config:
+ if(h->dev->isusb3)
+ return configusb3hub(h, dd, nr);
+ else
+ return configusb2hub(h, dd, nr);
}
static void