ref: e493115bba63849f73cb8980bbe8c4b5ebe99b04
parent: 03620a260f0d376c4876e4169aca62f5d96fc2b0
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Apr 23 16:03:01 EDT 2014
nusb: resolve endpoint id conflict with different input and output types ftrvxmtrx repots devices that use the endpoint number for input and output of different types like: nusb/ether: parsedesc endpoint 5[7] 07 05 81 03 08 00 09 # ep1 in intr nusb/ether: parsedesc endpoint 5[7] 07 05 82 02 00 02 00 nusb/ether: parsedesc endpoint 5[7] 07 05 01 02 00 02 00 # ep1 out bulk the previous change tried to work arround this but had the concequence that only the lastly defined endpoint was usable. this change addresses the issue by allowing up to 32 endpoints per device (16 output + 16 input endpoints) in devusb. the hci driver will ignore the 4th bit and will only use the lower 4 bits as endpoint address when talking to the usb device. when we encounter a conflict, we map the input endpoint to the upper id range 16..31 and the output endpoint to id 0..15 so two distinct endpoints are created.
--- a/sys/src/9/bcm/usbdwc.c
+++ b/sys/src/9/bcm/usbdwc.c
@@ -115,10 +115,10 @@
hcc = 0;
break;
default:
- hcc = ep->dev->nb<<ODevaddr;
+ hcc = (ep->dev->nb&Devmax)<<ODevaddr;
break;
}
- hcc |= ep->maxpkt | 1<<OMulticnt | ep->nb<<OEpnum;
+ hcc |= ep->maxpkt | 1<<OMulticnt | (ep->nb&Epmax)<<OEpnum;
switch(ep->ttype){case Tctl:
hcc |= Epctl;
--- a/sys/src/9/pc/usbohci.c
+++ b/sys/src/9/pc/usbohci.c
@@ -1719,7 +1719,7 @@
/* set the address if unset and out of configuration state */
if(ep->dev->state != Dconfig && ep->dev->state != Dreset)
if(cio->usbid == 0){- cio->usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ cio->usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
edsetaddr(cio->ed, cio->usbid);
}
/* adjust maxpkt if the user has learned a different one */
@@ -1986,7 +1986,7 @@
int i;
iso = ep->aux;
- iso->usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ iso->usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
iso->bw = ep->hz * ep->samplesz; /* bytes/sec */
if(ep->mode != OWRITE){ print("ohci: bug: iso input streams not implemented\n");@@ -2067,7 +2067,7 @@
case Tintr:
io = ep->aux = smalloc(sizeof(Qio)*2);
io[OREAD].debug = io[OWRITE].debug = ep->debug;
- usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
if(ep->mode != OREAD){if(ep->toggle[OWRITE] != 0)
io[OWRITE].toggle = Tddata1;
--- a/sys/src/9/pc/usbuhci.c
+++ b/sys/src/9/pc/usbuhci.c
@@ -1791,7 +1791,7 @@
case Tintr:
io = ep->aux = smalloc(sizeof(Qio)*2);
io[OREAD].debug = io[OWRITE].debug = ep->debug;
- usbid = ((ep->nb&Epmax)<<7)|(ep->dev->nb &Devmax);
+ usbid = ((ep->nb&Epmax)<<7)|(ep->dev->nb&Devmax);
if(ep->mode != OREAD){if(ep->toggle[OWRITE] != 0)
io[OWRITE].toggle = Tddata1;
--- a/sys/src/9/port/usb.h
+++ b/sys/src/9/port/usb.h
@@ -17,7 +17,7 @@
enum
{/* fundamental constants */
- Ndeveps = 16, /* max nb. of endpoints per device */
+ Ndeveps = 32, /* max nb. of endpoints per device (16 in + 16 out) */
/* tunable parameters */
Nhcis = 16, /* max nb. of HCIs */
--- a/sys/src/9/port/usbehci.c
+++ b/sys/src/9/port/usbehci.c
@@ -2578,7 +2578,7 @@
/* set the address if unset and out of configuration state */
if(ep->dev->state != Dconfig && ep->dev->state != Dreset)
if(cio->usbid == 0){- cio->usbid = (ep->nb&Epmax) << 7 | ep->dev->nb&Devmax;
+ cio->usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
coherence();
qhsetaddr(cio->qh, cio->usbid);
}
@@ -2688,8 +2688,8 @@
td->data = iso->data + i * ep->maxpkt;
td->epc = ep->dev->port << Stdportshift;
td->epc |= ep->dev->hub << Stdhubshift;
- td->epc |= ep->nb << Stdepshift;
- td->epc |= ep->dev->nb << Stddevshift;
+ td->epc |= (ep->nb&Epmax) << Stdepshift;
+ td->epc |= (ep->dev->nb&Devmax) << Stddevshift;
td->mfs = 034 << Stdscmshift | 1 << Stdssmshift;
if(ep->mode == OREAD){td->epc |= Stdin;
@@ -2743,7 +2743,7 @@
td->buffer[p] = pa;
pa += 0x1000;
}
- td->buffer[0] |= ep->nb << Itdepshift | ep->dev->nb << Itddevshift;
+ td->buffer[0] |= (ep->nb&Epmax)<<Itdepshift | (ep->dev->nb&Devmax)<<Itddevshift;
if(ep->mode == OREAD)
td->buffer[1] |= Itdin;
else
@@ -2789,7 +2789,7 @@
default:
error("iso i/o is half-duplex");}
- iso->usbid = ep->nb << 7 | ep->dev->nb & Devmax;
+ iso->usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
iso->state = Qidle;
coherence();
iso->debug = ep->debug;
@@ -2926,7 +2926,7 @@
case Tintr:
io = ep->aux = smalloc(sizeof(Qio)*2);
io[OREAD].debug = io[OWRITE].debug = ep->debug;
- usbid = (ep->nb&Epmax) << 7 | ep->dev->nb &Devmax;
+ usbid = (ep->nb&Epmax)<<7 | (ep->dev->nb&Devmax);
assert(ep->pollival != 0);
if(ep->mode != OREAD){if(ep->toggle[OWRITE] != 0)
--- a/sys/src/cmd/nusb/lib/dev.c
+++ b/sys/src/cmd/nusb/lib/dev.c
@@ -481,7 +481,7 @@
else
dir = 0;
r = Rh2d|Rstd|Rep;
- if(usbcmd(dev, r, Rclearfeature, Fhalt, ep->id|dir, nil, 0)<0){+ if(usbcmd(dev, r, Rclearfeature, Fhalt, (ep->id&0xF)|dir, nil, 0)<0){ werrstr("unstall: %s: %r", ep->dir);return -1;
}
--- a/sys/src/cmd/nusb/lib/parse.c
+++ b/sys/src/cmd/nusb/lib/parse.c
@@ -96,7 +96,7 @@
static int
parseendpt(Usbdev *d, Conf *c, Iface *ip, Altc *altc, uchar *b, int n, Ep **epp)
{- int i, dir, epid, type;
+ int i, dir, epid, type, addr;
Ep *ep;
DEp *dep;
@@ -109,25 +109,38 @@
altc->attrib = dep->bmAttributes; /* here? */
altc->interval = dep->bInterval;
- epid = dep->bEndpointAddress & 0xF;
- assert(epid < nelem(d->ep));
- if(dep->bEndpointAddress & 0x80)
+ type = dep->bmAttributes & 0x03;
+ addr = dep->bEndpointAddress;
+ if(addr & 0x80)
dir = Ein;
else
dir = Eout;
- type = dep->bmAttributes & 0x03;
+ epid = addr & 0xF; /* default map to 0..15 */
+ assert(epid < nelem(d->ep));
ep = d->ep[epid];
if(ep == nil){ep = mkep(d, epid);
ep->dir = dir;
- }else if((ep->addr & 0x80) != (dep->bEndpointAddress & 0x80) && ep->type == type)
- ep->dir = Eboth;
- else
- ep->dir = dir;
+ }else if((ep->addr & 0x80) != (addr & 0x80)){+ if(ep->type == type)
+ ep->dir = Eboth;
+ else {+ /*
+ * resolve conflict when same endpoint number
+ * is used for different input and output types.
+ * map input endpoint to 16..31 and output to 0..15.
+ */
+ ep->id = ((ep->addr & 0x80) != 0)<<4 | (ep->addr & 0xF);
+ d->ep[ep->id] = ep;
+ epid = ep->id ^ 0x10;
+ ep = mkep(d, epid);
+ ep->dir = dir;
+ }
+ }
ep->maxpkt = GET2(dep->wMaxPacketSize);
ep->ntds = 1 + ((ep->maxpkt >> 11) & 3);
ep->maxpkt &= 0x7FF;
- ep->addr = dep->bEndpointAddress;
+ ep->addr = addr;
ep->type = type;
ep->isotype = (dep->bmAttributes>>2) & 0x03;
ep->conf = c;
--
⑨