started work on new usbd

This commit is contained in:
aiju 2011-07-27 14:27:22 +02:00
parent abe6ead0ff
commit 1a2afe988b
7 changed files with 380 additions and 0 deletions

5
lib/usbdb Normal file
View file

@ -0,0 +1,5 @@
nusb/disk
class=8
nusb/serial
vid=0x9e88 did=0x9e8f

31
sys/src/cmd/nusb/mkfile Normal file
View file

@ -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
}

View file

@ -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;
};

View file

@ -0,0 +1,2 @@
void parserules(char*);
Rule* rulesmatch(Dev*);

View file

@ -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

View file

@ -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;
}

View file

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