xref: /plan9-contrib/sys/src/9/bcm/devusb.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
1 /*
2  * USB device driver framework.
3  *
4  * This is in charge of providing access to actual HCIs
5  * and providing I/O to the various endpoints of devices.
6  * A separate user program (usbd) is in charge of
7  * enumerating the bus, setting up endpoints and
8  * starting devices (also user programs).
9  *
10  * The interface provided is a violation of the standard:
11  * you're welcome.
12  *
13  * The interface consists of a root directory with several files
14  * plus a directory (epN.M) with two files per endpoint.
15  * A device is represented by its first endpoint, which
16  * is a control endpoint automatically allocated for each device.
17  * Device control endpoints may be used to create new endpoints.
18  * Devices corresponding to hubs may also allocate new devices,
19  * perhaps also hubs. Initially, a hub device is allocated for
20  * each controller present, to represent its root hub. Those can
21  * never be removed.
22  *
23  * All endpoints refer to the first endpoint (epN.0) of the device,
24  * which keeps per-device information, and also to the HCI used
25  * to reach them. Although all endpoints cache that information.
26  *
27  * epN.M/data files permit I/O and are considered DMEXCL.
28  * epN.M/ctl files provide status info and accept control requests.
29  *
30  * Endpoints may be given file names to be listed also at #u,
31  * for those drivers that have nothing to do after configuring the
32  * device and its endpoints.
33  *
34  * Drivers for different controllers are kept at usb[oue]hci.c
35  * It's likely we could factor out much from controllers into
36  * a generic controller driver, the problem is that details
37  * regarding how to handle toggles, tokens, Tds, etc. will
38  * get in the way. Thus, code is probably easier the way it is.
39  */
40 
41 #include	"u.h"
42 #include	"../port/lib.h"
43 #include	"mem.h"
44 #include	"dat.h"
45 #include	"fns.h"
46 #include	"io.h"
47 #include	"../port/error.h"
48 #include	"usb.h"
49 
50 typedef struct Hcitype Hcitype;
51 
52 enum
53 {
54 	/* Qid numbers */
55 	Qdir = 0,		/* #u */
56 	Qusbdir,			/* #u/usb */
57 	Qctl,			/* #u/usb/ctl - control requests */
58 
59 	Qep0dir,			/* #u/usb/ep0.0 - endpoint 0 dir */
60 	Qep0io,			/* #u/usb/ep0.0/data - endpoint 0 I/O */
61 	Qep0ctl,		/* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
62 	Qep0dummy,		/* give 4 qids to each endpoint */
63 
64 	Qepdir = 0,		/* (qid-qep0dir)&3 is one of these */
65 	Qepio,			/* to identify which file for the endpoint */
66 	Qepctl,
67 
68 	/* ... */
69 
70 	/* Usb ctls. */
71 	CMdebug = 0,		/* debug on|off */
72 	CMdump,			/* dump (data structures for debug) */
73 
74 	/* Ep. ctls */
75 	CMnew = 0,		/* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
76 	CMnewdev,		/* newdev full|low|high|super portnb (allocate new devices) */
77 	CMhub,			/* hub (set the device as a hub) */
78 	CMspeed,		/* speed full|low|high|no */
79 	CMmaxpkt,		/* maxpkt size */
80 	CMntds,			/* ntds nb (max nb. of tds per µframe) */
81 	CMclrhalt,		/* clrhalt (halt was cleared on endpoint) */
82 	CMpollival,		/* pollival interval (interrupt/iso) */
83 	CMhz,			/* hz n (samples/sec; iso) */
84 	CMsamplesz,		/* samplesz n (sample size; iso) */
85 	CMinfo,			/* info infostr (ke.ep info for humans) */
86 	CMdetach,		/* detach (abort I/O forever on this ep). */
87 	CMaddress,		/* address (address is assigned) */
88 	CMdebugep,		/* debug n (set/clear debug for this ep) */
89 	CMname,			/* name str (show up as #u/name as well) */
90 	CMtmout,		/* timeout n (activate timeouts for ep) */
91 	CMpreset,		/* reset the port */
92 
93 	/* Hub feature selectors */
94 	Rportenable	= 1,
95 	Rportreset	= 4,
96 
97 };
98 
99 struct Hcitype
100 {
101 	char*	type;
102 	int	(*reset)(Hci*);
103 };
104 
105 #define QID(q)	((int)(q).path)
106 
107 static Cmdtab usbctls[] =
108 {
109 	{CMdebug,	"debug",	2},
110 	{CMdump,	"dump",		1},
111 };
112 
113 static Cmdtab epctls[] =
114 {
115 	{CMnew,		"new",		4},
116 	{CMnewdev,	"newdev",	3},
117 	{CMhub,		"hub",		1},
118 	{CMspeed,	"speed",	2},
119 	{CMmaxpkt,	"maxpkt",	2},
120 	{CMntds,	"ntds",		2},
121 	{CMpollival,	"pollival",	2},
122 	{CMsamplesz,	"samplesz",	2},
123 	{CMhz,		"hz",		2},
124 	{CMinfo,	"info",		0},
125 	{CMdetach,	"detach",	1},
126 	{CMaddress,	"address",	1},
127 	{CMdebugep,	"debug",	2},
128 	{CMclrhalt,	"clrhalt",	1},
129 	{CMname,	"name",		2},
130 	{CMtmout,	"timeout",	2},
131 	{CMpreset,	"reset",	1},
132 };
133 
134 static Dirtab usbdir[] =
135 {
136 	"ctl",		{Qctl},		0,	0666,
137 };
138 
139 char *usbmodename[] =
140 {
141 	[OREAD]	"r",
142 	[OWRITE]	"w",
143 	[ORDWR]	"rw",
144 };
145 
146 static char *ttname[] =
147 {
148 	[Tnone]	"none",
149 	[Tctl]	"control",
150 	[Tiso]	"iso",
151 	[Tintr]	"interrupt",
152 	[Tbulk]	"bulk",
153 };
154 
155 static char *spname[] =
156 {
157 	[Superspeed]	"super",
158 	[Fullspeed]	"full",
159 	[Lowspeed]	"low",
160 	[Highspeed]	"high",
161 	[Nospeed]	"no",
162 };
163 
164 static int	debug;
165 static Hcitype	hcitypes[Nhcis];
166 static Hci*	hcis[Nhcis];
167 static QLock	epslck;		/* add, del, lookup endpoints */
168 static Ep*	eps[Neps];	/* all endpoints known */
169 static int	epmax;		/* 1 + last endpoint index used  */
170 static int	usbidgen;	/* device address generator */
171 
172 /*
173  * Is there something like this in a library? should it be?
174  */
175 char*
seprintdata(char * s,char * se,uchar * d,int n)176 seprintdata(char *s, char *se, uchar *d, int n)
177 {
178 	int i, l;
179 
180 	s = seprint(s, se, " %#p[%d]: ", d, n);
181 	l = n;
182 	if(l > 10)
183 		l = 10;
184 	for(i=0; i<l; i++)
185 		s = seprint(s, se, " %2.2ux", d[i]);
186 	if(l < n)
187 		s = seprint(s, se, "...");
188 	return s;
189 }
190 
191 static int
name2speed(char * name)192 name2speed(char *name)
193 {
194 	int i;
195 
196 	for(i = 0; i < nelem(spname); i++)
197 		if(strcmp(name, spname[i]) == 0)
198 			return i;
199 	return Nospeed;
200 }
201 
202 static int
name2ttype(char * name)203 name2ttype(char *name)
204 {
205 	int i;
206 
207 	for(i = 0; i < nelem(ttname); i++)
208 		if(strcmp(name, ttname[i]) == 0)
209 			return i;
210 	/* may be a std. USB ep. type */
211 	i = strtol(name, nil, 0);
212 	switch(i+1){
213 	case Tctl:
214 	case Tiso:
215 	case Tbulk:
216 	case Tintr:
217 		return i+1;
218 	default:
219 		return Tnone;
220 	}
221 }
222 
223 static int
name2mode(char * mode)224 name2mode(char *mode)
225 {
226 	int i;
227 
228 	for(i = 0; i < nelem(usbmodename); i++)
229 		if(strcmp(mode, usbmodename[i]) == 0)
230 			return i;
231 	return -1;
232 }
233 
234 static int
qid2epidx(int q)235 qid2epidx(int q)
236 {
237 	q = (q-Qep0dir)/4;
238 	if(q < 0 || q >= epmax || eps[q] == nil)
239 		return -1;
240 	return q;
241 }
242 
243 static int
isqtype(int q,int type)244 isqtype(int q, int type)
245 {
246 	if(q < Qep0dir)
247 		return 0;
248 	q -= Qep0dir;
249 	return (q & 3) == type;
250 }
251 
252 void
addhcitype(char * t,int (* r)(Hci *))253 addhcitype(char* t, int (*r)(Hci*))
254 {
255 	static int ntype;
256 
257 	if(ntype == Nhcis)
258 		panic("too many USB host interface types");
259 	hcitypes[ntype].type = t;
260 	hcitypes[ntype].reset = r;
261 	ntype++;
262 }
263 
264 static char*
seprintep(char * s,char * se,Ep * ep,int all)265 seprintep(char *s, char *se, Ep *ep, int all)
266 {
267 	static char* dsnames[] = { "config", "enabled", "detached", "reset" };
268 	Udev *d;
269 	int i;
270 	int di;
271 
272 	d = ep->dev;
273 
274 	qlock(ep);
275 	if(waserror()){
276 		qunlock(ep);
277 		nexterror();
278 	}
279 	di = ep->dev->nb;
280 	if(all)
281 		s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
282 	s = seprint(s, se, "%s", dsnames[ep->dev->state]);
283 	s = seprint(s, se, " %s", ttname[ep->ttype]);
284 	assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
285 	s = seprint(s, se, " %s", usbmodename[ep->mode]);
286 	s = seprint(s, se, " speed %s", spname[d->speed]);
287 	s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
288 	s = seprint(s, se, " pollival %ld", ep->pollival);
289 	s = seprint(s, se, " samplesz %ld", ep->samplesz);
290 	s = seprint(s, se, " hz %ld", ep->hz);
291 	s = seprint(s, se, " hub %d", ep->dev->hub);
292 	s = seprint(s, se, " port %d", ep->dev->port);
293 	s = seprint(s, se, " rootport %d", ep->dev->rootport);
294 	s = seprint(s, se, " addr %d", ep->dev->addr);
295 	if(ep->inuse)
296 		s = seprint(s, se, " busy");
297 	else
298 		s = seprint(s, se, " idle");
299 	if(all){
300 		s = seprint(s, se, " load %uld", ep->load);
301 		s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
302 		s = seprint(s, se, " idx %d", ep->idx);
303 		if(ep->name != nil)
304 			s = seprint(s, se, " name '%s'", ep->name);
305 		if(ep->tmout != 0)
306 			s = seprint(s, se, " tmout");
307 		if(ep == ep->ep0){
308 			s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
309 			s = seprint(s, se, " eps:");
310 			for(i = 0; i < nelem(d->eps); i++)
311 				if(d->eps[i] != nil)
312 					s = seprint(s, se, " ep%d.%d", di, i);
313 		}
314 	}
315 	if(ep->info != nil)
316 		s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
317 	else
318 		s = seprint(s, se, "\n");
319 	qunlock(ep);
320 	poperror();
321 	return s;
322 }
323 
324 static Ep*
epalloc(Hci * hp)325 epalloc(Hci *hp)
326 {
327 	Ep *ep;
328 	int i;
329 
330 	ep = smalloc(sizeof(Ep));
331 	ep->ref = 1;
332 	qlock(&epslck);
333 	for(i = 0; i < Neps; i++)
334 		if(eps[i] == nil)
335 			break;
336 	if(i == Neps){
337 		qunlock(&epslck);
338 		free(ep);
339 		print("usb: bug: too few endpoints.\n");
340 		return nil;
341 	}
342 	ep->idx = i;
343 	if(epmax <= i)
344 		epmax = i+1;
345 	eps[i] = ep;
346 	ep->hp = hp;
347 	ep->maxpkt = 8;
348 	ep->ntds = 1;
349 	ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
350 	qunlock(&epslck);
351 	return ep;
352 }
353 
354 static Ep*
getep(int i)355 getep(int i)
356 {
357 	Ep *ep;
358 
359 	if(i < 0 || i >= epmax || eps[i] == nil)
360 		return nil;
361 	qlock(&epslck);
362 	ep = eps[i];
363 	if(ep != nil)
364 		incref(ep);
365 	qunlock(&epslck);
366 	return ep;
367 }
368 
369 static void
putep(Ep * ep)370 putep(Ep *ep)
371 {
372 	Udev *d;
373 
374 	if(ep != nil && decref(ep) == 0){
375 		d = ep->dev;
376 		deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
377 		qlock(&epslck);
378 		eps[ep->idx] = nil;
379 		if(ep->idx == epmax-1)
380 			epmax--;
381 		if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
382 			usbidgen--;
383 		qunlock(&epslck);
384 		if(d != nil){
385 			qlock(ep->ep0);
386 			d->eps[ep->nb] = nil;
387 			qunlock(ep->ep0);
388 		}
389 		if(ep->ep0 != ep){
390 			putep(ep->ep0);
391 			ep->ep0 = nil;
392 		}
393 		free(ep->info);
394 		free(ep->name);
395 		free(ep);
396 	}
397 }
398 
399 static void
dumpeps(void)400 dumpeps(void)
401 {
402 	int i;
403 	static char buf[512];
404 	char *s;
405 	char *e;
406 	Ep *ep;
407 
408 	print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
409 	for(i = 0; i < epmax; i++){
410 		s = buf;
411 		e = buf+sizeof(buf);
412 		ep = getep(i);
413 		if(ep != nil){
414 			if(waserror()){
415 				putep(ep);
416 				nexterror();
417 			}
418 			s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
419 			seprintep(s, e, ep, 1);
420 			print("%s", buf);
421 			ep->hp->seprintep(buf, e, ep);
422 			print("%s", buf);
423 			poperror();
424 			putep(ep);
425 		}
426 	}
427 	print("usb dump hcis:\n");
428 	for(i = 0; i < Nhcis; i++)
429 		if(hcis[i] != nil)
430 			hcis[i]->dump(hcis[i]);
431 }
432 
433 static int
newusbid(Hci *)434 newusbid(Hci *)
435 {
436 	int id;
437 
438 	qlock(&epslck);
439 	id = ++usbidgen;
440 	if(id >= 0x7F)
441 		print("#u: too many device addresses; reuse them more\n");
442 	qunlock(&epslck);
443 	return id;
444 }
445 
446 /*
447  * Create endpoint 0 for a new device
448  */
449 static Ep*
newdev(Hci * hp,int ishub,int isroot)450 newdev(Hci *hp, int ishub, int isroot)
451 {
452 	Ep *ep;
453 	Udev *d;
454 
455 	ep = epalloc(hp);
456 	d = ep->dev = smalloc(sizeof(Udev));
457 	d->nb = newusbid(hp);
458 	d->addr = 0;
459 	d->eps[0] = ep;
460 	ep->nb = 0;
461 	ep->toggle[0] = ep->toggle[1] = 0;
462 	d->ishub = ishub;
463 	d->isroot = isroot;
464 	d->rootport = 0;
465 	d->routestr = 0;
466 	d->depth = -1;
467 	d->speed = Fullspeed;
468 	d->state = Dconfig;		/* address not yet set */
469 	ep->dev = d;
470 	ep->ep0 = ep;			/* no ref counted here */
471 	ep->ttype = Tctl;
472 	ep->tmout = Xfertmout;
473 	ep->mode = ORDWR;
474 	dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
475 	return ep;
476 }
477 
478 /*
479  * Create a new endpoint for the device
480  * accessed via the given endpoint 0.
481  */
482 static Ep*
newdevep(Ep * ep,int i,int tt,int mode)483 newdevep(Ep *ep, int i, int tt, int mode)
484 {
485 	Ep *nep;
486 	Udev *d;
487 
488 	d = ep->dev;
489 	if(d->eps[i] != nil)
490 		error("endpoint already in use");
491 	nep = epalloc(ep->hp);
492 	incref(ep);
493 	d->eps[i] = nep;
494 	nep->nb = i;
495 	nep->toggle[0] = nep->toggle[1] = 0;
496 	nep->ep0 = ep;
497 	nep->dev = ep->dev;
498 	nep->mode = mode;
499 	nep->ttype = tt;
500 	nep->debug = ep->debug;
501 	/* set defaults */
502 	switch(tt){
503 	case Tctl:
504 		nep->tmout = Xfertmout;
505 		break;
506 	case Tintr:
507 		nep->pollival = 10;
508 		break;
509 	case Tiso:
510 		nep->tmout = Xfertmout;
511 		nep->pollival = 10;
512 		nep->samplesz = 4;
513 		nep->hz = 44100;
514 		break;
515 	}
516 	deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
517 	return ep;
518 }
519 
520 static int
epdataperm(int mode)521 epdataperm(int mode)
522 {
523 
524 	switch(mode){
525 	case OREAD:
526 		return 0440|DMEXCL;
527 		break;
528 	case OWRITE:
529 		return 0220|DMEXCL;
530 		break;
531 	default:
532 		return 0660|DMEXCL;
533 	}
534 }
535 
536 static int
usbgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)537 usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
538 {
539 	Qid q;
540 	Dirtab *dir;
541 	int perm;
542 	char *se;
543 	Ep *ep;
544 	int nb;
545 	int mode;
546 
547 	if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
548 	if(s == DEVDOTDOT){
549 		if(QID(c->qid) <= Qusbdir){
550 			mkqid(&q, Qdir, 0, QTDIR);
551 			devdir(c, q, "#u", 0, eve, 0555, dp);
552 		}else{
553 			mkqid(&q, Qusbdir, 0, QTDIR);
554 			devdir(c, q, "usb", 0, eve, 0555, dp);
555 		}
556 		if(0)ddprint("ok\n");
557 		return 1;
558 	}
559 
560 	switch(QID(c->qid)){
561 	case Qdir:				/* list #u */
562 		if(s == 0){
563 			mkqid(&q, Qusbdir, 0, QTDIR);
564 			devdir(c, q, "usb", 0, eve, 0555, dp);
565 			if(0)ddprint("ok\n");
566 			return 1;
567 		}
568 		s--;
569 		if(s < 0 || s >= epmax)
570 			goto Fail;
571 		ep = getep(s);
572 		if(ep == nil || ep->name == nil){
573 			if(ep != nil)
574 				putep(ep);
575 			if(0)ddprint("skip\n");
576 			return 0;
577 		}
578 		if(waserror()){
579 			putep(ep);
580 			nexterror();
581 		}
582 		mkqid(&q, Qep0io+s*4, 0, QTFILE);
583 		devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
584 		putep(ep);
585 		poperror();
586 		if(0)ddprint("ok\n");
587 		return 1;
588 
589 	case Qusbdir:				/* list #u/usb */
590 	Usbdir:
591 		if(s < nelem(usbdir)){
592 			dir = &usbdir[s];
593 			mkqid(&q, dir->qid.path, 0, QTFILE);
594 			devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
595 			if(0)ddprint("ok\n");
596 			return 1;
597 		}
598 		s -= nelem(usbdir);
599 		if(s < 0 || s >= epmax)
600 			goto Fail;
601 		ep = getep(s);
602 		if(ep == nil){
603 			if(0)ddprint("skip\n");
604 			return 0;
605 		}
606 		if(waserror()){
607 			putep(ep);
608 			nexterror();
609 		}
610 		se = up->genbuf+sizeof(up->genbuf);
611 		seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
612 		mkqid(&q, Qep0dir+4*s, 0, QTDIR);
613 		putep(ep);
614 		poperror();
615 		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
616 		if(0)ddprint("ok\n");
617 		return 1;
618 
619 	case Qctl:
620 		s = 0;
621 		goto Usbdir;
622 
623 	default:				/* list #u/usb/epN.M */
624 		nb = qid2epidx(QID(c->qid));
625 		ep = getep(nb);
626 		if(ep == nil)
627 			goto Fail;
628 		mode = ep->mode;
629 		putep(ep);
630 		if(isqtype(QID(c->qid), Qepdir)){
631 		Epdir:
632 			switch(s){
633 			case 0:
634 				mkqid(&q, Qep0io+nb*4, 0, QTFILE);
635 				perm = epdataperm(mode);
636 				devdir(c, q, "data", 0, eve, perm, dp);
637 				break;
638 			case 1:
639 				mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
640 				devdir(c, q, "ctl", 0, eve, 0664, dp);
641 				break;
642 			default:
643 				goto Fail;
644 			}
645 		}else if(isqtype(QID(c->qid), Qepctl)){
646 			s = 1;
647 			goto Epdir;
648 		}else{
649 			s = 0;
650 			goto Epdir;
651 		}
652 		if(0)ddprint("ok\n");
653 		return 1;
654 	}
655 Fail:
656 	if(0)ddprint("fail\n");
657 	return -1;
658 }
659 
660 static Hci*
hciprobe(int cardno,int ctlrno)661 hciprobe(int cardno, int ctlrno)
662 {
663 	Hci *hp;
664 	char *type;
665 	char name[64];
666 	static int epnb = 1;	/* guess the endpoint nb. for the controller */
667 
668 	ddprint("hciprobe %d %d\n", cardno, ctlrno);
669 	hp = smalloc(sizeof(Hci));
670 	hp->ctlrno = ctlrno;
671 
672 	if(cardno < 0)
673 		for(cardno = 0; cardno < Nhcis; cardno++){
674 			if(hcitypes[cardno].type == nil)
675 				break;
676 			type = hp->type;
677 			if(type==nil || *type==0)
678 				type = "uhci";
679 			if(cistrcmp(hcitypes[cardno].type, type) == 0)
680 				break;
681 		}
682 
683 	if(cardno >= Nhcis || hcitypes[cardno].type == nil){
684 		free(hp);
685 		return nil;
686 	}
687 	dprint("%s...", hcitypes[cardno].type);
688 	if(hcitypes[cardno].reset(hp) < 0){
689 		free(hp);
690 		return nil;
691 	}
692 
693 	snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
694 	intrenable(hp->irq, hp->interrupt, hp, UNKNOWN, name);
695 
696 	print("#u/usb/ep%d.0: %s: port %#luX irq %d\n",
697 		epnb, hcitypes[cardno].type, hp->port, hp->irq);
698 	epnb++;
699 
700 	return hp;
701 }
702 
703 static void
usbreset(void)704 usbreset(void)
705 {
706 	int cardno, ctlrno;
707 	Hci *hp;
708 
709 	dprint("usbreset\n");
710 
711 	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
712 		if((hp = hciprobe(-1, ctlrno)) != nil)
713 			hcis[ctlrno] = hp;
714 	cardno = ctlrno = 0;
715 	while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
716 		if(hcis[ctlrno] != nil)
717 			ctlrno++;
718 		else{
719 			hp = hciprobe(cardno, ctlrno);
720 			if(hp == nil)
721 				cardno++;
722 			hcis[ctlrno++] = hp;
723 		}
724 	if(hcis[Nhcis-1] != nil)
725 		print("usbreset: bug: Nhcis too small\n");
726 }
727 
728 static int
numbits(uint n)729 numbits(uint n)
730 {
731 	int c = 0;
732 	while(n != 0){
733 		c++;
734 		n = (n-1) & n;
735 	}
736 	return c;
737 }
738 
739 static void
usbinit(void)740 usbinit(void)
741 {
742 	Hci *hp;
743 	int ctlrno;
744 	Ep *d;
745 	char info[40];
746 
747 	dprint("usbinit\n");
748 	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
749 		hp = hcis[ctlrno];
750 		if(hp != nil){
751 			int n;
752 
753 			if(hp->init != nil){
754 				if(waserror()){
755 					print("usbinit: %s: %s\n", hp->type, up->errstr);
756 					continue;
757 				}
758 				hp->init(hp);
759 				poperror();
760 			}
761 
762 			hp->superspeed &= (1<<hp->nports)-1;
763 			n = hp->nports - numbits(hp->superspeed);
764 			if(n > 0){
765 				d = newdev(hp, 1, 1);		/* new LS/FS/HS root hub */
766 				d->maxpkt = 64;
767 				if(hp->highspeed != 0)
768 					d->dev->speed = Highspeed;
769 				d->dev->state = Denabled;	/* although addr == 0 */
770 				snprint(info, sizeof(info), "roothub ports %d", n);
771 				kstrdup(&d->info, info);
772 			}
773 			n = numbits(hp->superspeed);
774 			if(n > 0){
775 				d = newdev(hp, 1, 1);		/* new SS root hub */
776 				d->maxpkt = 512;
777 				d->dev->speed = Superspeed;
778 				d->dev->state = Denabled;	/* although addr == 0 */
779 				snprint(info, sizeof(info), "roothub ports %d", n);
780 				kstrdup(&d->info, info);
781 			}
782 		}
783 	}
784 }
785 
786 static Chan*
usbattach(char * spec)787 usbattach(char *spec)
788 {
789 	return devattach(L'u', spec);
790 }
791 
792 static Walkqid*
usbwalk(Chan * c,Chan * nc,char ** name,int nname)793 usbwalk(Chan *c, Chan *nc, char **name, int nname)
794 {
795 	return devwalk(c, nc, name, nname, nil, 0, usbgen);
796 }
797 
798 static int
usbstat(Chan * c,uchar * db,int n)799 usbstat(Chan *c, uchar *db, int n)
800 {
801 	return devstat(c, db, n, nil, 0, usbgen);
802 }
803 
804 /*
805  * µs for the given transfer, for bandwidth allocation.
806  * This is a very rough worst case for what 5.11.3
807  * of the usb 2.0 spec says.
808  * Also, we are using maxpkt and not actual transfer sizes.
809  * Only when we are sure we
810  * are not exceeding b/w might we consider adjusting it.
811  */
812 static ulong
usbload(int speed,int maxpkt)813 usbload(int speed, int maxpkt)
814 {
815 	enum{ Hostns = 1000, Hubns = 333 };
816 	ulong l;
817 	ulong bs;
818 
819 	l = 0;
820 	bs = 10UL * maxpkt;
821 	switch(speed){
822 	case Highspeed:
823 		l = 55*8*2 + 2 * (3 + bs) + Hostns;
824 		break;
825 	case Fullspeed:
826 		l = 9107 + 84 * (4 + bs) + Hostns;
827 		break;
828 	case Lowspeed:
829 		l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
830 		break;
831 	default:
832 		print("usbload: bad speed %d\n", speed);
833 		/* let it run */
834 	}
835 	return l / 1000UL;	/* in µs */
836 }
837 
838 static Chan*
usbopen(Chan * c,int omode)839 usbopen(Chan *c, int omode)
840 {
841 	int q;
842 	Ep *ep;
843 	int mode;
844 
845 	mode = openmode(omode);
846 	q = QID(c->qid);
847 
848 	if(q >= Qep0dir && qid2epidx(q) < 0)
849 		error(Eio);
850 	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
851 		return devopen(c, omode, nil, 0, usbgen);
852 
853 	ep = getep(qid2epidx(q));
854 	if(ep == nil)
855 		error(Eio);
856 	deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
857 	if(waserror()){
858 		putep(ep);
859 		nexterror();
860 	}
861 	qlock(ep);
862 	if(ep->inuse){
863 		qunlock(ep);
864 		error(Einuse);
865 	}
866 	ep->inuse = 1;
867 	qunlock(ep);
868 	if(waserror()){
869 		ep->inuse = 0;
870 		nexterror();
871 	}
872 	if(mode != OREAD && ep->mode == OREAD)
873 		error(Eperm);
874 	if(mode != OWRITE && ep->mode == OWRITE)
875 		error(Eperm);
876 	if(ep->ttype == Tnone)
877 		error(Enotconf);
878 	ep->clrhalt = 0;
879 	ep->rhrepl = -1;
880 	if(ep->load == 0 && ep->dev->speed != Superspeed)
881 		ep->load = usbload(ep->dev->speed, ep->maxpkt);
882 	ep->hp->epopen(ep);
883 
884 	poperror();	/* ep->inuse */
885 	poperror();	/* don't putep(): ref kept for fid using the ep. */
886 
887 	c->mode = mode;
888 	c->flag |= COPEN;
889 	c->offset = 0;
890 	c->aux = nil;	/* paranoia */
891 	return c;
892 }
893 
894 static void
epclose(Ep * ep)895 epclose(Ep *ep)
896 {
897 	qlock(ep);
898 	if(waserror()){
899 		qunlock(ep);
900 		nexterror();
901 	}
902 	if(ep->inuse){
903 		ep->hp->epclose(ep);
904 		ep->inuse = 0;
905 	}
906 	qunlock(ep);
907 	poperror();
908 }
909 
910 static void
usbclose(Chan * c)911 usbclose(Chan *c)
912 {
913 	int q;
914 	Ep *ep;
915 
916 	q = QID(c->qid);
917 	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
918 		return;
919 
920 	ep = getep(qid2epidx(q));
921 	if(ep == nil)
922 		return;
923 	deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
924 	if(waserror()){
925 		putep(ep);
926 		nexterror();
927 	}
928 	if(c->flag & COPEN){
929 		free(c->aux);
930 		c->aux = nil;
931 		epclose(ep);
932 		putep(ep);	/* release ref kept since usbopen */
933 		c->flag &= ~COPEN;
934 	}
935 	poperror();
936 	putep(ep);
937 }
938 
939 static long
ctlread(Chan * c,void * a,long n,vlong offset)940 ctlread(Chan *c, void *a, long n, vlong offset)
941 {
942 	int q;
943 	char *s;
944 	char *us;
945 	char *se;
946 	Ep *ep;
947 	int i;
948 
949 	q = QID(c->qid);
950 	us = s = smalloc(READSTR);
951 	se = s + READSTR;
952 	if(waserror()){
953 		free(us);
954 		nexterror();
955 	}
956 	if(q == Qctl)
957 		for(i = 0; i < epmax; i++){
958 			ep = getep(i);
959 			if(ep != nil){
960 				if(waserror()){
961 					putep(ep);
962 					nexterror();
963 				}
964 				s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
965 				s = seprintep(s, se, ep, 0);
966 				poperror();
967 			}
968 			putep(ep);
969 		}
970 	else{
971 		ep = getep(qid2epidx(q));
972 		if(ep == nil)
973 			error(Eio);
974 		if(waserror()){
975 			putep(ep);
976 			nexterror();
977 		}
978 		if(c->aux != nil){
979 			/* After a new endpoint request we read
980 			 * the new endpoint name back.
981 			 */
982 			strecpy(s, se, c->aux);
983 			free(c->aux);
984 			c->aux = nil;
985 		}else
986 			seprintep(s, se, ep, 0);
987 		poperror();
988 		putep(ep);
989 	}
990 	n = readstr(offset, a, n, us);
991 	poperror();
992 	free(us);
993 	return n;
994 }
995 
996 /*
997  * Fake root hub emulation.
998  */
999 static long
rhubread(Ep * ep,void * a,long n)1000 rhubread(Ep *ep, void *a, long n)
1001 {
1002 	uchar b[8];
1003 
1004 	if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2 || ep->rhrepl == -1)
1005 		return -1;
1006 
1007 	b[0] = ep->rhrepl;
1008 	b[1] = ep->rhrepl>>8;
1009 	b[2] = ep->rhrepl>>16;
1010 	b[3] = ep->rhrepl>>24;
1011 	b[4] = ep->rhrepl>>32;
1012 	b[5] = ep->rhrepl>>40;
1013 	b[6] = ep->rhrepl>>48;
1014 	b[7] = ep->rhrepl>>56;
1015 
1016 	ep->rhrepl = -1;
1017 
1018 	if(n > sizeof(b))
1019 		n = sizeof(b);
1020 	memmove(a, b, n);
1021 
1022 	return n;
1023 }
1024 
1025 static int
rootport(Ep * ep,int port)1026 rootport(Ep *ep, int port)
1027 {
1028 	Hci *hp;
1029 	Udev *hub;
1030 	uint mask;
1031 	int rootport;
1032 
1033 	hp = ep->hp;
1034 	hub = ep->dev;
1035 	if(!hub->isroot)
1036 		return hub->rootport;
1037 
1038 	mask = hp->superspeed;
1039 	if(hub->speed != Superspeed)
1040 		mask = (1<<hp->nports)-1 & ~mask;
1041 
1042 	for(rootport = 1; mask != 0; rootport++){
1043 		if(mask & 1){
1044 			if(--port == 0)
1045 				return rootport;
1046 		}
1047 		mask >>= 1;
1048 	}
1049 
1050 	return 0;
1051 }
1052 
1053 static long
rhubwrite(Ep * ep,void * a,long n)1054 rhubwrite(Ep *ep, void *a, long n)
1055 {
1056 	uchar *s;
1057 	int cmd;
1058 	int feature;
1059 	int port;
1060 	Hci *hp;
1061 
1062 	if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
1063 		return -1;
1064 	if(n != Rsetuplen)
1065 		error("root hub is a toy hub");
1066 	ep->rhrepl = -1;
1067 	s = a;
1068 	if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
1069 		error("root hub is a toy hub");
1070 	hp = ep->hp;
1071 	cmd = s[Rreq];
1072 	feature = GET2(s+Rvalue);
1073 	port = rootport(ep, GET2(s+Rindex));
1074 	if(port == 0)
1075 		error("bad hub port number");
1076 	switch(feature){
1077 	case Rportenable:
1078 		ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
1079 		break;
1080 	case Rportreset:
1081 		ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
1082 		break;
1083 	case Rgetstatus:
1084 		ep->rhrepl = hp->portstatus(hp, port);
1085 		break;
1086 	default:
1087 		ep->rhrepl = 0;
1088 	}
1089 	return n;
1090 }
1091 
1092 static long
usbread(Chan * c,void * a,long n,vlong offset)1093 usbread(Chan *c, void *a, long n, vlong offset)
1094 {
1095 	int q;
1096 	Ep *ep;
1097 	int nr;
1098 
1099 	q = QID(c->qid);
1100 
1101 	if(c->qid.type == QTDIR)
1102 		return devdirread(c, a, n, nil, 0, usbgen);
1103 
1104 	if(q == Qctl || isqtype(q, Qepctl))
1105 		return ctlread(c, a, n, offset);
1106 
1107 	ep = getep(qid2epidx(q));
1108 	if(ep == nil)
1109 		error(Eio);
1110 	if(waserror()){
1111 		putep(ep);
1112 		nexterror();
1113 	}
1114 	if(ep->dev->state == Ddetach)
1115 		error(Edetach);
1116 	if(ep->mode == OWRITE || ep->inuse == 0)
1117 		error(Ebadusefd);
1118 	switch(ep->ttype){
1119 	case Tnone:
1120 		error("endpoint not configured");
1121 	case Tctl:
1122 		nr = rhubread(ep, a, n);
1123 		if(nr >= 0){
1124 			n = nr;
1125 			break;
1126 		}
1127 		/* else fall */
1128 	default:
1129 		ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
1130 		n = ep->hp->epread(ep, a, n);
1131 		break;
1132 	}
1133 	poperror();
1134 	putep(ep);
1135 	return n;
1136 }
1137 
1138 static long
pow2(int n)1139 pow2(int n)
1140 {
1141 	return 1 << n;
1142 }
1143 
1144 static void
setmaxpkt(Ep * ep,char * s)1145 setmaxpkt(Ep *ep, char* s)
1146 {
1147 	long spp, max;	/* samples per packet */
1148 
1149 	if(ep->dev->speed == Fullspeed)
1150 		spp = (ep->hz * ep->pollival + 999) / 1000;
1151 	else
1152 		spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
1153 	ep->maxpkt = spp * ep->samplesz;
1154 	deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
1155 		" ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
1156 		ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
1157 		spp, ep->maxpkt);
1158 	switch(ep->dev->speed){
1159 	case Fullspeed:
1160 		max = 1024;
1161 		break;
1162 	case Highspeed:
1163 		max = 3*1024;
1164 		break;
1165 	case Superspeed:
1166 		max = 48*1024;
1167 		break;
1168 	default:
1169 		return;
1170 	}
1171 	if(ep->maxpkt*ep->ntds > max){
1172 		print("usb: %s: maxpkt %ld > %ld for %s, truncating\n",
1173 			s, ep->maxpkt*ep->ntds, max, spname[ep->dev->speed]);
1174 		ep->maxpkt = max/ep->ntds;
1175 	}
1176 }
1177 
1178 /*
1179  * Many endpoint ctls. simply update the portable representation
1180  * of the endpoint. The actual controller driver will look
1181  * at them to setup the endpoints as dictated.
1182  */
1183 static long
epctl(Ep * ep,Chan * c,void * a,long n)1184 epctl(Ep *ep, Chan *c, void *a, long n)
1185 {
1186 	int i, l, mode, nb, tt;
1187 	char *b, *s;
1188 	Cmdbuf *cb;
1189 	Cmdtab *ct;
1190 	Ep *nep;
1191 	Udev *d;
1192 	static char *Info = "info ";
1193 
1194 	d = ep->dev;
1195 
1196 	cb = parsecmd(a, n);
1197 	if(waserror()){
1198 		free(cb);
1199 		nexterror();
1200 	}
1201 	ct = lookupcmd(cb, epctls, nelem(epctls));
1202 	if(ct == nil)
1203 		error(Ebadctl);
1204 	i = ct->index;
1205 	if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
1206 		if(ep != ep->ep0)
1207 			error("allowed only on a setup endpoint");
1208 	if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
1209 		if(ep != ep->ep0 && ep->inuse != 0)
1210 			error("must configure before using");
1211 	switch(i){
1212 	case CMnew:
1213 		deprint("usb epctl %s\n", cb->f[0]);
1214 		nb = strtol(cb->f[1], nil, 0);
1215 		if(nb < 0 || nb >= Ndeveps)
1216 			error("bad endpoint number");
1217 		tt = name2ttype(cb->f[2]);
1218 		if(tt == Tnone)
1219 			error("unknown endpoint type");
1220 		mode = name2mode(cb->f[3]);
1221 		if(mode < 0)
1222 			error("unknown i/o mode");
1223 		newdevep(ep, nb, tt, mode);
1224 		break;
1225 	case CMnewdev:
1226 		deprint("usb epctl %s\n", cb->f[0]);
1227 		if(ep != ep->ep0 || d->ishub == 0)
1228 			error("not a hub setup endpoint");
1229 		l = name2speed(cb->f[1]);
1230 		if(l == Nospeed)
1231 			error("speed must be full|low|high|super");
1232 		if(l != d->speed && (l == Superspeed || d->speed == Superspeed))
1233 			error("wrong speed for superspeed hub/device");
1234 		nep = newdev(ep->hp, 0, 0);
1235 		nep->dev->speed = l;
1236 		if(l == Superspeed)
1237 			nep->maxpkt = 512;
1238 		else if(l != Lowspeed)
1239 			nep->maxpkt = 64;	/* assume full speed */
1240 		nep->dev->hub = d->addr;
1241 		nep->dev->port = atoi(cb->f[2]);
1242 		nep->dev->depth = d->depth+1;
1243 		nep->dev->rootport = rootport(ep, nep->dev->port);
1244 		nep->dev->routestr = d->routestr | (((nep->dev->port&15) << 4*nep->dev->depth) >> 4);
1245 		/* next read request will read
1246 		 * the name for the new endpoint
1247 		 */
1248 		l = sizeof(up->genbuf);
1249 		snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
1250 		kstrdup(&c->aux, up->genbuf);
1251 		break;
1252 	case CMhub:
1253 		deprint("usb epctl %s\n", cb->f[0]);
1254 		d->ishub = 1;
1255 		break;
1256 	case CMspeed:
1257 		l = name2speed(cb->f[1]);
1258 		deprint("usb epctl %s %d\n", cb->f[0], l);
1259 		if(l == Nospeed)
1260 			error("speed must be full|low|high|super");
1261 		if(l != d->speed && (l == Superspeed || d->speed == Superspeed))
1262 			error("cannot change speed on superspeed device");
1263 		qlock(ep->ep0);
1264 		d->speed = l;
1265 		qunlock(ep->ep0);
1266 		break;
1267 	case CMmaxpkt:
1268 		l = strtoul(cb->f[1], nil, 0);
1269 		deprint("usb epctl %s %d\n", cb->f[0], l);
1270 		if(l < 1 || l > 1024)
1271 			error("maxpkt not in [1:1024]");
1272 		qlock(ep);
1273 		ep->maxpkt = l;
1274 		qunlock(ep);
1275 		break;
1276 	case CMntds:
1277 		l = strtoul(cb->f[1], nil, 0);
1278 		deprint("usb epctl %s %d\n", cb->f[0], l);
1279 		if(l < 1 || l > 3)
1280 			error("ntds not in [1:3]");
1281 		qlock(ep);
1282 		ep->ntds = l;
1283 		qunlock(ep);
1284 		break;
1285 	case CMpollival:
1286 		if(ep->ttype != Tintr && ep->ttype != Tiso)
1287 			error("not an intr or iso endpoint");
1288 		l = strtoul(cb->f[1], nil, 0);
1289 		deprint("usb epctl %s %d\n", cb->f[0], l);
1290 		if(ep->ttype == Tiso ||
1291 		   (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
1292 			if(l < 1 || l > 16)
1293 				error("pollival power not in [1:16]");
1294 			l = pow2(l-1);
1295 		}else
1296 			if(l < 1 || l > 255)
1297 				error("pollival not in [1:255]");
1298 		qlock(ep);
1299 		ep->pollival = l;
1300 		if(ep->ttype == Tiso)
1301 			setmaxpkt(ep, "pollival");
1302 		qunlock(ep);
1303 		break;
1304 	case CMsamplesz:
1305 		if(ep->ttype != Tiso)
1306 			error("not an iso endpoint");
1307 		l = strtoul(cb->f[1], nil, 0);
1308 		deprint("usb epctl %s %d\n", cb->f[0], l);
1309 		if(l <= 0 || l > 8)
1310 			error("samplesz not in [1:8]");
1311 		qlock(ep);
1312 		ep->samplesz = l;
1313 		setmaxpkt(ep, "samplesz");
1314 		qunlock(ep);
1315 		break;
1316 	case CMhz:
1317 		if(ep->ttype != Tiso)
1318 			error("not an iso endpoint");
1319 		l = strtoul(cb->f[1], nil, 0);
1320 		deprint("usb epctl %s %d\n", cb->f[0], l);
1321 		if(l <= 0 || l > 100000)
1322 			error("hz not in [1:100000]");
1323 		qlock(ep);
1324 		ep->hz = l;
1325 		setmaxpkt(ep, "hz");
1326 		qunlock(ep);
1327 		break;
1328 	case CMclrhalt:
1329 		qlock(ep);
1330 		deprint("usb epctl %s\n", cb->f[0]);
1331 		ep->clrhalt = 1;
1332 		qunlock(ep);
1333 		break;
1334 	case CMinfo:
1335 		deprint("usb epctl %s\n", cb->f[0]);
1336 		l = strlen(Info);
1337 		s = a;
1338 		if(n < l+2 || strncmp(Info, s, l) != 0)
1339 			error(Ebadctl);
1340 		if(n > 1024)
1341 			n = 1024;
1342 		b = smalloc(n);
1343 		memmove(b, s+l, n-l);
1344 		b[n-l] = 0;
1345 		if(b[n-l-1] == '\n')
1346 			b[n-l-1] = 0;
1347 		qlock(ep);
1348 		free(ep->info);
1349 		ep->info = b;
1350 		qunlock(ep);
1351 		break;
1352 	case CMaddress:
1353 		deprint("usb epctl %s\n", cb->f[0]);
1354 		if(ep->dev->addr == 0)
1355 			ep->dev->addr = ep->dev->nb;
1356 		ep->dev->state = Denabled;
1357 		break;
1358 	case CMdetach:
1359 		if(ep->dev->isroot != 0)
1360 			error("can't detach a root hub");
1361 		deprint("usb epctl %s ep%d.%d\n",
1362 			cb->f[0], ep->dev->nb, ep->nb);
1363 		ep->dev->state = Ddetach;
1364 		/* Release file system ref. for its endpoints */
1365 		for(i = 0; i < nelem(ep->dev->eps); i++)
1366 			putep(ep->dev->eps[i]);
1367 		break;
1368 	case CMdebugep:
1369 		if(strcmp(cb->f[1], "on") == 0)
1370 			ep->debug = 1;
1371 		else if(strcmp(cb->f[1], "off") == 0)
1372 			ep->debug = 0;
1373 		else
1374 			ep->debug = strtoul(cb->f[1], nil, 0);
1375 		print("usb: ep%d.%d debug %d\n",
1376 			ep->dev->nb, ep->nb, ep->debug);
1377 		break;
1378 	case CMname:
1379 		deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
1380 		validname(cb->f[1], 0);
1381 		kstrdup(&ep->name, cb->f[1]);
1382 		break;
1383 	case CMtmout:
1384 		deprint("usb epctl %s\n", cb->f[0]);
1385 		if(ep->ttype == Tiso || ep->ttype == Tctl)
1386 			error("ctl ignored for this endpoint type");
1387 		ep->tmout = strtoul(cb->f[1], nil, 0);
1388 		if(ep->tmout != 0 && ep->tmout < Xfertmout)
1389 			ep->tmout = Xfertmout;
1390 		break;
1391 	case CMpreset:
1392 		deprint("usb epctl %s\n", cb->f[0]);
1393 		if(ep->ttype != Tctl)
1394 			error("not a control endpoint");
1395 		if(ep->dev->state != Denabled)
1396 			error("forbidden on devices not enabled");
1397 		ep->dev->state = Dreset;
1398 		break;
1399 	default:
1400 		panic("usb: unknown epctl %d", ct->index);
1401 	}
1402 	free(cb);
1403 	poperror();
1404 	return n;
1405 }
1406 
1407 static long
usbctl(void * a,long n)1408 usbctl(void *a, long n)
1409 {
1410 	Cmdtab *ct;
1411 	Cmdbuf *cb;
1412 	Ep *ep;
1413 	int i;
1414 
1415 	cb = parsecmd(a, n);
1416 	if(waserror()){
1417 		free(cb);
1418 		nexterror();
1419 	}
1420 	ct = lookupcmd(cb, usbctls, nelem(usbctls));
1421 	dprint("usb ctl %s\n", cb->f[0]);
1422 	switch(ct->index){
1423 	case CMdebug:
1424 		if(strcmp(cb->f[1], "on") == 0)
1425 			debug = 1;
1426 		else if(strcmp(cb->f[1], "off") == 0)
1427 			debug = 0;
1428 		else
1429 			debug = strtol(cb->f[1], nil, 0);
1430 		print("usb: debug %d\n", debug);
1431 		for(i = 0; i < epmax; i++)
1432 			if((ep = getep(i)) != nil){
1433 				ep->hp->debug(ep->hp, debug);
1434 				putep(ep);
1435 			}
1436 		break;
1437 	case CMdump:
1438 		dumpeps();
1439 		break;
1440 	}
1441 	free(cb);
1442 	poperror();
1443 	return n;
1444 }
1445 
1446 static long
ctlwrite(Chan * c,void * a,long n)1447 ctlwrite(Chan *c, void *a, long n)
1448 {
1449 	int q;
1450 	Ep *ep;
1451 
1452 	q = QID(c->qid);
1453 	if(q == Qctl)
1454 		return usbctl(a, n);
1455 
1456 	ep = getep(qid2epidx(q));
1457 	if(ep == nil)
1458 		error(Eio);
1459 	if(waserror()){
1460 		putep(ep);
1461 		nexterror();
1462 	}
1463 	if(ep->dev->state == Ddetach)
1464 		error(Edetach);
1465 	if(isqtype(q, Qepctl) && c->aux != nil){
1466 		/* Be sure we don't keep a cloned ep name */
1467 		free(c->aux);
1468 		c->aux = nil;
1469 		error("read, not write, expected");
1470 	}
1471 	n = epctl(ep, c, a, n);
1472 	putep(ep);
1473 	poperror();
1474 	return n;
1475 }
1476 
1477 static long
usbwrite(Chan * c,void * a,long n,vlong off)1478 usbwrite(Chan *c, void *a, long n, vlong off)
1479 {
1480 	int nr, q;
1481 	Ep *ep;
1482 
1483 	if(c->qid.type == QTDIR)
1484 		error(Eisdir);
1485 
1486 	q = QID(c->qid);
1487 
1488 	if(q == Qctl || isqtype(q, Qepctl))
1489 		return ctlwrite(c, a, n);
1490 
1491 	ep = getep(qid2epidx(q));
1492 	if(ep == nil)
1493 		error(Eio);
1494 	if(waserror()){
1495 		putep(ep);
1496 		nexterror();
1497 	}
1498 	if(ep->dev->state == Ddetach)
1499 		error(Edetach);
1500 	if(ep->mode == OREAD || ep->inuse == 0)
1501 		error(Ebadusefd);
1502 
1503 	switch(ep->ttype){
1504 	case Tnone:
1505 		error("endpoint not configured");
1506 	case Tctl:
1507 		nr = rhubwrite(ep, a, n);
1508 		if(nr >= 0){
1509 			n = nr;
1510 			break;
1511 		}
1512 		/* else fall */
1513 	default:
1514 		ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
1515 		ep->hp->epwrite(ep, a, n);
1516 	}
1517 	putep(ep);
1518 	poperror();
1519 	return n;
1520 }
1521 
1522 Block*
usbbread(Chan * c,long n,ulong offset)1523 usbbread(Chan *c, long n, ulong offset)
1524 {
1525 	Block *bp;
1526 
1527 	bp = allocb(n);
1528 	if(bp == 0)
1529 		error(Enomem);
1530 	if(waserror()) {
1531 		freeb(bp);
1532 		nexterror();
1533 	}
1534 	bp->wp += usbread(c, bp->wp, n, offset);
1535 	poperror();
1536 	return bp;
1537 }
1538 
1539 long
usbbwrite(Chan * c,Block * bp,ulong offset)1540 usbbwrite(Chan *c, Block *bp, ulong offset)
1541 {
1542 	long n;
1543 
1544 	if(waserror()) {
1545 		freeb(bp);
1546 		nexterror();
1547 	}
1548 	n = usbwrite(c, bp->rp, BLEN(bp), offset);
1549 	poperror();
1550 	freeb(bp);
1551 
1552 	return n;
1553 }
1554 
1555 void
usbshutdown(void)1556 usbshutdown(void)
1557 {
1558 	Hci *hp;
1559 	int i;
1560 
1561 	for(i = 0; i < Nhcis; i++){
1562 		hp = hcis[i];
1563 		if(hp == nil)
1564 			continue;
1565 		if(hp->shutdown == nil)
1566 			print("#u: no shutdown function for %s\n", hp->type);
1567 		else
1568 			hp->shutdown(hp);
1569 	}
1570 }
1571 
1572 Dev usbdevtab = {
1573 	L'u',
1574 	"usb",
1575 
1576 	usbreset,
1577 	usbinit,
1578 	usbshutdown,
1579 	usbattach,
1580 	usbwalk,
1581 	usbstat,
1582 	usbopen,
1583 	devcreate,
1584 	usbclose,
1585 	usbread,
1586 	usbbread,
1587 	usbwrite,
1588 	usbbwrite,
1589 	devremove,
1590 	devwstat,
1591 };
1592