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