ref: 76142255a117a21da665282e7c6754b8b389bbc7
parent: 8420d3ad6929c2f6963bcef80797f8cc2b3d90f8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Apr 12 17:35:21 EDT 2023
nusb/usbd: only fetch first 8 bytes of device descriptor for getmaxpkt() (thanks k0ga) The first usb transaction we run on a device is reading the device descriptor, but todo this we need to know the maximum packet size on the control endpoint. But the packet size itself is stored in the device descriptor which needs to be read over the control endpoint. We used to fetch up to 64 bytes of device descriptor, and if that fails assume some default values. But this seems to cause errors down the line for some devices like k0gas usb keyboard. The new way is to read *ONLY* the first 8 bytes (that contain the bMaxPktSize0 field) and fetch the full device descriptor later once we have set the correct packet size.
--- a/sys/src/cmd/nusb/usbd/hub.c
+++ b/sys/src/cmd/nusb/usbd/hub.c
@@ -326,19 +326,15 @@
}
static int
-getmaxpkt(Dev *d, int islow)
+getmaxpkt(Dev *d)
{
- uchar buf[64]; /* More room to try to get device-specific descriptors */
+ uchar buf[8];
DDev *dd;
if(d->isusb3)
return 512;
dd = (DDev*)buf;
- if(islow)
- dd->bMaxPacketSize0 = 8;
- else
- dd->bMaxPacketSize0 = 64;
- if(usbcmd(d, Rd2h|Rstd|Rdev, Rgetdesc, Ddev<<8|0, 0, buf, sizeof(buf)) < 0)
+ if(usbcmd(d, Rd2h|Rstd|Rdev, Rgetdesc, Ddev<<8|0, 0, buf, sizeof(buf)) != sizeof(buf))
return -1;
return dd->bMaxPacketSize0;
}
@@ -440,7 +436,7 @@
dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p);
goto Fail;
}
- mp=getmaxpkt(nd, strcmp(sp, "low") == 0);
+ mp=getmaxpkt(nd);
if(mp < 0){
dprint(2, "%s: %s: port %d: getmaxpkt: %r\n", argv0, d->dir, p);
goto Fail;