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