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 816146bc9SDavid du Colombier enum { 916146bc9SDavid du Colombier Ndevs = 32, 1016146bc9SDavid du Colombier Arglen = 500, 1116146bc9SDavid du Colombier Nargs = 64, 12906943f9SDavid du Colombier Stack = 16 * 1024, 13906943f9SDavid du Colombier }; 14906943f9SDavid du Colombier 1516146bc9SDavid 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 { 71*d9cef801SDavid du Colombier int fd, i, n, nd, nr; 72906943f9SDavid du Colombier char *nm; 73*d9cef801SDavid du Colombier char dbuf[512], fbuf[40]; 74*d9cef801SDavid du Colombier Dir *d; 75906943f9SDavid du Colombier 76906943f9SDavid du Colombier fd = open("/dev/usb", OREAD); 77906943f9SDavid du Colombier if(fd < 0) 78906943f9SDavid du Colombier sysfatal("/dev/usb: %r"); 79906943f9SDavid du Colombier nd = dirreadall(fd, &d); 80906943f9SDavid du Colombier close(fd); 81906943f9SDavid du Colombier if(nd < 2) 82906943f9SDavid du Colombier sysfatal("/dev/usb: no devs"); 83906943f9SDavid du Colombier for(i = n = 0; i < nd && n < ndirs; i++){ 84906943f9SDavid du Colombier nm = d[i].name; 85906943f9SDavid du Colombier if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil) 86906943f9SDavid du Colombier continue; 87906943f9SDavid du Colombier snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm); 88906943f9SDavid du Colombier fd = open(fbuf, OREAD); 89906943f9SDavid du Colombier if(fd < 0) 90906943f9SDavid du Colombier continue; /* may be gone */ 91906943f9SDavid du Colombier nr = read(fd, dbuf, sizeof(dbuf)-1); 92906943f9SDavid du Colombier close(fd); 93906943f9SDavid du Colombier if(nr < 0) 94906943f9SDavid du Colombier continue; 95906943f9SDavid du Colombier dbuf[nr] = 0; 96906943f9SDavid du Colombier if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil) 97906943f9SDavid du Colombier if(matchf(dbuf, farg) == 0) 98906943f9SDavid du Colombier dirs[n++] = smprint("/dev/usb/%s", nm); 99906943f9SDavid du Colombier } 100906943f9SDavid du Colombier free(d); 101906943f9SDavid du Colombier if(usbdebug > 1) 102906943f9SDavid du Colombier for(nd = 0; nd < n; nd++) 103906943f9SDavid du Colombier fprint(2, "finddevs: %s\n", dirs[nd]); 104906943f9SDavid du Colombier return n; 105906943f9SDavid du Colombier } 106906943f9SDavid du Colombier 107906943f9SDavid du Colombier void 108*d9cef801SDavid du Colombier startdevs(char *args, char *argv[], int argc, int (*mf)(char*, void*), 109*d9cef801SDavid du Colombier void *ma, int (*df)(Dev*, int, char**)) 110906943f9SDavid du Colombier { 11116146bc9SDavid du Colombier int i, ndirs, ndevs; 112906943f9SDavid du Colombier char *dirs[Ndevs]; 113906943f9SDavid du Colombier char **dp; 114906943f9SDavid du Colombier Parg *parg; 115906943f9SDavid du Colombier Dev *dev; 116906943f9SDavid du Colombier Channel *rc; 117906943f9SDavid du Colombier 118906943f9SDavid du Colombier if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0) 119906943f9SDavid du Colombier sysfatal("#u: %r"); 120906943f9SDavid du Colombier 121906943f9SDavid du Colombier if(argc > 0){ 122906943f9SDavid du Colombier ndirs = argc; 123906943f9SDavid du Colombier dp = argv; 124906943f9SDavid du Colombier }else{ 125906943f9SDavid du Colombier dp = dirs; 126906943f9SDavid du Colombier ndirs = finddevs(mf, ma, dp, Ndevs); 127906943f9SDavid du Colombier if(ndirs == nelem(dirs)) 128906943f9SDavid du Colombier fprint(2, "%s: too many devices\n", argv0); 129906943f9SDavid du Colombier } 130906943f9SDavid du Colombier ndevs = 0; 131906943f9SDavid du Colombier rc = chancreate(sizeof(ulong), 0); 132906943f9SDavid du Colombier if(rc == nil) 133906943f9SDavid du Colombier sysfatal("no memory"); 134906943f9SDavid du Colombier for(i = 0; i < ndirs; i++){ 135906943f9SDavid du Colombier fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]); 136906943f9SDavid du Colombier dev = opendev(dp[i]); 137*d9cef801SDavid du Colombier if(dev == nil) 138*d9cef801SDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, dp[i]); 139*d9cef801SDavid du Colombier else if(configdev(dev) < 0){ 140906943f9SDavid du Colombier fprint(2, "%s: %s: config: %r\n", argv0, dp[i]); 141906943f9SDavid du Colombier closedev(dev); 142906943f9SDavid du Colombier }else{ 143906943f9SDavid du Colombier dprint(2, "%s: %U", argv0, dev); 144906943f9SDavid du Colombier parg = emallocz(sizeof(Parg), 0); 145906943f9SDavid du Colombier parg->args = estrdup(args); 146906943f9SDavid du Colombier parg->dev = dev; 147906943f9SDavid du Colombier parg->rc = rc; 148906943f9SDavid du Colombier parg->f = df; 149906943f9SDavid du Colombier proccreate(workproc, parg, Stack); 150906943f9SDavid du Colombier if(recvul(rc) == 0) 151906943f9SDavid du Colombier ndevs++; 152906943f9SDavid du Colombier } 153906943f9SDavid du Colombier if(dp != argv) 154906943f9SDavid du Colombier free(dirs[i]); 155906943f9SDavid du Colombier } 156906943f9SDavid du Colombier chanfree(rc); 157906943f9SDavid du Colombier if(ndevs == 0) 158*d9cef801SDavid du Colombier sysfatal("no unhandled devices found"); 159906943f9SDavid du Colombier } 160