Make reading of descriptors more robust to support more usb cdc-ecm devices,
and add realtek rtl8152 to usbdb for automatic recognition.
Note: this obsoletes the earlier patch maybe/usb-short-desc
Reference: /n/sources/patch/usb-ether-cdc
Date: Mon Mar 13 09:48:37 GMT 2017
Signed-off-by: [email protected]
--- /sys/src/cmd/usb/ether/cdc.c Mon Mar 13 09:41:51 2017
+++ /sys/src/cmd/usb/ether/cdc.c Mon Mar 13 09:41:49 2017
@@ -48,13 +48,29 @@
int
cdcreset(Ether *ether)
{
+ Usbdev *ud;
+ Ep *ep;
+ int i;
+
/*
* Assume that all communication devices are going to
* be std. ethernet communication devices. Specific controllers
* must have been probed first.
- * NB: This ignores unions.
*/
- if(ether->dev->usb->class == Clcomms)
+ ud = ether->dev->usb;
+ if(ud->class == Clcomms)
return getmac(ether);
+ if(getmac(ether) == 0){
+ for(i = 0; i < Nep; i++){
+ ep = ud->ep[i];
+ if(ep == nil)
+ continue;
+ if(ep->iface == nil || !okclass(ep->iface))
+ continue;
+ if(ep->conf->cval != 1)
+ usbcmd(ether->dev, Rh2d|Rstd|Rdev, Rsetconf, ep->conf->cval, 0, nil, 0);
+ return 0;
+ }
+ }
return -1;
}
--- /sys/src/cmd/usb/lib/dev.c Mon Mar 13 09:41:55 2017
+++ /sys/src/cmd/usb/lib/dev.c Mon Mar 13 09:41:53 2017
@@ -148,7 +148,7 @@
loaddevconf(Dev *d, int n)
{
uchar *buf;
- int nr;
+ int l, nr;
int type;
if(n >= nelem(d->usb->conf)){
@@ -158,11 +158,22 @@
}
buf = emallocz(Maxdevconf, 0);
type = Rd2h|Rstd|Rdev;
- nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Maxdevconf);
+ nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Dconflen);
if(nr < Dconflen){
free(buf);
return -1;
}
+ l = GET2(((DConf*)buf)->wTotalLength);
+ if(l > Maxdevconf){
+ free(buf);
+ return -1;
+ }
+ nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, l);
+ if(nr < l){
+ free(buf);
+ return -1;
+ }
+
if(d->usb->conf[n] == nil)
d->usb->conf[n] = emallocz(sizeof(Conf), 1);
nr = parseconf(d->usb, d->usb->conf[n], buf, nr);
@@ -188,6 +199,8 @@
char *s;
char *e;
+ if(n > b[0])
+ n = b[0];
if(n <= 2 || (n & 1) != 0)
return strdup("none");
n = (n - 2)/2;
@@ -204,42 +217,37 @@
char*
loaddevstr(Dev *d, int sid)
{
- uchar buf[128];
- int type;
- int nr;
+ uchar buf[256];
+ int type, langid, nr;
if(sid == 0)
return estrdup("none");
type = Rd2h|Rstd|Rdev;
- nr=usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf));
+ nr = usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf));
+ if(nr < 4)
+ langid = 0x0409; /* english */
+ else
+ langid = buf[3]<<8 | buf[2];
+ nr = usbcmd(d, type, Rgetdesc, Dstr<<8|sid, langid, buf, sizeof(buf));
+
return mkstr(buf, nr);
}
int
loaddevdesc(Dev *d)
{
- uchar buf[Ddevlen+255];
+ uchar buf[Ddevlen];
int nr;
int type;
Ep *ep0;
type = Rd2h|Rstd|Rdev;
- nr = sizeof(buf);
memset(buf, 0, Ddevlen);
- if((nr=usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, nr)) < 0)
+ if((nr = usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, Ddevlen)) < 0)
return -1;
- /*
- * Several hubs are returning descriptors of 17 bytes, not 18.
- * We accept them and leave number of configurations as zero.
- * (a get configuration descriptor also fails for them!)
- */
if(nr < Ddevlen){
- print("%s: %s: warning: device with short descriptor\n",
- argv0, d->dir);
- if(nr < Ddevlen-1){
- werrstr("short device descriptor (%d bytes)", nr);
- return -1;
- }
+ werrstr("short device descriptor (%d bytes)", nr);
+ return -1;
}
d->usb = emallocz(sizeof(Usbdev), 1);
ep0 = mkep(d->usb, 0);
@@ -254,6 +262,8 @@
d->usb->serial = loaddevstr(d, d->usb->ssid);
}
}
+ else
+ print("usbd: desc error: %r");
return nr;
}
--- /sys/src/cmd/usb/usbd/usbdb Mon Mar 13 09:41:59 2017
+++ /sys/src/cmd/usb/usbd/usbdb Mon Mar 13 09:41:57 2017
@@ -5,6 +5,7 @@
disk class=storage args=
ether class=255 csp=0x00ffff vid=0x0b95 args=
ether class=255 csp=0xff00ff vid=0x0424 did=0xec00 args=
+ ether class=255 csp=0x000602 vid=0x0bda did=0x8152 args=
serial class=255 csp=0xffffff vid=0x9e88 did=0x9e8f args=
serial class=255 csp=0xffffff vid=0x0403 args=
serial class=255 csp=0x0000ff vid=0x10c4 args=
|