xref: /plan9/sys/src/cmd/usb/lib/devs.c (revision 906943f9f6b8411972abb5e3a03ed19f74be7ccc)
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