#include <u.h>
#include <libc.h>
#include <thread.h>
#include "usb.h"
typedef struct Parg Parg;
enum {
Ndevs = 32,
Arglen = 500,
Nargs = 64,
Stack = 16 * 1024,
};
struct Parg {
char* args;
Dev* dev;
int (*f)(Dev*,int,char**);
Channel*rc;
};
static void
workproc(void *a)
{
Parg *pa;
char args[Arglen];
char *argv[Nargs];
int argc;
Channel *rc;
Dev *d;
int (*f)(Dev*,int,char**);
pa = a;
strecpy(args, args+sizeof(args), pa->args); /* don't leak */
d = pa->dev;
f = pa->f;
rc = pa->rc;
free(pa->args);
free(pa);
argc = tokenize(args, argv, nelem(argv)-1);
argv[argc] = nil;
if(f(d, argc, argv) < 0){
closedev(d);
fprint(2, "%s: devmain: %r\n", argv0);
sendul(rc, -1);
threadexits("devmain: %r");
}
sendul(rc, 0);
threadexits(nil);
}
int
matchdevcsp(char *info, void *a)
{
char sbuf[40];
int *csps;
csps = a;
for(; *csps != 0; csps++){
snprint(sbuf, sizeof(sbuf), "csp %#08ux", *csps);
if(strstr(info, sbuf) != nil)
return 0;
}
return -1;
}
int
finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs)
{
int fd, i, n, nd, nr;
char *nm;
char dbuf[512], fbuf[40];
Dir *d;
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 devs");
for(i = n = 0; i < nd && n < ndirs; i++){
nm = d[i].name;
if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil)
continue;
snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm);
fd = open(fbuf, OREAD);
if(fd < 0)
continue; /* may be gone */
nr = read(fd, dbuf, sizeof(dbuf)-1);
close(fd);
if(nr < 0)
continue;
dbuf[nr] = 0;
if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil)
if(matchf(dbuf, farg) == 0)
dirs[n++] = smprint("/dev/usb/%s", nm);
}
free(d);
if(usbdebug > 1)
for(nd = 0; nd < n; nd++)
fprint(2, "finddevs: %s\n", dirs[nd]);
return n;
}
void
startdevs(char *args, char *argv[], int argc, int (*mf)(char*, void*),
void *ma, int (*df)(Dev*, int, char**))
{
int i, ndirs, ndevs;
char *dirs[Ndevs];
char **dp;
Parg *parg;
Dev *dev;
Channel *rc;
if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
sysfatal("#u: %r");
if(argc > 0){
ndirs = argc;
dp = argv;
}else{
dp = dirs;
ndirs = finddevs(mf, ma, dp, Ndevs);
if(ndirs == nelem(dirs))
fprint(2, "%s: too many devices\n", argv0);
}
ndevs = 0;
rc = chancreate(sizeof(ulong), 0);
if(rc == nil)
sysfatal("no memory");
for(i = 0; i < ndirs; i++){
fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]);
dev = opendev(dp[i]);
if(dev == nil)
fprint(2, "%s: %s: %r\n", argv0, dp[i]);
else if(configdev(dev) < 0){
fprint(2, "%s: %s: config: %r\n", argv0, dp[i]);
closedev(dev);
}else{
dprint(2, "%s: %U", argv0, dev);
parg = emallocz(sizeof(Parg), 0);
parg->args = estrdup(args);
parg->dev = dev;
parg->rc = rc;
parg->f = df;
proccreate(workproc, parg, Stack);
if(recvul(rc) == 0)
ndevs++;
}
if(dp != argv)
free(dirs[i]);
}
chanfree(rc);
if(ndevs == 0)
sysfatal("no unhandled devices found");
}
|