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 device driver framework.
3
 *
4
 * This is in charge of providing access to actual HCIs
5
 * and providing I/O to the various endpoints of devices.
6
 * A separate user program (usbd) is in charge of
7
 * enumerating the bus, setting up endpoints and
8
 * starting devices (also user programs).
9
 *
10
 * The interface provided is a violation of the standard:
11
 * you're welcome.
12
 *
13
 * The interface consists of a root directory with several files
14
 * plus a directory (epN.M) with two files per endpoint.
15
 * A device is represented by its first endpoint, which
16
 * is a control endpoint automatically allocated for each device.
17
 * Device control endpoints may be used to create new endpoints.
18
 * Devices corresponding to hubs may also allocate new devices,
19
 * perhaps also hubs. Initially, a hub device is allocated for
20
 * each controller present, to represent its root hub. Those can
21
 * never be removed.
22
 *
23
 * All endpoints refer to the first endpoint (epN.0) of the device,
24
 * which keeps per-device information, and also to the HCI used
25
 * to reach them. Although all endpoints cache that information.
26
 *
27
 * epN.M/data files permit I/O and are considered DMEXCL.
28
 * epN.M/ctl files provide status info and accept control requests.
29
 *
30
 * Endpoints may be given file names to be listed also at #u,
31
 * for those drivers that have nothing to do after configuring the
32
 * device and its endpoints.
33
 *
34
 * Drivers for different controllers are kept at usb[oue]hci.c
35
 * It's likely we could factor out much from controllers into
36
 * a generic controller driver, the problem is that details
37
 * regarding how to handle toggles, tokens, Tds, etc. will
38
 * get in the way. Thus, code is probably easier the way it is.
39
 */
40
 
41
#include	"u.h"
42
#include	"../port/lib.h"
43
#include	"mem.h"
44
#include	"dat.h"
45
#include	"fns.h"
46
#include	"io.h"
47
#include	"../port/error.h"
48
#include	"../port/usb.h"
49
 
50
typedef struct Hcitype Hcitype;
51
 
52
enum
53
{
54
	/* Qid numbers */
55
	Qdir = 0,		/* #u */
56
	Qusbdir,			/* #u/usb */
57
	Qctl,			/* #u/usb/ctl - control requests */
58
 
59
	Qep0dir,			/* #u/usb/ep0.0 - endpoint 0 dir */
60
	Qep0io,			/* #u/usb/ep0.0/data - endpoint 0 I/O */
61
	Qep0ctl,		/* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
62
	Qep0dummy,		/* give 4 qids to each endpoint */
63
 
64
	Qepdir = 0,		/* (qid-qep0dir)&3 is one of these */
65
	Qepio,			/* to identify which file for the endpoint */
66
	Qepctl,
67
 
68
	/* ... */
69
 
70
	/* Usb ctls. */
71
	CMdebug = 0,		/* debug on|off */
72
	CMdump,			/* dump (data structures for debug) */
73
 
74
	/* Ep. ctls */
75
	CMnew = 0,		/* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
76
	CMnewdev,		/* newdev full|low|high portnb (allocate new devices) */
77
	CMhub,			/* hub (set the device as a hub) */
78
	CMspeed,		/* speed full|low|high|no */
79
	CMmaxpkt,		/* maxpkt size */
80
	CMntds,			/* ntds nb (max nb. of tds per µframe) */
81
	CMclrhalt,		/* clrhalt (halt was cleared on endpoint) */
82
	CMpollival,		/* pollival interval (interrupt/iso) */
83
	CMhz,			/* hz n (samples/sec; iso) */
84
	CMsamplesz,		/* samplesz n (sample size; iso) */
85
	CMinfo,			/* info infostr (ke.ep info for humans) */
86
	CMdetach,		/* detach (abort I/O forever on this ep). */
87
	CMaddress,		/* address (address is assigned) */
88
	CMdebugep,		/* debug n (set/clear debug for this ep) */
89
	CMname,			/* name str (show up as #u/name as well) */
90
	CMtmout,		/* timeout n (activate timeouts for ep) */
91
	CMpreset,		/* reset the port */
92
 
93
	/* Hub feature selectors */
94
	Rportenable	= 1,
95
	Rportreset	= 4,
96
 
97
};
98
 
99
struct Hcitype
100
{
101
	char*	type;
102
	int	(*reset)(Hci*);
103
};
104
 
105
#define QID(q)	((int)(q).path)
106
 
107
static Cmdtab usbctls[] =
108
{
109
	{CMdebug,	"debug",	2},
110
	{CMdump,	"dump",		1},
111
};
112
 
113
static Cmdtab epctls[] =
114
{
115
	{CMnew,		"new",		4},
116
	{CMnewdev,	"newdev",	3},
117
	{CMhub,		"hub",		1},
118
	{CMspeed,	"speed",	2},
119
	{CMmaxpkt,	"maxpkt",	2},
120
	{CMntds,	"ntds",		2},
121
	{CMpollival,	"pollival",	2},
122
	{CMsamplesz,	"samplesz",	2},
123
	{CMhz,		"hz",		2},
124
	{CMinfo,	"info",		0},
125
	{CMdetach,	"detach",	1},
126
	{CMaddress,	"address",	1},
127
	{CMdebugep,	"debug",	2},
128
	{CMclrhalt,	"clrhalt",	1},
129
	{CMname,	"name",		2},
130
	{CMtmout,	"timeout",	2},
131
	{CMpreset,	"reset",	1},
132
};
133
 
134
static Dirtab usbdir[] =
135
{
136
	"ctl",		{Qctl},		0,	0666,
137
};
138
 
139
char *usbmodename[] =
140
{
141
	[OREAD]	"r",
142
	[OWRITE]	"w",
143
	[ORDWR]	"rw",
144
};
145
 
146
static char *ttname[] =
147
{
148
	[Tnone]	"none",
149
	[Tctl]	"control",
150
	[Tiso]	"iso",
151
	[Tintr]	"interrupt",
152
	[Tbulk]	"bulk",
153
};
154
 
155
static char *spname[] =
156
{
157
	[Fullspeed]	"full",
158
	[Lowspeed]	"low",
159
	[Highspeed]	"high",
160
	[Nospeed]	"no",
161
};
162
 
163
static int	debug;
164
static Hcitype	hcitypes[Nhcis];
165
static Hci*	hcis[Nhcis];
166
static QLock	epslck;		/* add, del, lookup endpoints */
167
static Ep*	eps[Neps];	/* all endpoints known */
168
static int	epmax;		/* 1 + last endpoint index used  */
169
static int	usbidgen;	/* device address generator */
170
 
171
/*
172
 * Is there something like this in a library? should it be?
173
 */
174
char*
175
seprintdata(char *s, char *se, uchar *d, int n)
176
{
177
	int i, l;
178
 
179
	s = seprint(s, se, " %#p[%d]: ", d, n);
180
	l = n;
181
	if(l > 10)
182
		l = 10;
183
	for(i=0; i<l; i++)
184
		s = seprint(s, se, " %2.2ux", d[i]);
185
	if(l < n)
186
		s = seprint(s, se, "...");
187
	return s;
188
}
189
 
190
static int
191
name2speed(char *name)
192
{
193
	int i;
194
 
195
	for(i = 0; i < nelem(spname); i++)
196
		if(strcmp(name, spname[i]) == 0)
197
			return i;
198
	return Nospeed;
199
}
200
 
201
static int
202
name2ttype(char *name)
203
{
204
	int i;
205
 
206
	for(i = 0; i < nelem(ttname); i++)
207
		if(strcmp(name, ttname[i]) == 0)
208
			return i;
209
	/* may be a std. USB ep. type */
210
	i = strtol(name, nil, 0);
211
	switch(i+1){
212
	case Tctl:
213
	case Tiso:
214
	case Tbulk:
215
	case Tintr:
216
		return i+1;
217
	default:
218
		return Tnone;
219
	}
220
}
221
 
222
static int
223
name2mode(char *mode)
224
{
225
	int i;
226
 
227
	for(i = 0; i < nelem(usbmodename); i++)
228
		if(strcmp(mode, usbmodename[i]) == 0)
229
			return i;
230
	return -1;
231
}
232
 
233
static int
234
qid2epidx(int q)
235
{
236
	q = (q-Qep0dir)/4;
237
	if(q < 0 || q >= epmax || eps[q] == nil)
238
		return -1;
239
	return q;
240
}
241
 
242
static int
243
isqtype(int q, int type)
244
{
245
	if(q < Qep0dir)
246
		return 0;
247
	q -= Qep0dir;
248
	return (q & 3) == type;
249
}
250
 
251
void
252
addhcitype(char* t, int (*r)(Hci*))
253
{
254
	static int ntype;
255
 
256
	if(ntype == Nhcis)
257
		panic("too many USB host interface types");
258
	hcitypes[ntype].type = t;
259
	hcitypes[ntype].reset = r;
260
	ntype++;
261
}
262
 
263
static char*
264
seprintep(char *s, char *se, Ep *ep, int all)
265
{
266
	static char* dsnames[] = { "config", "enabled", "detached", "reset" };
267
	Udev *d;
268
	int i;
269
	int di;
270
 
271
	d = ep->dev;
272
 
273
	qlock(ep);
274
	if(waserror()){
275
		qunlock(ep);
276
		nexterror();
277
	}
278
	di = ep->dev->nb;
279
	if(all)
280
		s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
281
	s = seprint(s, se, "%s", dsnames[ep->dev->state]);
282
	s = seprint(s, se, " %s", ttname[ep->ttype]);
283
	assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
284
	s = seprint(s, se, " %s", usbmodename[ep->mode]);
285
	s = seprint(s, se, " speed %s", spname[d->speed]);
286
	s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
287
	s = seprint(s, se, " pollival %ld", ep->pollival);
288
	s = seprint(s, se, " samplesz %ld", ep->samplesz);
289
	s = seprint(s, se, " hz %ld", ep->hz);
290
	s = seprint(s, se, " hub %d", ep->dev->hub);
291
	s = seprint(s, se, " port %d", ep->dev->port);
292
	if(ep->inuse)
293
		s = seprint(s, se, " busy");
294
	else
295
		s = seprint(s, se, " idle");
296
	if(all){
297
		s = seprint(s, se, " load %uld", ep->load);
298
		s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
299
		s = seprint(s, se, " idx %d", ep->idx);
300
		if(ep->name != nil)
301
			s = seprint(s, se, " name '%s'", ep->name);
302
		if(ep->tmout != 0)
303
			s = seprint(s, se, " tmout");
304
		if(ep == ep->ep0){
305
			s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
306
			s = seprint(s, se, " eps:");
307
			for(i = 0; i < nelem(d->eps); i++)
308
				if(d->eps[i] != nil)
309
					s = seprint(s, se, " ep%d.%d", di, i);
310
		}
311
	}
312
	if(ep->info != nil)
313
		s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
314
	else
315
		s = seprint(s, se, "\n");
316
	qunlock(ep);
317
	poperror();
318
	return s;
319
}
320
 
321
static Ep*
322
epalloc(Hci *hp)
323
{
324
	Ep *ep;
325
	int i;
326
 
327
	ep = smalloc(sizeof(Ep));
328
	ep->ref = 1;
329
	qlock(&epslck);
330
	for(i = 0; i < Neps; i++)
331
		if(eps[i] == nil)
332
			break;
333
	if(i == Neps){
334
		qunlock(&epslck);
335
		free(ep);
336
		panic("usb: epalloc: too few endpoints (%d)", Neps);
337
	}
338
	ep->idx = i;
339
	if(epmax <= i)
340
		epmax = i+1;
341
	eps[i] = ep;
342
	ep->hp = hp;
343
	ep->maxpkt = 8;
344
	ep->ntds = 1;
345
	ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
346
	qunlock(&epslck);
347
	return ep;
348
}
349
 
350
static Ep*
351
getep(int i)
352
{
353
	Ep *ep;
354
 
355
	if(i < 0 || i >= epmax || eps[i] == nil)
356
		return nil;
357
	qlock(&epslck);
358
	ep = eps[i];
359
	if(ep != nil)
360
		incref(ep);
361
	qunlock(&epslck);
362
	return ep;
363
}
364
 
365
static void
366
putep(Ep *ep)
367
{
368
	Udev *d;
369
 
370
	if(ep != nil && decref(ep) == 0){
371
		d = ep->dev;
372
		deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
373
		qlock(&epslck);
374
		eps[ep->idx] = nil;
375
		if(ep->idx == epmax-1)
376
			epmax--;
377
		if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
378
			usbidgen--;
379
		qunlock(&epslck);
380
		if(d != nil){
381
			qlock(ep->ep0);
382
			d->eps[ep->nb] = nil;
383
			qunlock(ep->ep0);
384
		}
385
		if(ep->ep0 != ep){
386
			putep(ep->ep0);
387
			ep->ep0 = nil;
388
		}
389
		free(ep->info);
390
		free(ep->name);
391
		free(ep);
392
	}
393
}
394
 
395
static void
396
dumpeps(void)
397
{
398
	int i;
399
	static char buf[512];
400
	char *s;
401
	char *e;
402
	Ep *ep;
403
 
404
	print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
405
	for(i = 0; i < epmax; i++){
406
		s = buf;
407
		e = buf+sizeof(buf);
408
		ep = getep(i);
409
		if(ep != nil){
410
			if(waserror()){
411
				putep(ep);
412
				nexterror();
413
			}
414
			s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
415
			seprintep(s, e, ep, 1);
416
			print("%s", buf);
417
			ep->hp->seprintep(buf, e, ep);
418
			print("%s", buf);
419
			poperror();
420
			putep(ep);
421
		}
422
	}
423
	print("usb dump hcis:\n");
424
	for(i = 0; i < Nhcis; i++)
425
		if(hcis[i] != nil)
426
			hcis[i]->dump(hcis[i]);
427
}
428
 
429
static int
430
newusbid(Hci *)
431
{
432
	int id;
433
 
434
	qlock(&epslck);
435
	id = ++usbidgen;
436
	if(id >= 0x7F)
437
		print("#u: too many device addresses; reuse them more\n");
438
	qunlock(&epslck);
439
	return id;
440
}
441
 
442
/*
443
 * Create endpoint 0 for a new device
444
 */
445
static Ep*
446
newdev(Hci *hp, int ishub, int isroot)
447
{
448
	Ep *ep;
449
	Udev *d;
450
 
451
	ep = epalloc(hp);
452
	d = ep->dev = smalloc(sizeof(Udev));
453
	d->nb = newusbid(hp);
454
	d->eps[0] = ep;
455
	ep->nb = 0;
456
	ep->toggle[0] = ep->toggle[1] = 0;
457
	d->ishub = ishub;
458
	d->isroot = isroot;
459
	if(hp->highspeed != 0)
460
		d->speed = Highspeed;
461
	else
462
		d->speed = Fullspeed;
463
	d->state = Dconfig;		/* address not yet set */
464
	ep->dev = d;
465
	ep->ep0 = ep;			/* no ref counted here */
466
	ep->ttype = Tctl;
467
	ep->tmout = Xfertmout;
468
	ep->mode = ORDWR;
469
	dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
470
	return ep;
471
}
472
 
473
/*
474
 * Create a new endpoint for the device
475
 * accessed via the given endpoint 0.
476
 */
477
static Ep*
478
newdevep(Ep *ep, int i, int tt, int mode)
479
{
480
	Ep *nep;
481
	Udev *d;
482
 
483
	d = ep->dev;
484
	if(d->eps[i] != nil)
485
		error("endpoint already in use");
486
	nep = epalloc(ep->hp);
487
	incref(ep);
488
	d->eps[i] = nep;
489
	nep->nb = i;
490
	nep->toggle[0] = nep->toggle[1] = 0;
491
	nep->ep0 = ep;
492
	nep->dev = ep->dev;
493
	nep->mode = mode;
494
	nep->ttype = tt;
495
	nep->debug = ep->debug;
496
	/* set defaults */
497
	switch(tt){
498
	case Tctl:
499
		nep->tmout = Xfertmout;
500
		break;
501
	case Tintr:
502
		nep->pollival = 10;
503
		break;
504
	case Tiso:
505
		nep->tmout = Xfertmout;
506
		nep->pollival = 10;
507
		nep->samplesz = 4;
508
		nep->hz = 44100;
509
		break;
510
	}
511
	deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
512
	return ep;
513
}
514
 
515
static int
516
epdataperm(int mode)
517
{
518
 
519
	switch(mode){
520
	case OREAD:
521
		return 0440|DMEXCL;
522
		break;
523
	case OWRITE:
524
		return 0220|DMEXCL;
525
		break;
526
	default:
527
		return 0660|DMEXCL;
528
	}
529
}
530
 
531
static int
532
usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
533
{
534
	Qid q;
535
	Dirtab *dir;
536
	int perm;
537
	char *se;
538
	Ep *ep;
539
	int nb;
540
	int mode;
541
 
542
	if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
543
	if(s == DEVDOTDOT){
544
		if(QID(c->qid) <= Qusbdir){
545
			mkqid(&q, Qdir, 0, QTDIR);
546
			devdir(c, q, "#u", 0, eve, 0555, dp);
547
		}else{
548
			mkqid(&q, Qusbdir, 0, QTDIR);
549
			devdir(c, q, "usb", 0, eve, 0555, dp);
550
		}
551
		if(0)ddprint("ok\n");
552
		return 1;
553
	}
554
 
555
	switch(QID(c->qid)){
556
	case Qdir:				/* list #u */
557
		if(s == 0){
558
			mkqid(&q, Qusbdir, 0, QTDIR);
559
			devdir(c, q, "usb", 0, eve, 0555, dp);
560
			if(0)ddprint("ok\n");
561
			return 1;
562
		}
563
		s--;
564
		if(s < 0 || s >= epmax)
565
			goto Fail;
566
		ep = getep(s);
567
		if(ep == nil || ep->name == nil){
568
			if(ep != nil)
569
				putep(ep);
570
			if(0)ddprint("skip\n");
571
			return 0;
572
		}
573
		if(waserror()){
574
			putep(ep);
575
			nexterror();
576
		}
577
		mkqid(&q, Qep0io+s*4, 0, QTFILE);
578
		devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
579
		putep(ep);
580
		poperror();
581
		if(0)ddprint("ok\n");
582
		return 1;
583
 
584
	case Qusbdir:				/* list #u/usb */
585
	Usbdir:
586
		if(s < nelem(usbdir)){
587
			dir = &usbdir[s];
588
			mkqid(&q, dir->qid.path, 0, QTFILE);
589
			devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
590
			if(0)ddprint("ok\n");
591
			return 1;
592
		}
593
		s -= nelem(usbdir);
594
		if(s < 0 || s >= epmax)
595
			goto Fail;
596
		ep = getep(s);
597
		if(ep == nil){
598
			if(0)ddprint("skip\n");
599
			return 0;
600
		}
601
		if(waserror()){
602
			putep(ep);
603
			nexterror();
604
		}
605
		se = up->genbuf+sizeof(up->genbuf);
606
		seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
607
		mkqid(&q, Qep0dir+4*s, 0, QTDIR);
608
		putep(ep);
609
		poperror();
610
		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
611
		if(0)ddprint("ok\n");
612
		return 1;
613
 
614
	case Qctl:
615
		s = 0;
616
		goto Usbdir;
617
 
618
	default:				/* list #u/usb/epN.M */
619
		nb = qid2epidx(QID(c->qid));
620
		ep = getep(nb);
621
		if(ep == nil)
622
			goto Fail;
623
		mode = ep->mode;
624
		putep(ep);
625
		if(isqtype(QID(c->qid), Qepdir)){
626
		Epdir:
627
			switch(s){
628
			case 0:
629
				mkqid(&q, Qep0io+nb*4, 0, QTFILE);
630
				perm = epdataperm(mode);
631
				devdir(c, q, "data", 0, eve, perm, dp);
632
				break;
633
			case 1:
634
				mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
635
				devdir(c, q, "ctl", 0, eve, 0664, dp);
636
				break;
637
			default:
638
				goto Fail;
639
			}
640
		}else if(isqtype(QID(c->qid), Qepctl)){
641
			s = 1;
642
			goto Epdir;
643
		}else{
644
			s = 0;
645
			goto Epdir;
646
		}
647
		if(0)ddprint("ok\n");
648
		return 1;
649
	}
650
Fail:
651
	if(0)ddprint("fail\n");
652
	return -1;
653
}
654
 
655
static Hci*
656
hciprobe(int cardno, int ctlrno)
657
{
658
	Hci *hp;
659
	char *type;
660
	char name[64];
661
	static int epnb = 1;	/* guess the endpoint nb. for the controller */
662
 
663
	ddprint("hciprobe %d %d\n", cardno, ctlrno);
664
	hp = smalloc(sizeof(Hci));
665
	hp->ctlrno = ctlrno;
666
	hp->tbdf = BUSUNKNOWN;
667
 
668
	if(cardno < 0){
669
		if(isaconfig("usb", ctlrno, hp) == 0){
670
			free(hp);
671
			return nil;
672
		}
673
		for(cardno = 0; cardno < Nhcis; cardno++){
674
			if(hcitypes[cardno].type == nil)
675
				break;
676
			type = hp->type;
677
			if(type==nil || *type==0)
678
				type = "uhci";
679
			if(cistrcmp(hcitypes[cardno].type, type) == 0)
680
				break;
681
		}
682
	}
683
 
684
	if(cardno >= Nhcis || hcitypes[cardno].type == nil){
685
		free(hp);
686
		return nil;
687
	}
688
	dprint("%s...", hcitypes[cardno].type);
689
	if(hcitypes[cardno].reset(hp) < 0){
690
		free(hp);
691
		return nil;
692
	}
693
 
694
	/*
695
	 * IRQ2 doesn't really exist, it's used to gang the interrupt
696
	 * controllers together. A device set to IRQ2 will appear on
697
	 * the second interrupt controller as IRQ9.
698
	 */
699
	if(hp->irq == 2)
700
		hp->irq = 9;
701
	snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
702
	intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, name);
703
 
704
	/*
705
	 * modern machines have too many usb controllers to list on
706
	 * the console.
707
	 */
708
	dprint("#u/usb/ep%d.0: %s: port 0x%luX irq %d\n",
709
		epnb, hcitypes[cardno].type, hp->port, hp->irq);
710
	epnb++;
711
	return hp;
712
}
713
 
714
static void
715
usbreset(void)
716
{
717
	int cardno, ctlrno;
718
	Hci *hp;
719
 
720
	if(getconf("*nousbprobe"))
721
		return;
722
	dprint("usbreset\n");
723
 
724
	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
725
		if((hp = hciprobe(-1, ctlrno)) != nil)
726
			hcis[ctlrno] = hp;
727
	cardno = ctlrno = 0;
728
	while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
729
		if(hcis[ctlrno] != nil)
730
			ctlrno++;
731
		else{
732
			hp = hciprobe(cardno, ctlrno);
733
			if(hp == nil)
734
				cardno++;
735
			hcis[ctlrno++] = hp;
736
		}
737
	if(hcis[Nhcis-1] != nil)
738
		print("usbreset: bug: Nhcis (%d) too small\n", Nhcis);
739
}
740
 
741
static void
742
usbinit(void)
743
{
744
	Hci *hp;
745
	int ctlrno;
746
	Ep *d;
747
	char info[40];
748
 
749
	dprint("usbinit\n");
750
	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
751
		hp = hcis[ctlrno];
752
		if(hp != nil){
753
			if(hp->init != nil)
754
				hp->init(hp);
755
			d = newdev(hp, 1, 1);		/* new root hub */
756
			d->dev->state = Denabled;	/* although addr == 0 */
757
			d->maxpkt = 64;
758
			snprint(info, sizeof(info), "ports %d", hp->nports);
759
			kstrdup(&d->info, info);
760
		}
761
	}
762
}
763
 
764
static Chan*
765
usbattach(char *spec)
766
{
767
	return devattach(L'u', spec);
768
}
769
 
770
static Walkqid*
771
usbwalk(Chan *c, Chan *nc, char **name, int nname)
772
{
773
	return devwalk(c, nc, name, nname, nil, 0, usbgen);
774
}
775
 
776
static int
777
usbstat(Chan *c, uchar *db, int n)
778
{
779
	return devstat(c, db, n, nil, 0, usbgen);
780
}
781
 
782
/*
783
 * µs for the given transfer, for bandwidth allocation.
784
 * This is a very rough worst case for what 5.11.3
785
 * of the usb 2.0 spec says.
786
 * Also, we are using maxpkt and not actual transfer sizes.
787
 * Only when we are sure we
788
 * are not exceeding b/w might we consider adjusting it.
789
 */
790
static ulong
791
usbload(int speed, int maxpkt)
792
{
793
	enum{ Hostns = 1000, Hubns = 333 };
794
	ulong l;
795
	ulong bs;
796
 
797
	l = 0;
798
	bs = 10UL * maxpkt;
799
	switch(speed){
800
	case Highspeed:
801
		l = 55*8*2 + 2 * (3 + bs) + Hostns;
802
		break;
803
	case Fullspeed:
804
		l = 9107 + 84 * (4 + bs) + Hostns;
805
		break;
806
	case Lowspeed:
807
		l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
808
		break;
809
	default:
810
		print("usbload: bad speed %d\n", speed);
811
		/* let it run */
812
	}
813
	return l / 1000UL;	/* in µs */
814
}
815
 
816
static Chan*
817
usbopen(Chan *c, int omode)
818
{
819
	int q;
820
	Ep *ep;
821
	int mode;
822
 
823
	mode = openmode(omode);
824
	q = QID(c->qid);
825
 
826
	if(q >= Qep0dir && qid2epidx(q) < 0)
827
		error(Eio);
828
	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
829
		return devopen(c, omode, nil, 0, usbgen);
830
 
831
	ep = getep(qid2epidx(q));
832
	if(ep == nil)
833
		error(Eio);
834
	deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
835
	if(waserror()){
836
		putep(ep);
837
		nexterror();
838
	}
839
	qlock(ep);
840
	if(ep->inuse){
841
		qunlock(ep);
842
		error(Einuse);
843
	}
844
	ep->inuse = 1;
845
	qunlock(ep);
846
	if(waserror()){
847
		ep->inuse = 0;
848
		nexterror();
849
	}
850
	if(mode != OREAD && ep->mode == OREAD)
851
		error(Eperm);
852
	if(mode != OWRITE && ep->mode == OWRITE)
853
		error(Eperm);
854
	if(ep->ttype == Tnone)
855
		error(Enotconf);
856
	ep->clrhalt = 0;
857
	ep->rhrepl = -1;
858
	if(ep->load == 0)
859
		ep->load = usbload(ep->dev->speed, ep->maxpkt);
860
	ep->hp->epopen(ep);
861
 
862
	poperror();	/* ep->inuse */
863
	poperror();	/* don't putep(): ref kept for fid using the ep. */
864
 
865
	c->mode = mode;
866
	c->flag |= COPEN;
867
	c->offset = 0;
868
	c->aux = nil;	/* paranoia */
869
	return c;
870
}
871
 
872
static void
873
epclose(Ep *ep)
874
{
875
	qlock(ep);
876
	if(waserror()){
877
		qunlock(ep);
878
		nexterror();
879
	}
880
	if(ep->inuse){
881
		ep->hp->epclose(ep);
882
		ep->inuse = 0;
883
	}
884
	qunlock(ep);
885
	poperror();
886
}
887
 
888
static void
889
usbclose(Chan *c)
890
{
891
	int q;
892
	Ep *ep;
893
 
894
	q = QID(c->qid);
895
	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
896
		return;
897
 
898
	ep = getep(qid2epidx(q));
899
	if(ep == nil)
900
		return;
901
	deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
902
	if(waserror()){
903
		putep(ep);
904
		nexterror();
905
	}
906
	if(c->flag & COPEN){
907
		free(c->aux);
908
		c->aux = nil;
909
		epclose(ep);
910
		putep(ep);	/* release ref kept since usbopen */
911
		c->flag &= ~COPEN;
912
	}
913
	poperror();
914
	putep(ep);
915
}
916
 
917
static long
918
ctlread(Chan *c, void *a, long n, vlong offset)
919
{
920
	int q;
921
	char *s;
922
	char *us;
923
	char *se;
924
	Ep *ep;
925
	int i;
926
 
927
	q = QID(c->qid);
928
	us = s = smalloc(READSTR);
929
	se = s + READSTR;
930
	if(waserror()){
931
		free(us);
932
		nexterror();
933
	}
934
	if(q == Qctl)
935
		for(i = 0; i < epmax; i++){
936
			ep = getep(i);
937
			if(ep != nil){
938
				if(waserror()){
939
					putep(ep);
940
					nexterror();
941
				}
942
				s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
943
				s = seprintep(s, se, ep, 0);
944
				poperror();
945
			}
946
			putep(ep);
947
		}
948
	else{
949
		ep = getep(qid2epidx(q));
950
		if(ep == nil)
951
			error(Eio);
952
		if(waserror()){
953
			putep(ep);
954
			nexterror();
955
		}
956
		if(c->aux != nil){
957
			/* After a new endpoint request we read
958
			 * the new endpoint name back.
959
			 */
960
			strecpy(s, se, c->aux);
961
			free(c->aux);
962
			c->aux = nil;
963
		}else
964
			seprintep(s, se, ep, 0);
965
		poperror();
966
		putep(ep);
967
	}
968
	n = readstr(offset, a, n, us);
969
	poperror();
970
	free(us);
971
	return n;
972
}
973
 
974
/*
975
 * Fake root hub emulation.
976
 */
977
static long
978
rhubread(Ep *ep, void *a, long n)
979
{
980
	char *b;
981
 
982
	if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
983
		return -1;
984
	if(ep->rhrepl < 0)
985
		return -1;
986
 
987
	b = a;
988
	memset(b, 0, n);
989
	PUT2(b, ep->rhrepl);
990
	ep->rhrepl = -1;
991
	return n;
992
}
993
 
994
static long
995
rhubwrite(Ep *ep, void *a, long n)
996
{
997
	uchar *s;
998
	int cmd;
999
	int feature;
1000
	int port;
1001
	Hci *hp;
1002
 
1003
	if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
1004
		return -1;
1005
	if(n != Rsetuplen)
1006
		error("root hub is a toy hub");
1007
	ep->rhrepl = -1;
1008
	s = a;
1009
	if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
1010
		error("root hub is a toy hub");
1011
	hp = ep->hp;
1012
	cmd = s[Rreq];
1013
	feature = GET2(s+Rvalue);
1014
	port = GET2(s+Rindex);
1015
	if(port < 1 || port > hp->nports)
1016
		error("bad hub port number");
1017
	switch(feature){
1018
	case Rportenable:
1019
		ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
1020
		break;
1021
	case Rportreset:
1022
		ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
1023
		break;
1024
	case Rgetstatus:
1025
		ep->rhrepl = hp->portstatus(hp, port);
1026
		break;
1027
	default:
1028
		ep->rhrepl = 0;
1029
	}
1030
	return n;
1031
}
1032
 
1033
static long
1034
usbread(Chan *c, void *a, long n, vlong offset)
1035
{
1036
	int q;
1037
	Ep *ep;
1038
	int nr;
1039
 
1040
	q = QID(c->qid);
1041
 
1042
	if(c->qid.type == QTDIR)
1043
		return devdirread(c, a, n, nil, 0, usbgen);
1044
 
1045
	if(q == Qctl || isqtype(q, Qepctl))
1046
		return ctlread(c, a, n, offset);
1047
 
1048
	ep = getep(qid2epidx(q));
1049
	if(ep == nil)
1050
		error(Eio);
1051
	if(waserror()){
1052
		putep(ep);
1053
		nexterror();
1054
	}
1055
	if(ep->dev->state == Ddetach)
1056
		error(Edetach);
1057
	if(ep->mode == OWRITE || ep->inuse == 0)
1058
		error(Ebadusefd);
1059
	switch(ep->ttype){
1060
	case Tnone:
1061
		error("endpoint not configured");
1062
	case Tctl:
1063
		nr = rhubread(ep, a, n);
1064
		if(nr >= 0){
1065
			n = nr;
1066
			break;
1067
		}
1068
		/* else fall */
1069
	default:
1070
		ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
1071
		n = ep->hp->epread(ep, a, n);
1072
		break;
1073
	}
1074
	poperror();
1075
	putep(ep);
1076
	return n;
1077
}
1078
 
1079
static long
1080
pow2(int n)
1081
{
1082
	return 1 << n;
1083
}
1084
 
1085
static void
1086
setmaxpkt(Ep *ep, char* s)
1087
{
1088
	long spp;	/* samples per packet */
1089
 
1090
	if(ep->dev->speed == Highspeed)
1091
		spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
1092
	else
1093
		spp = (ep->hz * ep->pollival + 999) / 1000;
1094
	ep->maxpkt = spp * ep->samplesz;
1095
	deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
1096
		" ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
1097
		ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
1098
		spp, ep->maxpkt);
1099
	if(ep->maxpkt > 1024){
1100
		print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
1101
		ep->maxpkt = 1024;
1102
	}
1103
}
1104
 
1105
/*
1106
 * Many endpoint ctls. simply update the portable representation
1107
 * of the endpoint. The actual controller driver will look
1108
 * at them to setup the endpoints as dictated.
1109
 */
1110
static long
1111
epctl(Ep *ep, Chan *c, void *a, long n)
1112
{
1113
	int i, l, mode, nb, tt;
1114
	char *b, *s;
1115
	Cmdbuf *cb;
1116
	Cmdtab *ct;
1117
	Ep *nep;
1118
	Udev *d;
1119
	static char *Info = "info ";
1120
 
1121
	d = ep->dev;
1122
 
1123
	cb = parsecmd(a, n);
1124
	if(waserror()){
1125
		free(cb);
1126
		nexterror();
1127
	}
1128
	ct = lookupcmd(cb, epctls, nelem(epctls));
1129
	if(ct == nil)
1130
		error(Ebadctl);
1131
	i = ct->index;
1132
	if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
1133
		if(ep != ep->ep0)
1134
			error("allowed only on a setup endpoint");
1135
	if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
1136
		if(ep != ep->ep0 && ep->inuse != 0)
1137
			error("must configure before using");
1138
	switch(i){
1139
	case CMnew:
1140
		deprint("usb epctl %s\n", cb->f[0]);
1141
		nb = strtol(cb->f[1], nil, 0);
1142
		if(nb < 0 || nb >= Ndeveps)
1143
			error("bad endpoint number");
1144
		tt = name2ttype(cb->f[2]);
1145
		if(tt == Tnone)
1146
			error("unknown endpoint type");
1147
		mode = name2mode(cb->f[3]);
1148
		if(mode < 0)
1149
			error("unknown i/o mode");
1150
		newdevep(ep, nb, tt, mode);
1151
		break;
1152
	case CMnewdev:
1153
		deprint("usb epctl %s\n", cb->f[0]);
1154
		if(ep != ep->ep0 || d->ishub == 0)
1155
			error("not a hub setup endpoint");
1156
		l = name2speed(cb->f[1]);
1157
		if(l == Nospeed)
1158
			error("speed must be full|low|high");
1159
		nep = newdev(ep->hp, 0, 0);
1160
		nep->dev->speed = l;
1161
		if(nep->dev->speed  != Lowspeed)
1162
			nep->maxpkt = 64;	/* assume full speed */
1163
		nep->dev->hub = d->nb;
1164
		nep->dev->port = atoi(cb->f[2]);
1165
		/* next read request will read
1166
		 * the name for the new endpoint
1167
		 */
1168
		l = sizeof(up->genbuf);
1169
		snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
1170
		kstrdup(&c->aux, up->genbuf);
1171
		break;
1172
	case CMhub:
1173
		deprint("usb epctl %s\n", cb->f[0]);
1174
		d->ishub = 1;
1175
		break;
1176
	case CMspeed:
1177
		l = name2speed(cb->f[1]);
1178
		deprint("usb epctl %s %d\n", cb->f[0], l);
1179
		if(l == Nospeed)
1180
			error("speed must be full|low|high");
1181
		qlock(ep->ep0);
1182
		d->speed = l;
1183
		qunlock(ep->ep0);
1184
		break;
1185
	case CMmaxpkt:
1186
		l = strtoul(cb->f[1], nil, 0);
1187
		deprint("usb epctl %s %d\n", cb->f[0], l);
1188
		if(l < 1 || l > 1024)
1189
			error("maxpkt not in [1:1024]");
1190
		qlock(ep);
1191
		ep->maxpkt = l;
1192
		qunlock(ep);
1193
		break;
1194
	case CMntds:
1195
		l = strtoul(cb->f[1], nil, 0);
1196
		deprint("usb epctl %s %d\n", cb->f[0], l);
1197
		if(l < 1 || l > 3)
1198
			error("ntds not in [1:3]");
1199
		qlock(ep);
1200
		ep->ntds = l;
1201
		qunlock(ep);
1202
		break;
1203
	case CMpollival:
1204
		if(ep->ttype != Tintr && ep->ttype != Tiso)
1205
			error("not an intr or iso endpoint");
1206
		l = strtoul(cb->f[1], nil, 0);
1207
		deprint("usb epctl %s %d\n", cb->f[0], l);
1208
		if(ep->ttype == Tiso ||
1209
		   (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
1210
			if(l < 1 || l > 16)
1211
				error("pollival power not in [1:16]");
1212
			l = pow2(l-1);
1213
		}else
1214
			if(l < 1 || l > 255)
1215
				error("pollival not in [1:255]");
1216
		qlock(ep);
1217
		ep->pollival = l;
1218
		if(ep->ttype == Tiso)
1219
			setmaxpkt(ep, "pollival");
1220
		qunlock(ep);
1221
		break;
1222
	case CMsamplesz:
1223
		if(ep->ttype != Tiso)
1224
			error("not an iso endpoint");
1225
		l = strtoul(cb->f[1], nil, 0);
1226
		deprint("usb epctl %s %d\n", cb->f[0], l);
1227
		if(l <= 0 || l > 8)
1228
			error("samplesz not in [1:8]");
1229
		qlock(ep);
1230
		ep->samplesz = l;
1231
		setmaxpkt(ep, "samplesz");
1232
		qunlock(ep);
1233
		break;
1234
	case CMhz:
1235
		if(ep->ttype != Tiso)
1236
			error("not an iso endpoint");
1237
		l = strtoul(cb->f[1], nil, 0);
1238
		deprint("usb epctl %s %d\n", cb->f[0], l);
1239
		if(l <= 0 || l > 100000)
1240
			error("hz not in [1:100000]");
1241
		qlock(ep);
1242
		ep->hz = l;
1243
		setmaxpkt(ep, "hz");
1244
		qunlock(ep);
1245
		break;
1246
	case CMclrhalt:
1247
		qlock(ep);
1248
		deprint("usb epctl %s\n", cb->f[0]);
1249
		ep->clrhalt = 1;
1250
		qunlock(ep);
1251
		break;
1252
	case CMinfo:
1253
		deprint("usb epctl %s\n", cb->f[0]);
1254
		l = strlen(Info);
1255
		s = a;
1256
		if(n < l+2 || strncmp(Info, s, l) != 0)
1257
			error(Ebadctl);
1258
		if(n > 1024)
1259
			n = 1024;
1260
		b = smalloc(n);
1261
		memmove(b, s+l, n-l);
1262
		b[n-l] = 0;
1263
		if(b[n-l-1] == '\n')
1264
			b[n-l-1] = 0;
1265
		qlock(ep);
1266
		free(ep->info);
1267
		ep->info = b;
1268
		qunlock(ep);
1269
		break;
1270
	case CMaddress:
1271
		deprint("usb epctl %s\n", cb->f[0]);
1272
		ep->dev->state = Denabled;
1273
		break;
1274
	case CMdetach:
1275
		if(ep->dev->isroot != 0)
1276
			error("can't detach a root hub");
1277
		deprint("usb epctl %s ep%d.%d\n",
1278
			cb->f[0], ep->dev->nb, ep->nb);
1279
		ep->dev->state = Ddetach;
1280
		/* Release file system ref. for its endpoints */
1281
		for(i = 0; i < nelem(ep->dev->eps); i++)
1282
			putep(ep->dev->eps[i]);
1283
		break;
1284
	case CMdebugep:
1285
		if(strcmp(cb->f[1], "on") == 0)
1286
			ep->debug = 1;
1287
		else if(strcmp(cb->f[1], "off") == 0)
1288
			ep->debug = 0;
1289
		else
1290
			ep->debug = strtoul(cb->f[1], nil, 0);
1291
		print("usb: ep%d.%d debug %d\n",
1292
			ep->dev->nb, ep->nb, ep->debug);
1293
		break;
1294
	case CMname:
1295
		deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
1296
		validname(cb->f[1], 0);
1297
		kstrdup(&ep->name, cb->f[1]);
1298
		break;
1299
	case CMtmout:
1300
		deprint("usb epctl %s\n", cb->f[0]);
1301
		if(ep->ttype == Tiso || ep->ttype == Tctl)
1302
			error("ctl ignored for this endpoint type");
1303
		ep->tmout = strtoul(cb->f[1], nil, 0);
1304
		if(ep->tmout != 0 && ep->tmout < Xfertmout)
1305
			ep->tmout = Xfertmout;
1306
		break;
1307
	case CMpreset:
1308
		deprint("usb epctl %s\n", cb->f[0]);
1309
		if(ep->ttype != Tctl)
1310
			error("not a control endpoint");
1311
		if(ep->dev->state != Denabled)
1312
			error("forbidden on devices not enabled");
1313
		ep->dev->state = Dreset;
1314
		break;
1315
	default:
1316
		panic("usb: unknown epctl %d", ct->index);
1317
	}
1318
	free(cb);
1319
	poperror();
1320
	return n;
1321
}
1322
 
1323
static long
1324
usbctl(void *a, long n)
1325
{
1326
	Cmdtab *ct;
1327
	Cmdbuf *cb;
1328
	Ep *ep;
1329
	int i;
1330
 
1331
	cb = parsecmd(a, n);
1332
	if(waserror()){
1333
		free(cb);
1334
		nexterror();
1335
	}
1336
	ct = lookupcmd(cb, usbctls, nelem(usbctls));
1337
	dprint("usb ctl %s\n", cb->f[0]);
1338
	switch(ct->index){
1339
	case CMdebug:
1340
		if(strcmp(cb->f[1], "on") == 0)
1341
			debug = 1;
1342
		else if(strcmp(cb->f[1], "off") == 0)
1343
			debug = 0;
1344
		else
1345
			debug = strtol(cb->f[1], nil, 0);
1346
		print("usb: debug %d\n", debug);
1347
		for(i = 0; i < epmax; i++)
1348
			if((ep = getep(i)) != nil){
1349
				ep->hp->debug(ep->hp, debug);
1350
				putep(ep);
1351
			}
1352
		break;
1353
	case CMdump:
1354
		dumpeps();
1355
		break;
1356
	}
1357
	free(cb);
1358
	poperror();
1359
	return n;
1360
}
1361
 
1362
static long
1363
ctlwrite(Chan *c, void *a, long n)
1364
{
1365
	int q;
1366
	Ep *ep;
1367
 
1368
	q = QID(c->qid);
1369
	if(q == Qctl)
1370
		return usbctl(a, n);
1371
 
1372
	ep = getep(qid2epidx(q));
1373
	if(ep == nil)
1374
		error(Eio);
1375
	if(waserror()){
1376
		putep(ep);
1377
		nexterror();
1378
	}
1379
	if(ep->dev->state == Ddetach)
1380
		error(Edetach);
1381
	if(isqtype(q, Qepctl) && c->aux != nil){
1382
		/* Be sure we don't keep a cloned ep name */
1383
		free(c->aux);
1384
		c->aux = nil;
1385
		error("read, not write, expected");
1386
	}
1387
	n = epctl(ep, c, a, n);
1388
	putep(ep);
1389
	poperror();
1390
	return n;
1391
}
1392
 
1393
static long
1394
usbwrite(Chan *c, void *a, long n, vlong off)
1395
{
1396
	int nr, q;
1397
	Ep *ep;
1398
 
1399
	if(c->qid.type == QTDIR)
1400
		error(Eisdir);
1401
 
1402
	q = QID(c->qid);
1403
 
1404
	if(q == Qctl || isqtype(q, Qepctl))
1405
		return ctlwrite(c, a, n);
1406
 
1407
	ep = getep(qid2epidx(q));
1408
	if(ep == nil)
1409
		error(Eio);
1410
	if(waserror()){
1411
		putep(ep);
1412
		nexterror();
1413
	}
1414
	if(ep->dev->state == Ddetach)
1415
		error(Edetach);
1416
	if(ep->mode == OREAD || ep->inuse == 0)
1417
		error(Ebadusefd);
1418
 
1419
	switch(ep->ttype){
1420
	case Tnone:
1421
		error("endpoint not configured");
1422
	case Tctl:
1423
		nr = rhubwrite(ep, a, n);
1424
		if(nr >= 0){
1425
			n = nr;
1426
			break;
1427
		}
1428
		/* else fall */
1429
	default:
1430
		ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
1431
		ep->hp->epwrite(ep, a, n);
1432
	}
1433
	putep(ep);
1434
	poperror();
1435
	return n;
1436
}
1437
 
1438
void
1439
usbshutdown(void)
1440
{
1441
	Hci *hp;
1442
	int i;
1443
 
1444
	for(i = 0; i < Nhcis; i++){
1445
		hp = hcis[i];
1446
		if(hp == nil)
1447
			continue;
1448
		if(hp->shutdown == nil)
1449
			print("#u: no shutdown function for %s\n", hp->type);
1450
		else
1451
			hp->shutdown(hp);
1452
	}
1453
}
1454
 
1455
Dev usbdevtab = {
1456
	L'u',
1457
	"usb",
1458
 
1459
	usbreset,
1460
	usbinit,
1461
	usbshutdown,
1462
	usbattach,
1463
	usbwalk,
1464
	usbstat,
1465
	usbopen,
1466
	devcreate,
1467
	usbclose,
1468
	usbread,
1469
	devbread,
1470
	usbwrite,
1471
	devbwrite,
1472
	devremove,
1473
	devwstat,
1474
};