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