ref: 9ae4b3d9fc0b4521422af57d5b5dbb565e51f6d8
parent: bada582e187efc6514e4b2a518da0f9532c7da96
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Nov 3 07:18:46 EST 2024
nusb/usbd: issue SetConfiguration(0) request to USB3 hub on attach
--- a/sys/src/cmd/nusb/usbd/hub.c
+++ b/sys/src/cmd/nusb/usbd/hub.c
@@ -74,6 +74,12 @@
pp->pwrctl = (PortPwrCtrlMask[offset] & mask) != 0;
}
h->mtt = h->dev->usb->ver == 0x0200 && Proto(h->dev->usb->csp) == 2;
+
+ if(usbcmd(h->dev, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
+ fprint(2, "%s: %s: hub setconf #1: %r\n", argv0, h->dev->dir);
+ return -1;
+ }
+
if(h->mtt){ /* try enable multi TT */
if(usbcmd(h->dev, Rh2d|Rstd|Riface, Rsetiface, 1, 0, nil, 0) < 0){
fprint(2, "%s: %s: setifcace (mtt): %r\n", argv0, h->dev->dir);
@@ -111,6 +117,18 @@
pp->removable = (dd->DeviceRemovable[offset] & mask) != 0;
}
h->mtt = 0;
+
+ /*
+ * SetConfiguration(0) appears to be neccessary for self powered
+ * usb3 hub after upstream disconnect with the power remaining.
+ */
+ if(usbcmd(h->dev, Rh2d|Rstd|Rdev, Rsetconf, 0, 0, nil, 0) < 0)
+ fprint(2, "%s: %s: hub setconf #0: %r\n", argv0, h->dev->dir);
+
+ if(usbcmd(h->dev, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
+ fprint(2, "%s: %s: hub setconf #1: %r\n", argv0, h->dev->dir);
+ return -1;
+ }
if(usbcmd(h->dev, Rh2d|Rclass|Rdev, Rsethubdepth, h->dev->depth, 0, nil, 0) < 0){
fprint(2, "%s: %s: sethubdepth: %r\n", argv0, h->dev->dir);
return -1;
@@ -462,10 +480,9 @@
return -1;
sleep(i*50);
}
-
/*
* for xhci, this command is ignored by the driver as the device address
- * has already been assigned by the controller firmware.
+ * has already been assigned by the controller firmware when opening ep0.
*/
if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id&0x7f, 0, nil, 0) < 0){
dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p);
@@ -494,18 +511,6 @@
return -1;
}
- /*
- * We always set conf #1. BUG.
- */
- if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
- dprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p);
- if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0)
- return -1;
- }
-
- pp->state = Pconfigured;
- dprint(2, "%s: %s: port %d: configured: %s\n", argv0, d->dir, p, nd->dir);
-
/* assign stable name based on device descriptor */
assignhname(nd);
@@ -519,8 +524,21 @@
if(pp->hub == nil)
return -1;
+ pp->state = Pconfigured;
return 0;
}
+
+ /*
+ * We always set conf #1. BUG.
+ */
+ if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
+ fprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p);
+ if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0)
+ return -1;
+ }
+
+ pp->state = Pconfigured;
+ dprint(2, "%s: %s: port %d: configured: %s\n", argv0, d->dir, p, nd->dir);
/* close control endpoint so driver can open it */
close(nd->dfd);
--
⑨