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