123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <thread.h>
- #include <usb/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;
- threadsetname("workproc %s", pa->dev->dir);
- 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 %#08x", *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(uint32_t), 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");
- }
|