⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <thread.h>#include "usb.h"#include "dat.h"#include "fns.h"#define STACKSIZE 128*1024static int dontfork;Ref	busy;int debug;typedef struct Enum Enum;struct Enum{	Hub *hub;	int port;};void (*dprinter[])(Device *, int, ulong, void *b, int n) = {	[STRING] pstring,	[DEVICE] pdevice,	[0x29] phub,};static voidusage(void){	fprint(2, "usage: usbd\n");	threadexitsall("usage");}voidwork(void *a){	int port;	Hub *hub;	Enum *arg;	hub = a;	for (port = 1; port <= hub->nport; port++) {		if (debug)			fprint(2, "enumerate port %H.%d\n", hub, port);		arg = emallocz(sizeof(Enum), 1);		arg->hub = hub;		arg->port = port;		incref(&busy);		threadcreate(enumerate, arg, STACKSIZE);	}	decref(&busy);	for(;;) {		yield();		if (busy.ref == 0)			sleep(2000);	}}voidthreadmain(int argc, char **argv){	int i;	Hub *h;	ARGBEGIN{	case 'f':		dontfork=1;		break;	case 'd':		debug++;		break;	case 'v':		verbose = 1;		break;	}ARGEND	if (argc)		usage();	if (access("/dev/usb0", 0) < 0 && bind("#U", "/dev", MAFTER) < 0)		sysfatal("%s: can't bind #U after /dev: %r\n", argv0);	usbfmtinit();	fmtinstall('H', Hfmt);	/* always fork off usb[1-n] */	for(i=1; (h = roothub(i)) != nil; i++) {		incref(&busy);		proccreate(work, h, STACKSIZE);	}	/* usb0 might be handled in this proc */	if((h = roothub(0)) != nil){		incref(&busy);		if (dontfork) {			work(h);		} else {			rfork(RFNOTEG);			proccreate(work, h, STACKSIZE);			/* don't hold window open */			close(0);			close(1);			if(!debug && !verbose)				close(2);		}	}	if (debug)		fprint(2, "done\n");	while (busy.ref)		sleep(100);	threadexits(nil);}voidenumerate(void *v){	int i, port;	Device *d;	Enum *arg;	Hub *h, *nh;	arg = v;	h = arg->hub;	port = arg->port;	free(arg);	for (;;) {		if((portstatus(h, port) & (1<<PORT_CONNECTION)) == 0) {			decref(&busy);			if (verbose)				fprint(2, "usbd: %H: port %d empty\n", h, port);			do {				yield();				if (debugdebug)					fprint(2, "usbd: probing %H.%d\n", h, port);				sleep(500);			} while((portstatus(h, port) & (1<<PORT_CONNECTION)) == 0);			incref(&busy);		}		if(verbose)			fprint(2, "usbd: %H: port %d attached\n", h, port);		d = configure(h, port);		if(d == nil) {			if(verbose)				fprint(2, "usbd: can't configure port %H.%d\n", h, port);			decref(&busy);			threadexits("configure");		}		if(d->class == Hubclass) {			if(debug)				fprint(2, "usbd: %H.%d: hub %d attached\n", h, port, d->id);			setconfig(d, 1);			nh = newhub(h, d);			if(nh == nil) {				detach(h, port);				decref(&busy);				threadexits("describehub");			}			if(debug)				fprint(2, "usbd: traversing hub %H\n", nh);			/* TO DO: initialise status endpoint */			for(i=1; i<=nh->nport; i++)				portpower(nh, i, 1);			sleep(nh->pwrms);			for(i=1; i<=nh->nport; i++) {				arg = emallocz(sizeof(Enum), 1);				arg->hub = nh;				arg->port = i;				incref(&busy);				threadcreate(enumerate, arg, STACKSIZE);			}		}else{			if(debug)				fprint(2, "usbd: %H.%d: %d: not hub, %s speed\n", h, port, d->id, d->ls?"low":"high");			setconfig(d, 1);	/* TO DO *///unconscionable kludge (testing camera)if(d->class == 10) setup0(d, RH2D|Rinterface, SET_INTERFACE, 10, 0, 0);		}		decref(&busy);		while(portstatus(h, port) & (1<<PORT_CONNECTION)) {			if (debugdebug)				fprint(2, "checking %H.%d\n", h, port);			yield();			if (d->state == Detached) {				if (verbose)					fprint(2, "%H: port %d detached by parent hub\n", h, port);				/* parent hub died */				threadexits(nil);			}		}		if(verbose)			fprint(2, "%H: port %d detached\n", h, port);		detach(h, port);	}}Device*configure(Hub *h, int port){	Port *p;	Device *d;	int i, s, maxpkt, ls;	portenable(h, port, 1);	sleep(20);	portreset(h, port);	sleep(20);	s = portstatus(h, port);	if (debug)		fprint(2, "%H.%d status %#ux\n", h, port, s);	if ((s & (1<<PORT_CONNECTION)) == 0)		return nil;	if ((s & (1<<PORT_SUSPEND)) == 0) {		if (debug)			fprint(2, "enabling port %H.%d\n", h, port);		portenable(h, port, 1);		s = portstatus(h, port);		if (debug)			fprint(2, "%H.%d status now %#ux\n", h, port, s);	}	ls = (s & (1<<PORT_LOW_SPEED)) != 0;	devspeed(h->dev0, ls);	maxpkt = getmaxpkt(h->dev0);	if(maxpkt < 0) {Error0:		portenable(h, port, 0);		return nil;	}	d = opendev(h->ctlrno, -1);	d->ls = ls;	d->state = Enabled;	d->ep[0]->maxpkt = maxpkt;	if(fprint(d->ctl, "maxpkt 0 %d", maxpkt) < 0) {Error1:		closedev(d);		goto Error0;	}	if(setaddress(h->dev0, d->id) < 0)		goto Error1;	d->state = Assigned;	devspeed(d, ls);	if(describedevice(d) < 0)		goto Error1;	/* read configurations 0 to n */	for(i=0; i<d->nconf; i++) {		if(d->config[i] == nil)			d->config[i] = mallocz(sizeof(*d->config[i]),1);		loadconfig(d, i);	}	for(i=0; i<16; i++)		setdevclass(d, i);	p = &h->port[port-1];	p->d = d;	return d;}voiddetach(Hub *h, int port){	Port *p;	Device *d;	p = &h->port[port-1];	if(p->hub != nil) {		freehub(p->hub);		p->hub = nil;	}	d = p->d;	d->state = Detached;	/* return i/o error on access */	closedev(d);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -