Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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