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