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 static int 355 conndirgen(Usbfs *fs, Qid q, int i, Dir *d, void *) 356 { 357 Dirtab *tab; 358 359 i++; /* skip root */ 360 if(i < nelem(conndirtab) - 1) /* null terminated */ 361 tab = &conndirtab[i]; 362 else 363 return -1; 364 filldir(fs, d, tab, qnum(q.path)); 365 return 0; 366 } 367 368 static int 369 fswalk(Usbfs *fs, Fid *fid, char *name) 370 { 371 int cn, i; 372 char *es; 373 Dirtab *tab; 374 Ether *e; 375 Qid qid; 376 377 e = fs->aux; 378 qid = fid->qid; 379 qid.path &= ~fs->qid; 380 if((qid.type & QTDIR) == 0){ 381 werrstr("walk in non-directory"); 382 return -1; 383 } 384 385 if(strcmp(name, "..") == 0){ 386 /* must be /etherU%d; i.e. our root dir. */ 387 fid->qid.path = mkqid(0, Qroot) | fs->qid; 388 fid->qid.vers = 0; 389 fid->qid.type = QTDIR; 390 return 0; 391 } 392 switch(qtype(qid.path)){ 393 case Qroot: 394 if(name[0] >= '0' && name[0] <= '9'){ 395 es = name; 396 cn = strtoul(name, &es, 10); 397 if(cn >= e->nconns || *es != 0){ 398 werrstr(Enotfound); 399 return -1; 400 } 401 fid->qid.path = mkqid(cn, Qndir) | fs->qid; 402 fid->qid.vers = 0; 403 return 0; 404 } 405 /* fall */ 406 case Qndir: 407 if(qtype(qid.path) == Qroot) 408 tab = rootdirtab; 409 else 410 tab = conndirtab; 411 cn = qnum(qid.path); 412 for(i = 0; tab[i].name != nil; tab++) 413 if(strcmp(tab[i].name, name) == 0){ 414 fid->qid.path = mkqid(cn, tab[i].qid)|fs->qid; 415 fid->qid.vers = 0; 416 if((tab[i].mode & DMDIR) != 0) 417 fid->qid.type = QTDIR; 418 else 419 fid->qid.type = QTFILE; 420 return 0; 421 } 422 break; 423 default: 424 sysfatal("usb: ether: fswalk bug"); 425 } 426 return -1; 427 } 428 429 static Dirtab* 430 qdirtab(vlong q) 431 { 432 int i, qt; 433 Dirtab *tab; 434 435 qt = qtype(q); 436 if(qt < nelem(rootdirtab) - 1){ /* null terminated */ 437 tab = rootdirtab; 438 i = qt; 439 }else{ 440 tab = conndirtab; 441 i = qt - (nelem(rootdirtab) - 1); 442 assert(i < nelem(conndirtab) - 1); 443 } 444 return &tab[i]; 445 } 446 447 static int 448 fsstat(Usbfs *fs, Qid qid, Dir *d) 449 { 450 filldir(fs, d, qdirtab(qid.path), qnum(qid.path)); 451 return 0; 452 } 453 454 static int 455 fsopen(Usbfs *fs, Fid *fid, int omode) 456 { 457 int qt; 458 vlong qid; 459 Conn *c; 460 Dirtab *tab; 461 Ether *e; 462 463 qid = fid->qid.path & ~fs->qid; 464 e = fs->aux; 465 qt = qtype(qid); 466 tab = qdirtab(qid); 467 omode &= 3; 468 if(omode != OREAD && (tab->mode&0222) == 0){ 469 werrstr(Eperm); 470 return -1; 471 } 472 switch(qt){ 473 case Qclone: 474 c = newconn(e); 475 if(c == nil){ 476 werrstr("no more connections"); 477 return -1; 478 } 479 fid->qid.type = QTFILE; 480 fid->qid.path = mkqid(c->nb, Qnctl)|fs->qid; 481 fid->qid.vers = 0; 482 break; 483 case Qndata: 484 case Qnctl: 485 case Qnifstats: 486 case Qnstats: 487 case Qntype: 488 c = getconn(e, qnum(qid), 1); 489 if(c == nil) 490 sysfatal("usb: ether: fsopen bug"); 491 incref(c); 492 break; 493 } 494 etherdump(e); 495 return 0; 496 } 497 498 static int 499 prom(Ether *e, int set) 500 { 501 if(e->promiscuous != nil) 502 return e->promiscuous(e, set); 503 return 0; 504 } 505 506 static void 507 fsclunk(Usbfs *fs, Fid *fid) 508 { 509 int qt; 510 vlong qid; 511 Buf *bp; 512 Conn *c; 513 Ether *e; 514 515 e = fs->aux; 516 qid = fid->qid.path & ~fs->qid; 517 qt = qtype(qid); 518 switch(qt){ 519 case Qndata: 520 case Qnctl: 521 case Qnifstats: 522 case Qnstats: 523 case Qntype: 524 if(fid->omode != ONONE){ 525 c = getconn(e, qnum(qid), 0); 526 if(c == nil) 527 sysfatal("usb: ether: fsopen bug"); 528 if(decref(c) == 0){ 529 while((bp = nbrecvp(c->rc)) != nil) 530 freebuf(e, bp); 531 qlock(e); 532 if(c->prom != 0) 533 if(decref(&e->prom) == 0) 534 prom(e, 0); 535 c->prom = c->type = 0; 536 qunlock(e); 537 } 538 } 539 break; 540 } 541 etherdump(e); 542 } 543 544 int 545 parseaddr(uchar *m, char *s) 546 { 547 int i, n; 548 uchar v; 549 550 if(strlen(s) < 12) 551 return -1; 552 if(strlen(s) > 12 && strlen(s) < 17) 553 return -1; 554 for(i = n = 0; i < strlen(s); i++){ 555 if(s[i] == ':') 556 continue; 557 if(s[i] >= 'A' && s[i] <= 'F') 558 v = 10 + s[i] - 'A'; 559 else if(s[i] >= 'a' && s[i] <= 'f') 560 v = 10 + s[i] - 'a'; 561 else if(s[i] >= '0' && s[i] <= '9') 562 v = s[i] - '0'; 563 else 564 return -1; 565 if(n&1) 566 m[n/2] |= v; 567 else 568 m[n/2] = v<<4; 569 n++; 570 } 571 return 0; 572 } 573 574 static long 575 fsread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 576 { 577 int cn, qt; 578 char *s, *se; 579 char buf[128]; 580 Buf *bp; 581 Conn *c; 582 Ether *e; 583 Qid q; 584 585 q = fid->qid; 586 q.path &= ~fs->qid; 587 e = fs->aux; 588 s = buf; 589 se = buf+sizeof(buf); 590 qt = qtype(q.path); 591 cn = qnum(q.path); 592 switch(qt){ 593 case Qroot: 594 count = usbdirread(fs, q, data, count, offset, rootdirgen, nil); 595 break; 596 case Qaddr: 597 s = seprintaddr(s, se, e->addr); 598 count = usbreadbuf(data, count, offset, buf, s - buf); 599 break; 600 case Qnifstats: 601 /* BUG */ 602 case Qifstats: 603 s = seprintifstats(s, se, e); 604 if(e->seprintstats != nil) 605 s = e->seprintstats(s, se, e); 606 count = usbreadbuf(data, count, offset, buf, s - buf); 607 break; 608 case Qnstats: 609 /* BUG */ 610 case Qstats: 611 s = seprintstats(s, se, e); 612 count = usbreadbuf(data, count, offset, buf, s - buf); 613 break; 614 615 case Qndir: 616 count = usbdirread(fs, q, data, count, offset, conndirgen, nil); 617 break; 618 case Qndata: 619 c = getconn(e, cn, 0); 620 if(c == nil){ 621 werrstr(Eio); 622 return -1; 623 } 624 bp = recvp(c->rc); 625 if(bp == nil) 626 return -1; 627 if(etherdebug > 1) 628 dumpframe("etherin", bp->rp, bp->ndata); 629 count = usbreadbuf(data, count, 0LL, bp->rp, bp->ndata); 630 freebuf(e, bp); 631 break; 632 case Qnctl: 633 s = seprint(s, se, "%11d ", cn); 634 count = usbreadbuf(data, count, offset, buf, s - buf); 635 break; 636 case Qntype: 637 c = getconn(e, cn, 0); 638 if(c == nil) 639 s = seprint(s, se, "%11d ", 0); 640 else 641 s = seprint(s, se, "%11d ", c->type); 642 count = usbreadbuf(data, count, offset, buf, s - buf); 643 break; 644 default: 645 sysfatal("usb: ether: fsread bug"); 646 } 647 return count; 648 } 649 650 static int 651 typeinuse(Ether *e, int t) 652 { 653 int i; 654 655 for(i = 0; i < e->nconns; i++) 656 if(e->conns[i]->ref > 0 && e->conns[i]->type == t) 657 return 1; 658 return 0; 659 } 660 661 static int 662 isloopback(Ether *e, Buf *) 663 { 664 return e->prom.ref > 0; /* BUG: also loopbacks and broadcasts */ 665 } 666 667 static int 668 etherctl(Ether *e, Conn *c, char *buf) 669 { 670 uchar addr[Eaddrlen]; 671 int t; 672 673 deprint(2, "%s: etherctl: %s\n", argv0, buf); 674 if(strncmp(buf, "connect ", 8) == 0){ 675 t = atoi(buf+8); 676 qlock(e); 677 if(typeinuse(e, t)){ 678 werrstr("type already in use"); 679 qunlock(e); 680 return -1; 681 } 682 c->type = atoi(buf+8); 683 qunlock(e); 684 return 0; 685 } 686 if(strncmp(buf, "nonblocking", 11) == 0){ 687 if(buf[11] == '\n' || buf[11] == 0) 688 e->nblock = 1; 689 else 690 e->nblock = atoi(buf + 12); 691 deprint(2, "%s: nblock %d\n", argv0, e->nblock); 692 return 0; 693 } 694 if(strncmp(buf, "promiscuous", 11) == 0){ 695 if(c->prom == 0) 696 incref(&e->prom); 697 c->prom = 1; 698 return prom(e, 1); 699 } 700 if(strncmp(buf, "headersonly", 11) == 0){ 701 c->headersonly = 1; 702 return 0; 703 } 704 if(strncmp(buf, "addmulti ", 9) == 0 || strncmp(buf, "remmulti ", 9) == 0){ 705 if(parseaddr(addr, buf+9) < 0){ 706 werrstr("bad address"); 707 return -1; 708 } 709 if(e->multicast == nil) 710 return 0; 711 if(strncmp(buf, "add", 3) == 0){ 712 e->nmcasts++; 713 return e->multicast(e, addr, 1); 714 }else{ 715 e->nmcasts--; 716 return e->multicast(e, addr, 0); 717 } 718 } 719 720 if(e->ctl != nil) 721 return e->ctl(e, buf); 722 werrstr(Ebadctl); 723 return -1; 724 } 725 726 static long 727 etherbread(Ether *e, Buf *bp) 728 { 729 deprint(2, "%s: etherbread\n", argv0); 730 bp->rp = bp->data + Hdrsize; 731 bp->ndata = -1; 732 bp->ndata = read(e->epin->dfd, bp->rp, sizeof(bp->data)-Hdrsize); 733 if(bp->ndata < 0){ 734 deprint(2, "%s: etherbread: %r\n", argv0); /* keep { and } */ 735 }else 736 deprint(2, "%s: etherbread: got %d bytes\n", argv0, bp->ndata); 737 return bp->ndata; 738 } 739 740 static long 741 etherbwrite(Ether *e, Buf *bp) 742 { 743 long n; 744 745 deprint(2, "%s: etherbwrite %d bytes\n", argv0, bp->ndata); 746 n = write(e->epout->dfd, bp->rp, bp->ndata); 747 if(n < 0){ 748 deprint(2, "%s: etherbwrite: %r\n", argv0); /* keep { and } */ 749 }else 750 deprint(2, "%s: etherbwrite wrote %ld bytes\n", argv0, n); 751 if(n <= 0) 752 return n; 753 if((bp->ndata % e->epout->maxpkt) == 0){ 754 deprint(2, "%s: short pkt write\n", argv0); 755 write(e->epout->dfd, "", 1); 756 } 757 return n; 758 } 759 760 static long 761 fswrite(Usbfs *fs, Fid *fid, void *data, long count, vlong) 762 { 763 int cn, qt; 764 char buf[128]; 765 Buf *bp; 766 Conn *c; 767 Ether *e; 768 Qid q; 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 maxpkt %d; ep out %s maxpkt %d\n", 846 e->epin->dir, e->epin->maxpkt, e->epout->dir, e->epout->maxpkt); 847 848 /* time outs are not activated for I/O endpoints */ 849 850 if(usbdebug > 2 || etherdebug > 2){ 851 devctl(e->epin, "debug 1"); 852 devctl(e->epout, "debug 1"); 853 devctl(e->dev, "debug 1"); 854 } 855 856 return 0; 857 } 858 859 static int 860 usage(void) 861 { 862 werrstr("usage: usb/ether [-d]"); 863 return -1; 864 } 865 866 static Usbfs etherfs = { 867 .walk = fswalk, 868 .open = fsopen, 869 .read = fsread, 870 .write = fswrite, 871 .stat = fsstat, 872 .clunk = fsclunk, 873 }; 874 875 static void 876 shutdownchan(Channel *c) 877 { 878 Buf *bp; 879 880 while((bp=nbrecvp(c)) != nil) 881 free(bp); 882 chanfree(c); 883 } 884 885 static void 886 etherfree(Ether *e) 887 { 888 int i; 889 Buf *bp; 890 891 if(e->free != nil) 892 e->free(e); 893 closedev(e->epin); 894 closedev(e->epout); 895 if(e->rc == nil){ /* not really started */ 896 free(e); 897 return; 898 } 899 for(i = 0; i < e->nconns; i++) 900 if(e->conns[i] != nil){ 901 while((bp = nbrecvp(e->conns[i]->rc)) != nil) 902 free(bp); 903 chanfree(e->conns[i]->rc); 904 free(e->conns[i]); 905 } 906 shutdownchan(e->bc); 907 shutdownchan(e->rc); 908 shutdownchan(e->wc); 909 e->epin = e->epout = nil; 910 free(e); 911 } 912 913 static void 914 etherdevfree(void *a) 915 { 916 Ether *e = a; 917 918 if(e != nil) 919 etherfree(e); 920 } 921 922 /* must return 1 if c wants bp; 0 if not */ 923 static int 924 cwantsbp(Conn *c, Buf *bp) 925 { 926 if(c->ref != 0 && (c->prom != 0 || c->type < 0 || c->type == bp->type)) 927 return 1; 928 return 0; 929 } 930 931 static void 932 etherwriteproc(void *a) 933 { 934 Ether *e = a; 935 Buf *bp; 936 Channel *wc; 937 938 wc = e->wc; 939 while(e->exiting == 0){ 940 bp = recvp(wc); 941 if(bp == nil || e->exiting != 0){ 942 free(bp); 943 break; 944 } 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