diff --git a/lib/usbdb b/lib/usbdb new file mode 100644 index 000000000..dee888877 --- /dev/null +++ b/lib/usbdb @@ -0,0 +1,5 @@ +nusb/disk + class=8 + +nusb/serial + vid=0x9e88 did=0x9e8f diff --git a/sys/src/cmd/nusb/mkfile b/sys/src/cmd/nusb/mkfile new file mode 100644 index 000000000..6b08a281a --- /dev/null +++ b/sys/src/cmd/nusb/mkfile @@ -0,0 +1,31 @@ + +#include +#include +#include +#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 Dev dummy; + +struct field { + char *s; + void* v; +} fields[] = { + "class", &dummy.class, + "vid", &dummy.vid, + "did", &dummy.did, + 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(Dev *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 new file mode 100644 index 000000000..54d91d575 --- /dev/null +++ b/sys/src/cmd/nusb/usbd/usbd.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include <9p.h> +#include "dat.h" +#include "fns.h" + +char *luser; +char *rules; + +static File *usbdb; +static char Enonexist[] = "does not exist"; + +static void +usbdread(Req *req) +{ + if(usbdb->qid.path == req->fid->qid.path){ + readstr(req, rules); + respond(req, nil); + return; + } + respond(req, Enonexist); +} + +Srv usbdsrv = { + .read = usbdread, +}; + +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); +} + +void +main() +{ + readrules(); + parserules(rules); + luser = getuser(); + usbdsrv.tree = alloctree(luser, luser, 0555, nil); + usbdb = createfile(usbdsrv.tree->root, "usbdb", luser, 0775, nil); + postsharesrv(&usbdsrv, nil, "usb", "usbd", "b"); +}