1 /*
2 * Framework for USB devices.
3 * Some of them may be embedded into usbd and some of
4 * them may exist as /bin/usb/* binaries on their own.
5 *
6 * When embedded, devmain() is given a ref of an already
7 * configured and open Dev. If devmain()
8 * does not fail it should release this ref when done and
9 * use incref to add further refs to it.
10 */
11 #include <u.h>
12 #include <libc.h>
13 #include <thread.h>
14 #include "usb.h"
15 #include "usbd.h"
16
17 static Lock masklck;
18 extern Devtab devtab[];
19 static char* cputype;
20
21 int
getdevnb(uvlong * maskp)22 getdevnb(uvlong *maskp)
23 {
24 int i;
25
26 lock(&masklck);
27 for(i = 0; i < 8 * sizeof *maskp; i++)
28 if((*maskp & (1ULL<<i)) == 0){
29 *maskp |= 1ULL<<i;
30 unlock(&masklck);
31 return i;
32 }
33 unlock(&masklck);
34 return -1;
35 }
36
37 void
putdevnb(uvlong * maskp,int id)38 putdevnb(uvlong *maskp, int id)
39 {
40 lock(&masklck);
41 if(id >= 0)
42 *maskp &= ~(1ULL<<id);
43 unlock(&masklck);
44 }
45
46 static int
cspmatch(Devtab * dt,int dcsp)47 cspmatch(Devtab *dt, int dcsp)
48 {
49 int i;
50 int csp;
51
52 for(i = 0; i < nelem(dt->csps); i++)
53 if((csp=dt->csps[i]) != 0)
54 if(csp == dcsp)
55 return 1;
56 else if((csp&DCL) && (csp&~DCL) == Class(dcsp))
57 return 1;
58 return 0;
59 }
60
61 static int
devmatch(Devtab * dt,Usbdev * d)62 devmatch(Devtab *dt, Usbdev *d)
63 {
64 int i;
65 int c;
66 Conf *cp;
67
68 if(dt->noauto)
69 return 0;
70 if(dt->vid != -1 && d->vid != dt->vid)
71 return 0;
72 if(dt->did != -1 && d->did != dt->did)
73 return 0;
74 if(cspmatch(dt, d->csp))
75 return 1;
76 for(c = 0; c < Nconf; c++)
77 if((cp=d->conf[c]) != nil)
78 for(i = 0; i < Niface; i++)
79 if(cp->iface[i] != nil)
80 if(cspmatch(dt, cp->iface[i]->csp))
81 return 1;
82 return 0;
83 }
84
85 /* We can't use procexec to execute drivers, because
86 * procexec mounts #| at /mnt/temp and we do *not*
87 * have /mnt/temp at boot time.
88 * Instead, we use access to guess if we can execute the file.
89 * and reply as procexec. Be careful that the child inherits
90 * all the shared state of the thread library. It should run unnoticed.
91 */
92 static void
xexec(Channel * c,char * nm,char * args[])93 xexec(Channel *c, char *nm, char *args[])
94 {
95 int pid;
96
97 if(access(nm, AEXEC) == 0){
98 pid = rfork(RFFDG|RFREND|RFPROC);
99 switch(pid){
100 case 0:
101 exec(nm, args);
102 _exits("exec");
103 case -1:
104 break;
105 default:
106 sendul(c, pid);
107 threadexits(nil);
108 }
109 }
110 }
111
112 typedef struct Sarg Sarg;
113 struct Sarg{
114 Port *pp;
115 Devtab* dt;
116 Channel*rc;
117 char fname[80];
118 char args[128];
119 char *argv[40];
120 };
121
122 static void
startdevproc(void * a)123 startdevproc(void *a)
124 {
125 Sarg *sa = a;
126 Dev *d;
127 Devtab *dt;
128 int argc;
129 char *args, *argse, **argv;
130 char *fname;
131
132 threadsetgrp(threadid());
133 d = sa->pp->dev;
134 dt = sa->dt;
135 args = sa->args;
136 argse = sa->args + sizeof sa->args;
137 argv = sa->argv;
138 fname = sa->fname;
139 sa->pp->devmaskp = &dt->devmask;
140 sa->pp->devnb = getdevnb(&dt->devmask);
141 if(sa->pp->devnb < 0){
142 sa->pp->devmaskp = nil;
143 sa->pp->devnb = 0;
144 }else
145 args = seprint(args, argse, "-N %d", sa->pp->devnb);
146 if(dt->args != nil)
147 seprint(args, argse, " %s", dt->args);
148 args = sa->args;
149 dprint(2, "%s: start: %s %s\n", argv0, dt->name, args);
150 argv[0] = dt->name;
151 argc = 1;
152 if(args[0] != 0)
153 argc += tokenize(args, argv+1, nelem(sa->argv)-2);
154 argv[argc] = nil;
155 if(dt->init == nil){
156 if(d->dfd > 0 ){
157 close(d->dfd);
158 d->dfd = -1;
159 }
160 rfork(RFCFDG);
161 open("/dev/null", OREAD);
162 open("/dev/cons", OWRITE);
163 open("/dev/cons", OWRITE);
164
165 xexec(sa->rc, argv[0], argv);
166 snprint(fname, sizeof(sa->fname), "/bin/usb/%s", dt->name);
167 xexec(sa->rc, fname, argv);
168 snprint(fname, sizeof(sa->fname), "/boot/%s", dt->name);
169 xexec(sa->rc, fname, argv);
170 if(cputype == nil)
171 cputype = getenv("cputype");
172 if(cputype != nil){
173 snprint(fname, sizeof(sa->fname), "/%s/bin/%s",
174 cputype, dt->name);
175 argv[0] = fname;
176 xexec(sa->rc, fname, argv);
177 }
178 fprint(2, "%s: %s: not found. can't exec\n", argv0, dt->name);
179 sendul(sa->rc, -1);
180 threadexits("exec");
181 }else{
182 sa->pp->dev = opendev(d->dir);
183 sendul(sa->rc, 0);
184 if(dt->init(d, argc, argv) < 0)
185 fprint(2, "%s: %s: %r\n", argv0, dt->name);
186 closedev(d);
187 free(sa);
188 }
189 threadexits(nil);
190 }
191
192 static void
writeinfo(Dev * d)193 writeinfo(Dev *d)
194 {
195 char buf[128];
196 char *s;
197 char *se;
198 Usbdev *ud;
199 Conf *c;
200 Iface *ifc;
201 int i, j;
202
203 ud = d->usb;
204 s = buf;
205 se = buf+sizeof(buf);
206 s = seprint(s, se, "info %s csp %#08ulx", classname(ud->class), ud->csp);
207 for(i = 0; i < ud->nconf; i++){
208 c = ud->conf[i];
209 if(c == nil)
210 break;
211 for(j = 0; j < nelem(c->iface); j++){
212 ifc = c->iface[j];
213 if(ifc == nil)
214 break;
215 if(ifc->csp != ud->csp)
216 s = seprint(s, se, " csp %#08ulx", ifc->csp);
217 }
218 }
219 s = seprint(s, se, " vid %06#x did %06#x", ud->vid, ud->did);
220 seprint(s, se, " %q %q", ud->vendor, ud->product);
221 devctl(d, "%s", buf);
222 }
223
224 int
startdev(Port * pp)225 startdev(Port *pp)
226 {
227 Dev *d;
228 Usbdev *ud;
229 Devtab *dt;
230 Sarg *sa;
231 Channel *rc;
232
233 d = pp->dev;
234 assert(d);
235 ud = d->usb;
236 assert(ud != nil);
237
238 writeinfo(d);
239
240 if(ud->class == Clhub){
241 /*
242 * Hubs are handled directly by this process avoiding
243 * concurrent operation so that at most one device
244 * has the config address in use.
245 * We cancel kernel debug for these eps. too chatty.
246 */
247 pp->hub = newhub(d->dir, d);
248 if(pp->hub == nil)
249 fprint(2, "%s: %s: %r\n", argv0, d->dir);
250 else
251 fprint(2, "usb/hub... ");
252 if(usbdebug > 1)
253 devctl(d, "debug 0"); /* polled hubs are chatty */
254 return pp->hub == nil ? -1 : 0;
255 }
256
257 for(dt = devtab; dt->name != nil; dt++)
258 if(devmatch(dt, ud))
259 break;
260 /*
261 * From here on the device is for the driver.
262 * When we return pp->dev contains a Dev just for us
263 * with only the ctl open. Both devs are released on the last closedev:
264 * driver's upon I/O errors and ours upon port dettach.
265 */
266 if(dt->name == nil){
267 dprint(2, "%s: no configured entry for %s (csp %#08lx)\n",
268 argv0, d->dir, ud->csp);
269 close(d->dfd);
270 d->dfd = -1;
271 return 0;
272 }
273 sa = emallocz(sizeof(Sarg), 1);
274 sa->pp = pp;
275 sa->dt = dt;
276 rc = sa->rc = chancreate(sizeof(ulong), 1);
277 procrfork(startdevproc, sa, Stack, RFNOTEG);
278 if(recvul(rc) != 0)
279 free(sa);
280 chanfree(rc);
281 fprint(2, "usb/%s... ", dt->name);
282
283 sleep(Spawndelay); /* in case we re-spawn too fast */
284 return 0;
285 }
286