1 /* 2 * usb/ether - usb ethernet adapter. 3 * BUG: This should use /dev/etherfile to 4 * use the kernel ether device code. 5 */ 6 #include <u.h> 7 #include <libc.h> 8 #include <fcall.h> 9 #include <thread.h> 10 #include "usb.h" 11 #include "usbfs.h" 12 #include "ether.h" 13 14 typedef struct Dirtab Dirtab; 15 16 enum 17 { 18 /* Qids. Maintain order (relative to dirtabs structs) */ 19 Qroot = 0, 20 Qclone, 21 Qaddr, 22 Qifstats, 23 Qstats, 24 Qndir, 25 Qndata, 26 Qnctl, 27 Qnifstats, 28 Qnstats, 29 Qntype, 30 Qmax, 31 }; 32 33 struct Dirtab 34 { 35 char *name; 36 int qid; 37 int mode; 38 }; 39 40 typedef int (*Resetf)(Ether*); 41 42 /* 43 * Controllers by vid/vid. Used to locate 44 * specific adapters that do not implement cdc ethernet 45 * Keep null terminated. 46 */ 47 Cinfo cinfo[] = 48 { 49 /* Asix controllers. 50 * Only A88178 and A881772 are implemented. 51 * Others are easy to add by borrowing code 52 * from other systems. 53 */ 54 {0x077b, 0x2226, A8817x}, 55 {0x0b95, 0x1720, A8817x}, 56 {0x0557, 0x2009, A8817x}, 57 {0x0411, 0x003d, A8817x}, 58 {0x0411, 0x006e, A88178}, 59 {0x6189, 0x182d, A8817x}, 60 {0x07aa, 0x0017, A8817x}, 61 {0x1189, 0x0893, A8817x}, 62 {0x1631, 0x6200, A8817x}, 63 {0x04f1, 0x3008, A8817x}, 64 {0x0b95, 0x1780, A88178}, /* Geoff */ 65 {0x13b1, 0x0018, A88772}, 66 {0x1557, 0x7720, A88772}, 67 {0x07d1, 0x3c05, A88772}, 68 {0x2001, 0x3c05, A88772}, 69 {0x1737, 0x0039, A88178}, 70 {0x050d, 0x5055, A88178}, 71 {0x05ac, 0x1402, A88772}, /* Apple */ 72 {0x0b95, 0x772a, A88772}, 73 {0x14ea, 0xab11, A88178}, 74 {0x0db0, 0xa877, A88772}, 75 {0, 0, 0}, 76 }; 77 78 /* 79 * Each etherU%d is the root of our file system, 80 * which is added to the usb root directory. We only 81 * have to concern ourselfs with each /etherU%d subtree. 82 * 83 * NB: Maintain order in dirtabs, relative to the Qids enum. 84 */ 85 86 static Dirtab rootdirtab[] = 87 { 88 "/", Qroot, DMDIR|0555, /* etherU%d */ 89 "clone", Qclone, 0666, 90 "addr", Qaddr, 0444, 91 "ifstats", Qifstats, 0444, 92 "stats", Qstats, 0444, 93 /* one dir per connection here */ 94 nil, 0, 0, 95 }; 96 97 static Dirtab conndirtab[] = 98 { 99 "%d", Qndir, DMDIR|0555, 100 "data", Qndata, 0666, 101 "ctl", Qnctl, 0666, 102 "ifstats", Qnifstats, 0444, 103 "stats", Qnstats, 0444, 104 "type", Qntype, 0444, 105 nil, 0, 106 }; 107 108 int etherdebug; 109 110 Resetf ethers[] = 111 { 112 asixreset, 113 cdcreset, /* keep last */ 114 }; 115 116 static int 117 qtype(vlong q) 118 { 119 return q&0xFF; 120 } 121 122 static int 123 qnum(vlong q) 124 { 125 return (q >> 8) & 0xFFFFFF; 126 } 127 128 static uvlong 129 mkqid(int n, int t) 130 { 131 uvlong q; 132 133 q = (n&0xFFFFFF) << 8 | t&0xFF; 134 return q; 135 } 136 137 static void 138 freebuf(Ether *e, Buf *bp) 139 { 140 if(0)deprint(2, "%s: freebuf %#p\n", argv0, bp); 141 if(bp != nil){ 142 qlock(e); 143 e->nbufs--; 144 qunlock(e); 145 sendp(e->bc, bp); 146 } 147 } 148 149 static Buf* 150 allocbuf(Ether *e) 151 { 152 Buf *bp; 153 154 bp = nbrecvp(e->bc); 155 if(bp == nil){ 156 qlock(e); 157 if(e->nabufs < Nconns){ 158 bp = emallocz(sizeof(Buf), 1); 159 e->nabufs++; 160 setmalloctag(bp, getcallerpc(&e)); 161 deprint(2, "%s: %d buffers\n", argv0, e->nabufs); 162 } 163 qunlock(e); 164 } 165 if(bp == nil) 166 bp = recvp(e->bc); 167 bp->rp = bp->data + Hdrsize; 168 bp->ndata = 0; 169 if(0)deprint(2, "%s: allocbuf %#p\n", argv0, bp); 170 qlock(e); 171 e->nbufs++; 172 qunlock(e); 173 return bp; 174 } 175 176 static Conn* 177 newconn(Ether *e) 178 { 179 int i; 180 Conn *c; 181 182 qlock(e); 183 for(i = 0; i < nelem(e->conns); i++){ 184 c = e->conns[i]; 185 if(c == nil || c->ref == 0){ 186 if(c == nil){ 187 c = emallocz(sizeof(Conn), 1); 188 c->rc = chancreate(sizeof(Buf*), 2); 189 c->nb = i; 190 } 191 c->ref = 1; 192 if(i == e->nconns) 193 e->nconns++; 194 e->conns[i] = c; 195 deprint(2, "%s: newconn %d\n", argv0, i); 196 qunlock(e); 197 return c; 198 } 199 } 200 qunlock(e); 201 return nil; 202 } 203 204 static char* 205 seprintaddr(char *s, char *se, uchar *addr) 206 { 207 int i; 208 209 for(i = 0; i < Eaddrlen; i++) 210 s = seprint(s, se, "%02x", addr[i]); 211 return s; 212 } 213 214 void 215 dumpframe(char *tag, void *p, int n) 216 { 217 Etherpkt *ep; 218 char buf[128]; 219 char *s, *se; 220 int i; 221 222 ep = p; 223 if(n < Eaddrlen * 2 + 2){ 224 fprint(2, "short packet (%d bytes)\n", n); 225 return; 226 } 227 se = buf+sizeof(buf); 228 s = seprint(buf, se, "%s [%d]: ", tag, n); 229 s = seprintaddr(s, se, ep->s); 230 s = seprint(s, se, " -> "); 231 s = seprintaddr(s, se, ep->d); 232 s = seprint(s, se, " type 0x%02ux%02ux ", ep->type[0], ep->type[1]); 233 n -= Eaddrlen * 2 + 2; 234 for(i = 0; i < n && i < 16; i++) 235 s = seprint(s, se, "%02x", ep->data[i]); 236 if(n >= 16) 237 fprint(2, "%s...\n", buf); 238 else 239 fprint(2, "%s\n", buf); 240 } 241 242 static char* 243 seprintstats(char *s, char *se, Ether *e) 244 { 245 qlock(e); 246 s = seprint(s, se, "in: %ld\n", e->nin); 247 s = seprint(s, se, "out: %ld\n", e->nout); 248 s = seprint(s, se, "input errs: %ld\n", e->nierrs); 249 s = seprint(s, se, "output errs: %ld\n", e->noerrs); 250 s = seprint(s, se, "mbps: %d\n", e->mbps); 251 s = seprint(s, se, "prom: %ld\n", e->prom.ref); 252 s = seprint(s, se, "addr: "); 253 s = seprintaddr(s, se, e->addr); 254 s = seprint(s, se, "\n"); 255 qunlock(e); 256 return s; 257 } 258 259 static char* 260 seprintifstats(char *s, char *se, Ether *e) 261 { 262 int i; 263 Conn *c; 264 265 qlock(e); 266 s = seprint(s, se, "ctlr id: %#x\n", e->cid); 267 s = seprint(s, se, "phy: %#x\n", e->phy); 268 s = seprint(s, se, "exiting: %#x\n", e->exiting); 269 s = seprint(s, se, "conns: %d\n", e->nconns); 270 s = seprint(s, se, "allocated bufs: %d\n", e->nabufs); 271 s = seprint(s, se, "used bufs: %d\n", e->nbufs); 272 for(i = 0; i < nelem(e->conns); i++){ 273 c = e->conns[i]; 274 if(c == nil) 275 continue; 276 if(c->ref == 0) 277 s = seprint(s, se, "c[%d]: free\n", i); 278 else{ 279 s = seprint(s, se, "c[%d]: refs %ld t %#x h %d p %d\n", 280 c->nb, c->ref, c->type, c->headersonly, c->prom); 281 } 282 } 283 qunlock(e); 284 return s; 285 } 286 287 static void 288 etherdump(Ether *e) 289 { 290 char buf[256]; 291 292 if(etherdebug == 0) 293 return; 294 seprintifstats(buf, buf+sizeof(buf), e); 295 fprint(2, "%s: ether %#p:\n%s\n", argv0, e, buf); 296 } 297 298 static Conn* 299 getconn(Ether *e, int i, int idleok) 300 { 301 Conn *c; 302 303 qlock(e); 304 if(i < 0 || i >= e->nconns) 305 c = nil; 306 else{ 307 c = e->conns[i]; 308 if(idleok == 0 && c != nil && c->ref == 0) 309 c = nil; 310 } 311 qunlock(e); 312 return c; 313 } 314 315 static void 316 filldir(Usbfs *fs, Dir *d, Dirtab *tab, int cn) 317 { 318 d->qid.path = mkqid(cn, tab->qid); 319 d->qid.path |= fs->qid; 320 d->mode = tab->mode; 321 if((d->mode & DMDIR) != 0) 322 d->qid.type = QTDIR; 323 else 324 d->qid.type = QTFILE; 325 if(tab->qid == Qndir) 326 sprint(d->name, "%d", cn); 327 else 328 d->name = tab->name; 329 } 330 331 static int 332 rootdirgen(Usbfs *fs, Qid, int i, Dir *d, void *) 333 { 334 Ether *e; 335 Dirtab *tab; 336 int cn; 337 338 e = fs->aux; 339 i++; /* skip root */ 340 cn = 0; 341 if(i < nelem(rootdirtab) - 1) /* null terminated */ 342 tab = &rootdirtab[i]; 343 else{ 344 cn = i - nelem(rootdirtab) + 1; 345 if(cn < e->nconns) 346 tab = &conndirtab[0]; 347 else 348 return -1; 349 } 350 filldir(fs, d, tab, cn); 351 return 0; 352 353 } 354 355 static int 356 conndirgen(Usbfs *fs, Qid q, int i, Dir *d, void *) 357 { 358 Dirtab *tab; 359 360 i++; /* skip root */ 361 if(i < nelem(conndirtab) - 1) /* null terminated */ 362 tab = &conndirtab[i]; 363 else 364 return -1; 365 filldir(fs, d, tab, qnum(q.path)); 366 return 0; 367 } 368 369 static int 370 fswalk(Usbfs *fs, Fid *fid, char *name) 371 { 372 Ether *e; 373 int i; 374 Qid qid; 375 char *es; 376 Dirtab *tab; 377 int cn; 378 379 e = fs->aux; 380 qid = fid->qid; 381 qid.path &= ~fs->qid; 382 if((qid.type & QTDIR) == 0){ 383 werrstr("walk in non-directory"); 384 return -1; 385 } 386 387 if(strcmp(name, "..") == 0){ 388 /* must be /etherU%d; i.e. our root dir. */ 389 fid->qid.path = mkqid(0, Qroot) | fs->qid; 390 fid->qid.vers = 0; 391 fid->qid.type = QTDIR; 392 return 0; 393 } 394 switch(qtype(qid.path)){ 395 case Qroot: 396 if(name[0] >= '0' && name[0] <= '9'){ 397 es = name; 398 cn = strtoul(name, &es, 10); 399 if(cn >= e->nconns || *es != 0){ 400 werrstr(Enotfound); 401 return -1; 402 } 403 fid->qid.path = mkqid(cn, Qndir) | fs->qid; 404 fid->qid.vers = 0; 405 return 0; 406 } 407 /* fall */ 408 case Qndir: 409 if(qtype(qid.path) == Qroot) 410 tab = rootdirtab; 411 else 412 tab = conndirtab; 413 cn = qnum(qid.path); 414 for(i = 0; tab[i].name != nil; tab++) 415 if(strcmp(tab[i].name, name) == 0){ 416 fid->qid.path = mkqid(cn, tab[i].qid)|fs->qid; 417 fid->qid.vers = 0; 418 if((tab[i].mode & DMDIR) != 0) 419 fid->qid.type = QTDIR; 420 else 421 fid->qid.type = QTFILE; 422 return 0; 423 } 424 break; 425 default: 426 sysfatal("usb: ether: fswalk bug"); 427 } 428 return -1; 429 } 430 431 static Dirtab* 432 qdirtab(vlong q) 433 { 434 int qt; 435 Dirtab *tab; 436 int i; 437 438 qt = qtype(q); 439 if(qt < nelem(rootdirtab) - 1){ /* null terminated */ 440 tab = rootdirtab; 441 i = qt; 442 }else{ 443 tab = conndirtab; 444 i = qt - (nelem(rootdirtab) - 1); 445 assert(i < nelem(conndirtab) - 1); 446 } 447 return &tab[i]; 448 } 449 450 static int 451 fsstat(Usbfs *fs, Qid qid, Dir *d) 452 { 453 filldir(fs, d, qdirtab(qid.path), qnum(qid.path)); 454 return 0; 455 } 456 457 static int 458 fsopen(Usbfs *fs, Fid *fid, int omode) 459 { 460 Ether *e; 461 int qt; 462 Dirtab *tab; 463 Conn *c; 464 vlong qid; 465 466 qid = fid->qid.path & ~fs->qid; 467 e = fs->aux; 468 qt = qtype(qid); 469 tab = qdirtab(qid); 470 omode &= 3; 471 if(omode != OREAD && (tab->mode&0222) == 0){ 472 werrstr(Eperm); 473 return -1; 474 } 475 switch(qt){ 476 case Qclone: 477 c = newconn(e); 478 if(c == nil){ 479 werrstr("no more connections"); 480 return -1; 481 } 482 fid->qid.type = QTFILE; 483 fid->qid.path = mkqid(c->nb, Qnctl)|fs->qid; 484 fid->qid.vers = 0; 485 break; 486 case Qndata: 487 case Qnctl: 488 case Qnifstats: 489 case Qnstats: 490 case Qntype: 491 c = getconn(e, qnum(qid), 1); 492 if(c == nil) 493 sysfatal("usb: ether: fsopen bug"); 494 incref(c); 495 break; 496 } 497 etherdump(e); 498 return 0; 499 } 500 501 static int 502 prom(Ether *e, int set) 503 { 504 if(e->promiscuous != nil) 505 return e->promiscuous(e, set); 506 return 0; 507 } 508 509 static void 510 fsclunk(Usbfs *fs, Fid *fid) 511 { 512 Ether *e; 513 int qt; 514 Conn *c; 515 vlong qid; 516 Buf *bp; 517 518 e = fs->aux; 519 qid = fid->qid.path & ~fs->qid; 520 qt = qtype(qid); 521 switch(qt){ 522 case Qndata: 523 case Qnctl: 524 case Qnifstats: 525 case Qnstats: 526 case Qntype: 527 if(fid->omode != ONONE){ 528 c = getconn(e, qnum(qid), 0); 529 if(c == nil) 530 sysfatal("usb: ether: fsopen bug"); 531 if(decref(c) == 0){ 532 while((bp = nbrecvp(c->rc)) != nil) 533 freebuf(e, bp); 534 qlock(e); 535 if(c->prom != 0) 536 if(decref(&e->prom) == 0) 537 prom(e, 0); 538 c->prom = c->type = 0; 539 qunlock(e); 540 } 541 } 542 break; 543 } 544 etherdump(e); 545 } 546 547 int 548 parseaddr(uchar *m, char *s) 549 { 550 int i; 551 int n; 552 uchar v; 553 554 if(strlen(s) < 12) 555 return -1; 556 if(strlen(s) > 12 && strlen(s) < 17) 557 return -1; 558 for(i = n = 0; i < strlen(s); i++){ 559 if(s[i] == ':') 560 continue; 561 if(s[i] >= 'A' && s[i] <= 'F') 562 v = 10 + s[i] - 'A'; 563 else if(s[i] >= 'a' && s[i] <= 'f') 564 v = 10 + s[i] - 'a'; 565 else if(s[i] >= '0' && s[i] <= '9') 566 v = s[i] - '0'; 567 else 568 return -1; 569 if(n&1) 570 m[n/2] |= v; 571 else 572 m[n/2] = v<<4; 573 n++; 574 } 575 return 0; 576 } 577 578 static long 579 fsread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 580 { 581 Qid q; 582 Buf *bp; 583 Ether *e; 584 int qt; 585 int cn; 586 char buf[128]; 587 char *s; 588 char *se; 589 Conn *c; 590 591 q = fid->qid; 592 q.path &= ~fs->qid; 593 e = fs->aux; 594 s = buf; 595 se = buf+sizeof(buf); 596 qt = qtype(q.path); 597 cn = qnum(q.path); 598 switch(qt){ 599 case Qroot: 600 count = usbdirread(fs, q, data, count, offset, rootdirgen, nil); 601 break; 602 case Qaddr: 603 s = seprintaddr(s, se, e->addr); 604 count = usbreadbuf(data, count, offset, buf, s - buf); 605 break; 606 case Qnifstats: 607 /* BUG */ 608 case Qifstats: 609 s = seprintifstats(s, se, e); 610 if(e->seprintstats != nil) 611 s = e->seprintstats(s, se, e); 612 count = usbreadbuf(data, count, offset, buf, s - buf); 613 break; 614 case Qnstats: 615 /* BUG */ 616 case Qstats: 617 s = seprintstats(s, se, e); 618 count = usbreadbuf(data, count, offset, buf, s - buf); 619 break; 620 621 case Qndir: 622 count = usbdirread(fs, q, data, count, offset, conndirgen, nil); 623 break; 624 case Qndata: 625 c = getconn(e, cn, 0); 626 if(c == nil){ 627 werrstr(Eio); 628 return -1; 629 } 630 bp = recvp(c->rc); 631 if(bp == nil) 632 return -1; 633 if(etherdebug > 1) 634 dumpframe("etherin", bp->rp, bp->ndata); 635 count = usbreadbuf(data, count, 0LL, bp->rp, bp->ndata); 636 freebuf(e, bp); 637 break; 638 case Qnctl: 639 s = seprint(s, se, "%11d ", cn); 640 count = usbreadbuf(data, count, offset, buf, s - buf); 641 break; 642 case Qntype: 643 c = getconn(e, cn, 0); 644 if(c == nil) 645 s = seprint(s, se, "%11d ", 0); 646 else 647 s = seprint(s, se, "%11d ", c->type); 648 count = usbreadbuf(data, count, offset, buf, s - buf); 649 break; 650 default: 651 sysfatal("usb: ether: fsread bug"); 652 } 653 return count; 654 } 655 656 static int 657 typeinuse(Ether *e, int t) 658 { 659 int i; 660 661 for(i = 0; i < e->nconns; i++) 662 if(e->conns[i]->ref > 0 && e->conns[i]->type == t) 663 return 1; 664 return 0; 665 } 666 667 static int 668 isloopback(Ether *e, Buf *) 669 { 670 return e->prom.ref > 0; /* BUG: also loopbacks and broadcasts */ 671 } 672 673 static int 674 etherctl(Ether *e, Conn *c, char *buf) 675 { 676 uchar addr[Eaddrlen]; 677 int t; 678 679 deprint(2, "%s: etherctl: %s\n", argv0, buf); 680 if(strncmp(buf, "connect ", 8) == 0){ 681 t = atoi(buf+8); 682 qlock(e); 683 if(typeinuse(e, t)){ 684 werrstr("type already in use"); 685 qunlock(e); 686 return -1; 687 } 688 c->type = atoi(buf+8); 689 qunlock(e); 690 return 0; 691 } 692 if(strncmp(buf, "nonblocking", 11) == 0){ 693 if(buf[11] == '\n' || buf[11] == 0) 694 e->nblock = 1; 695 else 696 e->nblock = atoi(buf + 12); 697 deprint(2, "%s: nblock %d\n", argv0, e->nblock); 698 return 0; 699 } 700 if(strncmp(buf, "promiscuous", 11) == 0){ 701 if(c->prom == 0) 702 incref(&e->prom); 703 c->prom = 1; 704 return prom(e, 1); 705 } 706 if(strncmp(buf, "headersonly", 11) == 0){ 707 c->headersonly = 1; 708 return 0; 709 } 710 if(!strncmp(buf, "addmulti ", 9) || !strncmp(buf, "remmulti ", 9)){ 711 if(parseaddr(addr, buf+9) < 0){ 712 werrstr("bad address"); 713 return -1; 714 } 715 if(e->multicast == nil) 716 return 0; 717 if(strncmp(buf, "add", 3) == 0){ 718 e->nmcasts++; 719 return e->multicast(e, addr, 1); 720 }else{ 721 e->nmcasts--; 722 return e->multicast(e, addr, 0); 723 } 724 } 725 726 if(e->ctl != nil) 727 return e->ctl(e, buf); 728 werrstr(Ebadctl); 729 return -1; 730 } 731 732 static long 733 etherbread(Ether *e, Buf *bp) 734 { 735 deprint(2, "%s: etherbread\n", argv0); 736 bp->rp = bp->data + Hdrsize; 737 bp->ndata = read(e->epin->dfd, bp->rp, sizeof(bp->data)-Hdrsize); 738 deprint(2, "%s: etherbread got %d bytes\n", argv0, bp->ndata); 739 return bp->ndata; 740 } 741 742 static long 743 etherbwrite(Ether *e, Buf *bp) 744 { 745 long n; 746 747 deprint(2, "%s: etherbwrite %d bytes\n", argv0, bp->ndata); 748 n = write(e->epout->dfd, bp->rp, bp->ndata); 749 deprint(2, "%s: etherbwrite wrote %ld bytes\n", argv0, n); 750 if(n <= 0) 751 return n; 752 if((bp->ndata % e->epout->maxpkt) == 0){ 753 deprint(2, "%s: short pkt write\n", argv0); 754 write(e->epout->dfd, "", 0); 755 } 756 return n; 757 } 758 759 static long 760 fswrite(Usbfs *fs, Fid *fid, void *data, long count, vlong) 761 { 762 Qid q; 763 Ether *e; 764 int qt; 765 int cn; 766 char buf[128]; 767 Conn *c; 768 Buf *bp; 769 770 q = fid->qid; 771 q.path &= ~fs->qid; 772 e = fs->aux; 773 qt = qtype(q.path); 774 cn = qnum(q.path); 775 switch(qt){ 776 case Qndata: 777 c = getconn(e, cn, 0); 778 if(c == nil){ 779 werrstr(Eio); 780 return -1; 781 } 782 bp = allocbuf(e); 783 if(count > sizeof(bp->data)-Hdrsize) 784 count = sizeof(bp->data)-Hdrsize; 785 memmove(bp->rp, data, count); 786 bp->ndata = count; 787 if(etherdebug > 1) 788 dumpframe("etherout", bp->rp, bp->ndata); 789 if(e->nblock == 0) 790 sendp(e->wc, bp); 791 else if(nbsendp(e->wc, bp) < 0){ 792 deprint(2, "%s: (out) packet lost\n", argv0); 793 freebuf(e, bp); 794 } 795 break; 796 case Qnctl: 797 c = getconn(e, cn, 0); 798 if(c == nil){ 799 werrstr(Eio); 800 return -1; 801 } 802 if(count > sizeof(buf) - 1) 803 count = sizeof(buf) - 1; 804 memmove(buf, data, count); 805 buf[count] = 0; 806 if(etherctl(e, c, buf) < 0) 807 return -1; 808 break; 809 default: 810 sysfatal("usb: ether: fsread bug"); 811 } 812 return count; 813 } 814 815 static int 816 openeps(Ether *e, int epin, int epout) 817 { 818 e->epin = openep(e->dev, epin); 819 if(e->epin == nil){ 820 fprint(2, "ether: in: openep %d: %r\n", epin); 821 return -1; 822 } 823 if(epout == epin){ 824 incref(e->epin); 825 e->epout = e->epin; 826 }else 827 e->epout = openep(e->dev, epout); 828 if(e->epout == nil){ 829 fprint(2, "ether: out: openep %d: %r\n", epout); 830 closedev(e->epin); 831 return -1; 832 } 833 if(e->epin == e->epout) 834 opendevdata(e->epin, ORDWR); 835 else{ 836 opendevdata(e->epin, OREAD); 837 opendevdata(e->epout, OWRITE); 838 } 839 if(e->epin->dfd < 0 || e->epout->dfd < 0){ 840 fprint(2, "ether: open i/o ep data: %r\n"); 841 closedev(e->epin); 842 closedev(e->epout); 843 return -1; 844 } 845 dprint(2, "ether: ep in %s out %s\n", e->epin->dir, e->epout->dir); 846 847 if(usbdebug > 2 || etherdebug > 2){ 848 devctl(e->epin, "debug 1"); 849 devctl(e->epout, "debug 1"); 850 devctl(e->dev, "debug 1"); 851 } 852 return 0; 853 } 854 855 static int 856 usage(void) 857 { 858 werrstr("usage: usb/ether [-d]"); 859 return -1; 860 } 861 862 static Usbfs etherfs = { 863 .walk = fswalk, 864 .open = fsopen, 865 .read = fsread, 866 .write = fswrite, 867 .stat = fsstat, 868 .clunk = fsclunk, 869 }; 870 871 static void 872 etherfree(Ether *e) 873 { 874 int i; 875 Buf *bp; 876 877 if(e->free != nil) 878 e->free(e); 879 closedev(e->epin); 880 closedev(e->epout); 881 if(e->rc == nil){ 882 free(e); 883 return; 884 } 885 for(i = 0; i < e->nconns; i++) 886 if(e->conns[i] != nil){ 887 while((bp = nbrecvp(e->conns[i]->rc)) != nil) 888 free(bp); 889 chanfree(e->conns[i]->rc); 890 free(e->conns[i]); 891 } 892 while((bp = nbrecvp(e->bc)) != nil) 893 free(bp); 894 chanfree(e->bc); 895 chanfree(e->rc); 896 /* chanfree(e->wc); released by writeproc */ 897 e->epin = e->epout = nil; 898 free(e); 899 900 } 901 902 /* must return 1 if c wants bp; 0 if not */ 903 static int 904 cwantsbp(Conn *c, Buf *bp) 905 { 906 if(c->ref != 0 && (c->prom != 0 || c->type < 0 || c->type == bp->type)) 907 return 1; 908 return 0; 909 } 910 911 static void 912 etherwriteproc(void *a) 913 { 914 Ether *e = a; 915 Buf *bp; 916 Channel *wc; 917 918 wc = e->wc; 919 while(e->exiting == 0){ 920 bp = recvp(wc); 921 if(bp == nil || e->exiting != 0) 922 break; 923 e->nout++; 924 if(e->bwrite(e, bp) < 0) 925 e->noerrs++; 926 if(isloopback(e, bp)) 927 sendp(e->rc, bp); /* send to input queue */ 928 else 929 freebuf(e, bp); 930 } 931 while((bp = nbrecvp(wc)) != nil) 932 free(bp); 933 chanfree(wc); 934 deprint(2, "%s: writeproc exiting\n", argv0); 935 } 936 937 static void 938 etherreadproc(void *a) 939 { 940 Ether *e = a; 941 int i; 942 int n; 943 Buf *bp; 944 Buf *dbp; 945 int nwants; 946 947 while(e->exiting == 0){ 948 bp = nbrecvp(e->rc); 949 if(bp == nil){ 950 bp = allocbuf(e); /* seems to leak bps kept at bc */ 951 if(e->bread(e, bp) < 0){ 952 freebuf(e, bp); 953 break; 954 } 955 if(bp->ndata == 0){ 956 /* may be a short packet; continue */ 957 if(0)dprint(2, "%s: read: short\n", argv0); 958 freebuf(e, bp); 959 continue; 960 } 961 } 962 e->nin++; 963 nwants = 0; 964 for(i = 0; i < e->nconns; i++) 965 nwants += cwantsbp(e->conns[i], bp); 966 for(i = 0; nwants > 0 && i < e->nconns; i++) 967 if(cwantsbp(e->conns[i], bp)){ 968 n = bp->ndata; 969 if(e->conns[i]->type == -2 && n > 64) 970 n = 64; 971 if(nwants-- == 1){ 972 bp->ndata = n; 973 dbp = bp; 974 bp = nil; 975 }else{ 976 dbp = allocbuf(e); 977 memmove(dbp->rp, bp->rp, n); 978 dbp->ndata = n; 979 } 980 if(nbsendp(e->conns[i]->rc, dbp) < 0){ 981 e->nierrs++; 982 freebuf(e, dbp); 983 } 984 } 985 freebuf(e, bp); 986 } 987 while(e->exiting == 0) /* give them time... */ 988 yield(); 989 while((bp = nbrecvp(e->rc)) != nil) 990 free(bp); 991 deprint(2, "%s: writeproc exiting\n", argv0); 992 etherfree(e); 993 } 994 995 static void 996 etherdevfree(void *a) 997 { 998 Ether *e = a; 999 1000 if(e == nil) 1001 return; 1002 if(e->free != nil) 1003 e->free(e); 1004 if(e->rc == nil){ 1005 /* no readproc; free everything ourselves */ 1006 etherfree(e); 1007 return; 1008 } 1009 /* ether resources released by etherreadproc 1010 * It will exit its main look for sure, because 1011 * the endpoints must be detached by now. 1012 */ 1013 close(e->epin->dfd); 1014 e->epin->dfd = -1; 1015 close(e->epout->dfd); 1016 e->epout->dfd = -1; 1017 e->exiting = 1; 1018 } 1019 1020 static void 1021 setalt(Dev *d, int ifcid, int altid) 1022 { 1023 int r; 1024 1025 r = Rh2d|Rstd|Riface; 1026 if(usbcmd(d, r, Rsetiface, altid, ifcid, nil, 0) < 0) 1027 dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid); 1028 } 1029 1030 static int 1031 ifaceinit(Ether *e, Iface *ifc, int *ei, int *eo) 1032 { 1033 int i; 1034 Ep *ep; 1035 int epin; 1036 int epout; 1037 int altid; 1038 1039 if(ifc == nil) 1040 return -1; 1041 1042 altid = epin = epout = -1; 1043 for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++) 1044 if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){ 1045 if(ep->dir == Eboth || ep->dir == Ein) 1046 if(epin == -1) 1047 epin = ep->id; 1048 if(ep->dir == Eboth || ep->dir == Eout) 1049 if(epout == -1) 1050 epout = ep->id; 1051 } 1052 if(epin == -1 || epout == -1) 1053 return -1; 1054 dprint(2, "ether: ep ids: in %d out %d\n", epin, epout); 1055 for(i = 0; i < nelem(ifc->altc); i++) 1056 if(ifc->altc[i] != nil){ 1057 altid = ifc->altc[i]->attrib; 1058 break; 1059 } 1060 if(altid != -1) 1061 setalt(e->dev, ifc->id, altid); 1062 1063 *ei = epin; 1064 *eo = epout; 1065 return 0; 1066 } 1067 1068 static int 1069 etherinit(Ether *e, int *ei, int *eo) 1070 { 1071 Usbdev *ud; 1072 Conf *c; 1073 int i; 1074 int j; 1075 1076 *ei = *eo = -1; 1077 ud = e->dev->usb; 1078 for(i = 0; i < nelem(ud->conf); i++) 1079 if((c = ud->conf[i]) != nil) 1080 for(j = 0; j < nelem(c->iface); j++) 1081 if(ifaceinit(e,c->iface[j],ei,eo) != -1) 1082 return 0; 1083 dprint(2, "%s: no valid endpoints", argv0); 1084 return -1; 1085 } 1086 1087 int 1088 ethermain(Dev *dev, int argc, char **argv) 1089 { 1090 Ether *e; 1091 int epin; 1092 int epout; 1093 int i; 1094 1095 ARGBEGIN{ 1096 case 'd': 1097 if(etherdebug == 0) 1098 fprint(2, "ether debug on\n"); 1099 etherdebug++; 1100 break; 1101 default: 1102 return usage(); 1103 }ARGEND 1104 if(argc != 0) 1105 return usage(); 1106 1107 e = dev->aux = emallocz(sizeof(Ether), 1); 1108 e->dev = dev; 1109 dev->free = etherdevfree; 1110 1111 for(i = 0; i < nelem(ethers); i++) 1112 if(ethers[i](e) == 0) 1113 break; 1114 if(i == nelem(ethers)) 1115 return -1; 1116 if(e->init == nil) 1117 e->init = etherinit; 1118 if(e->init(e, &epin, &epout) < 0) 1119 return -1; 1120 if(e->bwrite == nil) 1121 e->bwrite = etherbwrite; 1122 if(e->bread == nil) 1123 e->bread = etherbread; 1124 1125 if(openeps(e, epin, epout) < 0) 1126 return -1; 1127 e->fs = etherfs; 1128 snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", dev->id); 1129 e->fs.dev = dev; 1130 e->fs.aux = e; 1131 e->bc = chancreate(sizeof(Buf*), Nconns); 1132 e->rc = chancreate(sizeof(Buf*), Nconns/2); 1133 e->wc = chancreate(sizeof(Buf*), Nconns*2); 1134 proccreate(etherwriteproc, e, 16*1024); 1135 proccreate(etherreadproc, e, 16*1024); 1136 deprint(2, "%s: dev ref %ld\n", argv0, dev->ref); 1137 usbfsadd(&e->fs); 1138 return 0; 1139 } 1140