1906943f9SDavid du Colombier #include <u.h> 2906943f9SDavid du Colombier #include <libc.h> 3906943f9SDavid du Colombier #include <thread.h> 4906943f9SDavid du Colombier #include "usb.h" 5906943f9SDavid du Colombier 6906943f9SDavid du Colombier typedef struct Parg Parg; 7906943f9SDavid du Colombier 8*16146bc9SDavid du Colombier enum { 9*16146bc9SDavid du Colombier Ndevs = 32, 10*16146bc9SDavid du Colombier Arglen = 500, 11*16146bc9SDavid du Colombier Nargs = 64, 12906943f9SDavid du Colombier Stack = 16 * 1024, 13906943f9SDavid du Colombier }; 14906943f9SDavid du Colombier 15*16146bc9SDavid du Colombier struct Parg { 16906943f9SDavid du Colombier char* args; 17906943f9SDavid du Colombier Dev* dev; 18906943f9SDavid du Colombier int (*f)(Dev*,int,char**); 19906943f9SDavid du Colombier Channel*rc; 20906943f9SDavid du Colombier }; 21906943f9SDavid du Colombier 22906943f9SDavid du Colombier static void 23906943f9SDavid du Colombier workproc(void *a) 24906943f9SDavid du Colombier { 25906943f9SDavid du Colombier Parg *pa; 26906943f9SDavid du Colombier char args[Arglen]; 27906943f9SDavid du Colombier char *argv[Nargs]; 28906943f9SDavid du Colombier int argc; 29906943f9SDavid du Colombier Channel *rc; 30906943f9SDavid du Colombier Dev *d; 31906943f9SDavid du Colombier int (*f)(Dev*,int,char**); 32906943f9SDavid du Colombier 33906943f9SDavid du Colombier pa = a; 34906943f9SDavid du Colombier strecpy(args, args+sizeof(args), pa->args); /* don't leak */ 35906943f9SDavid du Colombier d = pa->dev; 36906943f9SDavid du Colombier f = pa->f; 37906943f9SDavid du Colombier rc = pa->rc; 38906943f9SDavid du Colombier free(pa->args); 39906943f9SDavid du Colombier free(pa); 40906943f9SDavid du Colombier argc = tokenize(args, argv, nelem(argv)-1); 41906943f9SDavid du Colombier argv[argc] = nil; 42906943f9SDavid du Colombier if(f(d, argc, argv) < 0){ 43906943f9SDavid du Colombier closedev(d); 44906943f9SDavid du Colombier fprint(2, "%s: devmain: %r\n", argv0); 45906943f9SDavid du Colombier sendul(rc, -1); 46906943f9SDavid du Colombier threadexits("devmain: %r"); 47906943f9SDavid du Colombier } 48906943f9SDavid du Colombier sendul(rc, 0); 49906943f9SDavid du Colombier threadexits(nil); 50906943f9SDavid du Colombier 51906943f9SDavid du Colombier } 52906943f9SDavid du Colombier 53906943f9SDavid du Colombier int 54906943f9SDavid du Colombier matchdevcsp(char *info, void *a) 55906943f9SDavid du Colombier { 56906943f9SDavid du Colombier char sbuf[40]; 57906943f9SDavid du Colombier int *csps; 58906943f9SDavid du Colombier 59906943f9SDavid du Colombier csps = a; 60906943f9SDavid du Colombier for(; *csps != 0; csps++){ 61906943f9SDavid du Colombier snprint(sbuf, sizeof(sbuf), "csp %#08ux", *csps); 62906943f9SDavid du Colombier if(strstr(info, sbuf) != nil) 63906943f9SDavid du Colombier return 0; 64906943f9SDavid du Colombier } 65906943f9SDavid du Colombier return -1; 66906943f9SDavid du Colombier } 67906943f9SDavid du Colombier 68906943f9SDavid du Colombier int 69906943f9SDavid du Colombier finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs) 70906943f9SDavid du Colombier { 71906943f9SDavid du Colombier int fd; 72906943f9SDavid du Colombier char fbuf[40]; 73906943f9SDavid du Colombier char dbuf[512]; 74906943f9SDavid du Colombier Dir *d; 75906943f9SDavid du Colombier int nd, nr; 76906943f9SDavid du Colombier int n; 77906943f9SDavid du Colombier int i; 78906943f9SDavid du Colombier char *nm; 79906943f9SDavid du Colombier 80906943f9SDavid du Colombier fd = open("/dev/usb", OREAD); 81906943f9SDavid du Colombier if(fd < 0) 82906943f9SDavid du Colombier sysfatal("/dev/usb: %r"); 83906943f9SDavid du Colombier nd = dirreadall(fd, &d); 84906943f9SDavid du Colombier close(fd); 85906943f9SDavid du Colombier if(nd < 2) 86906943f9SDavid du Colombier sysfatal("/dev/usb: no devs"); 87906943f9SDavid du Colombier for(i = n = 0; i < nd && n < ndirs; i++){ 88906943f9SDavid du Colombier nm = d[i].name; 89906943f9SDavid du Colombier if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil) 90906943f9SDavid du Colombier continue; 91906943f9SDavid du Colombier snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm); 92906943f9SDavid du Colombier fd = open(fbuf, OREAD); 93906943f9SDavid du Colombier if(fd < 0) 94906943f9SDavid du Colombier continue; /* may be gone */ 95906943f9SDavid du Colombier nr = read(fd, dbuf, sizeof(dbuf)-1); 96906943f9SDavid du Colombier close(fd); 97906943f9SDavid du Colombier if(nr < 0) 98906943f9SDavid du Colombier continue; 99906943f9SDavid du Colombier dbuf[nr] = 0; 100906943f9SDavid du Colombier if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil) 101906943f9SDavid du Colombier if(matchf(dbuf, farg) == 0) 102906943f9SDavid du Colombier dirs[n++] = smprint("/dev/usb/%s", nm); 103906943f9SDavid du Colombier } 104906943f9SDavid du Colombier free(d); 105906943f9SDavid du Colombier if(usbdebug > 1) 106906943f9SDavid du Colombier for(nd = 0; nd < n; nd++) 107906943f9SDavid du Colombier fprint(2, "finddevs: %s\n", dirs[nd]); 108906943f9SDavid du Colombier return n; 109906943f9SDavid du Colombier } 110906943f9SDavid du Colombier 111906943f9SDavid du Colombier void 112906943f9SDavid du Colombier startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**)) 113906943f9SDavid du Colombier { 114*16146bc9SDavid du Colombier int i, ndirs, ndevs; 115906943f9SDavid du Colombier char *dirs[Ndevs]; 116906943f9SDavid du Colombier char **dp; 117906943f9SDavid du Colombier Parg *parg; 118906943f9SDavid du Colombier Dev *dev; 119906943f9SDavid du Colombier Channel *rc; 120906943f9SDavid du Colombier 121906943f9SDavid du Colombier if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0) 122906943f9SDavid du Colombier sysfatal("#u: %r"); 123906943f9SDavid du Colombier 124906943f9SDavid du Colombier if(argc > 0){ 125906943f9SDavid du Colombier ndirs = argc; 126906943f9SDavid du Colombier dp = argv; 127906943f9SDavid du Colombier }else{ 128906943f9SDavid du Colombier dp = dirs; 129906943f9SDavid du Colombier ndirs = finddevs(mf, ma, dp, Ndevs); 130906943f9SDavid du Colombier if(ndirs == nelem(dirs)) 131906943f9SDavid du Colombier fprint(2, "%s: too many devices\n", argv0); 132906943f9SDavid du Colombier } 133906943f9SDavid du Colombier ndevs = 0; 134906943f9SDavid du Colombier rc = chancreate(sizeof(ulong), 0); 135906943f9SDavid du Colombier if(rc == nil) 136906943f9SDavid du Colombier sysfatal("no memory"); 137906943f9SDavid du Colombier for(i = 0; i < ndirs; i++){ 138906943f9SDavid du Colombier fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]); 139906943f9SDavid du Colombier dev = opendev(dp[i]); 140906943f9SDavid du Colombier if(dev != nil){ 141906943f9SDavid du Colombier if(configdev(dev) < 0){ 142906943f9SDavid du Colombier fprint(2, "%s: %s: config: %r\n", argv0, dp[i]); 143906943f9SDavid du Colombier closedev(dev); 144906943f9SDavid du Colombier }else{ 145906943f9SDavid du Colombier dprint(2, "%s: %U", argv0, dev); 146906943f9SDavid du Colombier parg = emallocz(sizeof(Parg), 0); 147906943f9SDavid du Colombier parg->args = estrdup(args); 148906943f9SDavid du Colombier parg->dev = dev; 149906943f9SDavid du Colombier parg->rc = rc; 150906943f9SDavid du Colombier parg->f = df; 151906943f9SDavid du Colombier proccreate(workproc, parg, Stack); 152906943f9SDavid du Colombier if(recvul(rc) == 0) 153906943f9SDavid du Colombier ndevs++; 154906943f9SDavid du Colombier } 155906943f9SDavid du Colombier }else 156906943f9SDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, dp[i]); 157906943f9SDavid du Colombier if(dp != argv) 158906943f9SDavid du Colombier free(dirs[i]); 159906943f9SDavid du Colombier } 160906943f9SDavid du Colombier chanfree(rc); 161906943f9SDavid du Colombier if(ndevs == 0) 162906943f9SDavid du Colombier sysfatal("no device found"); 163906943f9SDavid du Colombier } 164