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

📄 devusb.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	Usbhost *uh;	for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++){		uh = usbhost[ctlrno];		if(uh == nil)			continue;		if(uh->init != 0)			uh->init(uh);		/* reserve device for configuration */		d = usbnewdevice(uh);		incref(d);		d->state = Attached;	}}Chan *usbattach(char *spec){	return devattach('U', spec);}static Walkqid*usbwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, nil, 0, usbgen);}static intusbstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, nil, 0, usbgen);}Chan*usbopen(Chan *c, int omode){	Udev *d;	Endpt *e;	int f, s, type;	Usbhost *uh;	if(c->qid.type == QTDIR)		return devopen(c, omode, nil, 0, usbgen);	f = 0;	type = TYPE(c->qid);	if(type == Qnew){		d = usbdevice(c);		d = usbnewdevice(d->uh);		XPRINT("usbopen, new dev 0x%p\n", d);		if(d == nil) {			XPRINT("usbopen failed (usbnewdevice)\n");			error(Enodev);		}		type = Qctl;		mkqid(&c->qid, PATH(type, d->x, CTLR(c->qid)), d->id, QTFILE);		f = 1;	}	if(type < Q3rd){		XPRINT("usbopen, devopen < Q3rd\n");		return devopen(c, omode, nil, 0, usbgen);	}	d = usbdevice(c);	uh = d->uh;	qlock(uh);	if(waserror()){		qunlock(uh);		nexterror();	}	switch(type){	case Qctl:		if(0&&d->busy)			error(Einuse);		d->busy = 1;		if(!f)			incref(d);		XPRINT("usbopen, Qctl 0x%p\n", d);		break;	default:		s = type - Qep0;		XPRINT("usbopen, default 0x%p, %d\n", d, s);		if(s >= 0 && s < nelem(d->ep)){			if((e = d->ep[s]) == nil) {				XPRINT("usbopen failed (endpoint)\n");				error(Enodev);			}			XPRINT("usbopen: dev 0x%p, ept 0x%p\n", d, e);			uh->epopen(uh, e);			e->foffset = 0;			e->toffset = 0;			e->poffset = 0;			e->buffered = 0;		}		incref(d);		break;	}	poperror();	qunlock(uh);	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;}voidusbclose(Chan *c){	Udev *d;	int ept, type;	Usbhost *uh;	type = TYPE(c->qid);	if(c->qid.type == QTDIR || type < Q3rd)		return;	d = usbdevice(c);	uh = d->uh;	qlock(uh);	if(waserror()){		qunlock(uh);		nexterror();	}	if(type == Qctl)		d->busy = 0;	XPRINT("usbclose: dev 0x%p\n", d);	if(c->flag & COPEN){		ept = (type != Qctl) ? type - Qep0 : -1;		XPRINT("usbclose: freedev 0x%p\n", d);		freedev(d, ept);	}	poperror();	qunlock(uh);}static char *epstatus(char *s, char *se, Endpt *e, int i){	char *p;	p = seprint(s, se, "%2d %#6.6lux %10lud bytes %10lud blocks\n", i, e->csp, e->nbytes, e->nblocks);	if(e->iso){		p = seprint(p, se, "bufsize %6d buffered %6d", e->maxpkt, e->buffered);		if(e->toffset)			p = seprint(p, se, " offset  %10lud time %19lld\n", e->toffset, e->time);		p = seprint(p, se, "\n");	}	return p;}longusbread(Chan *c, void *a, long n, vlong offset){	int t, i;	Udev *d;	Endpt *e;	Usbhost *uh;	char *s, *se, *p;	if(c->qid.type == QTDIR)		return devdirread(c, a, n, nil, 0, usbgen);	d = usbdevice(c);	uh = d->uh;	t = TYPE(c->qid);	if(t >= Qep0) {		t -= Qep0;		if(t >= nelem(d->ep))			error(Eio);		e = d->ep[t];		if(e == nil || e->mode == OWRITE)			error(Egreg);		if(t == 0) {			if(e->iso)				error(Egreg); 			e->rdata01 = 1;			n = uh->read(uh, e, a, n, 0LL);			if(e->setin){				e->setin = 0;				e->wdata01 = 1;				uh->write(uh, e, "", 0, 0LL, TokOUT);			}			return n;		}		return uh->read(uh, e, a, n, offset);	}	s = smalloc(READSTR);	se = s+READSTR;	if(waserror()){		free(s);		nexterror();	}	switch(t){	case Qport:		uh->portinfo(uh, s, se);		break;	case Qctl:		seprint(s, se, "%11d %11d\n", d->x, d->id);		break;	case Qstatus:		if (d->did || d->vid)			p = seprint(s, se, "%s %#6.6lux %#4.4ux %#4.4ux\n", devstates[d->state], d->csp, d->vid, d->did);		else			p = seprint(s, se, "%s %#6.6lux\n", devstates[d->state], d->csp);		for(i=0; i<nelem(d->ep); i++) {			e = d->ep[i];			if(e == nil)				continue;			/* TO DO: freeze e */			p = epstatus(p, se, e, i);		}	}	n = readstr(offset, a, n, s);	poperror();	free(s);	return n;}longusbwrite(Chan *c, void *a, long n, vlong offset){	Udev *d;	Endpt *e;	Cmdtab *ct;	Cmdbuf *cb;	Usbhost *uh;	int id, nw, t, i;	char cmd[50];	if(c->qid.type == QTDIR)		error(Egreg);	d = usbdevice(c);	uh = d->uh;	t = TYPE(c->qid);	switch(t){	case Qport:		cb = parsecmd(a, n);		if(waserror()){			free(cb);			nexterror();		}		ct = lookupcmd(cb, usbportmsg, nelem(usbportmsg));		id = strtol(cb->f[1], nil, 0);		switch(ct->index){		case PMdisable:			uh->portenable(uh, id, 0);			break;		case PMenable:			uh->portenable(uh, id, 1);			break;		case PMreset:			uh->portreset(uh, id);			break;		}			poperror();		free(cb);		return n;	case Qctl:		cb = parsecmd(a, n);		if(waserror()){			free(cb);			nexterror();		}		ct = lookupcmd(cb, usbctlmsg, nelem(usbctlmsg));		switch(ct->index){		case CMspeed:			d->ls = strtoul(cb->f[1], nil, 0) == 0;			break;		case CMclass:			if (cb->nf != 4 && cb->nf != 6)				cmderror(cb, Ebadusbmsg);			/* class #ifc ept csp ( == class subclass proto) [vendor product] */			d->npt = strtoul(cb->f[1], nil, 0);	/* # of interfaces */			i = strtoul(cb->f[2], nil, 0);		/* endpoint */			if (i < 0 || i >= nelem(d->ep)			 || d->npt > nelem(d->ep) || i >= d->npt)				cmderror(cb, Ebadusbmsg);			if (cb->nf == 6) {				d->vid = strtoul(cb->f[4], nil, 0);				d->did = strtoul(cb->f[5], nil, 0);			}			if (i == 0)				d->csp = strtoul(cb->f[3], nil, 0);			if(d->ep[i] == nil){				XPRINT("calling devendpt in usbwrite (CMclass)\n");				d->ep[i] = devendpt(d, i, 1);			}			d->ep[i]->csp = strtoul(cb->f[3], nil, 0);			break;		case CMdata:			i = strtoul(cb->f[1], nil, 0);			if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil)				error(Ebadusbmsg);			e = d->ep[i];			e->wdata01 = e->rdata01 = strtoul(cb->f[2], nil, 0) != 0;			break;		case CMmaxpkt:			i = strtoul(cb->f[1], nil, 0);			if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil)				error(Ebadusbmsg);			e = d->ep[i];			e->maxpkt = strtoul(cb->f[2], nil, 0);			if(e->maxpkt > 1500)				e->maxpkt = 1500;			break;		case CMadjust:			i = strtoul(cb->f[1], nil, 0);			if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil)				error(Ebadusbmsg);			e = d->ep[i];			if (e->iso == 0)				error(Eperm);			i = strtoul(cb->f[2], nil, 0);			/* speed may not result in change of maxpkt */			if (i < (e->maxpkt-1)/e->samplesz * 1000/e->pollms			  || i > e->maxpkt/e->samplesz * 1000/e->pollms){				snprint(cmd, sizeof(cmd), "%d < %d < %d?",					(e->maxpkt-1)/e->samplesz * 1000/e->pollms,					i,					e->maxpkt/e->samplesz * 1000/e->pollms);				error(cmd);			}			e->hz = i;			break;		case CMdebug:			i = strtoul(cb->f[1], nil, 0);			if(i < -1 || i >= nelem(d->ep) || d->ep[i] == nil)				error(Ebadusbmsg);			if (i == -1)				debug = 0;			else {				debug = 1;				e = d->ep[i];				e->debug = strtoul(cb->f[2], nil, 0);			}			break;		case CMunstall:			i = strtoul(cb->f[1], nil, 0);			if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil)				error(Ebadusbmsg);			e = d->ep[i];			e->err = nil;			break;		case CMep:			/* ep n `bulk' mode maxpkt nbuf     OR			 * ep n period mode samplesize Hz			 */			i = strtoul(cb->f[1], nil, 0);			if(i < 0 || i >= nelem(d->ep)) {				XPRINT("field 1: 0 <= %d < %d\n", i, nelem(d->ep));				error(Ebadarg);			}			if((e = d->ep[i]) == nil){				XPRINT("calling devendpt in usbwrite (CMep)\n");				e = devendpt(d, i, 1);			}			qlock(uh);			if(waserror()){				freept(e);				qunlock(uh);				nexterror();			}			if(e->active)				error(Eperm);			if(strcmp(cb->f[2], "bulk") == 0){				/* ep n `bulk' mode maxpkt nbuf */				e->iso = 0;				i = strtoul(cb->f[4], nil, 0);				if(i < 8 || i > 1023)					i = 8;				e->maxpkt = i;				i = strtoul(cb->f[5], nil, 0);				if(i >= 1 && i <= 32)					e->nbuf = i;			} else {				/* ep n period mode samplesize Hz */				i = strtoul(cb->f[2], nil, 0);				if(i > 0 && i <= 1000){					e->pollms = i;				}else {					XPRINT("field 4: 0 <= %d <= 1000\n", i);					error(Ebadarg);				}				i = strtoul(cb->f[4], nil, 0);				if(i >= 1 && i <= 8){					e->samplesz = i;				}else {					XPRINT("field 4: 0 < %d <= 8\n", i);					error(Ebadarg);				}				i = strtoul(cb->f[5], nil, 0);				if(i >= 1 && i*e->samplesz <= 12*1000*1000){					/* Hz */					e->hz = i;					e->remain = 0;				}else {					XPRINT("field 5: 1 < %d <= 100000 Hz\n", i);					error(Ebadarg);				}				e->maxpkt = (e->hz * e->pollms + 999)/1000 * e->samplesz;				e->iso = 1;			}			e->mode = strcmp(cb->f[3],"r") == 0? OREAD :				  	strcmp(cb->f[3],"w") == 0? OWRITE : ORDWR;			uh->epmode(uh, e);			poperror();			qunlock(uh);		}			poperror();		free(cb);		return n;	case Qep0:	/* SETUP endpoint 0 */		/* should canqlock etc */		e = d->ep[0];		if(e == nil || e->iso)			error(Egreg);		if(n < 8)			error(Eio);		nw = *(uchar*)a & RD2H;		e->wdata01 = 0;		n = uh->write(uh, e, a, n, 0LL, TokSETUP);		if(nw == 0) {	/* host to device: use IN[DATA1] to ack */			e->rdata01 = 1;			nw = uh->read(uh, e, cmd, 0LL, 8);			if(nw != 0)				error(Eio);	/* could provide more status */		}else			e->setin = 1;	/* two-phase */		break;	default:	/* sends DATA[01] */		t -= Qep0;		if(t < 0 || t >= nelem(d->ep))			error(Egreg);		e = d->ep[t];		if(e == nil || e->mode == OREAD)			error(Egreg);		n = uh->write(uh, e, a, n, offset, TokOUT);		break;	}	return n;}Dev usbdevtab = {	'U',	"usb",	usbreset,	usbinit,	devshutdown,	usbattach,	usbwalk,	usbstat,	usbopen,	devcreate,	usbclose,	usbread,	devbread,	usbwrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

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