From 4792c6bef97728520e391857a01e1cbbd94db82f Mon Sep 17 00:00:00 2001 From: aiju Date: Thu, 28 Jul 2011 17:31:45 +0200 Subject: [PATCH] usbd: added event file, removed usbdb --- sys/src/cmd/nusb/usbd/dat.h | 17 -- sys/src/cmd/nusb/usbd/fns.h | 2 - sys/src/cmd/nusb/usbd/mkfile | 1 - sys/src/cmd/nusb/usbd/rules.c | 241 -------------------------- sys/src/cmd/nusb/usbd/usbd.c | 311 ++++++++++++++++++++++++++-------- 5 files changed, 245 insertions(+), 327 deletions(-) delete mode 100644 sys/src/cmd/nusb/usbd/rules.c diff --git a/sys/src/cmd/nusb/usbd/dat.h b/sys/src/cmd/nusb/usbd/dat.h index d87b25c62..e67ff6dc5 100644 --- a/sys/src/cmd/nusb/usbd/dat.h +++ b/sys/src/cmd/nusb/usbd/dat.h @@ -1,24 +1,7 @@ -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 { Stack = 32*1024, diff --git a/sys/src/cmd/nusb/usbd/fns.h b/sys/src/cmd/nusb/usbd/fns.h index 3879ae8bc..7f016536f 100644 --- 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); diff --git a/sys/src/cmd/nusb/usbd/mkfile b/sys/src/cmd/nusb/usbd/mkfile index b0b3c5050..4e8beeb6a 100644 --- 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=\ diff --git a/sys/src/cmd/nusb/usbd/rules.c b/sys/src/cmd/nusb/usbd/rules.c deleted file mode 100644 index eae988fd3..000000000 --- a/sys/src/cmd/nusb/usbd/rules.c +++ /dev/null @@ -1,241 +0,0 @@ -#include -#include -#include -#include -#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; -} diff --git a/sys/src/cmd/nusb/usbd/usbd.c b/sys/src/cmd/nusb/usbd/usbd.c index ee5ed2075..81aedcdb3 100644 --- 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 +}; + +char *names[] = { + "", + "usbevent", +}; -static File *usbdb; 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); +} + +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 +usbdopen(Req *req) +{ + 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; + } + l = &r->aux; + } + 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, }; -static void -readrules(void) -{ - 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) - 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; - } - if(rules == nil) - rules = ""; - close(fd); -} - 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 @@ main(int argc, char **argv) { 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 @@ main(int argc, char **argv) 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"); }