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: %s\n", e->exiting ? "y" : "n"); 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 int cn, i; 373 char *es; 374 Dirtab *tab; 375 Ether *e; 376 Qid qid; 377 378 e = fs->aux; 379 qid = fid->qid; 380 qid.path &= ~fs->qid; 381 if((qid.type & QTDIR) == 0){ 382 werrstr("walk in non-directory"); 383 return -1; 384 } 385 386 if(strcmp(name, "..") == 0){ 387 /* must be /etherU%d; i.e. our root dir. */ 388 fid->qid.path = mkqid(0, Qroot) | fs->qid; 389 fid->qid.vers = 0; 390 fid->qid.type = QTDIR; 391 return 0; 392 } 393 switch(qtype(qid.path)){ 394 case Qroot: 395 if(name[0] >= '0' && name[0] <= '9'){ 396 es = name; 397 cn = strtoul(name, &es, 10); 398 if(cn >= e->nconns || *es != 0){ 399 werrstr(Enotfound); 400 return -1; 401 } 402 fid->qid.path = mkqid(cn, Qndir) | fs->qid; 403 fid->qid.vers = 0; 404 return 0; 405 } 406 /* fall */ 407 case Qndir: 408 if(qtype(qid.path) == Qroot) 409 tab = rootdirtab; 410 else 411 tab = conndirtab; 412 cn = qnum(qid.path); 413 for(i = 0; tab[i].name != nil; tab++) 414 if(strcmp(tab[i].name, name) == 0){ 415 fid->qid.path = mkqid(cn, tab[i].qid)|fs->qid; 416 fid->qid.vers = 0; 417 if((tab[i].mode & DMDIR) != 0) 418 fid->qid.type = QTDIR; 419 else 420 fid->qid.type = QTFILE; 421 return 0; 422 } 423 break; 424 default: 425 sysfatal("usb: ether: fswalk bug"); 426 } 427 return -1; 428 } 429 430 static Dirtab* 431 qdirtab(vlong q) 432 { 433 int i, qt; 434 Dirtab *tab; 435 436 qt = qtype(q); 437 if(qt < nelem(rootdirtab) - 1){ /* null terminated */ 438 tab = rootdirtab; 439 i = qt; 440 }else{ 441 tab = conndirtab; 442 i = qt - (nelem(rootdirtab) - 1); 443 assert(i < nelem(conndirtab) - 1); 444 } 445 return &tab[i]; 446 } 447 448 static int 449 fsstat(Usbfs *fs, Qid qid, Dir *d) 450 { 451 filldir(fs, d, qdirtab(qid.path), qnum(qid.path)); 452 return 0; 453 } 454 455 static int 456 fsopen(Usbfs *fs, Fid *fid, int omode) 457 { 458 int qt; 459 vlong qid; 460 Conn *c; 461 Dirtab *tab; 462 Ether *e; 463 464 qid = fid->qid.path & ~fs->qid; 465 e = fs->aux; 466 qt = qtype(qid); 467 tab = qdirtab(qid); 468 omode &= 3; 469 if(omode != OREAD && (tab->mode&0222) == 0){ 470 werrstr(Eperm); 471 return -1; 472 } 473 switch(qt){ 474 case Qclone: 475 c = newconn(e); 476 if(c == nil){ 477 werrstr("no more connections"); 478 return -1; 479 } 480 fid->qid.type = QTFILE; 481 fid->qid.path = mkqid(c->nb, Qnctl)|fs->qid; 482 fid->qid.vers = 0; 483 break; 484 case Qndata: 485 case Qnctl: 486 case Qnifstats: 487 case Qnstats: 488 case Qntype: 489 c = getconn(e, qnum(qid), 1); 490 if(c == nil) 491 sysfatal("usb: ether: fsopen bug"); 492 incref(c); 493 break; 494 } 495 etherdump(e); 496 return 0; 497 } 498 499 static int 500 prom(Ether *e, int set) 501 { 502 if(e->promiscuous != nil) 503 return e->promiscuous(e, set); 504 return 0; 505 } 506 507 static void 508 fsclunk(Usbfs *fs, Fid *fid) 509 { 510 int qt; 511 vlong qid; 512 Buf *bp; 513 Conn *c; 514 Ether *e; 515 516 e = fs->aux; 517 qid = fid->qid.path & ~fs->qid; 518 qt = qtype(qid); 519 switch(qt){ 520 case Qndata: 521 case Qnctl: 522 case Qnifstats: 523 case Qnstats: 524 case Qntype: 525 if(fid->omode != ONONE){ 526 c = getconn(e, qnum(qid), 0); 527 if(c == nil) 528 sysfatal("usb: ether: fsopen bug"); 529 if(decref(c) == 0){ 530 while((bp = nbrecvp(c->rc)) != nil) 531 freebuf(e, bp); 532 qlock(e); 533 if(c->prom != 0) 534 if(decref(&e->prom) == 0) 535 prom(e, 0); 536 c->prom = c->type = 0; 537 qunlock(e); 538 } 539 } 540 break; 541 } 542 etherdump(e); 543 } 544 545 int 546 parseaddr(uchar *m, char *s) 547 { 548 int i, n; 549 uchar v; 550 551 if(strlen(s) < 12) 552 return -1; 553 if(strlen(s) > 12 && strlen(s) < 17) 554 return -1; 555 for(i = n = 0; i < strlen(s); i++){ 556 if(s[i] == ':') 557 continue; 558 if(s[i] >= 'A' && s[i] <= 'F') 559 v = 10 + s[i] - 'A'; 560 else if(s[i] >= 'a' && s[i] <= 'f') 561 v = 10 + s[i] - 'a'; 562 else if(s[i] >= '0' && s[i] <= '9') 563 v = s[i] - '0'; 564 else 565 return -1; 566 if(n&1) 567 m[n/2] |= v; 568 else 569 m[n/2] = v<<4; 570 n++; 571 } 572 return 0; 573 } 574 575 static long 576 fsread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 577 { 578 int cn, qt; 579 char *s, *se; 580 char buf[128]; 581 Buf *bp; 582 Conn *c; 583 Ether *e; 584 Qid q; 585 586 q = fid->qid; 587 q.path &= ~fs->qid; 588 e = fs->aux; 589 s = buf; 590 se = buf+sizeof(buf); 591 qt = qtype(q.path); 592 cn = qnum(q.path); 593 switch(qt){ 594 case Qroot: 595 count = usbdirread(fs, q, data, count, offset, rootdirgen, nil); 596 break; 597 case Qaddr: 598 s = seprintaddr(s, se, e->addr); 599 count = usbreadbuf(data, count, offset, buf, s - buf); 600 break; 601 case Qnifstats: 602 /* BUG */ 603 case Qifstats: 604 s = seprintifstats(s, se, e); 605 if(e->seprintstats != nil) 606 s = e->seprintstats(s, se, e); 607 count = usbreadbuf(data, count, offset, buf, s - buf); 608 break; 609 case Qnstats: 610 /* BUG */ 611 case Qstats: 612 s = seprintstats(s, se, e); 613 count = usbreadbuf(data, count, offset, buf, s - buf); 614 break; 615 616 case Qndir: 617 count = usbdirread(fs, q, data, count, offset, conndirgen, nil); 618 break; 619 case Qndata: 620 c = getconn(e, cn, 0); 621 if(c == nil){ 622 werrstr(Eio); 623 return -1; 624 } 625 bp = recvp(c->rc); 626 if(bp == nil) 627 return -1; 628 if(etherdebug > 1) 629 dumpframe("etherin", bp->rp, bp->ndata); 630 count = usbreadbuf(data, count, 0LL, bp->rp, bp->ndata); 631 freebuf(e, bp); 632 break; 633 case Qnctl: 634 s = seprint(s, se, "%11d ", cn); 635 count = usbreadbuf(data, count, offset, buf, s - buf); 636 break; 637 case Qntype: 638 c = getconn(e, cn, 0); 639 if(c == nil) 640 s = seprint(s, se, "%11d ", 0); 641 else 642 s = seprint(s, se, "%11d ", c->type); 643 count = usbreadbuf(data, count, offset, buf, s - buf); 644 break; 645 default: 646 sysfatal("usb: ether: fsread bug"); 647 } 648 return count; 649 } 650 651 static int 652 typeinuse(Ether *e, int t) 653 { 654 int i; 655 656 for(i = 0; i < e->nconns; i++) 657 if(e->conns[i]->ref > 0 && e->conns[i]->type == t) 658 return 1; 659 return 0; 660 } 661 662 static int 663 isloopback(Ether *e, Buf *) 664 { 665 return e->prom.ref > 0; /* BUG: also loopbacks and broadcasts */ 666 } 667 668 static int 669 etherctl(Ether *e, Conn *c, char *buf) 670 { 671 uchar addr[Eaddrlen]; 672 int t; 673 674 deprint(2, "%s: etherctl: %s\n", argv0, buf); 675 if(strncmp(buf, "connect ", 8) == 0){ 676 t = atoi(buf+8); 677 qlock(e); 678 if(typeinuse(e, t)){ 679 werrstr("type already in use"); 680 qunlock(e); 681 return -1; 682 } 683 c->type = atoi(buf+8); 684 qunlock(e); 685 return 0; 686 } 687 if(strncmp(buf, "nonblocking", 11) == 0){ 688 if(buf[11] == '\n' || buf[11] == 0) 689 e->nblock = 1; 690 else 691 e->nblock = atoi(buf + 12); 692 deprint(2, "%s: nblock %d\n", argv0, e->nblock); 693 return 0; 694 } 695 if(strncmp(buf, "promiscuous", 11) == 0){ 696 if(c->prom == 0) 697 incref(&e->prom); 698 c->prom = 1; 699 return prom(e, 1); 700 } 701 if(strncmp(buf, "headersonly", 11) == 0){ 702 c->headersonly = 1; 703 return 0; 704 } 705 if(strncmp(buf, "addmulti ", 9) == 0 || strncmp(buf, "remmulti ", 9) == 0){ 706 if(parseaddr(addr, buf+9) < 0){ 707 werrstr("bad address"); 708 return -1; 709 } 710 if(e->multicast == nil) 711 return 0; 712 if(strncmp(buf, "add", 3) == 0){ 713 e->nmcasts++; 714 return e->multicast(e, addr, 1); 715 }else{ 716 e->nmcasts--; 717 return e->multicast(e, addr, 0); 718 } 719 } 720 721 if(e->ctl != nil) 722 return e->ctl(e, buf); 723 werrstr(Ebadctl); 724 return -1; 725 } 726 727 static long 728 etherbread(Ether *e, Buf *bp) 729 { 730 deprint(2, "%s: etherbread\n", argv0); 731 bp->rp = bp->data + Hdrsize; 732 bp->ndata = -1; 733 bp->ndata = read(e->epin->dfd, bp->rp, sizeof(bp->data)-Hdrsize); 734 if(bp->ndata < 0) 735 deprint(2, "%s: etherbread: %r\n", argv0); 736 else 737 deprint(2, "%s: etherbread: got %d bytes\n", argv0, bp->ndata); 738 return bp->ndata; 739 } 740 741 static long 742 etherbwrite(Ether *e, Buf *bp) 743 { 744 long n; 745 746 deprint(2, "%s: etherbwrite %d bytes\n", argv0, bp->ndata); 747 n = write(e->epout->dfd, bp->rp, bp->ndata); 748 if(n < 0) 749 deprint(2, "%s: etherbwrite: %r\n", argv0); 750 else 751 deprint(2, "%s: etherbwrite wrote %ld bytes\n", argv0, n); 752 if(n <= 0) 753 return n; 754 if((bp->ndata % e->epout->maxpkt) == 0){ 755 deprint(2, "%s: short pkt write\n", argv0); 756 write(e->epout->dfd, "", 1); 757 } 758 return n; 759 } 760 761 static long 762 fswrite(Usbfs *fs, Fid *fid, void *data, long count, vlong) 763 { 764 int cn, qt; 765 char buf[128]; 766 Buf *bp; 767 Conn *c; 768 Ether *e; 769 Qid q; 770 771 q = fid->qid; 772 q.path &= ~fs->qid; 773 e = fs->aux; 774 qt = qtype(q.path); 775 cn = qnum(q.path); 776 switch(qt){ 777 case Qndata: 778 c = getconn(e, cn, 0); 779 if(c == nil){ 780 werrstr(Eio); 781 return -1; 782 } 783 bp = allocbuf(e); 784 if(count > sizeof(bp->data)-Hdrsize) 785 count = sizeof(bp->data)-Hdrsize; 786 memmove(bp->rp, data, count); 787 bp->ndata = count; 788 if(etherdebug > 1) 789 dumpframe("etherout", bp->rp, bp->ndata); 790 if(e->nblock == 0) 791 sendp(e->wc, bp); 792 else if(nbsendp(e->wc, bp) < 0){ 793 deprint(2, "%s: (out) packet lost\n", argv0); 794 freebuf(e, bp); 795 } 796 break; 797 case Qnctl: 798 c = getconn(e, cn, 0); 799 if(c == nil){ 800 werrstr(Eio); 801 return -1; 802 } 803 if(count > sizeof(buf) - 1) 804 count = sizeof(buf) - 1; 805 memmove(buf, data, count); 806 buf[count] = 0; 807 if(etherctl(e, c, buf) < 0) 808 return -1; 809 break; 810 default: 811 sysfatal("usb: ether: fsread bug"); 812 } 813 return count; 814 } 815 816 static int 817 openeps(Ether *e, int epin, int epout) 818 { 819 e->epin = openep(e->dev, epin); 820 if(e->epin == nil){ 821 fprint(2, "ether: in: openep %d: %r\n", epin); 822 return -1; 823 } 824 if(epout == epin){ 825 incref(e->epin); 826 e->epout = e->epin; 827 }else 828 e->epout = openep(e->dev, epout); 829 if(e->epout == nil){ 830 fprint(2, "ether: out: openep %d: %r\n", epout); 831 closedev(e->epin); 832 return -1; 833 } 834 if(e->epin == e->epout) 835 opendevdata(e->epin, ORDWR); 836 else{ 837 opendevdata(e->epin, OREAD); 838 opendevdata(e->epout, OWRITE); 839 } 840 if(e->epin->dfd < 0 || e->epout->dfd < 0){ 841 fprint(2, "ether: open i/o ep data: %r\n"); 842 closedev(e->epin); 843 closedev(e->epout); 844 return -1; 845 } 846 dprint(2, "ether: ep in %s maxpkt %d; ep out %s maxpkt %d\n", 847 e->epin->dir, e->epin->maxpkt, e->epout->dir, e->epout->maxpkt); 848 849 /* time outs are not activated for I/O endpoints */ 850 851 if(usbdebug > 2 || etherdebug > 2){ 852 devctl(e->epin, "debug 1"); 853 devctl(e->epout, "debug 1"); 854 devctl(e->dev, "debug 1"); 855 } 856 857 return 0; 858 } 859 860 static int 861 usage(void) 862 { 863 werrstr("usage: usb/ether [-d]"); 864 return -1; 865 } 866 867 static Usbfs etherfs = { 868 .walk = fswalk, 869 .open = fsopen, 870 .read = fsread, 871 .write = fswrite, 872 .stat = fsstat, 873 .clunk = fsclunk, 874 }; 875 876 static void 877 shutdownchan(Channel *c) 878 { 879 Buf *bp; 880 881 while((bp=nbrecvp(c)) != nil) 882 free(bp); 883 chanfree(c); 884 } 885 886 static void 887 etherfree(Ether *e) 888 { 889 int i; 890 Buf *bp; 891 892 if(e->free != nil) 893 e->free(e); 894 closedev(e->epin); 895 closedev(e->epout); 896 if(e->rc == nil){ /* not really started */ 897 free(e); 898 return; 899 } 900 for(i = 0; i < e->nconns; i++) 901 if(e->conns[i] != nil){ 902 while((bp = nbrecvp(e->conns[i]->rc)) != nil) 903 free(bp); 904 chanfree(e->conns[i]->rc); 905 free(e->conns[i]); 906 } 907 shutdownchan(e->bc); 908 shutdownchan(e->rc); 909 shutdownchan(e->wc); 910 e->epin = e->epout = nil; 911 free(e); 912 913 } 914 915 static void 916 etherdevfree(void *a) 917 { 918 Ether *e = a; 919 920 if(e != nil) 921 etherfree(e); 922 } 923 924 /* must return 1 if c wants bp; 0 if not */ 925 static int 926 cwantsbp(Conn *c, Buf *bp) 927 { 928 if(c->ref != 0 && (c->prom != 0 || c->type < 0 || c->type == bp->type)) 929 return 1; 930 return 0; 931 } 932 933 static void 934 etherwriteproc(void *a) 935 { 936 Ether *e = a; 937 Buf *bp; 938 Channel *wc; 939 940 wc = e->wc; 941 while(e->exiting == 0){ 942 bp = recvp(wc); 943 if(bp == nil || e->exiting != 0) 944 break; 945 e->nout++; 946 if(e->bwrite(e, bp) < 0) 947 e->noerrs++; 948 if(isloopback(e, bp) && e->exiting == 0) 949 sendp(e->rc, bp); /* send to input queue */ 950 else 951 freebuf(e, bp); 952 } 953 deprint(2, "%s: writeproc exiting\n", argv0); 954 closedev(e->dev); 955 } 956 957 static void 958 setbuftype(Buf *bp) 959 { 960 uchar *p; 961 962 bp->type = 0; 963 if(bp->ndata >= Ehdrsize){ 964 p = bp->rp + Eaddrlen*2; 965 bp->type = p[0]<<8 | p[1]; 966 } 967 } 968 969 static void 970 etherexiting(Ether *e) 971 { 972 devctl(e->dev, "detach"); 973 e->exiting = 1; 974 close(e->epin->dfd); 975 e->epin->dfd = -1; 976 close(e->epout->dfd); 977 e->epout->dfd = -1; 978 nbsend(e->wc, nil); 979 } 980 981 static void 982 etherreadproc(void *a) 983 { 984 int i, n, nwants; 985 Buf *bp, *dbp; 986 Ether *e = a; 987 988 while(e->exiting == 0){ 989 bp = nbrecvp(e->rc); 990 if(bp == nil){ 991 bp = allocbuf(e); /* leak() may think we leak */ 992 if(e->bread(e, bp) < 0){ 993 freebuf(e, bp); 994 break; 995 } 996 if(bp->ndata == 0){ 997 /* may be a short packet; continue */ 998 if(0)dprint(2, "%s: read: short\n", argv0); 999 freebuf(e, bp); 1000 continue; 1001 }else 1002 setbuftype(bp); 1003 } 1004 e->nin++; 1005 nwants = 0; 1006 for(i = 0; i < e->nconns; i++) 1007 nwants += cwantsbp(e->conns[i], bp); 1008 for(i = 0; nwants > 0 && i < e->nconns; i++) 1009 if(cwantsbp(e->conns[i], bp)){ 1010 n = bp->ndata; 1011 if(e->conns[i]->type == -2 && n > 64) 1012 n = 64; 1013 if(nwants-- == 1){ 1014 bp->ndata = n; 1015 dbp = bp; 1016 bp = nil; 1017 }else{ 1018 dbp = allocbuf(e); 1019 memmove(dbp->rp, bp->rp, n); 1020 dbp->ndata = n; 1021 dbp->type = bp->type; 1022 } 1023 if(nbsendp(e->conns[i]->rc, dbp) < 0){ 1024 e->nierrs++; 1025 freebuf(e, dbp); 1026 } 1027 } 1028 freebuf(e, bp); 1029 } 1030 deprint(2, "%s: writeproc exiting\n", argv0); 1031 etherexiting(e); 1032 closedev(e->dev); 1033 } 1034 1035 static void 1036 setalt(Dev *d, int ifcid, int altid) 1037 { 1038 if(usbcmd(d, Rh2d|Rstd|Riface, Rsetiface, altid, ifcid, nil, 0) < 0) 1039 dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid); 1040 } 1041 1042 static int 1043 ifaceinit(Ether *e, Iface *ifc, int *ei, int *eo) 1044 { 1045 Ep *ep; 1046 int epin, epout, i; 1047 1048 if(ifc == nil) 1049 return -1; 1050 1051 epin = epout = -1; 1052 for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++) 1053 if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){ 1054 if(ep->dir == Eboth || ep->dir == Ein) 1055 if(epin == -1) 1056 epin = ep->id; 1057 if(ep->dir == Eboth || ep->dir == Eout) 1058 if(epout == -1) 1059 epout = ep->id; 1060 } 1061 if(epin == -1 || epout == -1) 1062 return -1; 1063 1064 dprint(2, "ether: ep ids: in %d out %d\n", epin, epout); 1065 for(i = 0; i < nelem(ifc->altc); i++) 1066 if(ifc->altc[i] != nil) 1067 setalt(e->dev, ifc->id, i); 1068 1069 *ei = epin; 1070 *eo = epout; 1071 return 0; 1072 } 1073 1074 static int 1075 etherinit(Ether *e, int *ei, int *eo) 1076 { 1077 int ctlid, datid, i, j; 1078 Conf *c; 1079 Desc *desc; 1080 Iface *ctlif, *datif; 1081 Usbdev *ud; 1082 1083 *ei = *eo = -1; 1084 ud = e->dev->usb; 1085 1086 /* look for union descriptor with ethernet ctrl interface */ 1087 for(i = 0; i < nelem(ud->ddesc); i++){ 1088 if((desc = ud->ddesc[i]) == nil) 1089 continue; 1090 if(desc->data.bLength < 5 || desc->data.bbytes[0] != Cdcunion) 1091 continue; 1092 1093 ctlid = desc->data.bbytes[1]; 1094 datid = desc->data.bbytes[2]; 1095 1096 if((c = desc->conf) == nil) 1097 continue; 1098 1099 ctlif = datif = nil; 1100 for(j = 0; j < nelem(c->iface); j++){ 1101 if(c->iface[j] == nil) 1102 continue; 1103 if(c->iface[j]->id == ctlid) 1104 ctlif = c->iface[j]; 1105 if(c->iface[j]->id == datid) 1106 datif = c->iface[j]; 1107 1108 if(datif != nil && ctlif != nil){ 1109 if(Subclass(ctlif->csp) == Scether && 1110 ifaceinit(e, datif, ei, eo) != -1) 1111 return 0; 1112 break; 1113 } 1114 } 1115 } 1116 /* try any other one that seems to be ok */ 1117 for(i = 0; i < nelem(ud->conf); i++) 1118 if((c = ud->conf[i]) != nil) 1119 for(j = 0; j < nelem(c->iface); j++) 1120 if(ifaceinit(e, c->iface[j], ei, eo) != -1) 1121 return 0; 1122 dprint(2, "%s: no valid endpoints", argv0); 1123 return -1; 1124 } 1125 1126 int 1127 ethermain(Dev *dev, int argc, char **argv) 1128 { 1129 int epin, epout, i; 1130 Ether *e; 1131 1132 ARGBEGIN{ 1133 case 'd': 1134 if(etherdebug == 0) 1135 fprint(2, "ether debug on\n"); 1136 etherdebug++; 1137 break; 1138 default: 1139 return usage(); 1140 }ARGEND 1141 if(argc != 0) 1142 return usage(); 1143 1144 e = dev->aux = emallocz(sizeof(Ether), 1); 1145 e->dev = dev; 1146 dev->free = etherdevfree; 1147 1148 for(i = 0; i < nelem(ethers); i++) 1149 if(ethers[i](e) == 0) 1150 break; 1151 if(i == nelem(ethers)) 1152 return -1; 1153 if(e->init == nil) 1154 e->init = etherinit; 1155 if(e->init(e, &epin, &epout) < 0) 1156 return -1; 1157 if(e->bwrite == nil) 1158 e->bwrite = etherbwrite; 1159 if(e->bread == nil) 1160 e->bread = etherbread; 1161 1162 if(openeps(e, epin, epout) < 0) 1163 return -1; 1164 e->fs = etherfs; 1165 snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", dev->id); 1166 e->fs.dev = dev; 1167 e->fs.aux = e; 1168 e->bc = chancreate(sizeof(Buf*), Nconns); 1169 e->rc = chancreate(sizeof(Buf*), Nconns/2); 1170 e->wc = chancreate(sizeof(Buf*), Nconns*2); 1171 incref(e->dev); 1172 proccreate(etherwriteproc, e, 16*1024); 1173 incref(e->dev); 1174 proccreate(etherreadproc, e, 16*1024); 1175 deprint(2, "%s: dev ref %ld\n", argv0, dev->ref); 1176 usbfsadd(&e->fs); 1177 return 0; 1178 } 1179