shithub: riscv

Download patch

ref: 4792c6bef97728520e391857a01e1cbbd94db82f
parent: 27fd88af23b165c1c3c454cb1e1f889d9b74784c
author: aiju <[email protected]>
date: Thu Jul 28 13:31:45 EDT 2011

usbd: added event file, removed usbdb

--- a/sys/src/cmd/nusb/usbd/dat.h
+++ b/sys/src/cmd/nusb/usbd/dat.h
@@ -1,23 +1,6 @@
-typedef struct Rule Rule;
-typedef struct Cond Cond;
 typedef struct Hub Hub;
 typedef struct DHub DHub;
 typedef struct Port Port;
-
-struct Rule {
-	char **argv;
-	int argc;
-	Cond *cond;
-	Rule *next;
-} *rulefirst, *rulelast;
-
-RWLock rulelock;
-
-struct Cond {
-	int field;
-	u32int value;
-	Cond *and, *or;
-};
 
 enum
 {
--- a/sys/src/cmd/nusb/usbd/fns.h
+++ b/sys/src/cmd/nusb/usbd/fns.h
@@ -1,4 +1,2 @@
-void	parserules(char*);
-Rule*	rulesmatch(Usbdev*);
 int	startdev(Port*);
 void	work(void);
--- a/sys/src/cmd/nusb/usbd/mkfile
+++ b/sys/src/cmd/nusb/usbd/mkfile
@@ -2,7 +2,6 @@
 
 OFILES=\
 	usbd.$O\
-	rules.$O\
 	hub.$O\
 
 HFILES=\
--- a/sys/src/cmd/nusb/usbd/rules.c
+++ /dev/null
@@ -1,241 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <ctype.h>
-#include "usb.h"
-#include "dat.h"
-#include "fns.h"
-
-static char *pos;
-static int lineno;
-
-static void
-skipempty(void)
-{
-	char *s;
-
-	for(;;){
-		s = pos;
-		if(*s == 0)
-			return;
-		while(*s != '\n' && isspace(*s))
-			s++;
-		if(*s == '#')
-			while(*s != 0 && *s != '\n')
-				s++;
-		if(*s != 0 && *s != '\n')
-			return;
-		pos = s;
-		if(*pos != 0){
-			pos++;
-			lineno++;
-		}
-	}
-}
-
-static void
-parsesh(int *argc, char ***argv)
-{
-	char *e;
-
-	*argc = 0;
-	*argv = nil;
-	for(;;){
-		while(isspace(*pos) && *pos != '\n')
-			pos++;
-		if(*pos == '\n' || *pos == 0 || *pos == '#')
-			break;
-		e = pos;
-		while(*e != 0 && *e != '#' && !isspace(*e))
-			e++;
-		(*argc)++;
-		*argv = realloc(*argv, (*argc + 2) * sizeof(char *));
-		if(*argv == nil)
-			sysfatal("realloc: %r");
-		(*argv)[*argc - 1] = mallocz(e - pos + 1, 1);
-		if((*argv)[*argc - 1] == nil)
-			sysfatal("malloc: %r");
-		memmove((*argv)[*argc - 1], pos, e - pos);
-		pos = e;
-	}
-	if(*argv != nil){
-		(*argv)[*argc] = nil;
-		(*argv)[*argc + 1] = nil;
-	}
-}
-
-static Usbdev dummy;
-
-struct field {
-	char *s;
-	void* v;
-} fields[] = {
-	"class", &dummy.class,
-	"vid", &dummy.vid,
-	"did", &dummy.did,
-	"csp", &dummy.csp,
-	nil, nil,
-};
-
-static int
-parsecond(Rule *r, Cond **last)
-{
-	Cond *c, *cc, **l;
-	char *e;
-	struct field *f;
-
-	skipempty();
-	if(!isspace(*pos))
-		return 0;
-	l = nil;
-	for(;;){
-		while(isspace(*pos) && *pos != '\n')
-			pos++;
-		if(*pos == '\n' || *pos == '#')
-			return 1;
-		e = pos;
-		while(*e != 0 && *e != '\n' && *e != '=')
-			e++;
-		if(*e != '=')
-			return -1;
-		c = mallocz(sizeof(*c), 1);
-		if(c == nil)
-			sysfatal("malloc: %r");
-		for(f = fields; f->s != nil; f++)
-			if(strlen(f->s) == e - pos && strncmp(pos, f->s, e - pos) == 0){
-				c->field = (int)((char*)f->v - (char*)&dummy);
-				break;
-			}
-		if(f->s == nil)
-			goto Error;
-		pos = e + 1;
-		c->value = strtol(pos, &e, 0);
-		if(pos == e)
-			goto Error;
-		pos = e;
-		if(l != nil)
-			*l = c;
-		else if(*last){
-			for(cc = *last; cc != nil; cc = cc->and)
-				cc->or = c;
-			*last = c;
-		}else
-			*last = r->cond = c;
-		l = &c->and;
-	}
-Error:
-	free(c);
-	return -1;
-}
-
-static int
-parserule(void)
-{
-	Rule *r;
-	int rc;
-	Cond *c;
-	
-	skipempty();
-	if(*pos == 0)
-		return 0;
-	if(isspace(*pos))
-		return -1;
-	r = mallocz(sizeof(*r), 1);
-	if(r == nil)
-		sysfatal("malloc: %r");
-	parsesh(&r->argc, &r->argv);
-	c = nil;
-	do
-		rc = parsecond(r, &c);
-	while(rc > 0);
-	if(rc < 0)
-		return -1;
-	if(rulefirst != nil)
-		rulelast->next = r;
-	else
-		rulefirst = r;
-	rulelast = r;
-	return 1;
-}
-
-static void
-freerules(void)
-{
-	Rule *r, *rr;
-	Cond *c, *cc;
-	
-	wlock(&rulelock);
-	for(r = rulefirst; r != nil; r = rr){
-		for(c = r->cond; c != nil; c = cc){
-			cc = c->and;
-			if(cc == nil)
-				cc = c->or;
-			free(c);
-		}
-		rr = r->next;
-		free(r);
-	}
-	rulefirst = rulelast = nil;
-	wunlock(&rulelock);
-}
-
-static void
-printrules(void)
-{
-	Rule *r;
-	Cond *c;
-	int i;
-
-	for(r = rulefirst; r != nil; r = r->next){
-		for(i = 0; i < r->argc; i++)
-			print("[%s] ", r->argv[i]);
-		print("\n\t");
-		for(c = r->cond; c != nil; ){
-			print("%d=%ud", c->field, c->value);
-			if(c->and == nil){
-				print("\n\t");
-				c = c->or;
-			}else{
-				print(" ");
-				c = c->and;
-			}
-		}
-		print("\n");
-	}
-}
-
-void
-parserules(char *s)
-{
-	int rc;
-
-	freerules();
-	lineno = 1;
-	pos = s;
-	do
-		rc = parserule();
-	while(rc > 0);
-	if(rc < 0)
-		sysfatal("syntax error in line %d", lineno);
-}
-
-Rule *
-rulesmatch(Usbdev *dev)
-{
-	Rule *r;
-	Cond *c;
-
-	for(r = rulefirst; r != nil; r = r->next){
-		c = r->cond;
-		while(c){
-			if(*(u32int*)((char*)dev + c->field) == c->value){
-				if(c->and == nil)
-					goto yes;
-				c = c->and;
-			}else
-				c = c->or;
-		}
-	}
-yes:
-	return r;
-}
--- a/sys/src/cmd/nusb/usbd/usbd.c
+++ b/sys/src/cmd/nusb/usbd/usbd.c
@@ -7,87 +7,272 @@
 #include "dat.h"
 #include "fns.h"
 
-char *luser;
-char *rules;
+enum {
+	Qroot,
+	Qusbevent,
+	Qmax
+};
 
-static File *usbdb;
+char *names[] = {
+	"",
+	"usbevent",
+};
+
 static char Enonexist[] = "does not exist";
 
+typedef struct Event Event;
+
+struct Event {
+	char *data;
+	int len;
+	Event *link;
+	int ref;
+};
+
+static Event *evfirst, *evlast;
+static Req *reqfirst, *reqlast;
+static QLock evlock;
+
 static void
+addreader(Req *req)
+{
+	req->aux = nil;
+	if(reqfirst == nil)
+		reqfirst = req;
+	else
+		reqlast->aux = req;
+	reqlast = req;
+}
+
+static void
+fulfill(Req *req, Event *e)
+{
+	int n;
+	
+	n = e->len;
+	if(n > req->ifcall.count)
+		n = req->ifcall.count;
+	memmove(req->ofcall.data, e->data, n);
+	req->ofcall.count = n;
+}
+
+static void
+initevent(void)
+{
+	evfirst = mallocz(sizeof(*evfirst), 1);
+	if(evfirst == nil)
+		sysfatal("malloc: %r");
+	evlast = evfirst;
+}
+
+static void
+readevent(Req *req)
+{
+	Event *e;
+
+	qlock(&evlock);
+	e = req->fid->aux;
+	if(e == evlast){
+		addreader(req);
+		qunlock(&evlock);
+		return;
+	}
+	fulfill(req, e);
+	req->fid->aux = e->link;
+	e->link->ref++;
+	if(--e->ref == 0 && e == evfirst){
+		evfirst = e->link;
+		free(e->data);
+		free(e);
+	}
+	qunlock(&evlock);
+	respond(req, nil);
+}
+
+static void
+pushevent(char *data)
+{
+	Event *e, *ee;
+	Req *r, *rr;
+	
+	qlock(&evlock);
+	e = evlast;
+	ee = emallocz(sizeof(Event), 1);
+	if(ee == nil)
+		sysfatal("malloc: %r");
+	evlast = ee;
+	e->data = data;
+	e->len = strlen(data);
+	e->link = ee;
+	for(r = reqfirst; r != nil; r = rr){
+		rr = r->aux;
+		r->aux = nil;
+		r->fid->aux = ee;
+		ee->ref++;
+		e->ref--;
+		fulfill(r, e);
+		respond(r, nil);
+	}
+	if(e->ref == 0 && e == evfirst){
+		evfirst = ee;
+		free(e->data);
+		free(e);
+	}
+	reqfirst = nil;
+	reqlast = nil;
+	qunlock(&evlock);
+}
+
+static int
+dirgen(int n, Dir *d, void *)
+{
+	if(n >= Qmax - 1)
+		return -1;
+	d->qid.path = n + 1;
+	d->qid.vers = 0;
+	if(n >= 0)
+		d->qid.type = 0;
+	else
+		d->qid.type = QTDIR;
+	d->uid = strdup(getuser());
+	d->gid = strdup(d->uid);
+	d->muid = strdup(d->uid);
+	d->name = strdup(names[n+1]);
+	d->mode = 0555 | (d->qid.type << 24);
+	d->atime = d->mtime = time(0);
+	d->length = 0;
+	return 0;
+}
+
+static void
+usbdattach(Req *req)
+{
+	req->fid->qid = (Qid) {Qroot, 0, QTDIR};
+	req->ofcall.qid = req->fid->qid;
+	respond(req, nil);
+}
+
+static char *
+usbdwalk(Fid *fid, char *name, Qid *qid)
+{
+	int i;
+
+	if(strcmp(name, "..") == 0){
+		fid->qid = (Qid) {Qroot, 0, QTDIR};
+		*qid = fid->qid;
+		return nil;
+	}
+	if(fid->qid.path != Qroot)
+		return "not a directory";
+	for(i = 0; i < Qmax; i++)
+		if(strcmp(name, names[i]) == 0){
+			fid->qid = (Qid) {i, 0, 0};
+			*qid = fid->qid;
+			return nil;
+		}
+	return "does not exist";
+}
+
+static void
 usbdread(Req *req)
 {
-	if(usbdb->qid.path == req->fid->qid.path){
-		readstr(req, rules);
+	switch((long)req->fid->qid.path){
+	case Qroot:
+		dirread9p(req, dirgen, nil);
 		respond(req, nil);
-		return;
+		break;
+	case Qusbevent:
+		readevent(req);
+		break;
+	default:
+		respond(req, Enonexist);
+		break;
 	}
-	respond(req, Enonexist);
 }
 
-Srv usbdsrv = {
-	.read = usbdread,
-};
+static void
+usbdstat(Req *req)
+{
+	if(dirgen(req->fid->qid.path - 1, &req->d, nil) < 0)
+		respond(req, "the front fell off");
+	else
+		respond(req, nil);
+}
 
 static void
-readrules(void)
+usbdopen(Req *req)
 {
-	int fd, rc, n;
-	char buf[4096];
-	
-	fd = open("/lib/usbdb", OREAD);
-	if(fd < 0)
-		sysfatal("open /lib/usbdb: %r");
-	rules = nil;
-	n = 0;
-	for(;;){
-		rc = readn(fd, buf, sizeof buf);
-		if(rc == 0)
+	if(req->fid->qid.path == Qusbevent){
+		qlock(&evlock);
+		req->fid->aux = evlast;
+		evlast->ref++;
+		qunlock(&evlock);
+	}
+	respond(req, nil);
+}
+
+static void
+usbddestroyfid(Fid *fid)
+{
+	Event *e, *ee;
+
+	if(fid->qid.path == Qusbevent){
+		qlock(&evlock);
+		e = fid->aux;
+		if(--e->ref == 0 && e == evfirst){
+			while(e->ref == 0 && e != evlast){
+				ee = e->link;
+				free(e->data);
+				free(e);
+				e = ee;
+			}
+			evfirst = e;
+		}
+		qunlock(&evlock);
+	}
+}
+
+static void
+usbdflush(Req *req)
+{
+	Req **l, *r;
+	qlock(&evlock);
+	l = &reqfirst;
+	while(r = *l){
+		if(r == req->oldreq){
+			*l = r->aux;
 			break;
-		if(rc < 0)
-			sysfatal("read: %r");
-		rules = realloc(rules, 1 + n + rc);
-		if(rules == nil)
-			sysfatal("realloc: %r");
-		memmove(rules + n, buf, rc);
-		n += rc;
-		rules[n] = 0;
+		}
+		l = &r->aux;
 	}
-	if(rules == nil)
-		rules = "";
-	close(fd);
+	qunlock(&evlock);
+	respond(req->oldreq, "interrupted");
+	respond(req, nil);
 }
 
+Srv usbdsrv = {
+	.attach = usbdattach,
+	.walk1 = usbdwalk,
+	.read = usbdread,
+	.stat = usbdstat,
+	.open = usbdopen,
+	.flush = usbdflush,
+	.destroyfid = usbddestroyfid,
+};
+
 int
 startdev(Port *p)
 {
-	Rule *r;
-	char buf[14];
+	Dev *d;
+	Usbdev *u;
 
-	if(p->dev == nil || p->dev->usb == nil){
+	if((d = p->dev) == nil || (u = p->dev->usb) == nil){
 		fprint(2, "okay what?\n");
 		return -1;
 	}
-	rlock(&rulelock);
-	r = rulesmatch(p->dev->usb);
-	if(r == nil || r->argv == nil){
-		fprint(2, "no driver for device\n");
-		runlock(&rulelock);
-		return -1;
-	}
-	snprint(buf, sizeof buf, "%d", p->dev->id);
-	r->argv[r->argc] = buf;
+	pushevent(smprint("in id %d vid 0x%.4x did 0x%.4x csp 0x%.8x\n",
+		d->id, u->vid, u->did, u->csp));
 	closedev(p->dev);
-	switch(fork()){
-	case -1:
-		fprint(2, "fork: %r");
-		runlock(&rulelock);
-		return -1;
-	case 0:
-		chdir("/bin");
-		exec(r->argv[0], r->argv);
-		sysfatal("exec: %r");
-	}
-	runlock(&rulelock);
 	return 0;
 }
 
@@ -96,13 +281,9 @@
 {
 	int fd, i, nd;
 	Dir *d;
-
-	readrules();
-	parserules(rules);
-	luser = getuser();
 	
 	argc--; argv++;
-
+	initevent();
 	rfork(RFNOTEG);
 	switch(rfork(RFPROC|RFMEM)){
 	case -1: sysfatal("rfork: %r");
@@ -124,7 +305,5 @@
 		for(i = 0; i < argc; i++)
 			rendezvous(work, strdup(argv[i]));
 	rendezvous(work, nil);
-	usbdsrv.tree = alloctree(luser, luser, 0555, nil);
-	usbdb = createfile(usbdsrv.tree->root, "usbdb", luser, 0775, nil);
 	postsharesrv(&usbdsrv, nil, "usb", "usbd", "b");
 }