1*906943f9SDavid du Colombier #include <u.h> 2*906943f9SDavid du Colombier #include <libc.h> 3*906943f9SDavid du Colombier #include <thread.h> 4*906943f9SDavid du Colombier #include "usb.h" 5*906943f9SDavid du Colombier 6*906943f9SDavid du Colombier typedef struct Parg Parg; 7*906943f9SDavid du Colombier 8*906943f9SDavid du Colombier enum 9*906943f9SDavid du Colombier { 10*906943f9SDavid du Colombier Ndevs = 10, 11*906943f9SDavid du Colombier Arglen = 80, 12*906943f9SDavid du Colombier Nargs = 10, 13*906943f9SDavid du Colombier Stack = 16 * 1024, 14*906943f9SDavid du Colombier }; 15*906943f9SDavid du Colombier 16*906943f9SDavid du Colombier struct Parg 17*906943f9SDavid du Colombier { 18*906943f9SDavid du Colombier char* args; 19*906943f9SDavid du Colombier Dev* dev; 20*906943f9SDavid du Colombier int (*f)(Dev*,int,char**); 21*906943f9SDavid du Colombier Channel* rc; 22*906943f9SDavid du Colombier }; 23*906943f9SDavid du Colombier 24*906943f9SDavid du Colombier static void 25*906943f9SDavid du Colombier workproc(void *a) 26*906943f9SDavid du Colombier { 27*906943f9SDavid du Colombier Parg *pa; 28*906943f9SDavid du Colombier char args[Arglen]; 29*906943f9SDavid du Colombier char *argv[Nargs]; 30*906943f9SDavid du Colombier int argc; 31*906943f9SDavid du Colombier Channel *rc; 32*906943f9SDavid du Colombier Dev *d; 33*906943f9SDavid du Colombier int (*f)(Dev*,int,char**); 34*906943f9SDavid du Colombier 35*906943f9SDavid du Colombier pa = a; 36*906943f9SDavid du Colombier strecpy(args, args+sizeof(args), pa->args); /* don't leak */ 37*906943f9SDavid du Colombier d = pa->dev; 38*906943f9SDavid du Colombier f = pa->f; 39*906943f9SDavid du Colombier rc = pa->rc; 40*906943f9SDavid du Colombier free(pa->args); 41*906943f9SDavid du Colombier free(pa); 42*906943f9SDavid du Colombier argc = tokenize(args, argv, nelem(argv)-1); 43*906943f9SDavid du Colombier argv[argc] = nil; 44*906943f9SDavid du Colombier if(f(d, argc, argv) < 0){ 45*906943f9SDavid du Colombier closedev(d); 46*906943f9SDavid du Colombier fprint(2, "%s: devmain: %r\n", argv0); 47*906943f9SDavid du Colombier sendul(rc, -1); 48*906943f9SDavid du Colombier threadexits("devmain: %r"); 49*906943f9SDavid du Colombier } 50*906943f9SDavid du Colombier sendul(rc, 0); 51*906943f9SDavid du Colombier threadexits(nil); 52*906943f9SDavid du Colombier 53*906943f9SDavid du Colombier } 54*906943f9SDavid du Colombier 55*906943f9SDavid du Colombier int 56*906943f9SDavid du Colombier matchdevcsp(char *info, void *a) 57*906943f9SDavid du Colombier { 58*906943f9SDavid du Colombier char sbuf[40]; 59*906943f9SDavid du Colombier int *csps; 60*906943f9SDavid du Colombier 61*906943f9SDavid du Colombier csps = a; 62*906943f9SDavid du Colombier for(; *csps != 0; csps++){ 63*906943f9SDavid du Colombier snprint(sbuf, sizeof(sbuf), "csp %#08ux", *csps); 64*906943f9SDavid du Colombier if(strstr(info, sbuf) != nil) 65*906943f9SDavid du Colombier return 0; 66*906943f9SDavid du Colombier } 67*906943f9SDavid du Colombier return -1; 68*906943f9SDavid du Colombier } 69*906943f9SDavid du Colombier 70*906943f9SDavid du Colombier int 71*906943f9SDavid du Colombier finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs) 72*906943f9SDavid du Colombier { 73*906943f9SDavid du Colombier int fd; 74*906943f9SDavid du Colombier char fbuf[40]; 75*906943f9SDavid du Colombier char dbuf[512]; 76*906943f9SDavid du Colombier Dir *d; 77*906943f9SDavid du Colombier int nd, nr; 78*906943f9SDavid du Colombier int n; 79*906943f9SDavid du Colombier int i; 80*906943f9SDavid du Colombier char *nm; 81*906943f9SDavid du Colombier 82*906943f9SDavid du Colombier fd = open("/dev/usb", OREAD); 83*906943f9SDavid du Colombier if(fd < 0) 84*906943f9SDavid du Colombier sysfatal("/dev/usb: %r"); 85*906943f9SDavid du Colombier nd = dirreadall(fd, &d); 86*906943f9SDavid du Colombier close(fd); 87*906943f9SDavid du Colombier if(nd < 2) 88*906943f9SDavid du Colombier sysfatal("/dev/usb: no devs"); 89*906943f9SDavid du Colombier for(i = n = 0; i < nd && n < ndirs; i++){ 90*906943f9SDavid du Colombier nm = d[i].name; 91*906943f9SDavid du Colombier if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil) 92*906943f9SDavid du Colombier continue; 93*906943f9SDavid du Colombier snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm); 94*906943f9SDavid du Colombier fd = open(fbuf, OREAD); 95*906943f9SDavid du Colombier if(fd < 0) 96*906943f9SDavid du Colombier continue; /* may be gone */ 97*906943f9SDavid du Colombier nr = read(fd, dbuf, sizeof(dbuf)-1); 98*906943f9SDavid du Colombier close(fd); 99*906943f9SDavid du Colombier if(nr < 0) 100*906943f9SDavid du Colombier continue; 101*906943f9SDavid du Colombier dbuf[nr] = 0; 102*906943f9SDavid du Colombier if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil) 103*906943f9SDavid du Colombier if(matchf(dbuf, farg) == 0) 104*906943f9SDavid du Colombier dirs[n++] = smprint("/dev/usb/%s", nm); 105*906943f9SDavid du Colombier } 106*906943f9SDavid du Colombier free(d); 107*906943f9SDavid du Colombier if(usbdebug > 1) 108*906943f9SDavid du Colombier for(nd = 0; nd < n; nd++) 109*906943f9SDavid du Colombier fprint(2, "finddevs: %s\n", dirs[nd]); 110*906943f9SDavid du Colombier return n; 111*906943f9SDavid du Colombier } 112*906943f9SDavid du Colombier 113*906943f9SDavid du Colombier void 114*906943f9SDavid du Colombier startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**)) 115*906943f9SDavid du Colombier { 116*906943f9SDavid du Colombier char *dirs[Ndevs]; 117*906943f9SDavid du Colombier char **dp; 118*906943f9SDavid du Colombier Parg *parg; 119*906943f9SDavid du Colombier int ndirs; 120*906943f9SDavid du Colombier int ndevs; 121*906943f9SDavid du Colombier Dev *dev; 122*906943f9SDavid du Colombier int i; 123*906943f9SDavid du Colombier Channel *rc; 124*906943f9SDavid du Colombier 125*906943f9SDavid du Colombier if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0) 126*906943f9SDavid du Colombier sysfatal("#u: %r"); 127*906943f9SDavid du Colombier 128*906943f9SDavid du Colombier if(argc > 0){ 129*906943f9SDavid du Colombier ndirs = argc; 130*906943f9SDavid du Colombier dp = argv; 131*906943f9SDavid du Colombier }else{ 132*906943f9SDavid du Colombier dp = dirs; 133*906943f9SDavid du Colombier ndirs = finddevs(mf, ma, dp, Ndevs); 134*906943f9SDavid du Colombier if(ndirs == nelem(dirs)) 135*906943f9SDavid du Colombier fprint(2, "%s: too many devices\n", argv0); 136*906943f9SDavid du Colombier } 137*906943f9SDavid du Colombier ndevs = 0; 138*906943f9SDavid du Colombier rc = chancreate(sizeof(ulong), 0); 139*906943f9SDavid du Colombier if(rc == nil) 140*906943f9SDavid du Colombier sysfatal("no memory"); 141*906943f9SDavid du Colombier for(i = 0; i < ndirs; i++){ 142*906943f9SDavid du Colombier fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]); 143*906943f9SDavid du Colombier dev = opendev(dp[i]); 144*906943f9SDavid du Colombier if(dev != nil){ 145*906943f9SDavid du Colombier if(configdev(dev) < 0){ 146*906943f9SDavid du Colombier fprint(2, "%s: %s: config: %r\n", argv0, dp[i]); 147*906943f9SDavid du Colombier closedev(dev); 148*906943f9SDavid du Colombier }else{ 149*906943f9SDavid du Colombier dprint(2, "%s: %U", argv0, dev); 150*906943f9SDavid du Colombier parg = emallocz(sizeof(Parg), 0); 151*906943f9SDavid du Colombier parg->args = estrdup(args); 152*906943f9SDavid du Colombier parg->dev = dev; 153*906943f9SDavid du Colombier parg->rc = rc; 154*906943f9SDavid du Colombier parg->f = df; 155*906943f9SDavid du Colombier proccreate(workproc, parg, Stack); 156*906943f9SDavid du Colombier if(recvul(rc) == 0) 157*906943f9SDavid du Colombier ndevs++; 158*906943f9SDavid du Colombier } 159*906943f9SDavid du Colombier }else 160*906943f9SDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, dp[i]); 161*906943f9SDavid du Colombier if(dp != argv) 162*906943f9SDavid du Colombier free(dirs[i]); 163*906943f9SDavid du Colombier } 164*906943f9SDavid du Colombier chanfree(rc); 165*906943f9SDavid du Colombier if(ndevs == 0) 166*906943f9SDavid du Colombier sysfatal("no device found"); 167*906943f9SDavid du Colombier } 168