xref: /plan9-contrib/sys/src/cmd/usb/ether/ether.c (revision e1c0af539adcc53c770ef6e067291d1d2730e221)
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