1 /* 2 * USB device and framework. 3 * usb*.c contains host controller interface drivers. 4 */ 5 #include "u.h" 6 #include "../port/lib.h" 7 #include "mem.h" 8 #include "dat.h" 9 #include "fns.h" 10 #include "io.h" 11 #include "../port/error.h" 12 13 #include "usb.h" 14 15 static int debug = 0; 16 17 #define Chatty 1 18 #define DPRINT if(Chatty)print 19 #define XPRINT if(debug)iprint 20 21 Usbhost* usbhost[MaxUsb]; 22 23 static char *devstates[] = { 24 [Disabled] "Disabled", 25 [Attached] "Attached", 26 [Enabled] "Enabled", 27 [Assigned] "Assigned", 28 [Configured] "Configured", 29 }; 30 31 static char Ebadusbmsg[] = "invalid parameters to USB ctl message"; 32 33 enum 34 { 35 Qtopdir = 0, 36 Q2nd, 37 Qnew, 38 Qport, 39 Q3rd, 40 Qctl, 41 Qstatus, 42 Qep0, 43 /* other endpoint files */ 44 }; 45 46 /* 47 * Qid path is: 48 * 8 bits of file type (qids above) 49 * 8 bits of slot number; default address 0 used for per-controller files 50 * 4 bits of controller number 51 */ 52 enum { 53 TYPEBITS = 8, 54 SLOTBITS = 8, 55 CTLRBITS = 4, 56 57 SLOTSHIFT = TYPEBITS, 58 CTLRSHIFT = SLOTSHIFT+SLOTBITS, 59 60 TYPEMASK = (1<<TYPEBITS)-1, 61 SLOTMASK = (1<<SLOTBITS)-1, 62 CTLRMASK = (1<<CTLRBITS)-1, 63 }; 64 65 #define TYPE(q) (((ulong)(q).path)&TYPEMASK) 66 #define SLOT(q) ((((ulong)(q).path)>>SLOTSHIFT)&SLOTMASK) 67 #define CTLR(q) ((((ulong)(q).path)>>CTLRSHIFT)&CTLRMASK) 68 #define PATH(t, s, c) ((t)|((s)<<SLOTSHIFT)|((c)<<CTLRSHIFT)) 69 70 static Dirtab usbdir2[] = { 71 "new", {Qnew}, 0, 0666, 72 "port", {Qport}, 0, 0666, 73 }; 74 75 static Dirtab usbdir3[]={ 76 "ctl", {Qctl}, 0, 0666, 77 "status", {Qstatus}, 0, 0444, 78 "setup", {Qep0}, 0, 0666, 79 /* epNdata names are generated on demand */ 80 }; 81 82 enum 83 { 84 PMdisable, 85 PMenable, 86 PMreset, 87 }; 88 89 enum 90 { 91 CMclass, 92 CMdata, 93 CMdebug, 94 CMep, 95 CMmaxpkt, 96 CMadjust, 97 CMspeed, 98 CMunstall, 99 }; 100 101 static Cmdtab usbportmsg[] = 102 { 103 PMdisable, "disable", 2, 104 PMenable, "enable", 2, 105 PMreset, "reset", 2, 106 }; 107 108 static Cmdtab usbctlmsg[] = 109 { 110 CMclass, "class", 0, 111 CMdata, "data", 3, 112 CMdebug, "debug", 3, 113 CMep, "ep", 6, 114 CMmaxpkt, "maxpkt", 3, 115 CMadjust, "adjust", 3, 116 CMspeed, "speed", 2, 117 CMunstall, "unstall", 2, 118 }; 119 120 static struct 121 { 122 char* type; 123 int (*reset)(Usbhost*); 124 } usbtypes[MaxUsb+1]; 125 126 void 127 addusbtype(char* t, int (*r)(Usbhost*)) 128 { 129 static int ntype; 130 131 if(ntype == MaxUsb) 132 panic("too many USB host interface types"); 133 usbtypes[ntype].type = t; 134 usbtypes[ntype].reset = r; 135 ntype++; 136 } 137 138 static Udev* 139 usbdeviceofslot(Usbhost *uh, int s) 140 { 141 if(s < 0 || s >= nelem(uh->dev)) 142 return nil; 143 return uh->dev[s]; 144 } 145 146 static Udev* 147 usbdevice(Chan *c) 148 { 149 int bus; 150 Udev *d; 151 Usbhost *uh; 152 153 bus = CTLR(c->qid); 154 if(bus >= nelem(usbhost) || (uh = usbhost[bus]) == nil) { 155 error(Egreg); 156 return nil; /* for compiler */ 157 } 158 d = usbdeviceofslot(uh, SLOT(c->qid)); 159 if(d == nil || d->id != c->qid.vers || d->state == Disabled) 160 error(Ehungup); 161 return d; 162 } 163 164 static Endpt * 165 devendpt(Udev *d, int id, int add) 166 { 167 Usbhost *uh; 168 Endpt *e, **p; 169 170 p = &d->ep[id&0xF]; 171 lock(d); 172 e = *p; 173 if(e != nil){ 174 incref(e); 175 XPRINT("incref(0x%p) in devendpt, new value %ld\n", e, e->ref); 176 unlock(d); 177 return e; 178 } 179 unlock(d); 180 if(!add) 181 return nil; 182 183 e = mallocz(sizeof(*e), 1); 184 e->ref = 1; 185 e->x = id&0xF; 186 e->id = id; 187 e->sched = -1; 188 e->maxpkt = 8; 189 e->nbuf = 1; 190 e->dev = d; 191 e->active = 0; 192 193 uh = d->uh; 194 uh->epalloc(uh, e); 195 196 lock(d); 197 if(*p != nil){ 198 incref(*p); 199 XPRINT("incref(0x%p) in devendpt, new value %ld\n", 200 *p, (*p)->ref); 201 unlock(d); 202 uh->epfree(uh, e); 203 free(e); 204 return *p; 205 } 206 *p = e; 207 unlock(d); 208 e->rq = qopen(8*1024, 0, nil, e); 209 e->wq = qopen(8*1024, 0, nil, e); 210 return e; 211 } 212 213 static void 214 freept(Endpt *e) 215 { 216 Usbhost *uh; 217 218 if(e != nil && decref(e) == 0){ 219 XPRINT("freept(%d,%d)\n", e->dev->x, e->x); 220 uh = e->dev->uh; 221 uh->epclose(uh, e); 222 e->dev->ep[e->x] = nil; 223 uh->epfree(uh, e); 224 free(e); 225 } 226 } 227 228 static Udev* 229 usbnewdevice(Usbhost *uh) 230 { 231 int i; 232 Udev *d; 233 Endpt *e; 234 235 d = nil; 236 qlock(uh); 237 if(waserror()){ 238 if (d) { 239 uh->dev[d->x] = nil; 240 freept(d->ep[0]); 241 free(d); 242 } 243 qunlock(uh); 244 nexterror(); 245 } 246 for(i=0; i<nelem(uh->dev); i++) 247 if(uh->dev[i] == nil){ 248 uh->idgen++; 249 d = mallocz(sizeof(*d), 1); 250 d->uh = uh; 251 d->ref = 1; 252 d->x = i; 253 d->id = (uh->idgen << 8) | i; 254 d->state = Enabled; 255 XPRINT("calling devendpt in usbnewdevice\n"); 256 e = devendpt(d, 0, 1); /* always provide ctl endpt 0 */ 257 e->mode = ORDWR; 258 e->in.epmode = e->out.epmode = Ctlmode; /* OHCI */ 259 // epsetMPS(e, 64, 64); /* OHCI; see epalloc*/ 260 e->iso = 0; 261 e->sched = -1; 262 uh->dev[i] = d; 263 break; 264 } 265 poperror(); 266 qunlock(uh); 267 return d; 268 } 269 270 static void 271 freedev(Udev *d, int ept) 272 { 273 int i; 274 Endpt *e; 275 Usbhost *uh; 276 277 uh = d->uh; 278 if(decref(d) == 0){ 279 XPRINT("freedev 0x%p, 0\n", d); 280 for(i=0; i<nelem(d->ep); i++) 281 freept(d->ep[i]); 282 if(d->x >= 0) 283 uh->dev[d->x] = nil; 284 free(d); 285 } else { 286 if(ept >= 0 && ept < nelem(d->ep)){ 287 e = d->ep[ept]; 288 XPRINT("freedev, freept 0x%p\n", e); 289 if(e != nil) 290 uh->epclose(uh, e); 291 } 292 } 293 } 294 295 static int 296 usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) 297 { 298 Qid q; 299 Udev *d; 300 Endpt *e; 301 Dirtab *tab; 302 Usbhost *uh; 303 int t, bus, slot, perm; 304 305 /* 306 * Top level directory contains the controller names. 307 */ 308 if(c->qid.path == Qtopdir){ 309 if(s == DEVDOTDOT){ 310 mkqid(&q, Qtopdir, 0, QTDIR); 311 devdir(c, q, "#U", 0, eve, 0555, dp); 312 return 1; 313 } 314 if(s >= nelem(usbhost) || usbhost[s] == nil) 315 return -1; 316 mkqid(&q, PATH(Q2nd, 0, s), 0, QTDIR); 317 snprint(up->genbuf, sizeof up->genbuf, "usb%d", s); 318 devdir(c, q, up->genbuf, 0, eve, 0555, dp); 319 return 1; 320 } 321 bus = CTLR(c->qid); 322 if(bus >= nelem(usbhost) || (uh = usbhost[bus]) == nil) 323 return -1; 324 325 /* 326 * Second level contains "new", "port", and a numbered 327 * directory for each enumerated device on the bus. 328 */ 329 t = TYPE(c->qid); 330 if(t < Q3rd){ 331 if(s == DEVDOTDOT){ 332 mkqid(&q, Qtopdir, 0, QTDIR); 333 devdir(c, q, "#U", 0, eve, 0555, dp); 334 return 1; 335 } 336 if(s < nelem(usbdir2)){ 337 d = uh->dev[0]; 338 if(d == nil) 339 return -1; 340 tab = &usbdir2[s]; 341 mkqid(&q, PATH(tab->qid.path, 0, bus), d->id, QTFILE); 342 devdir(c, q, tab->name, tab->length, eve, tab->perm, dp); 343 return 1; 344 } 345 s -= nelem(usbdir2); 346 if(s >= 0 && s < nelem(uh->dev)) { 347 d = uh->dev[s]; 348 if(d == nil) 349 return 0; 350 snprint(up->genbuf, sizeof up->genbuf, "%d", s); 351 mkqid(&q, PATH(Q3rd, s, bus), d->id, QTDIR); 352 devdir(c, q, up->genbuf, 0, eve, 0555, dp); 353 return 1; 354 } 355 return -1; 356 } 357 358 /* 359 * Third level. 360 */ 361 slot = SLOT(c->qid); 362 if(s == DEVDOTDOT) { 363 mkqid(&q, PATH(Q2nd, 0, bus), c->qid.vers, QTDIR); 364 snprint(up->genbuf, sizeof up->genbuf, "usb%d", bus); 365 devdir(c, q, up->genbuf, 0, eve, 0555, dp); 366 return 1; 367 } 368 if(s < nelem(usbdir3)) { 369 tab = &usbdir3[s]; 370 mkqid(&q, PATH(tab->qid.path, slot, bus), c->qid.vers, QTFILE); 371 devdir(c, q, tab->name, tab->length, eve, tab->perm, dp); 372 return 1; 373 } 374 s -= nelem(usbdir3); 375 376 /* active endpoints */ 377 d = usbdeviceofslot(uh, slot); 378 if(d == nil || s >= nelem(d->ep)) 379 return -1; 380 if(s == 0 || (e = d->ep[s]) == nil) /* ep0data is called "setup" */ 381 return 0; 382 snprint(up->genbuf, sizeof up->genbuf, "ep%ddata", s); 383 mkqid(&q, PATH(Qep0+s, slot, bus), c->qid.vers, QTFILE); 384 switch(e->mode) { 385 case OREAD: 386 perm = 0444; 387 break; 388 case OWRITE: 389 perm = 0222; 390 break; 391 default: 392 perm = 0666; 393 break; 394 } 395 devdir(c, q, up->genbuf, e->buffered, eve, perm, dp); 396 return 1; 397 } 398 399 static Usbhost* 400 usbprobe(int cardno, int ctlrno) 401 { 402 Usbhost *uh; 403 char buf[128], *ebuf, name[64], *p, *type; 404 405 uh = mallocz(sizeof *uh, 1); 406 uh->tbdf = BUSUNKNOWN; 407 408 if(cardno < 0){ 409 if(isaconfig("usb", ctlrno, uh) == 0){ 410 free(uh); 411 return nil; 412 } 413 for(cardno = 0; usbtypes[cardno].type; cardno++){ 414 type = uh->type; 415 if(type==nil || *type==0) 416 type = "uhci"; 417 if(cistrcmp(usbtypes[cardno].type, type) == 0) 418 break; 419 } 420 } 421 422 if(cardno >= MaxUsb || usbtypes[cardno].type == nil || 423 usbtypes[cardno].reset(uh) < 0){ 424 free(uh); 425 return nil; 426 } 427 428 /* 429 * IRQ2 doesn't really exist, it's used to gang the interrupt 430 * controllers together. A device set to IRQ2 will appear on 431 * the second interrupt controller as IRQ9. 432 */ 433 if(uh->irq == 2) 434 uh->irq = 9; 435 snprint(name, sizeof(name), "usb%d", ctlrno); 436 intrenable(uh->irq, uh->interrupt, uh, uh->tbdf, name); 437 438 ebuf = buf + sizeof buf; 439 p = seprint(buf, ebuf, "#U/usb%d: %s: port 0x%luX irq %d", 440 ctlrno, usbtypes[cardno].type, uh->port, uh->irq); 441 if(uh->mem) 442 p = seprint(p, ebuf, " addr 0x%luX", PADDR(uh->mem)); 443 if(uh->size) 444 seprint(p, ebuf, " size 0x%luX", uh->size); 445 print("%s\n", buf); 446 447 return uh; 448 } 449 450 static void 451 usbreset(void) 452 { 453 int cardno, ctlrno; 454 Usbhost *uh; 455 456 for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++) 457 if((uh = usbprobe(-1, ctlrno)) != nil) 458 usbhost[ctlrno] = uh; 459 460 if(getconf("*nousbprobe")) 461 return; 462 463 cardno = ctlrno = 0; 464 while(usbtypes[cardno].type != nil && ctlrno < MaxUsb){ 465 if(usbhost[ctlrno] != nil){ 466 ctlrno++; 467 continue; 468 } 469 if((uh = usbprobe(cardno, ctlrno)) == nil){ 470 cardno++; 471 continue; 472 } 473 usbhost[ctlrno] = uh; 474 ctlrno++; 475 } 476 } 477 478 void 479 usbinit(void) 480 { 481 Udev *d; 482 int ctlrno; 483 Usbhost *uh; 484 485 for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++){ 486 uh = usbhost[ctlrno]; 487 if(uh == nil) 488 continue; 489 if(uh->init != nil) 490 uh->init(uh); 491 492 /* reserve device for configuration */ 493 d = usbnewdevice(uh); 494 incref(d); 495 d->state = Attached; 496 } 497 } 498 499 Chan * 500 usbattach(char *spec) 501 { 502 return devattach('U', spec); 503 } 504 505 static Walkqid* 506 usbwalk(Chan *c, Chan *nc, char **name, int nname) 507 { 508 return devwalk(c, nc, name, nname, nil, 0, usbgen); 509 } 510 511 static int 512 usbstat(Chan *c, uchar *db, int n) 513 { 514 return devstat(c, db, n, nil, 0, usbgen); 515 } 516 517 Chan* 518 usbopen(Chan *c, int omode) 519 { 520 Udev *d; 521 Endpt *e; 522 int f, s, type; 523 Usbhost *uh; 524 525 if(c->qid.type == QTDIR) 526 return devopen(c, omode, nil, 0, usbgen); 527 528 f = 0; 529 type = TYPE(c->qid); 530 if(type == Qnew){ 531 d = usbdevice(c); 532 d = usbnewdevice(d->uh); 533 XPRINT("usbopen, new dev 0x%p\n", d); 534 if(d == nil) { 535 XPRINT("usbopen failed (usbnewdevice)\n"); 536 error(Enodev); 537 } 538 type = Qctl; 539 mkqid(&c->qid, PATH(type, d->x, CTLR(c->qid)), d->id, QTFILE); 540 f = 1; 541 } 542 543 if(type < Q3rd){ 544 XPRINT("usbopen, devopen < Q3rd\n"); 545 return devopen(c, omode, nil, 0, usbgen); 546 } 547 548 d = usbdevice(c); 549 uh = d->uh; 550 qlock(uh); 551 if(waserror()){ 552 qunlock(uh); 553 nexterror(); 554 } 555 556 switch(type){ 557 case Qctl: 558 if(0&&d->busy) 559 error(Einuse); 560 d->busy = 1; 561 if(!f) 562 incref(d); 563 XPRINT("usbopen, Qctl 0x%p\n", d); 564 break; 565 566 // case Qsetup: /* OHCI addition */ 567 // d = usbhdevice(c); 568 // doopen(ub, d, 0); 569 // incref(d); 570 // break; 571 572 default: 573 s = type - Qep0; 574 XPRINT("usbopen, default 0x%p, %d\n", d, s); 575 if(s >= 0 && s < nelem(d->ep)){ 576 if((e = d->ep[s]) == nil) { 577 XPRINT("usbopen failed (endpoint)\n"); 578 error(Enodev); 579 } 580 XPRINT("usbopen: dev 0x%p, ept 0x%p\n", d, e); 581 uh->epopen(uh, e); 582 e->foffset = 0; 583 e->toffset = 0; 584 e->poffset = 0; 585 e->buffered = 0; 586 } 587 incref(d); 588 break; 589 } 590 poperror(); 591 qunlock(uh); 592 c->mode = openmode(omode); 593 c->flag |= COPEN; 594 c->offset = 0; 595 return c; 596 } 597 598 void 599 usbclose(Chan *c) 600 { 601 Udev *d; 602 int ept, type; 603 Usbhost *uh; 604 605 type = TYPE(c->qid); 606 if(c->qid.type == QTDIR || type < Q3rd) 607 return; 608 d = usbdevice(c); 609 uh = d->uh; 610 qlock(uh); 611 if(waserror()){ 612 qunlock(uh); 613 nexterror(); 614 } 615 if(type == Qctl) 616 d->busy = 0; 617 XPRINT("usbclose: dev 0x%p\n", d); 618 if(c->flag & COPEN){ 619 ept = (type != Qctl) ? type - Qep0 : -1; 620 XPRINT("usbclose: freedev 0x%p\n", d); 621 freedev(d, ept); 622 } 623 poperror(); 624 qunlock(uh); 625 } 626 627 static char * 628 epstatus(char *s, char *se, Endpt *e, int i) 629 { 630 char *p; 631 632 p = seprint(s, se, "%2d %#6.6lux %10lud bytes %10lud blocks\n", 633 i, e->csp, e->nbytes, e->nblocks); 634 if(e->iso){ 635 p = seprint(p, se, "bufsize %6d buffered %6d", 636 e->maxpkt, e->buffered); 637 if(e->toffset) 638 p = seprint(p, se, " offset %10lud time %19lld\n", 639 e->toffset, e->time); 640 p = seprint(p, se, "\n"); 641 } 642 return p; 643 } 644 645 long 646 usbread(Chan *c, void *a, long n, vlong offset) 647 { 648 int t, i; 649 Udev *d; 650 Endpt *e; 651 Usbhost *uh; 652 char *s, *se, *p; 653 654 if(c->qid.type == QTDIR) 655 return devdirread(c, a, n, nil, 0, usbgen); 656 657 d = usbdevice(c); 658 uh = d->uh; 659 t = TYPE(c->qid); 660 661 if(t >= Qep0) { 662 t -= Qep0; 663 if(t >= nelem(d->ep)) 664 error(Eio); 665 e = d->ep[t]; 666 if(e == nil || e->mode == OWRITE) 667 error(Egreg); 668 if(t == 0) { 669 if(e->iso) 670 error(Egreg); 671 e->rdata01 = 1; 672 n = uh->read(uh, e, a, n, 0LL); 673 if(e->setin){ 674 e->setin = 0; 675 e->wdata01 = 1; 676 uh->write(uh, e, "", 0, 0LL, uh->tokout); 677 } 678 return n; 679 } 680 return uh->read(uh, e, a, n, offset); 681 } 682 683 s = smalloc(READSTR); 684 se = s+READSTR; 685 if(waserror()){ 686 free(s); 687 nexterror(); 688 } 689 switch(t){ 690 case Qport: 691 uh->portinfo(uh, s, se); 692 break; 693 694 case Qctl: 695 seprint(s, se, "%11d %11d\n", d->x, d->id); 696 break; 697 698 case Qstatus: 699 if (d->did || d->vid) 700 p = seprint(s, se, "%s %#6.6lux %#4.4ux %#4.4ux\n", 701 devstates[d->state], d->csp, d->vid, d->did); 702 else 703 p = seprint(s, se, "%s %#6.6lux\n", 704 devstates[d->state], d->csp); 705 for(i=0; i<nelem(d->ep); i++) { 706 e = d->ep[i]; 707 if(e == nil) 708 continue; 709 /* TO DO: freeze e */ 710 p = epstatus(p, se, e, i); 711 } 712 } 713 n = readstr(offset, a, n, s); 714 poperror(); 715 free(s); 716 return n; 717 } 718 719 long 720 usbwrite(Chan *c, void *a, long n, vlong offset) 721 { 722 Udev *d; 723 Endpt *e; 724 Cmdtab *ct; 725 Cmdbuf *cb; 726 Usbhost *uh; 727 int id, nw, t, i; 728 char cmd[50]; 729 730 if(c->qid.type == QTDIR) 731 error(Egreg); 732 d = usbdevice(c); 733 uh = d->uh; 734 t = TYPE(c->qid); 735 switch(t){ 736 case Qport: 737 cb = parsecmd(a, n); 738 if(waserror()){ 739 free(cb); 740 nexterror(); 741 } 742 743 ct = lookupcmd(cb, usbportmsg, nelem(usbportmsg)); 744 id = strtol(cb->f[1], nil, 0); 745 switch(ct->index){ 746 case PMdisable: 747 uh->portenable(uh, id, 0); 748 break; 749 case PMenable: 750 uh->portenable(uh, id, 1); 751 break; 752 case PMreset: 753 uh->portreset(uh, id); 754 break; 755 } 756 757 poperror(); 758 free(cb); 759 return n; 760 case Qctl: 761 cb = parsecmd(a, n); 762 if(waserror()){ 763 free(cb); 764 nexterror(); 765 } 766 767 ct = lookupcmd(cb, usbctlmsg, nelem(usbctlmsg)); 768 switch(ct->index){ 769 case CMspeed: 770 d->ls = strtoul(cb->f[1], nil, 0) == 0; 771 break; 772 case CMclass: 773 if (cb->nf != 4 && cb->nf != 6) 774 cmderror(cb, Ebadusbmsg); 775 /* 776 * class #ifc ept csp 777 * (== class subclass proto) [vendor product] 778 */ 779 d->npt = strtoul(cb->f[1], nil, 0); /* # of interfaces */ 780 i = strtoul(cb->f[2], nil, 0); /* endpoint */ 781 if (i < 0 || i >= nelem(d->ep) || 782 d->npt > nelem(d->ep) || i >= d->npt) 783 cmderror(cb, Ebadusbmsg); 784 if (cb->nf == 6) { 785 d->vid = strtoul(cb->f[4], nil, 0); 786 d->did = strtoul(cb->f[5], nil, 0); 787 } 788 if (i == 0) 789 d->csp = strtoul(cb->f[3], nil, 0); 790 if(d->ep[i] == nil){ 791 XPRINT("calling devendpt in usbwrite (CMclass)\n"); 792 d->ep[i] = devendpt(d, i, 1); 793 } 794 d->ep[i]->csp = strtoul(cb->f[3], nil, 0); 795 break; 796 case CMdata: 797 i = strtoul(cb->f[1], nil, 0); 798 if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) 799 error(Ebadusbmsg); 800 e = d->ep[i]; 801 e->wdata01 = e->rdata01 = strtoul(cb->f[2], nil, 0) != 0; 802 break; 803 case CMmaxpkt: 804 i = strtoul(cb->f[1], nil, 0); 805 if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) 806 error(Ebadusbmsg); 807 e = d->ep[i]; 808 e->maxpkt = strtoul(cb->f[2], nil, 0); 809 if(e->maxpkt > 1500) 810 e->maxpkt = 1500; 811 break; 812 case CMadjust: 813 i = strtoul(cb->f[1], nil, 0); 814 if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) 815 error(Ebadusbmsg); 816 e = d->ep[i]; 817 if (e->iso == 0) 818 error(Eperm); 819 i = strtoul(cb->f[2], nil, 0); 820 /* speed may not result in change of maxpkt */ 821 if (i < (e->maxpkt-1)/e->samplesz * 1000/e->pollms 822 || i > e->maxpkt/e->samplesz * 1000/e->pollms){ 823 snprint(cmd, sizeof(cmd), "%d < %d < %d?", 824 (e->maxpkt-1)/e->samplesz * 1000/e->pollms, 825 i, 826 e->maxpkt/e->samplesz * 1000/e->pollms); 827 error(cmd); 828 } 829 e->hz = i; 830 break; 831 case CMdebug: 832 i = strtoul(cb->f[1], nil, 0); 833 if(i < -1 || i >= nelem(d->ep) || d->ep[i] == nil) 834 error(Ebadusbmsg); 835 if (i == -1) 836 debug = 0; 837 else { 838 debug = 1; 839 e = d->ep[i]; 840 e->debug = strtoul(cb->f[2], nil, 0); 841 } 842 break; 843 case CMunstall: 844 i = strtoul(cb->f[1], nil, 0); 845 if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) 846 error(Ebadusbmsg); 847 e = d->ep[i]; 848 e->err = nil; 849 break; 850 case CMep: 851 /* ep n `bulk' mode maxpkt nbuf OR 852 * ep n period mode samplesize Hz 853 */ 854 i = strtoul(cb->f[1], nil, 0); 855 if(i < 0 || i >= nelem(d->ep)) { 856 XPRINT("field 1: 0 <= %d < %d\n", 857 i, nelem(d->ep)); 858 error(Ebadarg); 859 } 860 if((e = d->ep[i]) == nil){ 861 XPRINT("calling devendpt in usbwrite (CMep)\n"); 862 e = devendpt(d, i, 1); 863 } 864 qlock(uh); 865 if(waserror()){ 866 freept(e); 867 qunlock(uh); 868 nexterror(); 869 } 870 if(e->active) 871 error(Eperm); 872 if(strcmp(cb->f[2], "bulk") == 0){ 873 /* ep n `bulk' mode maxpkt nbuf */ 874 e->iso = 0; 875 i = strtoul(cb->f[4], nil, 0); 876 if(i < 8 || i > 1023) 877 i = 8; 878 e->maxpkt = i; 879 i = strtoul(cb->f[5], nil, 0); 880 if(i >= 1 && i <= 32) 881 e->nbuf = i; 882 } else { 883 /* ep n period mode samplesize Hz */ 884 i = strtoul(cb->f[2], nil, 0); 885 if(i > 0 && i <= 1000){ 886 e->pollms = i; 887 }else { 888 XPRINT("field 4: 0 <= %d <= 1000\n", i); 889 error(Ebadarg); 890 } 891 i = strtoul(cb->f[4], nil, 0); 892 if(i >= 1 && i <= 8){ 893 e->samplesz = i; 894 }else { 895 XPRINT("field 4: 0 < %d <= 8\n", i); 896 error(Ebadarg); 897 } 898 i = strtoul(cb->f[5], nil, 0); 899 if(i >= 1 && i*e->samplesz <= 12*1000*1000){ 900 /* Hz */ 901 e->hz = i; 902 e->remain = 0; 903 }else { 904 XPRINT("field 5: 1 < %d <= 100000 Hz\n", 905 i); 906 error(Ebadarg); 907 } 908 e->maxpkt = (e->hz*e->pollms + 999)/1000 * 909 e->samplesz; 910 e->iso = 1; 911 } 912 e->mode = strcmp(cb->f[3],"r") == 0? OREAD: 913 strcmp(cb->f[3],"w") == 0? OWRITE: ORDWR; 914 uh->epmode(uh, e); 915 poperror(); 916 qunlock(uh); 917 } 918 919 poperror(); 920 free(cb); 921 return n; 922 923 case Qep0: /* SETUP endpoint 0 */ 924 /* should canqlock etc */ 925 e = d->ep[0]; 926 if(e == nil || e->iso) 927 error(Egreg); 928 if(n < 8) 929 error(Eio); 930 nw = *(uchar*)a & RD2H; 931 e->wdata01 = 0; 932 n = uh->write(uh, e, a, n, 0LL, uh->toksetup); 933 if(nw == 0) { /* host to device: use IN[DATA1] to ack */ 934 e->rdata01 = 1; 935 nw = uh->read(uh, e, cmd, 0LL, 8); 936 if(nw != 0) 937 error(Eio); /* could provide more status */ 938 }else 939 e->setin = 1; /* two-phase */ 940 break; 941 942 default: /* sends DATA[01] */ 943 t -= Qep0; 944 if(t < 0 || t >= nelem(d->ep)) 945 error(Egreg); 946 e = d->ep[t]; 947 if(e == nil || e->mode == OREAD) 948 error(Egreg); 949 n = uh->write(uh, e, a, n, offset, uh->tokout); 950 break; 951 } 952 return n; 953 } 954 955 Dev usbdevtab = { 956 'U', 957 "usb", 958 959 usbreset, 960 usbinit, 961 devshutdown, 962 usbattach, 963 usbwalk, 964 usbstat, 965 usbopen, 966 devcreate, 967 usbclose, 968 usbread, 969 devbread, 970 usbwrite, 971 devbwrite, 972 devremove, 973 devwstat, 974 }; 975