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");
}