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