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
qtype(vlong q)128 qtype(vlong q)
129 {
130 return q&0xFF;
131 }
132
133 static int
qnum(vlong q)134 qnum(vlong q)
135 {
136 return (q >> 8) & 0xFFFFFF;
137 }
138
139 static uvlong
mkqid(int n,int t)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
freebuf(Ether * e,Buf * bp)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*
allocbuf(Ether * e)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*
newconn(Ether * e)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*
seprintaddr(char * s,char * se,uchar * addr)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
dumpframe(char * tag,void * p,int n)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*
seprintstats(char * s,char * se,Ether * e)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*
seprintifstats(char * s,char * se,Ether * e)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
etherdump(Ether * e)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*
getconn(Ether * e,int i,int idleok)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
filldir(Usbfs * fs,Dir * d,Dirtab * tab,int cn)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
rootdirgen(Usbfs * fs,Qid,int i,Dir * d,void *)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
conndirgen(Usbfs * fs,Qid q,int i,Dir * d,void *)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
fswalk(Usbfs * fs,Fid * fid,char * name)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*
qdirtab(vlong q)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
fsstat(Usbfs * fs,Qid qid,Dir * d)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
fsopen(Usbfs * fs,Fid * fid,int omode)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
prom(Ether * e,int set)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
fsclunk(Usbfs * fs,Fid * fid)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
parseaddr(uchar * m,char * s)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
fsread(Usbfs * fs,Fid * fid,void * data,long count,vlong offset)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
typeinuse(Ether * e,int t)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
isloopback(Ether * e,Buf *)675 isloopback(Ether *e, Buf *)
676 {
677 return e->prom.ref > 0; /* BUG: also loopbacks and broadcasts */
678 }
679
680 static int
etherctl(Ether * e,Conn * c,char * buf)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
etherbread(Ether * e,Buf * bp)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
etherbwrite(Ether * e,Buf * bp)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
fswrite(Usbfs * fs,Fid * fid,void * data,long count,vlong)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
openeps(Ether * e,int epin,int epout)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
usage(void)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
shutdownchan(Channel * c)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
etherfree(Ether * e)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
etherdevfree(void * a)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
cwantsbp(Conn * c,Buf * bp)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
etherwriteproc(void * a)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
setbuftype(Buf * bp)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
etherexiting(Ether * e)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
etherreadproc(void * a)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
setalt(Dev * d,int ifcid,int altid)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
ifaceinit(Ether * e,Iface * ifc,int * ei,int * eo)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
etherinit(Ether * e,int * ei,int * eo)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
kernelproxy(Ether * e)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
ethermain(Dev * dev,int argc,char ** argv)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