Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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