summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraiju <aiju@phicode.de>2011-07-27 14:27:22 +0200
committeraiju <aiju@phicode.de>2011-07-27 14:27:22 +0200
commit1a2afe988b3075452b7f45d63b3d8d30e4358d0c (patch)
tree9856b7618acf2108feccbc38eba023ff394f7e7a
parentabe6ead0ffc3167871d39d62502afe36e9a5d2c9 (diff)
downloadplan9front-1a2afe988b3075452b7f45d63b3d8d30e4358d0c.tar.xz
started work on new usbd
-rw-r--r--lib/usbdb5
-rw-r--r--sys/src/cmd/nusb/mkfile31
-rw-r--r--sys/src/cmd/nusb/usbd/dat.h22
-rw-r--r--sys/src/cmd/nusb/usbd/fns.h2
-rw-r--r--sys/src/cmd/nusb/usbd/mkfile13
-rw-r--r--sys/src/cmd/nusb/usbd/rules.c239
-rw-r--r--sys/src/cmd/nusb/usbd/usbd.c68
7 files changed, 380 insertions, 0 deletions
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 @@
+</$objtype/mkfile
+
+# order matters here. build lib first and usbd last.
+DIRS=\
+ usbd\
+
+UPDATE=\
+ mkfile\
+
+default:V: all
+
+none:VQ:
+ echo mk all, install, installall, safeinstall, safeinstallall, clean, nuke, or update
+
+all clean nuke:VQ:
+ for (i in $DIRS) @{
+ cd $i && echo $i: && mk $target
+ }
+
+install installall safeinstall safeinstallall:V:
+ for (i in $DIRS) @{
+ cd $i && mk $target
+ }
+ cp probe /$objtype/bin/usb/probe
+
+update:V:
+ update $UPDATEFLAGS $UPDATE
+ for (i in $DIRS) @{
+ echo update $i
+ cd $i && mk 'UPDATEFLAGS='$"UPDATEFLAGS update
+ }
diff --git a/sys/src/cmd/nusb/usbd/dat.h b/sys/src/cmd/nusb/usbd/dat.h
new file mode 100644
index 000000000..7e77af421
--- /dev/null
+++ b/sys/src/cmd/nusb/usbd/dat.h
@@ -0,0 +1,22 @@
+typedef struct Rule Rule;
+typedef struct Cond Cond;
+typedef struct Dev Dev;
+
+struct Rule {
+ char **argv;
+ int argc;
+ Cond *cond;
+ Rule *next;
+} *rulefirst, *rulelast;
+
+RWLock rulelock;
+
+struct Cond {
+ int field;
+ u32int value;
+ Cond *and, *or;
+};
+
+struct Dev {
+ u32int class, vid, did;
+};
diff --git a/sys/src/cmd/nusb/usbd/fns.h b/sys/src/cmd/nusb/usbd/fns.h
new file mode 100644
index 000000000..cca197621
--- /dev/null
+++ b/sys/src/cmd/nusb/usbd/fns.h
@@ -0,0 +1,2 @@
+void parserules(char*);
+Rule* rulesmatch(Dev*);
diff --git a/sys/src/cmd/nusb/usbd/mkfile b/sys/src/cmd/nusb/usbd/mkfile
new file mode 100644
index 000000000..5eee54232
--- /dev/null
+++ b/sys/src/cmd/nusb/usbd/mkfile
@@ -0,0 +1,13 @@
+</$objtype/mkfile
+
+OFILES=\
+ usbd.$O\
+ rules.$O\
+
+HFILES=\
+ dat.h\
+ fns.h\
+
+TARG=usbd
+BIN=/$objtype/bin/nusb
+</sys/src/cmd/mkone
diff --git a/sys/src/cmd/nusb/usbd/rules.c b/sys/src/cmd/nusb/usbd/rules.c
new file mode 100644
index 000000000..33bb56f35
--- /dev/null
+++ b/sys/src/cmd/nusb/usbd/rules.c
@@ -0,0 +1,239 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <ctype.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 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 <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <fcall.h>
+#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");
+}