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