git: 9front

Download patch

ref: 5cbc4af193f973a48963c83da8267a64ecd4122f
parent: 4127edf657977213134d2e21e24dc25665e3783c
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;
--