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 A88772 are implemented. 51 * Others are easy to add by borrowing code 52 * from other systems. 53 */ 54 {0x0411, 0x003d, A8817x}, /* buffalo */ 55 {0x0411, 0x006e, A88178}, 56 {0x04f1, 0x3008, A8817x}, 57 {0x050d, 0x5055, A88178}, 58 {0x0557, 0x2009, A8817x}, 59 {0x05ac, 0x1402, A88772}, /* Apple */ 60 {0x077b, 0x2226, A8817x}, 61 {0x07aa, 0x0017, A8817x}, 62 {0x07d1, 0x3c05, A88772}, 63 {0x0b95, 0x1720, A8817x}, /* asix */ 64 {0x0b95, 0x1780, A88178}, /* Geoff */ 65 {0x0b95, 0x7720, A88772}, 66 {0x0b95, 0x772a, A88772}, 67 {0x0db0, 0xa877, A88772}, 68 {0x1189, 0x0893, A8817x}, 69 {0x13b1, 0x0018, A88772}, 70 {0x14ea, 0xab11, A88178}, 71 {0x1557, 0x7720, A88772}, 72 {0x1631, 0x6200, A8817x}, 73 {0x1737, 0x0039, A88178}, 74 {0x2001, 0x3c05, A88772}, 75 {0x6189, 0x182d, A8817x}, 76 {0, 0, 0}, 77 }; 78 79 /* 80 * Each etherU%d is the root of our file system, 81 * which is added to the usb root directory. We only 82 * have to concern ourselfs with each /etherU%d subtree. 83 * 84 * NB: Maintain order in dirtabs, relative to the Qids enum. 85 */ 86 87 static Dirtab rootdirtab[] = 88 { 89 "/", Qroot, DMDIR|0555, /* etherU%d */ 90 "clone", Qclone, 0666, 91 "addr", Qaddr, 0444, 92 "ifstats", Qifstats, 0444, 93 "stats", Qstats, 0444, 94 /* one dir per connection here */ 95 nil, 0, 0, 96 }; 97 98 static Dirtab conndirtab[] = 99 { 100 "%d", Qndir, DMDIR|0555, 101 "data", Qndata, 0666, 102 "ctl", Qnctl, 0666, 103 "ifstats", Qnifstats, 0444, 104 "stats", Qnstats, 0444, 105 "type", Qntype, 0444, 106 nil, 0, 107 }; 108 109 int etherdebug; 110 111 Resetf ethers[] = 112 { 113 asixreset, 114 cdcreset, /* keep last */ 115 }; 116 117 static int 118 qtype(vlong q) 119 { 120 return q&0xFF; 121 } 122 123 static int 124 qnum(vlong q) 125 { 126 return (q >> 8) & 0xFFFFFF; 127 } 128 129 static uvlong 130 mkqid(int n, int t) 131 { 132 uvlong q; 133 134 q = (n&0xFFFFFF) << 8 | t&0xFF; 135 return q; 136 } 137 138 static void 139 freebuf(Ether *e, Buf *bp) 140 { 141 if(0)deprint(2, "%s: freebuf %#p\n", argv0, bp); 142 if(bp != nil){ 143 qlock(e); 144 e->nbufs--; 145 qunlock(e); 146 sendp(e->bc, bp); 147 } 148 } 149 150 static Buf* 151 allocbuf(Ether *e) 152 { 153 Buf *bp; 154 155 bp = nbrecvp(e->bc); 156 if(bp == nil){ 157 qlock(e); 158 if(e->nabufs < Nconns){ 159 bp = emallocz(sizeof(Buf), 1); 160 e->nabufs++; 161 setmalloctag(bp, getcallerpc(&e)); 162 deprint(2, "%s: %d buffers\n", argv0, e->nabufs); 163 } 164 qunlock(e); 165 } 166 if(bp == nil) 167 bp = recvp(e->bc); 168 bp->rp = bp->data + Hdrsize; 169 bp->ndata = 0; 170 if(0)deprint(2, "%s: allocbuf %#p\n", argv0, bp); 171 qlock(e); 172 e->nbufs++; 173 qunlock(e); 174 return bp; 175 } 176 177 static Conn* 178 newconn(Ether *e) 179 { 180 int i; 181 Conn *c; 182 183 qlock(e); 184 for(i = 0; i < nelem(e->conns); i++){ 185 c = e->conns[i]; 186 if(c == nil || c->ref == 0){ 187 if(c == nil){ 188 c = emallocz(sizeof(Conn), 1); 189 c->rc = chancreate(sizeof(Buf*), 2); 190 c->nb = i; 191 } 192 c->ref = 1; 193 if(i == e->nconns) 194 e->nconns++; 195 e->conns[i] = c; 196 deprint(2, "%s: newconn %d\n", argv0, i); 197 qunlock(e); 198 return c; 199 } 200 } 201 qunlock(e); 202 return nil; 203 } 204 205 static char* 206 seprintaddr(char *s, char *se, uchar *addr) 207 { 208 int i; 209 210 for(i = 0; i < Eaddrlen; i++) 211 s = seprint(s, se, "%02x", addr[i]); 212 return s; 213 } 214 215 void 216 dumpframe(char *tag, void *p, int n) 217 { 218 Etherpkt *ep; 219 char buf[128]; 220 char *s, *se; 221 int i; 222 223 ep = p; 224 if(n < Eaddrlen * 2 + 2){ 225 fprint(2, "short packet (%d bytes)\n", n); 226 return; 227 } 228 se = buf+sizeof(buf); 229 s = seprint(buf, se, "%s [%d]: ", tag, n); 230 s = seprintaddr(s, se, ep->s); 231 s = seprint(s, se, " -> "); 232 s = seprintaddr(s, se, ep->d); 233 s = seprint(s, se, " type 0x%02ux%02ux ", ep->type[0], ep->type[1]); 234 n -= Eaddrlen * 2 + 2; 235 for(i = 0; i < n && i < 16; i++) 236 s = seprint(s, se, "%02x", ep->data[i]); 237 if(n >= 16) 238 fprint(2, "%s...\n", buf); 239 else 240 fprint(2, "%s\n", buf); 241 } 242 243 static char* 244 seprintstats(char *s, char *se, Ether *e) 245 { 246 qlock(e); 247 s = seprint(s, se, "in: %ld\n", e->nin); 248 s = seprint(s, se, "out: %ld\n", e->nout); 249 s = seprint(s, se, "input errs: %ld\n", e->nierrs); 250 s = seprint(s, se, "output errs: %ld\n", e->noerrs); 251 s = seprint(s, se, "mbps: %d\n", e->mbps); 252 s = seprint(s, se, "prom: %ld\n", e->prom.ref); 253 s = seprint(s, se, "addr: "); 254 s = seprintaddr(s, se, e->addr); 255 s = seprint(s, se, "\n"); 256 qunlock(e); 257 return s; 258 } 259 260 static char* 261 seprintifstats(char *s, char *se, Ether *e) 262 { 263 int i; 264 Conn *c; 265 266 qlock(e); 267 s = seprint(s, se, "ctlr id: %#x\n", e->cid); 268 s = seprint(s, se, "phy: %#x\n", e->phy); 269 s = seprint(s, se, "exiting: %s\n", e->exiting ? "y" : "n"); 270 s = seprint(s, se, "conns: %d\n", e->nconns); 271 s = seprint(s, se, "allocated bufs: %d\n", e->nabufs); 272 s = seprint(s, se, "used bufs: %d\n", e->nbufs); 273 for(i = 0; i < nelem(e->conns); i++){ 274 c = e->conns[i]; 275 if(c == nil) 276 continue; 277 if(c->ref == 0) 278 s = seprint(s, se, "c[%d]: free\n", i); 279 else{ 280 s = seprint(s, se, "c[%d]: refs %ld t %#x h %d p %d\n", 281 c->nb, c->ref, c->type, c->headersonly, c->prom); 282 } 283 } 284 qunlock(e); 285 return s; 286 } 287 288 static void 289 etherdump(Ether *e) 290 { 291 char buf[256]; 292 293 if(etherdebug == 0) 294 return; 295 seprintifstats(buf, buf+sizeof(buf), e); 296 fprint(2, "%s: ether %#p:\n%s\n", argv0, e, buf); 297 } 298 299 static Conn* 300 getconn(Ether *e, int i, int idleok) 301 { 302 Conn *c; 303 304 qlock(e); 305 if(i < 0 || i >= e->nconns) 306 c = nil; 307 else{ 308 c = e->conns[i]; 309 if(idleok == 0 && c != nil && c->ref == 0) 310 c = nil; 311 } 312 qunlock(e); 313 return c; 314 } 315 316 static void 317 filldir(Usbfs *fs, Dir *d, Dirtab *tab, int cn) 318 { 319 d->qid.path = mkqid(cn, tab->qid); 320 d->qid.path |= fs->qid; 321 d->mode = tab->mode; 322 if((d->mode & DMDIR) != 0) 323 d->qid.type = QTDIR; 324 else 325 d->qid.type = QTFILE; 326 if(tab->qid == Qndir) 327 snprint(d->name, Namesz, "%d", cn); 328 else 329 d->name = tab->name; 330 } 331 332 static int 333 rootdirgen(Usbfs *fs, Qid, int i, Dir *d, void *) 334 { 335 Ether *e; 336 Dirtab *tab; 337 int cn; 338 339 e = fs->aux; 340 i++; /* skip root */ 341 cn = 0; 342 if(i < nelem(rootdirtab) - 1) /* null terminated */ 343 tab = &rootdirtab[i]; 344 else{ 345 cn = i - nelem(rootdirtab) + 1; 346 if(cn < e->nconns) 347 tab = &conndirtab[0]; 348 else 349 return -1; 350 } 351 filldir(fs, d, tab, cn); 352 return 0; 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[2048]; /* keep this large for ifstats */ 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); /* keep { and } */ 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); /* keep { and } */ 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] [-N nb]"); 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 devctl(e->dev, "detach"); 912 free(e); 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 free(bp); 945 break; 946 } 947 e->nout++; 948 if(e->bwrite(e, bp) < 0) 949 e->noerrs++; 950 if(isloopback(e, bp) && e->exiting == 0) 951 sendp(e->rc, bp); /* send to input queue */ 952 else 953 freebuf(e, bp); 954 } 955 deprint(2, "%s: writeproc exiting\n", argv0); 956 closedev(e->dev); 957 } 958 959 static void 960 setbuftype(Buf *bp) 961 { 962 uchar *p; 963 964 bp->type = 0; 965 if(bp->ndata >= Ehdrsize){ 966 p = bp->rp + Eaddrlen*2; 967 bp->type = p[0]<<8 | p[1]; 968 } 969 } 970 971 static void 972 etherexiting(Ether *e) 973 { 974 devctl(e->dev, "detach"); 975 e->exiting = 1; 976 close(e->epin->dfd); 977 e->epin->dfd = -1; 978 close(e->epout->dfd); 979 e->epout->dfd = -1; 980 nbsend(e->wc, nil); 981 } 982 983 static void 984 etherreadproc(void *a) 985 { 986 int i, n, nwants; 987 Buf *bp, *dbp; 988 Ether *e = a; 989 990 while(e->exiting == 0){ 991 bp = nbrecvp(e->rc); 992 if(bp == nil){ 993 bp = allocbuf(e); /* leak() may think we leak */ 994 if(e->bread(e, bp) < 0){ 995 freebuf(e, bp); 996 break; 997 } 998 if(bp->ndata == 0){ 999 /* may be a short packet; continue */ 1000 if(0)dprint(2, "%s: read: short\n", argv0); 1001 freebuf(e, bp); 1002 continue; 1003 }else 1004 setbuftype(bp); 1005 } 1006 e->nin++; 1007 nwants = 0; 1008 for(i = 0; i < e->nconns; i++) 1009 nwants += cwantsbp(e->conns[i], bp); 1010 for(i = 0; nwants > 0 && i < e->nconns; i++) 1011 if(cwantsbp(e->conns[i], bp)){ 1012 n = bp->ndata; 1013 if(e->conns[i]->type == -2 && n > 64) 1014 n = 64; 1015 if(nwants-- == 1){ 1016 bp->ndata = n; 1017 dbp = bp; 1018 bp = nil; 1019 }else{ 1020 dbp = allocbuf(e); 1021 memmove(dbp->rp, bp->rp, n); 1022 dbp->ndata = n; 1023 dbp->type = bp->type; 1024 } 1025 if(nbsendp(e->conns[i]->rc, dbp) == 0){ 1026 e->nierrs++; 1027 freebuf(e, dbp); 1028 } 1029 } 1030 freebuf(e, bp); 1031 } 1032 deprint(2, "%s: writeproc exiting\n", argv0); 1033 etherexiting(e); 1034 closedev(e->dev); 1035 usbfsdel(&e->fs); 1036 } 1037 1038 static void 1039 setalt(Dev *d, int ifcid, int altid) 1040 { 1041 if(usbcmd(d, Rh2d|Rstd|Riface, Rsetiface, altid, ifcid, nil, 0) < 0) 1042 dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid); 1043 } 1044 1045 static int 1046 ifaceinit(Ether *e, Iface *ifc, int *ei, int *eo) 1047 { 1048 Ep *ep; 1049 int epin, epout, i; 1050 1051 if(ifc == nil) 1052 return -1; 1053 1054 epin = epout = -1; 1055 for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++) 1056 if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){ 1057 if(ep->dir == Eboth || ep->dir == Ein) 1058 if(epin == -1) 1059 epin = ep->id; 1060 if(ep->dir == Eboth || ep->dir == Eout) 1061 if(epout == -1) 1062 epout = ep->id; 1063 } 1064 if(epin == -1 || epout == -1) 1065 return -1; 1066 1067 dprint(2, "ether: ep ids: in %d out %d\n", epin, epout); 1068 for(i = 0; i < nelem(ifc->altc); i++) 1069 if(ifc->altc[i] != nil) 1070 setalt(e->dev, ifc->id, i); 1071 1072 *ei = epin; 1073 *eo = epout; 1074 return 0; 1075 } 1076 1077 static int 1078 etherinit(Ether *e, int *ei, int *eo) 1079 { 1080 int ctlid, datid, i, j; 1081 Conf *c; 1082 Desc *desc; 1083 Iface *ctlif, *datif; 1084 Usbdev *ud; 1085 1086 *ei = *eo = -1; 1087 ud = e->dev->usb; 1088 1089 /* look for union descriptor with ethernet ctrl interface */ 1090 for(i = 0; i < nelem(ud->ddesc); i++){ 1091 if((desc = ud->ddesc[i]) == nil) 1092 continue; 1093 if(desc->data.bLength < 5 || desc->data.bbytes[0] != Cdcunion) 1094 continue; 1095 1096 ctlid = desc->data.bbytes[1]; 1097 datid = desc->data.bbytes[2]; 1098 1099 if((c = desc->conf) == nil) 1100 continue; 1101 1102 ctlif = datif = nil; 1103 for(j = 0; j < nelem(c->iface); j++){ 1104 if(c->iface[j] == nil) 1105 continue; 1106 if(c->iface[j]->id == ctlid) 1107 ctlif = c->iface[j]; 1108 if(c->iface[j]->id == datid) 1109 datif = c->iface[j]; 1110 1111 if(datif != nil && ctlif != nil){ 1112 if(Subclass(ctlif->csp) == Scether && 1113 ifaceinit(e, datif, ei, eo) != -1) 1114 return 0; 1115 break; 1116 } 1117 } 1118 } 1119 /* try any other one that seems to be ok */ 1120 for(i = 0; i < nelem(ud->conf); i++) 1121 if((c = ud->conf[i]) != nil) 1122 for(j = 0; j < nelem(c->iface); j++) 1123 if(ifaceinit(e, c->iface[j], ei, eo) != -1) 1124 return 0; 1125 dprint(2, "%s: no valid endpoints", argv0); 1126 return -1; 1127 } 1128 1129 int 1130 ethermain(Dev *dev, int argc, char **argv) 1131 { 1132 int epin, epout, i, devid; 1133 Ether *e; 1134 1135 devid = dev->id; 1136 ARGBEGIN{ 1137 case 'd': 1138 if(etherdebug == 0) 1139 fprint(2, "ether debug on\n"); 1140 etherdebug++; 1141 break; 1142 case 'N': 1143 devid = atoi(EARGF(usage())); 1144 break; 1145 default: 1146 return usage(); 1147 }ARGEND 1148 if(argc != 0) { 1149 return usage(); 1150 } 1151 e = dev->aux = emallocz(sizeof(Ether), 1); 1152 e->dev = dev; 1153 dev->free = etherdevfree; 1154 1155 for(i = 0; i < nelem(ethers); i++) 1156 if(ethers[i](e) == 0) 1157 break; 1158 if(i == nelem(ethers)) 1159 return -1; 1160 if(e->init == nil) 1161 e->init = etherinit; 1162 if(e->init(e, &epin, &epout) < 0) 1163 return -1; 1164 if(e->bwrite == nil) 1165 e->bwrite = etherbwrite; 1166 if(e->bread == nil) 1167 e->bread = etherbread; 1168 1169 if(openeps(e, epin, epout) < 0) 1170 return -1; 1171 e->fs = etherfs; 1172 snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", devid); 1173 e->fs.dev = dev; 1174 e->fs.aux = e; 1175 e->bc = chancreate(sizeof(Buf*), Nconns); 1176 e->rc = chancreate(sizeof(Buf*), Nconns/2); 1177 e->wc = chancreate(sizeof(Buf*), Nconns*2); 1178 incref(e->dev); 1179 proccreate(etherwriteproc, e, 16*1024); 1180 incref(e->dev); 1181 proccreate(etherreadproc, e, 16*1024); 1182 deprint(2, "%s: dev ref %ld\n", argv0, dev->ref); 1183 incref(e->dev); 1184 usbfsadd(&e->fs); 1185 return 0; 1186 } 1187