xref: /plan9-contrib/sys/src/9/loongson/devusb.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
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	"../port/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 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 	[Fullspeed]	"full",
158 	[Lowspeed]	"low",
159 	[Highspeed]	"high",
160 	[Nospeed]	"no",
161 };
162 
163 static int	debug;
164 static Hcitype	hcitypes[Nhcis];
165 static Hci*	hcis[Nhcis];
166 static QLock	epslck;		/* add, del, lookup endpoints */
167 static Ep*	eps[Neps];	/* all endpoints known */
168 static int	epmax;		/* 1 + last endpoint index used  */
169 static int	usbidgen;	/* device address generator */
170 
171 /*
172  * Is there something like this in a library? should it be?
173  */
174 char*
seprintdata(char * s,char * se,uchar * d,int n)175 seprintdata(char *s, char *se, uchar *d, int n)
176 {
177 	int i, l;
178 
179 	s = seprint(s, se, " %#p[%d]: ", d, n);
180 	l = n;
181 	if(l > 10)
182 		l = 10;
183 	for(i=0; i<l; i++)
184 		s = seprint(s, se, " %2.2ux", d[i]);
185 	if(l < n)
186 		s = seprint(s, se, "...");
187 	return s;
188 }
189 
190 static int
name2speed(char * name)191 name2speed(char *name)
192 {
193 	int i;
194 
195 	for(i = 0; i < nelem(spname); i++)
196 		if(strcmp(name, spname[i]) == 0)
197 			return i;
198 	return Nospeed;
199 }
200 
201 static int
name2ttype(char * name)202 name2ttype(char *name)
203 {
204 	int i;
205 
206 	for(i = 0; i < nelem(ttname); i++)
207 		if(strcmp(name, ttname[i]) == 0)
208 			return i;
209 	/* may be a std. USB ep. type */
210 	i = strtol(name, nil, 0);
211 	switch(i+1){
212 	case Tctl:
213 	case Tiso:
214 	case Tbulk:
215 	case Tintr:
216 		return i+1;
217 	default:
218 		return Tnone;
219 	}
220 }
221 
222 static int
name2mode(char * mode)223 name2mode(char *mode)
224 {
225 	int i;
226 
227 	for(i = 0; i < nelem(usbmodename); i++)
228 		if(strcmp(mode, usbmodename[i]) == 0)
229 			return i;
230 	return -1;
231 }
232 
233 static int
qid2epidx(int q)234 qid2epidx(int q)
235 {
236 	q = (q-Qep0dir)/4;
237 	if(q < 0 || q >= epmax || eps[q] == nil)
238 		return -1;
239 	return q;
240 }
241 
242 static int
isqtype(int q,int type)243 isqtype(int q, int type)
244 {
245 	if(q < Qep0dir)
246 		return 0;
247 	q -= Qep0dir;
248 	return (q & 3) == type;
249 }
250 
251 void
addhcitype(char * t,int (* r)(Hci *))252 addhcitype(char* t, int (*r)(Hci*))
253 {
254 	static int ntype;
255 
256 	if(ntype == Nhcis)
257 		panic("too many USB host interface types");
258 	hcitypes[ntype].type = t;
259 	hcitypes[ntype].reset = r;
260 	ntype++;
261 }
262 
263 static char*
seprintep(char * s,char * se,Ep * ep,int all)264 seprintep(char *s, char *se, Ep *ep, int all)
265 {
266 	static char* dsnames[] = { "config", "enabled", "detached", "reset" };
267 	Udev *d;
268 	int i;
269 	int di;
270 
271 	d = ep->dev;
272 
273 	qlock(ep);
274 	if(waserror()){
275 		qunlock(ep);
276 		nexterror();
277 	}
278 	di = ep->dev->nb;
279 	if(all)
280 		s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
281 	s = seprint(s, se, "%s", dsnames[ep->dev->state]);
282 	s = seprint(s, se, " %s", ttname[ep->ttype]);
283 	assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
284 	s = seprint(s, se, " %s", usbmodename[ep->mode]);
285 	s = seprint(s, se, " speed %s", spname[d->speed]);
286 	s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
287 	s = seprint(s, se, " pollival %ld", ep->pollival);
288 	s = seprint(s, se, " samplesz %ld", ep->samplesz);
289 	s = seprint(s, se, " hz %ld", ep->hz);
290 	s = seprint(s, se, " hub %d", ep->dev->hub);
291 	s = seprint(s, se, " port %d", ep->dev->port);
292 	if(ep->inuse)
293 		s = seprint(s, se, " busy");
294 	else
295 		s = seprint(s, se, " idle");
296 	if(all){
297 		s = seprint(s, se, " load %uld", ep->load);
298 		s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
299 		s = seprint(s, se, " idx %d", ep->idx);
300 		if(ep->name != nil)
301 			s = seprint(s, se, " name '%s'", ep->name);
302 		if(ep->tmout != 0)
303 			s = seprint(s, se, " tmout");
304 		if(ep == ep->ep0){
305 			s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
306 			s = seprint(s, se, " eps:");
307 			for(i = 0; i < nelem(d->eps); i++)
308 				if(d->eps[i] != nil)
309 					s = seprint(s, se, " ep%d.%d", di, i);
310 		}
311 	}
312 	if(ep->info != nil)
313 		s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
314 	else
315 		s = seprint(s, se, "\n");
316 	qunlock(ep);
317 	poperror();
318 	return s;
319 }
320 
321 static Ep*
epalloc(Hci * hp)322 epalloc(Hci *hp)
323 {
324 	Ep *ep;
325 	int i;
326 
327 	ep = smalloc(sizeof(Ep));
328 	ep->ref = 1;
329 	qlock(&epslck);
330 	for(i = 0; i < Neps; i++)
331 		if(eps[i] == nil)
332 			break;
333 	if(i == Neps){
334 		qunlock(&epslck);
335 		free(ep);
336 		panic("usb: epalloc: too few endpoints (%d)", Neps);
337 	}
338 	ep->idx = i;
339 	if(epmax <= i)
340 		epmax = i+1;
341 	eps[i] = ep;
342 	ep->hp = hp;
343 	ep->maxpkt = 8;
344 	ep->ntds = 1;
345 	ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
346 	qunlock(&epslck);
347 	return ep;
348 }
349 
350 static Ep*
getep(int i)351 getep(int i)
352 {
353 	Ep *ep;
354 
355 	if(i < 0 || i >= epmax || eps[i] == nil)
356 		return nil;
357 	qlock(&epslck);
358 	ep = eps[i];
359 	if(ep != nil)
360 		incref(ep);
361 	qunlock(&epslck);
362 	return ep;
363 }
364 
365 static void
putep(Ep * ep)366 putep(Ep *ep)
367 {
368 	Udev *d;
369 
370 	if(ep != nil && decref(ep) == 0){
371 		d = ep->dev;
372 		deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
373 		qlock(&epslck);
374 		eps[ep->idx] = nil;
375 		if(ep->idx == epmax-1)
376 			epmax--;
377 		if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
378 			usbidgen--;
379 		qunlock(&epslck);
380 		if(d != nil){
381 			qlock(ep->ep0);
382 			d->eps[ep->nb] = nil;
383 			qunlock(ep->ep0);
384 		}
385 		if(ep->ep0 != ep){
386 			putep(ep->ep0);
387 			ep->ep0 = nil;
388 		}
389 		free(ep->info);
390 		free(ep->name);
391 		free(ep);
392 	}
393 }
394 
395 static void
dumpeps(void)396 dumpeps(void)
397 {
398 	int i;
399 	static char buf[512];
400 	char *s;
401 	char *e;
402 	Ep *ep;
403 
404 	print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
405 	for(i = 0; i < epmax; i++){
406 		s = buf;
407 		e = buf+sizeof(buf);
408 		ep = getep(i);
409 		if(ep != nil){
410 			if(waserror()){
411 				putep(ep);
412 				nexterror();
413 			}
414 			s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
415 			seprintep(s, e, ep, 1);
416 			print("%s", buf);
417 			ep->hp->seprintep(buf, e, ep);
418 			print("%s", buf);
419 			poperror();
420 			putep(ep);
421 		}
422 	}
423 	print("usb dump hcis:\n");
424 	for(i = 0; i < Nhcis; i++)
425 		if(hcis[i] != nil)
426 			hcis[i]->dump(hcis[i]);
427 }
428 
429 static int
newusbid(Hci *)430 newusbid(Hci *)
431 {
432 	int id;
433 
434 	qlock(&epslck);
435 	id = ++usbidgen;
436 	if(id >= 0x7F)
437 		print("#u: too many device addresses; reuse them more\n");
438 	qunlock(&epslck);
439 	return id;
440 }
441 
442 /*
443  * Create endpoint 0 for a new device
444  */
445 static Ep*
newdev(Hci * hp,int ishub,int isroot)446 newdev(Hci *hp, int ishub, int isroot)
447 {
448 	Ep *ep;
449 	Udev *d;
450 
451 	ep = epalloc(hp);
452 	d = ep->dev = smalloc(sizeof(Udev));
453 	d->nb = newusbid(hp);
454 	d->eps[0] = ep;
455 	ep->nb = 0;
456 	ep->toggle[0] = ep->toggle[1] = 0;
457 	d->ishub = ishub;
458 	d->isroot = isroot;
459 	if(hp->highspeed != 0)
460 		d->speed = Highspeed;
461 	else
462 		d->speed = Fullspeed;
463 	d->state = Dconfig;		/* address not yet set */
464 	ep->dev = d;
465 	ep->ep0 = ep;			/* no ref counted here */
466 	ep->ttype = Tctl;
467 	ep->tmout = Xfertmout;
468 	ep->mode = ORDWR;
469 	dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
470 	return ep;
471 }
472 
473 /*
474  * Create a new endpoint for the device
475  * accessed via the given endpoint 0.
476  */
477 static Ep*
newdevep(Ep * ep,int i,int tt,int mode)478 newdevep(Ep *ep, int i, int tt, int mode)
479 {
480 	Ep *nep;
481 	Udev *d;
482 
483 	d = ep->dev;
484 	if(d->eps[i] != nil)
485 		error("endpoint already in use");
486 	nep = epalloc(ep->hp);
487 	incref(ep);
488 	d->eps[i] = nep;
489 	nep->nb = i;
490 	nep->toggle[0] = nep->toggle[1] = 0;
491 	nep->ep0 = ep;
492 	nep->dev = ep->dev;
493 	nep->mode = mode;
494 	nep->ttype = tt;
495 	nep->debug = ep->debug;
496 	/* set defaults */
497 	switch(tt){
498 	case Tctl:
499 		nep->tmout = Xfertmout;
500 		break;
501 	case Tintr:
502 		nep->pollival = 10;
503 		break;
504 	case Tiso:
505 		nep->tmout = Xfertmout;
506 		nep->pollival = 10;
507 		nep->samplesz = 4;
508 		nep->hz = 44100;
509 		break;
510 	}
511 	deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
512 	return ep;
513 }
514 
515 static int
epdataperm(int mode)516 epdataperm(int mode)
517 {
518 
519 	switch(mode){
520 	case OREAD:
521 		return 0440|DMEXCL;
522 		break;
523 	case OWRITE:
524 		return 0220|DMEXCL;
525 		break;
526 	default:
527 		return 0660|DMEXCL;
528 	}
529 }
530 
531 static int
usbgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)532 usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
533 {
534 	Qid q;
535 	Dirtab *dir;
536 	int perm;
537 	char *se;
538 	Ep *ep;
539 	int nb;
540 	int mode;
541 
542 //	if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
543 	if(s == DEVDOTDOT){
544 		if(QID(c->qid) <= Qusbdir){
545 			mkqid(&q, Qdir, 0, QTDIR);
546 			devdir(c, q, "#u", 0, eve, 0555, dp);
547 		}else{
548 			mkqid(&q, Qusbdir, 0, QTDIR);
549 			devdir(c, q, "usb", 0, eve, 0555, dp);
550 		}
551 //		if(0)ddprint("ok\n");
552 		return 1;
553 	}
554 
555 	switch(QID(c->qid)){
556 	case Qdir:				/* list #u */
557 		if(s == 0){
558 			mkqid(&q, Qusbdir, 0, QTDIR);
559 			devdir(c, q, "usb", 0, eve, 0555, dp);
560 //			if(0)ddprint("ok\n");
561 			return 1;
562 		}
563 		s--;
564 		if(s < 0 || s >= epmax)
565 			goto Fail;
566 		ep = getep(s);
567 		if(ep == nil || ep->name == nil){
568 			if(ep != nil)
569 				putep(ep);
570 //			if(0)ddprint("skip\n");
571 			return 0;
572 		}
573 		if(waserror()){
574 			putep(ep);
575 			nexterror();
576 		}
577 		mkqid(&q, Qep0io+s*4, 0, QTFILE);
578 		devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
579 		putep(ep);
580 		poperror();
581 //		if(0)ddprint("ok\n");
582 		return 1;
583 
584 	case Qusbdir:				/* list #u/usb */
585 	Usbdir:
586 		if(s < nelem(usbdir)){
587 			dir = &usbdir[s];
588 			mkqid(&q, dir->qid.path, 0, QTFILE);
589 			devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
590 //			if(0)ddprint("ok\n");
591 			return 1;
592 		}
593 		s -= nelem(usbdir);
594 		if(s < 0 || s >= epmax)
595 			goto Fail;
596 		ep = getep(s);
597 		if(ep == nil){
598 //			if(0)ddprint("skip\n");
599 			return 0;
600 		}
601 		if(waserror()){
602 			putep(ep);
603 			nexterror();
604 		}
605 		se = up->genbuf+sizeof(up->genbuf);
606 		seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
607 		mkqid(&q, Qep0dir+4*s, 0, QTDIR);
608 		putep(ep);
609 		poperror();
610 		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
611 //		if(0)ddprint("ok\n");
612 		return 1;
613 
614 	case Qctl:
615 		s = 0;
616 		goto Usbdir;
617 
618 	default:				/* list #u/usb/epN.M */
619 		nb = qid2epidx(QID(c->qid));
620 		ep = getep(nb);
621 		if(ep == nil)
622 			goto Fail;
623 		mode = ep->mode;
624 		putep(ep);
625 		if(isqtype(QID(c->qid), Qepdir)){
626 		Epdir:
627 			switch(s){
628 			case 0:
629 				mkqid(&q, Qep0io+nb*4, 0, QTFILE);
630 				perm = epdataperm(mode);
631 				devdir(c, q, "data", 0, eve, perm, dp);
632 				break;
633 			case 1:
634 				mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
635 				devdir(c, q, "ctl", 0, eve, 0664, dp);
636 				break;
637 			default:
638 				goto Fail;
639 			}
640 		}else if(isqtype(QID(c->qid), Qepctl)){
641 			s = 1;
642 			goto Epdir;
643 		}else{
644 			s = 0;
645 			goto Epdir;
646 		}
647 //		if(0)ddprint("ok\n");
648 		return 1;
649 	}
650 Fail:
651 //	if(0)ddprint("fail\n");
652 	return -1;
653 }
654 
655 static Hci*
hciprobe(int cardno,int ctlrno)656 hciprobe(int cardno, int ctlrno)
657 {
658 	Hci *hp;
659 	char *type;
660 	char name[64];
661 	static int epnb = 1;	/* guess the endpoint nb. for the controller */
662 
663 	ddprint("hciprobe %d %d\n", cardno, ctlrno);
664 	hp = smalloc(sizeof(Hci));
665 	hp->ctlrno = ctlrno;
666 	hp->tbdf = BUSUNKNOWN;
667 
668 	if(cardno < 0)
669 		for(cardno = 0; cardno < Nhcis; cardno++){
670 			if(hcitypes[cardno].type == nil)
671 				break;
672 			type = hp->type;
673 			if(type==nil || *type==0)
674 				type = "uhci";
675 			if(cistrcmp(hcitypes[cardno].type, type) == 0)
676 				break;
677 		}
678 
679 	if(cardno >= Nhcis || hcitypes[cardno].type == nil){
680 		free(hp);
681 		return nil;
682 	}
683 	dprint("%s...", hcitypes[cardno].type);
684 	if(hcitypes[cardno].reset(hp) < 0){
685 		free(hp);
686 		return nil;
687 	}
688 
689 	snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
690 	intrenable(hp->irq, hp->interrupt, hp, pcisubirq(hp->tbdf));
691 
692 	print("#u/usb/ep%d.0: %s: port 0x%lux irq %d\n",
693 		epnb, hcitypes[cardno].type, hp->port, hp->irq);
694 	epnb++;
695 	return hp;
696 }
697 
698 static void
usbreset(void)699 usbreset(void)
700 {
701 	int cardno, ctlrno;
702 	Hci *hp;
703 
704 	if(getconf("*nousbprobe"))
705 		return;
706 	dprint("usbreset\n");
707 
708 	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
709 		if((hp = hciprobe(-1, ctlrno)) != nil)
710 			hcis[ctlrno] = hp;
711 	cardno = ctlrno = 0;
712 	while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
713 		if(hcis[ctlrno] != nil)
714 			ctlrno++;
715 		else{
716 			hp = hciprobe(cardno, ctlrno);
717 			if(hp == nil)
718 				cardno++;
719 			hcis[ctlrno++] = hp;
720 		}
721 	if(hcis[Nhcis-1] != nil)
722 		print("usbreset: bug: Nhcis (%d) too small\n", Nhcis);
723 }
724 
725 static void
usbinit(void)726 usbinit(void)
727 {
728 	Hci *hp;
729 	int ctlrno;
730 	Ep *d;
731 	char info[40];
732 
733 	dprint("usbinit\n");
734 	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
735 		hp = hcis[ctlrno];
736 		if(hp != nil){
737 			if(hp->init != nil)
738 				hp->init(hp);
739 			d = newdev(hp, 1, 1);		/* new root hub */
740 			d->dev->state = Denabled;	/* although addr == 0 */
741 			d->maxpkt = 64;
742 			snprint(info, sizeof(info), "ports %d", hp->nports);
743 			kstrdup(&d->info, info);
744 		}
745 	}
746 }
747 
748 static Chan*
usbattach(char * spec)749 usbattach(char *spec)
750 {
751 	return devattach(L'u', spec);
752 }
753 
754 static Walkqid*
usbwalk(Chan * c,Chan * nc,char ** name,int nname)755 usbwalk(Chan *c, Chan *nc, char **name, int nname)
756 {
757 	return devwalk(c, nc, name, nname, nil, 0, usbgen);
758 }
759 
760 static int
usbstat(Chan * c,uchar * db,int n)761 usbstat(Chan *c, uchar *db, int n)
762 {
763 	return devstat(c, db, n, nil, 0, usbgen);
764 }
765 
766 /*
767  * µs for the given transfer, for bandwidth allocation.
768  * This is a very rough worst case for what 5.11.3
769  * of the usb 2.0 spec says.
770  * Also, we are using maxpkt and not actual transfer sizes.
771  * Only when we are sure we
772  * are not exceeding b/w might we consider adjusting it.
773  */
774 static ulong
usbload(int speed,int maxpkt)775 usbload(int speed, int maxpkt)
776 {
777 	enum{ Hostns = 1000, Hubns = 333 };
778 	ulong l;
779 	ulong bs;
780 
781 	l = 0;
782 	bs = 10UL * maxpkt;
783 	switch(speed){
784 	case Highspeed:
785 		l = 55*8*2 + 2 * (3 + bs) + Hostns;
786 		break;
787 	case Fullspeed:
788 		l = 9107 + 84 * (4 + bs) + Hostns;
789 		break;
790 	case Lowspeed:
791 		l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
792 		break;
793 	default:
794 		print("usbload: bad speed %d\n", speed);
795 		/* let it run */
796 	}
797 	return l / 1000UL;	/* in µs */
798 }
799 
800 static Chan*
usbopen(Chan * c,int omode)801 usbopen(Chan *c, int omode)
802 {
803 	int q;
804 	Ep *ep;
805 	int mode;
806 
807 	mode = openmode(omode);
808 	q = QID(c->qid);
809 
810 	if(q >= Qep0dir && qid2epidx(q) < 0)
811 		error(Eio);
812 	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
813 		return devopen(c, omode, nil, 0, usbgen);
814 
815 	ep = getep(qid2epidx(q));
816 	if(ep == nil)
817 		error(Eio);
818 	deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
819 	if(waserror()){
820 		putep(ep);
821 		nexterror();
822 	}
823 	qlock(ep);
824 	if(ep->inuse){
825 		qunlock(ep);
826 		error(Einuse);
827 	}
828 	ep->inuse = 1;
829 	qunlock(ep);
830 	if(waserror()){
831 		ep->inuse = 0;
832 		nexterror();
833 	}
834 	if(mode != OREAD && ep->mode == OREAD)
835 		error(Eperm);
836 	if(mode != OWRITE && ep->mode == OWRITE)
837 		error(Eperm);
838 	if(ep->ttype == Tnone)
839 		error(Enotconf);
840 	ep->clrhalt = 0;
841 	ep->rhrepl = -1;
842 	if(ep->load == 0)
843 		ep->load = usbload(ep->dev->speed, ep->maxpkt);
844 	ep->hp->epopen(ep);
845 
846 	poperror();	/* ep->inuse */
847 	poperror();	/* don't putep(): ref kept for fid using the ep. */
848 
849 	c->mode = mode;
850 	c->flag |= COPEN;
851 	c->offset = 0;
852 	c->aux = nil;	/* paranoia */
853 	return c;
854 }
855 
856 static void
epclose(Ep * ep)857 epclose(Ep *ep)
858 {
859 	qlock(ep);
860 	if(waserror()){
861 		qunlock(ep);
862 		nexterror();
863 	}
864 	if(ep->inuse){
865 		ep->hp->epclose(ep);
866 		ep->inuse = 0;
867 	}
868 	qunlock(ep);
869 	poperror();
870 }
871 
872 static void
usbclose(Chan * c)873 usbclose(Chan *c)
874 {
875 	int q;
876 	Ep *ep;
877 
878 	q = QID(c->qid);
879 	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
880 		return;
881 
882 	ep = getep(qid2epidx(q));
883 	if(ep == nil)
884 		return;
885 	deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
886 	if(waserror()){
887 		putep(ep);
888 		nexterror();
889 	}
890 	if(c->flag & COPEN){
891 		free(c->aux);
892 		c->aux = nil;
893 		epclose(ep);
894 		putep(ep);	/* release ref kept since usbopen */
895 		c->flag &= ~COPEN;
896 	}
897 	poperror();
898 	putep(ep);
899 }
900 
901 static long
ctlread(Chan * c,void * a,long n,vlong offset)902 ctlread(Chan *c, void *a, long n, vlong offset)
903 {
904 	int q;
905 	char *s;
906 	char *us;
907 	char *se;
908 	Ep *ep;
909 	int i;
910 
911 	q = QID(c->qid);
912 	us = s = smalloc(READSTR);
913 	se = s + READSTR;
914 	if(waserror()){
915 		free(us);
916 		nexterror();
917 	}
918 	if(q == Qctl)
919 		for(i = 0; i < epmax; i++){
920 			ep = getep(i);
921 			if(ep != nil){
922 				if(waserror()){
923 					putep(ep);
924 					nexterror();
925 				}
926 				s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
927 				s = seprintep(s, se, ep, 0);
928 				poperror();
929 			}
930 			putep(ep);
931 		}
932 	else{
933 		ep = getep(qid2epidx(q));
934 		if(ep == nil)
935 			error(Eio);
936 		if(waserror()){
937 			putep(ep);
938 			nexterror();
939 		}
940 		if(c->aux != nil){
941 			/* After a new endpoint request we read
942 			 * the new endpoint name back.
943 			 */
944 			strecpy(s, se, c->aux);
945 			free(c->aux);
946 			c->aux = nil;
947 		}else
948 			seprintep(s, se, ep, 0);
949 		poperror();
950 		putep(ep);
951 	}
952 	n = readstr(offset, a, n, us);
953 	poperror();
954 	free(us);
955 	return n;
956 }
957 
958 /*
959  * Fake root hub emulation.
960  */
961 static long
rhubread(Ep * ep,void * a,long n)962 rhubread(Ep *ep, void *a, long n)
963 {
964 	char *b;
965 
966 	if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
967 		return -1;
968 	if(ep->rhrepl < 0)
969 		return -1;
970 
971 	b = a;
972 	memset(b, 0, n);
973 	PUT2(b, ep->rhrepl);
974 	ep->rhrepl = -1;
975 	return n;
976 }
977 
978 static long
rhubwrite(Ep * ep,void * a,long n)979 rhubwrite(Ep *ep, void *a, long n)
980 {
981 	uchar *s;
982 	int cmd;
983 	int feature;
984 	int port;
985 	Hci *hp;
986 
987 	if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
988 		return -1;
989 	if(n != Rsetuplen)
990 		error("root hub is a toy hub");
991 	ep->rhrepl = -1;
992 	s = a;
993 	if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
994 		error("root hub is a toy hub");
995 	hp = ep->hp;
996 	cmd = s[Rreq];
997 	feature = GET2(s+Rvalue);
998 	port = GET2(s+Rindex);
999 	if(port < 1 || port > hp->nports)
1000 		error("bad hub port number");
1001 	switch(feature){
1002 	case Rportenable:
1003 		ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
1004 		break;
1005 	case Rportreset:
1006 		ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
1007 		break;
1008 	case Rgetstatus:
1009 		ep->rhrepl = hp->portstatus(hp, port);
1010 		break;
1011 	default:
1012 		ep->rhrepl = 0;
1013 	}
1014 	return n;
1015 }
1016 
1017 static long
usbread(Chan * c,void * a,long n,vlong offset)1018 usbread(Chan *c, void *a, long n, vlong offset)
1019 {
1020 	int q;
1021 	Ep *ep;
1022 	int nr;
1023 
1024 	q = QID(c->qid);
1025 
1026 	if(c->qid.type == QTDIR)
1027 		return devdirread(c, a, n, nil, 0, usbgen);
1028 
1029 	if(q == Qctl || isqtype(q, Qepctl))
1030 		return ctlread(c, a, n, offset);
1031 
1032 	ep = getep(qid2epidx(q));
1033 	if(ep == nil)
1034 		error(Eio);
1035 	if(waserror()){
1036 		putep(ep);
1037 		nexterror();
1038 	}
1039 	if(ep->dev->state == Ddetach)
1040 		error(Edetach);
1041 	if(ep->mode == OWRITE || ep->inuse == 0)
1042 		error(Ebadusefd);
1043 	switch(ep->ttype){
1044 	case Tnone:
1045 		error("endpoint not configured");
1046 	case Tctl:
1047 		nr = rhubread(ep, a, n);
1048 		if(nr >= 0){
1049 			n = nr;
1050 			break;
1051 		}
1052 		/* else fall */
1053 	default:
1054 		ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
1055 		n = ep->hp->epread(ep, a, n);
1056 		break;
1057 	}
1058 	poperror();
1059 	putep(ep);
1060 	return n;
1061 }
1062 
1063 static long
pow2(int n)1064 pow2(int n)
1065 {
1066 	return 1 << n;
1067 }
1068 
1069 static void
setmaxpkt(Ep * ep,char * s)1070 setmaxpkt(Ep *ep, char* s)
1071 {
1072 	long spp;	/* samples per packet */
1073 
1074 	if(ep->dev->speed == Highspeed)
1075 		spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
1076 	else
1077 		spp = (ep->hz * ep->pollival + 999) / 1000;
1078 	ep->maxpkt = spp * ep->samplesz;
1079 	deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
1080 		" ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
1081 		ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
1082 		spp, ep->maxpkt);
1083 	if(ep->maxpkt > 1024){
1084 		print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
1085 		ep->maxpkt = 1024;
1086 	}
1087 }
1088 
1089 /*
1090  * Many endpoint ctls. simply update the portable representation
1091  * of the endpoint. The actual controller driver will look
1092  * at them to setup the endpoints as dictated.
1093  */
1094 static long
epctl(Ep * ep,Chan * c,void * a,long n)1095 epctl(Ep *ep, Chan *c, void *a, long n)
1096 {
1097 	int i, l, mode, nb, tt;
1098 	char *b, *s;
1099 	Cmdbuf *cb;
1100 	Cmdtab *ct;
1101 	Ep *nep;
1102 	Udev *d;
1103 	static char *Info = "info ";
1104 
1105 	d = ep->dev;
1106 
1107 	cb = parsecmd(a, n);
1108 	if(waserror()){
1109 		free(cb);
1110 		nexterror();
1111 	}
1112 	ct = lookupcmd(cb, epctls, nelem(epctls));
1113 	if(ct == nil)
1114 		error(Ebadctl);
1115 	i = ct->index;
1116 	if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
1117 		if(ep != ep->ep0)
1118 			error("allowed only on a setup endpoint");
1119 	if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
1120 		if(ep != ep->ep0 && ep->inuse != 0)
1121 			error("must configure before using");
1122 	switch(i){
1123 	case CMnew:
1124 		deprint("usb epctl %s\n", cb->f[0]);
1125 		nb = strtol(cb->f[1], nil, 0);
1126 		if(nb < 0 || nb >= Ndeveps)
1127 			error("bad endpoint number");
1128 		tt = name2ttype(cb->f[2]);
1129 		if(tt == Tnone)
1130 			error("unknown endpoint type");
1131 		mode = name2mode(cb->f[3]);
1132 		if(mode < 0)
1133 			error("unknown i/o mode");
1134 		newdevep(ep, nb, tt, mode);
1135 		break;
1136 	case CMnewdev:
1137 		deprint("usb epctl %s\n", cb->f[0]);
1138 		if(ep != ep->ep0 || d->ishub == 0)
1139 			error("not a hub setup endpoint");
1140 		l = name2speed(cb->f[1]);
1141 		if(l == Nospeed)
1142 			error("speed must be full|low|high");
1143 		nep = newdev(ep->hp, 0, 0);
1144 		nep->dev->speed = l;
1145 		if(nep->dev->speed  != Lowspeed)
1146 			nep->maxpkt = 64;	/* assume full speed */
1147 		nep->dev->hub = d->nb;
1148 		nep->dev->port = atoi(cb->f[2]);
1149 		/* next read request will read
1150 		 * the name for the new endpoint
1151 		 */
1152 		l = sizeof(up->genbuf);
1153 		snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
1154 		kstrdup(&c->aux, up->genbuf);
1155 		break;
1156 	case CMhub:
1157 		deprint("usb epctl %s\n", cb->f[0]);
1158 		d->ishub = 1;
1159 		break;
1160 	case CMspeed:
1161 		l = name2speed(cb->f[1]);
1162 		deprint("usb epctl %s %d\n", cb->f[0], l);
1163 		if(l == Nospeed)
1164 			error("speed must be full|low|high");
1165 		qlock(ep->ep0);
1166 		d->speed = l;
1167 		qunlock(ep->ep0);
1168 		break;
1169 	case CMmaxpkt:
1170 		l = strtoul(cb->f[1], nil, 0);
1171 		deprint("usb epctl %s %d\n", cb->f[0], l);
1172 		if(l < 1 || l > 1024)
1173 			error("maxpkt not in [1:1024]");
1174 		qlock(ep);
1175 		ep->maxpkt = l;
1176 		qunlock(ep);
1177 		break;
1178 	case CMntds:
1179 		l = strtoul(cb->f[1], nil, 0);
1180 		deprint("usb epctl %s %d\n", cb->f[0], l);
1181 		if(l < 1 || l > 3)
1182 			error("ntds not in [1:3]");
1183 		qlock(ep);
1184 		ep->ntds = l;
1185 		qunlock(ep);
1186 		break;
1187 	case CMpollival:
1188 		if(ep->ttype != Tintr && ep->ttype != Tiso)
1189 			error("not an intr or iso endpoint");
1190 		l = strtoul(cb->f[1], nil, 0);
1191 		deprint("usb epctl %s %d\n", cb->f[0], l);
1192 		if(ep->ttype == Tiso ||
1193 		   (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
1194 			if(l < 1 || l > 16)
1195 				error("pollival power not in [1:16]");
1196 			l = pow2(l-1);
1197 		}else
1198 			if(l < 1 || l > 255)
1199 				error("pollival not in [1:255]");
1200 		qlock(ep);
1201 		ep->pollival = l;
1202 		if(ep->ttype == Tiso)
1203 			setmaxpkt(ep, "pollival");
1204 		qunlock(ep);
1205 		break;
1206 	case CMsamplesz:
1207 		if(ep->ttype != Tiso)
1208 			error("not an iso endpoint");
1209 		l = strtoul(cb->f[1], nil, 0);
1210 		deprint("usb epctl %s %d\n", cb->f[0], l);
1211 		if(l <= 0 || l > 8)
1212 			error("samplesz not in [1:8]");
1213 		qlock(ep);
1214 		ep->samplesz = l;
1215 		setmaxpkt(ep, "samplesz");
1216 		qunlock(ep);
1217 		break;
1218 	case CMhz:
1219 		if(ep->ttype != Tiso)
1220 			error("not an iso endpoint");
1221 		l = strtoul(cb->f[1], nil, 0);
1222 		deprint("usb epctl %s %d\n", cb->f[0], l);
1223 		if(l <= 0 || l > 100000)
1224 			error("hz not in [1:100000]");
1225 		qlock(ep);
1226 		ep->hz = l;
1227 		setmaxpkt(ep, "hz");
1228 		qunlock(ep);
1229 		break;
1230 	case CMclrhalt:
1231 		qlock(ep);
1232 		deprint("usb epctl %s\n", cb->f[0]);
1233 		ep->clrhalt = 1;
1234 		qunlock(ep);
1235 		break;
1236 	case CMinfo:
1237 		deprint("usb epctl %s\n", cb->f[0]);
1238 		l = strlen(Info);
1239 		s = a;
1240 		if(n < l+2 || strncmp(Info, s, l) != 0)
1241 			error(Ebadctl);
1242 		if(n > 1024)
1243 			n = 1024;
1244 		b = smalloc(n);
1245 		memmove(b, s+l, n-l);
1246 		b[n-l] = 0;
1247 		if(b[n-l-1] == '\n')
1248 			b[n-l-1] = 0;
1249 		qlock(ep);
1250 		free(ep->info);
1251 		ep->info = b;
1252 		qunlock(ep);
1253 		break;
1254 	case CMaddress:
1255 		deprint("usb epctl %s\n", cb->f[0]);
1256 		ep->dev->state = Denabled;
1257 		break;
1258 	case CMdetach:
1259 		if(ep->dev->isroot != 0)
1260 			error("can't detach a root hub");
1261 		deprint("usb epctl %s ep%d.%d\n",
1262 			cb->f[0], ep->dev->nb, ep->nb);
1263 		ep->dev->state = Ddetach;
1264 		/* Release file system ref. for its endpoints */
1265 		for(i = 0; i < nelem(ep->dev->eps); i++)
1266 			putep(ep->dev->eps[i]);
1267 		break;
1268 	case CMdebugep:
1269 		if(strcmp(cb->f[1], "on") == 0)
1270 			ep->debug = 1;
1271 		else if(strcmp(cb->f[1], "off") == 0)
1272 			ep->debug = 0;
1273 		else
1274 			ep->debug = strtoul(cb->f[1], nil, 0);
1275 		print("usb: ep%d.%d debug %d\n",
1276 			ep->dev->nb, ep->nb, ep->debug);
1277 		break;
1278 	case CMname:
1279 		deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
1280 		validname(cb->f[1], 0);
1281 		kstrdup(&ep->name, cb->f[1]);
1282 		break;
1283 	case CMtmout:
1284 		deprint("usb epctl %s\n", cb->f[0]);
1285 		if(ep->ttype == Tiso || ep->ttype == Tctl)
1286 			error("ctl ignored for this endpoint type");
1287 		ep->tmout = strtoul(cb->f[1], nil, 0);
1288 		if(ep->tmout != 0 && ep->tmout < Xfertmout)
1289 			ep->tmout = Xfertmout;
1290 		break;
1291 	case CMpreset:
1292 		deprint("usb epctl %s\n", cb->f[0]);
1293 		if(ep->ttype != Tctl)
1294 			error("not a control endpoint");
1295 		if(ep->dev->state != Denabled)
1296 			error("forbidden on devices not enabled");
1297 		ep->dev->state = Dreset;
1298 		break;
1299 	default:
1300 		panic("usb: unknown epctl %d", ct->index);
1301 	}
1302 	free(cb);
1303 	poperror();
1304 	return n;
1305 }
1306 
1307 static long
usbctl(void * a,long n)1308 usbctl(void *a, long n)
1309 {
1310 	Cmdtab *ct;
1311 	Cmdbuf *cb;
1312 	Ep *ep;
1313 	int i;
1314 
1315 	cb = parsecmd(a, n);
1316 	if(waserror()){
1317 		free(cb);
1318 		nexterror();
1319 	}
1320 	ct = lookupcmd(cb, usbctls, nelem(usbctls));
1321 	dprint("usb ctl %s\n", cb->f[0]);
1322 	switch(ct->index){
1323 	case CMdebug:
1324 		if(strcmp(cb->f[1], "on") == 0)
1325 			debug = 1;
1326 		else if(strcmp(cb->f[1], "off") == 0)
1327 			debug = 0;
1328 		else
1329 			debug = strtol(cb->f[1], nil, 0);
1330 		print("usb: debug %d\n", debug);
1331 		for(i = 0; i < epmax; i++)
1332 			if((ep = getep(i)) != nil){
1333 				ep->hp->debug(ep->hp, debug);
1334 				putep(ep);
1335 			}
1336 		break;
1337 	case CMdump:
1338 		dumpeps();
1339 		break;
1340 	}
1341 	free(cb);
1342 	poperror();
1343 	return n;
1344 }
1345 
1346 static long
ctlwrite(Chan * c,void * a,long n)1347 ctlwrite(Chan *c, void *a, long n)
1348 {
1349 	int q;
1350 	Ep *ep;
1351 
1352 	q = QID(c->qid);
1353 	if(q == Qctl)
1354 		return usbctl(a, n);
1355 
1356 	ep = getep(qid2epidx(q));
1357 	if(ep == nil)
1358 		error(Eio);
1359 	if(waserror()){
1360 		putep(ep);
1361 		nexterror();
1362 	}
1363 	if(ep->dev->state == Ddetach)
1364 		error(Edetach);
1365 	if(isqtype(q, Qepctl) && c->aux != nil){
1366 		/* Be sure we don't keep a cloned ep name */
1367 		free(c->aux);
1368 		c->aux = nil;
1369 		error("read, not write, expected");
1370 	}
1371 	n = epctl(ep, c, a, n);
1372 	putep(ep);
1373 	poperror();
1374 	return n;
1375 }
1376 
1377 static long
usbwrite(Chan * c,void * a,long n,vlong off)1378 usbwrite(Chan *c, void *a, long n, vlong off)
1379 {
1380 	int nr, q;
1381 	Ep *ep;
1382 
1383 	if(c->qid.type == QTDIR)
1384 		error(Eisdir);
1385 
1386 	q = QID(c->qid);
1387 
1388 	if(q == Qctl || isqtype(q, Qepctl))
1389 		return ctlwrite(c, a, n);
1390 
1391 	ep = getep(qid2epidx(q));
1392 	if(ep == nil)
1393 		error(Eio);
1394 	if(waserror()){
1395 		putep(ep);
1396 		nexterror();
1397 	}
1398 	if(ep->dev->state == Ddetach)
1399 		error(Edetach);
1400 	if(ep->mode == OREAD || ep->inuse == 0)
1401 		error(Ebadusefd);
1402 
1403 	switch(ep->ttype){
1404 	case Tnone:
1405 		error("endpoint not configured");
1406 	case Tctl:
1407 		nr = rhubwrite(ep, a, n);
1408 		if(nr >= 0){
1409 			n = nr;
1410 			break;
1411 		}
1412 		/* else fall */
1413 	default:
1414 		ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
1415 		ep->hp->epwrite(ep, a, n);
1416 	}
1417 	putep(ep);
1418 	poperror();
1419 	return n;
1420 }
1421 
1422 void
usbshutdown(void)1423 usbshutdown(void)
1424 {
1425 	Hci *hp;
1426 	int i;
1427 
1428 	for(i = 0; i < Nhcis; i++){
1429 		hp = hcis[i];
1430 		if(hp == nil)
1431 			continue;
1432 		if(hp->shutdown == nil)
1433 			print("#u: no shutdown function for %s\n", hp->type);
1434 		else
1435 			hp->shutdown(hp);
1436 	}
1437 }
1438 
1439 Dev usbdevtab = {
1440 	L'u',
1441 	"usb",
1442 
1443 	usbreset,
1444 	usbinit,
1445 	usbshutdown,
1446 	usbattach,
1447 	usbwalk,
1448 	usbstat,
1449 	usbopen,
1450 	devcreate,
1451 	usbclose,
1452 	usbread,
1453 	devbread,
1454 	usbwrite,
1455 	devbwrite,
1456 	devremove,
1457 	devwstat,
1458 };
1459