plan9fox/sys/src/cmd/nusb/usbd/usbd.c
2011-07-27 20:07:30 +02:00

131 lines
2.3 KiB
C

#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "usb.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);
}
int
startdev(Port *p)
{
Rule *r;
char buf[14];
if(p->dev == nil || 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;
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;
}
void
main(int argc, char **argv)
{
int fd, i, nd;
Dir *d;
readrules();
parserules(rules);
luser = getuser();
argc--; argv++;
rfork(RFNOTEG);
switch(rfork(RFPROC|RFMEM)){
case -1: sysfatal("rfork: %r");
case 0: work(); exits(nil);
}
if(argc == 0){
fd = open("/dev/usb", OREAD);
if(fd < 0)
sysfatal("/dev/usb: %r");
nd = dirreadall(fd, &d);
close(fd);
if(nd < 2)
sysfatal("/dev/usb: no hubs");
for(i = 0; i < nd; i++)
if(strcmp(d[i].name, "ctl") != 0)
rendezvous(work, smprint("/dev/usb/%s", d[i].name));
free(d);
}else
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");
}