1433d6423SLionel Sambuc #include <stdio.h>
2433d6423SLionel Sambuc #include <stdlib.h>
3433d6423SLionel Sambuc #include <getopt.h>
4433d6423SLionel Sambuc #include <errno.h>
5433d6423SLionel Sambuc #include <string.h>
6433d6423SLionel Sambuc #include <lib.h>
7433d6423SLionel Sambuc #include <sys/stat.h>
8433d6423SLionel Sambuc #include <dirent.h>
9433d6423SLionel Sambuc #include <assert.h>
10433d6423SLionel Sambuc #include <signal.h>
11433d6423SLionel Sambuc #include <minix/dmap.h>
12*c58da9fbSDavid van Moolenbroek #include <minix/paths.h>
13433d6423SLionel Sambuc #include "usb_driver.h"
14433d6423SLionel Sambuc #include "proto.h"
15433d6423SLionel Sambuc
16433d6423SLionel Sambuc #define DEVMAN_TYPE_NAME "dev_type"
17433d6423SLionel Sambuc #define PATH_LEN 256
18433d6423SLionel Sambuc #define INVAL_MAJOR -1
19433d6423SLionel Sambuc #define MAX_CONFIG_DIRS 4
20433d6423SLionel Sambuc
21433d6423SLionel Sambuc static void main_loop();
22433d6423SLionel Sambuc static void handle_event();
23433d6423SLionel Sambuc static void cleanup();
24433d6423SLionel Sambuc static void parse_config();
25433d6423SLionel Sambuc static void display_usage();
26433d6423SLionel Sambuc static enum dev_type determine_type(char *path);
27433d6423SLionel Sambuc static int get_major();
28433d6423SLionel Sambuc static void create_pid_file();
29433d6423SLionel Sambuc static void put_major(int major);
30433d6423SLionel Sambuc static struct devmand_usb_driver* match_usb_driver(struct usb_device_id *id);
31433d6423SLionel Sambuc static struct devmand_driver_instance *find_instance(int dev_id);
32433d6423SLionel Sambuc
33433d6423SLionel Sambuc #define dbg(fmt, ... ) \
34433d6423SLionel Sambuc if (args.verbose) \
35433d6423SLionel Sambuc printf("%8s:%4d: %13s()| "fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )
36433d6423SLionel Sambuc
37433d6423SLionel Sambuc static LIST_HEAD(usb_driver_head, devmand_usb_driver) drivers =
38433d6423SLionel Sambuc LIST_HEAD_INITIALIZER(drivers);
39433d6423SLionel Sambuc static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
40433d6423SLionel Sambuc LIST_HEAD_INITIALIZER(instances);
41433d6423SLionel Sambuc
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc static int _run = 1;
44433d6423SLionel Sambuc struct global_args {
45433d6423SLionel Sambuc char *path;
46433d6423SLionel Sambuc char *config_dirs[MAX_CONFIG_DIRS];
47433d6423SLionel Sambuc int config_dir_count ;
48433d6423SLionel Sambuc int major_offset;
49433d6423SLionel Sambuc int verbose;
50433d6423SLionel Sambuc int check_config;
51433d6423SLionel Sambuc };
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc enum dev_type {
54433d6423SLionel Sambuc DEV_TYPE_USB_DEVICE,
55433d6423SLionel Sambuc DEV_TYPE_USB_INTF,
56433d6423SLionel Sambuc DEV_TYPE_UNKOWN
57433d6423SLionel Sambuc };
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc extern FILE *yyin;
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc static struct global_args args = {
62433d6423SLionel Sambuc .path = NULL,
63433d6423SLionel Sambuc .config_dirs = {NULL,NULL,NULL,NULL},
64433d6423SLionel Sambuc .config_dir_count = 0,
65433d6423SLionel Sambuc .major_offset = USB_BASE_MAJOR,
66433d6423SLionel Sambuc .verbose = 0,
67433d6423SLionel Sambuc .check_config = 0};
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc static struct option options[] =
70433d6423SLionel Sambuc {
71433d6423SLionel Sambuc {"dir" , required_argument, NULL, 'd'},
72433d6423SLionel Sambuc {"path", required_argument, NULL, 'p'},
73433d6423SLionel Sambuc {"verbose", required_argument, NULL, 'v'},
74433d6423SLionel Sambuc {"check-config", no_argument, NULL, 'x'},
75433d6423SLionel Sambuc {0,0,0,0} /* terminating entry */
76433d6423SLionel Sambuc };
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc static char major_bitmap[16]; /* can store up to 128 major number states */
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc
81433d6423SLionel Sambuc /*===========================================================================*
82433d6423SLionel Sambuc * run_upscript *
83433d6423SLionel Sambuc *===========================================================================*/
run_upscript(struct devmand_driver_instance * inst)84433d6423SLionel Sambuc int run_upscript(struct devmand_driver_instance *inst)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc char cmdl[1024];
87433d6423SLionel Sambuc cmdl[0] = 0;
88433d6423SLionel Sambuc int ret;
89433d6423SLionel Sambuc
90683d394dSBen Gras assert(inst->drv->upscript);
91683d394dSBen Gras assert(inst->label);
92683d394dSBen Gras
93433d6423SLionel Sambuc snprintf(cmdl, 1024, "%s up %s %d %d",
94433d6423SLionel Sambuc inst->drv->upscript, inst->label, inst->major, inst->dev_id);
95433d6423SLionel Sambuc dbg("Running Upscript: \"%s\"", cmdl);
96433d6423SLionel Sambuc ret = system(cmdl);
97433d6423SLionel Sambuc if (ret != 0) {
98433d6423SLionel Sambuc return EINVAL;
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc return 0;
101433d6423SLionel Sambuc }
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc /*===========================================================================*
104433d6423SLionel Sambuc * run_cleanscript *
105433d6423SLionel Sambuc *===========================================================================*/
run_cleanscript(struct devmand_usb_driver * drv)106433d6423SLionel Sambuc int run_cleanscript(struct devmand_usb_driver *drv)
107433d6423SLionel Sambuc {
108433d6423SLionel Sambuc char cmdl[1024];
109433d6423SLionel Sambuc cmdl[0] = 0;
110433d6423SLionel Sambuc int ret;
111433d6423SLionel Sambuc
112683d394dSBen Gras assert(drv->upscript);
113683d394dSBen Gras assert(drv->devprefix);
114683d394dSBen Gras
115433d6423SLionel Sambuc snprintf(cmdl, 1024, "%s clean %s ",
116433d6423SLionel Sambuc drv->upscript, drv->devprefix);
117433d6423SLionel Sambuc dbg("Running Upscript: \"%s\"", cmdl);
118433d6423SLionel Sambuc ret = system(cmdl);
119433d6423SLionel Sambuc
120433d6423SLionel Sambuc if (ret != 0) {
121433d6423SLionel Sambuc return EINVAL;
122433d6423SLionel Sambuc }
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc return 0;
125433d6423SLionel Sambuc }
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc
128433d6423SLionel Sambuc /*===========================================================================*
129433d6423SLionel Sambuc * run_downscript *
130433d6423SLionel Sambuc *===========================================================================*/
run_downscript(struct devmand_driver_instance * inst)131433d6423SLionel Sambuc int run_downscript(struct devmand_driver_instance *inst)
132433d6423SLionel Sambuc {
133433d6423SLionel Sambuc char cmdl[1024];
134433d6423SLionel Sambuc cmdl[0] = 0;
135433d6423SLionel Sambuc int ret;
136433d6423SLionel Sambuc
137683d394dSBen Gras assert(inst->drv->downscript);
138683d394dSBen Gras assert(inst->label);
139683d394dSBen Gras
140433d6423SLionel Sambuc snprintf(cmdl, 1024, "%s down %s %d",
141433d6423SLionel Sambuc inst->drv->downscript, inst->label, inst->major);
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc dbg("Running Upscript: \"%s\"", cmdl);
144433d6423SLionel Sambuc
145433d6423SLionel Sambuc ret = system(cmdl);
146433d6423SLionel Sambuc
147433d6423SLionel Sambuc if (ret != 0) {
148433d6423SLionel Sambuc return EINVAL;
149433d6423SLionel Sambuc }
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc return 0;
152433d6423SLionel Sambuc }
153433d6423SLionel Sambuc
154433d6423SLionel Sambuc
155433d6423SLionel Sambuc /*===========================================================================*
156433d6423SLionel Sambuc * stop_driver *
157433d6423SLionel Sambuc *===========================================================================*/
stop_driver(struct devmand_driver_instance * inst)158433d6423SLionel Sambuc int stop_driver(struct devmand_driver_instance *inst)
159433d6423SLionel Sambuc {
160433d6423SLionel Sambuc char cmdl[1024];
161433d6423SLionel Sambuc cmdl[0] = 0;
162433d6423SLionel Sambuc int ret;
163433d6423SLionel Sambuc
164683d394dSBen Gras assert(inst->label);
165683d394dSBen Gras
166433d6423SLionel Sambuc snprintf(cmdl, 1024, "%s down %s %d",
167*c58da9fbSDavid van Moolenbroek _PATH_MINIX_SERVICE, inst->label, inst->dev_id);
168*c58da9fbSDavid van Moolenbroek dbg("executing minix-service: \"%s\"", cmdl);
169433d6423SLionel Sambuc ret = system(cmdl);
170433d6423SLionel Sambuc if (ret != 0)
171433d6423SLionel Sambuc {
172433d6423SLionel Sambuc return EINVAL;
173433d6423SLionel Sambuc }
174433d6423SLionel Sambuc printf("Stopped driver %s with label %s for device %d.\n",
175433d6423SLionel Sambuc inst->drv->binary, inst->label, inst->dev_id);
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc return 0;
178433d6423SLionel Sambuc }
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc
181433d6423SLionel Sambuc /*===========================================================================*
182433d6423SLionel Sambuc * start_driver *
183433d6423SLionel Sambuc *===========================================================================*/
start_driver(struct devmand_driver_instance * inst)184433d6423SLionel Sambuc int start_driver(struct devmand_driver_instance *inst)
185433d6423SLionel Sambuc {
186433d6423SLionel Sambuc char cmdl[1024];
187433d6423SLionel Sambuc cmdl[0] = 0;
188433d6423SLionel Sambuc int ret;
189433d6423SLionel Sambuc
190433d6423SLionel Sambuc /* generate label */
191433d6423SLionel Sambuc ret = snprintf(inst->label, 32, "%s%d", inst->drv->devprefix,
192433d6423SLionel Sambuc inst->dev_id);
193433d6423SLionel Sambuc if (ret < 0 || ret > DEVMAND_DRIVER_LABEL_LEN) {
194433d6423SLionel Sambuc dbg("label too long");
195433d6423SLionel Sambuc return ENOMEM;
196433d6423SLionel Sambuc }
197433d6423SLionel Sambuc
198683d394dSBen Gras assert(inst->drv->binary);
199683d394dSBen Gras assert(inst->label);
200683d394dSBen Gras
201433d6423SLionel Sambuc snprintf(cmdl, 1024, "%s up %s -major %d -devid %d -label %s",
202*c58da9fbSDavid van Moolenbroek _PATH_MINIX_SERVICE, inst->drv->binary, inst->major, inst->dev_id,
203433d6423SLionel Sambuc inst->label);
204*c58da9fbSDavid van Moolenbroek dbg("executing minix-service: \"%s\"", cmdl);
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc ret = system(cmdl);
207433d6423SLionel Sambuc
208433d6423SLionel Sambuc if (ret != 0) {
209433d6423SLionel Sambuc return EINVAL;
210433d6423SLionel Sambuc }
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc printf("Started driver %s with label %s for device %d.\n",
213433d6423SLionel Sambuc inst->drv->binary, inst->label, inst->dev_id);
214433d6423SLionel Sambuc
215433d6423SLionel Sambuc return 0;
216433d6423SLionel Sambuc }
217433d6423SLionel Sambuc
218433d6423SLionel Sambuc /*===========================================================================*
219433d6423SLionel Sambuc * find_instance *
220433d6423SLionel Sambuc *===========================================================================*/
221433d6423SLionel Sambuc static struct devmand_driver_instance *
find_instance(int dev_id)222433d6423SLionel Sambuc find_instance(int dev_id)
223433d6423SLionel Sambuc {
224433d6423SLionel Sambuc struct devmand_driver_instance *inst;
225433d6423SLionel Sambuc
226433d6423SLionel Sambuc LIST_FOREACH(inst, &instances, list) {
227433d6423SLionel Sambuc if (inst->dev_id == dev_id) {
228433d6423SLionel Sambuc return inst;
229433d6423SLionel Sambuc }
230433d6423SLionel Sambuc }
231433d6423SLionel Sambuc return NULL;
232433d6423SLionel Sambuc }
233433d6423SLionel Sambuc
234433d6423SLionel Sambuc /*===========================================================================*
235433d6423SLionel Sambuc * match_usb_driver *
236433d6423SLionel Sambuc *===========================================================================*/
237433d6423SLionel Sambuc static int
match_usb_id(struct devmand_usb_match_id * mid,struct usb_device_id * id)238433d6423SLionel Sambuc match_usb_id(struct devmand_usb_match_id *mid, struct usb_device_id *id)
239433d6423SLionel Sambuc {
240433d6423SLionel Sambuc int res = 1;
241433d6423SLionel Sambuc unsigned long match = mid->match_flags;
242433d6423SLionel Sambuc struct usb_device_id *_id = &mid->match_id;
243433d6423SLionel Sambuc
244433d6423SLionel Sambuc if (match & USB_MATCH_ID_VENDOR)
245433d6423SLionel Sambuc if (id->idVendor != _id->idVendor) res = 0;
246433d6423SLionel Sambuc if (match & USB_MATCH_ID_PRODUCT)
247433d6423SLionel Sambuc if (id->idProduct != _id->idProduct) res = 0;
248433d6423SLionel Sambuc if (match & USB_MATCH_BCD_DEVICE)
249433d6423SLionel Sambuc if (id->bcdDevice != _id->bcdDevice) res = 0;
250433d6423SLionel Sambuc if (match & USB_MATCH_DEVICE_PROTOCOL)
251433d6423SLionel Sambuc if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
252433d6423SLionel Sambuc if (match & USB_MATCH_DEVICE_SUBCLASS)
253433d6423SLionel Sambuc if (id->bDeviceSubClass != _id->bDeviceSubClass) res = 0;
254433d6423SLionel Sambuc if (match & USB_MATCH_DEVICE_PROTOCOL)
255433d6423SLionel Sambuc if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
256433d6423SLionel Sambuc if (match & USB_MATCH_INTERFACE_CLASS)
257433d6423SLionel Sambuc if (id->bInterfaceClass != _id->bInterfaceClass) res = 0;
258433d6423SLionel Sambuc if (match & USB_MATCH_INTERFACE_SUBCLASS)
259433d6423SLionel Sambuc if (id->bInterfaceSubClass != _id->bInterfaceSubClass) res = 0;
260433d6423SLionel Sambuc if (match & USB_MATCH_INTERFACE_PROTOCOL)
261433d6423SLionel Sambuc if (id->bInterfaceProtocol != _id->bInterfaceProtocol) res = 0;
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc if (match == 0UL) {
264433d6423SLionel Sambuc res = 0;
265433d6423SLionel Sambuc }
266433d6423SLionel Sambuc
267433d6423SLionel Sambuc return res;
268433d6423SLionel Sambuc }
269433d6423SLionel Sambuc
270433d6423SLionel Sambuc /*===========================================================================*
271433d6423SLionel Sambuc * match_usb_driver *
272433d6423SLionel Sambuc *===========================================================================*/
273433d6423SLionel Sambuc static struct devmand_usb_driver*
match_usb_driver(struct usb_device_id * id)274433d6423SLionel Sambuc match_usb_driver(struct usb_device_id *id)
275433d6423SLionel Sambuc {
276433d6423SLionel Sambuc struct devmand_usb_driver *driver;
277433d6423SLionel Sambuc struct devmand_usb_match_id *mid;
278433d6423SLionel Sambuc
279433d6423SLionel Sambuc LIST_FOREACH(driver, &drivers, list) {
280433d6423SLionel Sambuc LIST_FOREACH(mid, &driver->ids, list) {
281433d6423SLionel Sambuc if (match_usb_id(mid, id)) {
282433d6423SLionel Sambuc return driver;
283433d6423SLionel Sambuc }
284433d6423SLionel Sambuc }
285433d6423SLionel Sambuc }
286433d6423SLionel Sambuc return NULL;
287433d6423SLionel Sambuc }
288433d6423SLionel Sambuc
289433d6423SLionel Sambuc /*===========================================================================*
290433d6423SLionel Sambuc * add_usb_match_id *
291433d6423SLionel Sambuc *===========================================================================*/
add_usb_driver(char * name)292433d6423SLionel Sambuc struct devmand_usb_driver * add_usb_driver(char *name)
293433d6423SLionel Sambuc {
294433d6423SLionel Sambuc struct devmand_usb_driver *udrv = (struct devmand_usb_driver*)
295433d6423SLionel Sambuc malloc(sizeof(struct devmand_usb_driver));
296433d6423SLionel Sambuc
297433d6423SLionel Sambuc LIST_INSERT_HEAD(&drivers, udrv, list);
298433d6423SLionel Sambuc LIST_INIT(&udrv->ids);
299433d6423SLionel Sambuc
300433d6423SLionel Sambuc udrv->name = name;
301433d6423SLionel Sambuc return udrv;
302433d6423SLionel Sambuc }
303433d6423SLionel Sambuc
304433d6423SLionel Sambuc /*===========================================================================*
305433d6423SLionel Sambuc * add_usb_match_id *
306433d6423SLionel Sambuc *===========================================================================*/
307433d6423SLionel Sambuc struct devmand_usb_match_id *
add_usb_match_id(struct devmand_usb_driver * drv)308433d6423SLionel Sambuc add_usb_match_id
309433d6423SLionel Sambuc (struct devmand_usb_driver *drv)
310433d6423SLionel Sambuc {
311433d6423SLionel Sambuc struct devmand_usb_match_id *id = (struct devmand_usb_match_id*)
312433d6423SLionel Sambuc malloc(sizeof(struct devmand_usb_match_id));
313433d6423SLionel Sambuc
314433d6423SLionel Sambuc memset(id, 0, sizeof(struct devmand_usb_match_id));
315433d6423SLionel Sambuc
316433d6423SLionel Sambuc LIST_INSERT_HEAD(&drv->ids, id, list);
317433d6423SLionel Sambuc
318433d6423SLionel Sambuc return id;
319433d6423SLionel Sambuc }
320433d6423SLionel Sambuc
321433d6423SLionel Sambuc
322433d6423SLionel Sambuc /*===========================================================================*
323433d6423SLionel Sambuc * parse_config *
324433d6423SLionel Sambuc *===========================================================================*/
parse_config()325433d6423SLionel Sambuc static void parse_config()
326433d6423SLionel Sambuc {
327433d6423SLionel Sambuc int i, status, error;
328433d6423SLionel Sambuc struct stat stats;
329433d6423SLionel Sambuc char * dirname;
330433d6423SLionel Sambuc
331433d6423SLionel Sambuc DIR * dir;
332433d6423SLionel Sambuc struct dirent entry;
333433d6423SLionel Sambuc struct dirent *result;
334433d6423SLionel Sambuc char config_file[PATH_MAX];
335433d6423SLionel Sambuc
336433d6423SLionel Sambuc dbg("Parsing configuration directories... ");
337433d6423SLionel Sambuc /* Next parse the configuration directories */
338433d6423SLionel Sambuc for(i=0; i < args.config_dir_count; i++){
339433d6423SLionel Sambuc dirname = args.config_dirs[i];
340433d6423SLionel Sambuc dbg("Parsing config dir %s ", dirname);
341433d6423SLionel Sambuc status = stat(dirname,&stats);
342433d6423SLionel Sambuc if (status == -1){
343433d6423SLionel Sambuc error = errno;
344433d6423SLionel Sambuc dbg("Failed to read directory '%s':%s (skipping) \n",
345433d6423SLionel Sambuc dirname,strerror(error));
346433d6423SLionel Sambuc continue;
347433d6423SLionel Sambuc }
348433d6423SLionel Sambuc if (!S_ISDIR(stats.st_mode)){
349433d6423SLionel Sambuc dbg("Parse configuration skipping %s "
350433d6423SLionel Sambuc "(not a directory) \n",dirname);
351433d6423SLionel Sambuc continue;
352433d6423SLionel Sambuc }
353433d6423SLionel Sambuc dir = opendir(dirname);
354433d6423SLionel Sambuc if (dir == NULL){
355433d6423SLionel Sambuc error = errno;
356433d6423SLionel Sambuc dbg("Parse configuration failed to read dir '%s'"
357433d6423SLionel Sambuc "(skipping) :%s\n",dirname, strerror(error));
358433d6423SLionel Sambuc continue;
359433d6423SLionel Sambuc }
360433d6423SLionel Sambuc while( (status = readdir_r(dir,&entry,&result)) == 0 ){
361433d6423SLionel Sambuc if (result == NULL){ /* last entry */
362433d6423SLionel Sambuc closedir(dir);
363433d6423SLionel Sambuc break;
364433d6423SLionel Sambuc }
365433d6423SLionel Sambuc
366433d6423SLionel Sambuc /* concatenate dir and file name to open it */
367433d6423SLionel Sambuc snprintf(config_file,PATH_MAX, "%s/%s",
368433d6423SLionel Sambuc dirname,entry.d_name);
369433d6423SLionel Sambuc status = stat(config_file, &stats);
370433d6423SLionel Sambuc if (status == -1){
371433d6423SLionel Sambuc error = errno;
372433d6423SLionel Sambuc dbg("Parse configuration Failed to stat file "
373433d6423SLionel Sambuc "'%s': %s (skipping)\n", config_file,
374433d6423SLionel Sambuc strerror(error));
375433d6423SLionel Sambuc }
376433d6423SLionel Sambuc if (S_ISREG(stats.st_mode)){
377433d6423SLionel Sambuc dbg("Parsing file %s",config_file);
378433d6423SLionel Sambuc yyin = fopen(config_file, "r");
379433d6423SLionel Sambuc
380e3cf9c04SJacob Adams if (yyin == NULL) {
381433d6423SLionel Sambuc dbg("Can not open config file:"
382433d6423SLionel Sambuc " %d.\n", errno);
383433d6423SLionel Sambuc }
384433d6423SLionel Sambuc yyparse();
385433d6423SLionel Sambuc dbg("Done.");
386433d6423SLionel Sambuc fclose(yyin);
387433d6423SLionel Sambuc }
388433d6423SLionel Sambuc }
389433d6423SLionel Sambuc }
390433d6423SLionel Sambuc dbg("Parsing configuration directories done... ");
391433d6423SLionel Sambuc
392433d6423SLionel Sambuc }
393433d6423SLionel Sambuc
394433d6423SLionel Sambuc /*===========================================================================*
395433d6423SLionel Sambuc * cleanup *
396433d6423SLionel Sambuc *===========================================================================*/
cleanup()397433d6423SLionel Sambuc static void cleanup() {
398433d6423SLionel Sambuc struct devmand_driver_instance *inst;
399433d6423SLionel Sambuc /* destroy fifo */
400433d6423SLionel Sambuc dbg("cleaning up... ");
401433d6423SLionel Sambuc /* quit all running drivers */
402433d6423SLionel Sambuc LIST_FOREACH(inst, &instances, list) {
403433d6423SLionel Sambuc dbg("stopping driver %s", inst->label);
404683d394dSBen Gras if(inst->drv->downscript) {
405433d6423SLionel Sambuc run_downscript (inst);
406683d394dSBen Gras }
407433d6423SLionel Sambuc stop_driver(inst);
408433d6423SLionel Sambuc }
409433d6423SLionel Sambuc unlink("/var/run/devmand.pid");
410433d6423SLionel Sambuc }
411433d6423SLionel Sambuc
sig_int(int sig)412433d6423SLionel Sambuc static void sig_int(int sig) {
413433d6423SLionel Sambuc dbg("devman: Received SIGINT... cleaning up.");
414433d6423SLionel Sambuc _run = 0;
415433d6423SLionel Sambuc }
416433d6423SLionel Sambuc
417433d6423SLionel Sambuc /*===========================================================================*
418433d6423SLionel Sambuc * create_pid_file *
419433d6423SLionel Sambuc *===========================================================================*/
create_pid_file()420433d6423SLionel Sambuc void create_pid_file()
421433d6423SLionel Sambuc {
422433d6423SLionel Sambuc FILE *fd;
423433d6423SLionel Sambuc
424433d6423SLionel Sambuc fd = fopen("/var/run/devmand.pid", "r");
425433d6423SLionel Sambuc if(fd) {
426433d6423SLionel Sambuc fprintf(stderr, "devmand: /var/run/devmand.pid exists... "
427433d6423SLionel Sambuc "another devmand running?\n");
428433d6423SLionel Sambuc fclose(fd);
429433d6423SLionel Sambuc exit(1);
430433d6423SLionel Sambuc } else {
431433d6423SLionel Sambuc fd = fopen("/var/run/devmand.pid","w");
432433d6423SLionel Sambuc fprintf(fd, "%d", getpid());
433433d6423SLionel Sambuc fclose(fd);
434433d6423SLionel Sambuc }
435433d6423SLionel Sambuc }
436433d6423SLionel Sambuc
437433d6423SLionel Sambuc /*===========================================================================*
438433d6423SLionel Sambuc * main *
439433d6423SLionel Sambuc *===========================================================================*/
main(int argc,char * argv[])440433d6423SLionel Sambuc int main(int argc, char *argv[])
441433d6423SLionel Sambuc {
442433d6423SLionel Sambuc int opt, optindex;
443433d6423SLionel Sambuc struct devmand_usb_driver *driver;
444433d6423SLionel Sambuc
445433d6423SLionel Sambuc
446433d6423SLionel Sambuc /* get command line arguments */
447433d6423SLionel Sambuc while ((opt = getopt_long(argc, argv, "d:p:vxh?", options, &optindex))
448433d6423SLionel Sambuc != -1) {
449433d6423SLionel Sambuc switch (opt) {
450433d6423SLionel Sambuc case 'd':/* config directory */
451433d6423SLionel Sambuc if (args.config_dir_count >= MAX_CONFIG_DIRS){
452433d6423SLionel Sambuc fprintf(stderr,"Parse arguments: Maximum"
453433d6423SLionel Sambuc " of %i configuration directories"
454433d6423SLionel Sambuc " reached skipping directory '%s'\n"
455433d6423SLionel Sambuc , MAX_CONFIG_DIRS, optarg);
456433d6423SLionel Sambuc break;
457433d6423SLionel Sambuc }
458433d6423SLionel Sambuc args.config_dirs[args.config_dir_count] = optarg;
459433d6423SLionel Sambuc args.config_dir_count++;
460433d6423SLionel Sambuc break;
461433d6423SLionel Sambuc case 'p': /* sysfs path */
462433d6423SLionel Sambuc args.path = optarg;
463433d6423SLionel Sambuc break;
464433d6423SLionel Sambuc case 'v': /* verbose */
465433d6423SLionel Sambuc args.verbose = 1;
466433d6423SLionel Sambuc break;
467433d6423SLionel Sambuc case 'x': /* check config */
468433d6423SLionel Sambuc args.check_config = 1;
469433d6423SLionel Sambuc break;
470433d6423SLionel Sambuc case 'h': /* help */
471433d6423SLionel Sambuc case '?': /* help */
472433d6423SLionel Sambuc default:
473433d6423SLionel Sambuc display_usage(argv[0]);
474433d6423SLionel Sambuc return 0;
475433d6423SLionel Sambuc }
476433d6423SLionel Sambuc }
477433d6423SLionel Sambuc
478433d6423SLionel Sambuc
479433d6423SLionel Sambuc /* is path set? */
480433d6423SLionel Sambuc if (args.path == NULL) {
481433d6423SLionel Sambuc args.path = "/sys/";
482433d6423SLionel Sambuc }
483433d6423SLionel Sambuc
484433d6423SLionel Sambuc /* is the configuration directory set? */
485433d6423SLionel Sambuc if (args.config_dir_count == 0) {
486433d6423SLionel Sambuc dbg("Using default configuration directory");
487433d6423SLionel Sambuc args.config_dirs[0] = "/etc/devmand";
488433d6423SLionel Sambuc args.config_dir_count = 1;
489433d6423SLionel Sambuc }
490433d6423SLionel Sambuc
491433d6423SLionel Sambuc /* If we only check the configuration run and exit imediately */
492433d6423SLionel Sambuc if (args.check_config == 1){
493433d6423SLionel Sambuc fprintf(stdout, "Only parsing configuration\n");
494433d6423SLionel Sambuc parse_config();
495433d6423SLionel Sambuc exit(0);
496433d6423SLionel Sambuc }
497433d6423SLionel Sambuc
498433d6423SLionel Sambuc create_pid_file();
499433d6423SLionel Sambuc
500433d6423SLionel Sambuc parse_config();
501433d6423SLionel Sambuc LIST_FOREACH(driver, &drivers, list) {
502683d394dSBen Gras if (driver->upscript) {
503433d6423SLionel Sambuc run_cleanscript(driver);
504433d6423SLionel Sambuc }
505683d394dSBen Gras }
506433d6423SLionel Sambuc
507433d6423SLionel Sambuc signal(SIGINT, sig_int);
508433d6423SLionel Sambuc
509433d6423SLionel Sambuc main_loop();
510433d6423SLionel Sambuc
511433d6423SLionel Sambuc cleanup();
512433d6423SLionel Sambuc
513433d6423SLionel Sambuc return 0;
514433d6423SLionel Sambuc }
515433d6423SLionel Sambuc
516433d6423SLionel Sambuc /*===========================================================================*
517433d6423SLionel Sambuc * determine_type *
518433d6423SLionel Sambuc *===========================================================================*/
determine_type(char * path)519433d6423SLionel Sambuc static enum dev_type determine_type (char *path)
520433d6423SLionel Sambuc {
521433d6423SLionel Sambuc FILE * fd;
522433d6423SLionel Sambuc char *mypath;
523433d6423SLionel Sambuc char buf[256];
524433d6423SLionel Sambuc int res;
525433d6423SLionel Sambuc
526433d6423SLionel Sambuc mypath = (char *) calloc(1, strlen(path)+strlen(DEVMAN_TYPE_NAME)+1);
527433d6423SLionel Sambuc
528433d6423SLionel Sambuc if (mypath == NULL) {
529433d6423SLionel Sambuc fprintf(stderr, "ERROR: out of mem\n");
530433d6423SLionel Sambuc cleanup();
531433d6423SLionel Sambuc exit(1);
532433d6423SLionel Sambuc }
533433d6423SLionel Sambuc
534433d6423SLionel Sambuc strcat(mypath, path);
535433d6423SLionel Sambuc strcat(mypath, DEVMAN_TYPE_NAME);
536433d6423SLionel Sambuc
537433d6423SLionel Sambuc fd = fopen(mypath, "r");
538433d6423SLionel Sambuc free(mypath);
539433d6423SLionel Sambuc
540433d6423SLionel Sambuc if (fd == NULL) {
541433d6423SLionel Sambuc fprintf(stderr, "WARN: could not open %s\n", mypath);
542433d6423SLionel Sambuc return DEV_TYPE_UNKOWN;
543433d6423SLionel Sambuc }
544433d6423SLionel Sambuc
5453a1943c1SJacob Adams res = fscanf(fd , "%255s\n", buf);
546433d6423SLionel Sambuc fclose(fd);
547433d6423SLionel Sambuc
548433d6423SLionel Sambuc if (res != 1) {
549433d6423SLionel Sambuc fprintf(stderr, "WARN: could not parse %s\n", mypath);
550433d6423SLionel Sambuc return DEV_TYPE_UNKOWN;
551433d6423SLionel Sambuc }
552433d6423SLionel Sambuc
553433d6423SLionel Sambuc if (strcmp(buf, "USB_DEV") == 0) {
554433d6423SLionel Sambuc return DEV_TYPE_USB_DEVICE;
555433d6423SLionel Sambuc } else if (strcmp(buf, "USB_INTF") == 0) {
556433d6423SLionel Sambuc return DEV_TYPE_USB_INTF;
557433d6423SLionel Sambuc }
558433d6423SLionel Sambuc
559433d6423SLionel Sambuc return DEV_TYPE_UNKOWN;
560433d6423SLionel Sambuc }
561433d6423SLionel Sambuc
562433d6423SLionel Sambuc /*===========================================================================*
563433d6423SLionel Sambuc * read_hex_uint *
564433d6423SLionel Sambuc *===========================================================================*/
read_hex_uint(char * base_path,char * name,unsigned int * val)565433d6423SLionel Sambuc static int read_hex_uint(char *base_path, char *name, unsigned int* val )
566433d6423SLionel Sambuc {
567433d6423SLionel Sambuc char my_path[PATH_LEN];
568433d6423SLionel Sambuc FILE *fd;
569433d6423SLionel Sambuc memset(my_path,0,PATH_LEN);
570433d6423SLionel Sambuc int ret = 0;
571433d6423SLionel Sambuc
572433d6423SLionel Sambuc strcat(my_path, base_path);
573433d6423SLionel Sambuc strcat(my_path, name);
574433d6423SLionel Sambuc
575433d6423SLionel Sambuc fd = fopen(my_path, "r");
576433d6423SLionel Sambuc
577433d6423SLionel Sambuc if (fd == NULL) {
578433d6423SLionel Sambuc fprintf(stderr, "WARN: could not open %s\n", my_path);
579433d6423SLionel Sambuc return EEXIST;
580433d6423SLionel Sambuc } else if (fscanf(fd, "0x%x\n", val ) != 1) {
581433d6423SLionel Sambuc fprintf(stderr, "WARN: could not parse %s\n", my_path);
582433d6423SLionel Sambuc ret = EINVAL;
583433d6423SLionel Sambuc }
584433d6423SLionel Sambuc fclose(fd);
585433d6423SLionel Sambuc
586433d6423SLionel Sambuc return ret;
587433d6423SLionel Sambuc }
588433d6423SLionel Sambuc
589433d6423SLionel Sambuc /*===========================================================================*
590433d6423SLionel Sambuc * get_major *
591433d6423SLionel Sambuc *===========================================================================*/
get_major()592433d6423SLionel Sambuc static int get_major() {
593433d6423SLionel Sambuc int i, ret = args.major_offset;
594433d6423SLionel Sambuc
595433d6423SLionel Sambuc for (i=0; i < 16; i++) {
596433d6423SLionel Sambuc int j;
597433d6423SLionel Sambuc for (j = 0; j < 8; j++ ) {
598433d6423SLionel Sambuc if ((major_bitmap[i] & (1 << j))) {
599433d6423SLionel Sambuc major_bitmap[i] &= !(1 << j);
600433d6423SLionel Sambuc return ret;
601433d6423SLionel Sambuc }
602433d6423SLionel Sambuc ret++;
603433d6423SLionel Sambuc }
604433d6423SLionel Sambuc }
605433d6423SLionel Sambuc return INVAL_MAJOR;
606433d6423SLionel Sambuc }
607433d6423SLionel Sambuc
608433d6423SLionel Sambuc /*===========================================================================*
609433d6423SLionel Sambuc * put_major *
610433d6423SLionel Sambuc *===========================================================================*/
put_major(int major)611433d6423SLionel Sambuc static void put_major(int major) {
612433d6423SLionel Sambuc int i;
613433d6423SLionel Sambuc major -= args.major_offset;
614433d6423SLionel Sambuc assert(major >= 0);
615433d6423SLionel Sambuc
616433d6423SLionel Sambuc for (i=0; i < 16; i++) {
617433d6423SLionel Sambuc int j;
618433d6423SLionel Sambuc for (j = 0; j < 8; j++ ) {
619433d6423SLionel Sambuc if (major==0) {
620433d6423SLionel Sambuc assert(!(major_bitmap[i] & (1 <<j)));
621433d6423SLionel Sambuc major_bitmap[i] |= (1 << j);
622433d6423SLionel Sambuc return;
623433d6423SLionel Sambuc }
624433d6423SLionel Sambuc major--;
625433d6423SLionel Sambuc }
626433d6423SLionel Sambuc }
627433d6423SLionel Sambuc }
628433d6423SLionel Sambuc
629433d6423SLionel Sambuc /*===========================================================================*
630433d6423SLionel Sambuc * generate_usb_device_id *
631433d6423SLionel Sambuc *===========================================================================*/
632433d6423SLionel Sambuc static struct usb_device_id *
generate_usb_device_id(char * path,int is_interface)633433d6423SLionel Sambuc generate_usb_device_id(char * path, int is_interface)
634433d6423SLionel Sambuc {
635433d6423SLionel Sambuc struct usb_device_id *ret;
636433d6423SLionel Sambuc int res;
637433d6423SLionel Sambuc unsigned int val;
638433d6423SLionel Sambuc
639433d6423SLionel Sambuc ret = (struct usb_device_id *)
640433d6423SLionel Sambuc calloc(1,sizeof (struct usb_device_id));
641433d6423SLionel Sambuc
642433d6423SLionel Sambuc if (is_interface) {
643433d6423SLionel Sambuc
644433d6423SLionel Sambuc res = read_hex_uint(path, "../idVendor", &val);
645433d6423SLionel Sambuc if (res) goto err;
646433d6423SLionel Sambuc ret->idVendor = val;
647433d6423SLionel Sambuc
648433d6423SLionel Sambuc res = read_hex_uint(path, "../idProduct", &val);
649433d6423SLionel Sambuc if (res) goto err;
650433d6423SLionel Sambuc ret->idProduct = val;
651433d6423SLionel Sambuc #if 0
652433d6423SLionel Sambuc res = read_hex_uint(path, "../bcdDevice", &val);
653433d6423SLionel Sambuc if (res) goto err;
654433d6423SLionel Sambuc ret->bcdDevice = val;
655433d6423SLionel Sambuc #endif
656433d6423SLionel Sambuc res = read_hex_uint(path, "../bDeviceClass", &val);
657433d6423SLionel Sambuc if (res) goto err;
658433d6423SLionel Sambuc ret->bDeviceClass = val;
659433d6423SLionel Sambuc
660433d6423SLionel Sambuc res = read_hex_uint(path, "../bDeviceSubClass", &val);
661433d6423SLionel Sambuc if (res) goto err;
662433d6423SLionel Sambuc ret->bDeviceSubClass = val;
663433d6423SLionel Sambuc
664433d6423SLionel Sambuc res = read_hex_uint(path, "../bDeviceProtocol", &val);
665433d6423SLionel Sambuc if (res) goto err;
666433d6423SLionel Sambuc ret->bDeviceProtocol = val;
667433d6423SLionel Sambuc
668433d6423SLionel Sambuc res = read_hex_uint(path, "/bInterfaceClass", &val);
669433d6423SLionel Sambuc if (res) goto err;
670433d6423SLionel Sambuc ret->bInterfaceClass = val;
671433d6423SLionel Sambuc
672433d6423SLionel Sambuc res = read_hex_uint(path, "/bInterfaceSubClass", &val);
673433d6423SLionel Sambuc if (res) goto err;
674433d6423SLionel Sambuc ret->bInterfaceSubClass = val;
675433d6423SLionel Sambuc
676433d6423SLionel Sambuc res = read_hex_uint(path, "/bInterfaceProtocol", &val);
677433d6423SLionel Sambuc if (res) goto err;
678433d6423SLionel Sambuc ret->bInterfaceProtocol = val;
679433d6423SLionel Sambuc }
680433d6423SLionel Sambuc
681433d6423SLionel Sambuc return ret;
682433d6423SLionel Sambuc
683433d6423SLionel Sambuc err:
684433d6423SLionel Sambuc free(ret);
685433d6423SLionel Sambuc return NULL;
686433d6423SLionel Sambuc }
687433d6423SLionel Sambuc
688433d6423SLionel Sambuc /*===========================================================================*
689433d6423SLionel Sambuc * usb_intf_add_even *
690433d6423SLionel Sambuc *===========================================================================*/
usb_intf_add_event(char * path,int dev_id)691433d6423SLionel Sambuc static void usb_intf_add_event(char *path, int dev_id)
692433d6423SLionel Sambuc {
693433d6423SLionel Sambuc struct usb_device_id *id;
694433d6423SLionel Sambuc struct devmand_usb_driver *drv;
695433d6423SLionel Sambuc struct devmand_driver_instance *drv_inst;
696433d6423SLionel Sambuc int major, ret;
697433d6423SLionel Sambuc
698433d6423SLionel Sambuc /* generate usb_match_id */
699433d6423SLionel Sambuc id = generate_usb_device_id(path,TRUE);
700433d6423SLionel Sambuc if (id == NULL) {
701433d6423SLionel Sambuc fprintf(stderr, "WARN: could not create usb_device id...\n"
702433d6423SLionel Sambuc " ommiting event\n");
703433d6423SLionel Sambuc free(id);
704433d6423SLionel Sambuc return;
705433d6423SLionel Sambuc }
706433d6423SLionel Sambuc
707433d6423SLionel Sambuc /* find suitable driver */
708433d6423SLionel Sambuc drv = match_usb_driver(id);
709433d6423SLionel Sambuc free (id);
710433d6423SLionel Sambuc
711433d6423SLionel Sambuc if (drv == NULL) {
712433d6423SLionel Sambuc dbg("INFO: could not find a suitable driver for %s", path);
713433d6423SLionel Sambuc return;
714433d6423SLionel Sambuc }
715433d6423SLionel Sambuc
716433d6423SLionel Sambuc /* create instance */
717433d6423SLionel Sambuc drv_inst = (struct devmand_driver_instance *)
718433d6423SLionel Sambuc calloc(1,sizeof(struct devmand_driver_instance));
719433d6423SLionel Sambuc
720433d6423SLionel Sambuc if (drv_inst == NULL) {
721433d6423SLionel Sambuc fprintf(stderr, "ERROR: out of memory");
722433d6423SLionel Sambuc return; /* maybe better quit here. */
723433d6423SLionel Sambuc }
724433d6423SLionel Sambuc
725433d6423SLionel Sambuc
726433d6423SLionel Sambuc /* allocate inode number, if device files needed */
727433d6423SLionel Sambuc major = get_major();
728433d6423SLionel Sambuc if (major == INVAL_MAJOR) {
729433d6423SLionel Sambuc fprintf(stderr, "WARN: ran out of major numbers\n"
730433d6423SLionel Sambuc " cannot start driver %s for %s\n",
731433d6423SLionel Sambuc drv->name, path);
732433d6423SLionel Sambuc return;
733433d6423SLionel Sambuc }
734433d6423SLionel Sambuc
735433d6423SLionel Sambuc drv_inst->major = major;
736433d6423SLionel Sambuc drv_inst->drv = drv;
737433d6423SLionel Sambuc drv_inst->dev_id = dev_id;
738433d6423SLionel Sambuc
739433d6423SLionel Sambuc
740*c58da9fbSDavid van Moolenbroek /* start driver (invoke minix-service) */
741433d6423SLionel Sambuc start_driver(drv_inst);
742433d6423SLionel Sambuc
743433d6423SLionel Sambuc /*
744433d6423SLionel Sambuc * run the up action
745433d6423SLionel Sambuc *
746433d6423SLionel Sambuc * An up action can be any executable. Before running it devmand
747433d6423SLionel Sambuc * will set certain environment variables so the script can configure
748433d6423SLionel Sambuc * the device (or generate device files, etc). See up_action() for that.
749433d6423SLionel Sambuc */
750433d6423SLionel Sambuc if (drv->upscript) {
751433d6423SLionel Sambuc ret = run_upscript(drv_inst);
752433d6423SLionel Sambuc if (ret) {
753433d6423SLionel Sambuc stop_driver(drv_inst);
754433d6423SLionel Sambuc fprintf(stderr, "devmand: warning, could not run up_action\n");
755433d6423SLionel Sambuc free(drv_inst);
756433d6423SLionel Sambuc return;
757433d6423SLionel Sambuc }
758433d6423SLionel Sambuc }
759433d6423SLionel Sambuc
760433d6423SLionel Sambuc LIST_INSERT_HEAD(&instances,drv_inst,list);
761433d6423SLionel Sambuc }
762433d6423SLionel Sambuc
763433d6423SLionel Sambuc /*===========================================================================*
764433d6423SLionel Sambuc * usb_intf_remove_event *
765433d6423SLionel Sambuc *===========================================================================*/
usb_intf_remove_event(char * path,int dev_id)766433d6423SLionel Sambuc static void usb_intf_remove_event(char *path, int dev_id)
767433d6423SLionel Sambuc {
768433d6423SLionel Sambuc struct devmand_driver_instance *inst;
769433d6423SLionel Sambuc struct devmand_usb_driver *drv;
770433d6423SLionel Sambuc int ret;
771433d6423SLionel Sambuc
772433d6423SLionel Sambuc /* find the driver instance */
773433d6423SLionel Sambuc inst = find_instance(dev_id);
774433d6423SLionel Sambuc
775433d6423SLionel Sambuc if (inst == NULL) {
776433d6423SLionel Sambuc dbg("No driver running for id: %d", dev_id);
777433d6423SLionel Sambuc return;
778433d6423SLionel Sambuc }
779433d6423SLionel Sambuc drv = inst->drv;
780433d6423SLionel Sambuc
781433d6423SLionel Sambuc /* run the down script */
782433d6423SLionel Sambuc if (drv->downscript) {
783433d6423SLionel Sambuc ret = run_downscript(inst);
784433d6423SLionel Sambuc if (ret) {
785433d6423SLionel Sambuc fprintf(stderr, "WARN: error running up_action");
786433d6423SLionel Sambuc }
787433d6423SLionel Sambuc }
788433d6423SLionel Sambuc
789433d6423SLionel Sambuc /* stop the driver */
790433d6423SLionel Sambuc stop_driver(inst);
791433d6423SLionel Sambuc
792433d6423SLionel Sambuc /* free major */
793433d6423SLionel Sambuc put_major(inst->major);
794433d6423SLionel Sambuc
795433d6423SLionel Sambuc /* free instance */
796433d6423SLionel Sambuc LIST_REMOVE(inst,list);
797433d6423SLionel Sambuc free(inst);
798433d6423SLionel Sambuc }
799433d6423SLionel Sambuc
800433d6423SLionel Sambuc /*===========================================================================*
801433d6423SLionel Sambuc * handle_event *
802433d6423SLionel Sambuc *===========================================================================*/
handle_event(char * event)803433d6423SLionel Sambuc static void handle_event(char *event)
804433d6423SLionel Sambuc {
805433d6423SLionel Sambuc enum dev_type type;
806433d6423SLionel Sambuc char path[PATH_LEN];
807433d6423SLionel Sambuc char tmp_path[PATH_LEN];
808433d6423SLionel Sambuc int dev_id, res;
809433d6423SLionel Sambuc
810433d6423SLionel Sambuc path[0]=0;
811433d6423SLionel Sambuc
812433d6423SLionel Sambuc if (strncmp("ADD ", event, 4) == 0) {
813433d6423SLionel Sambuc
814433d6423SLionel Sambuc /* read data from event */
815433d6423SLionel Sambuc res = sscanf(event, "ADD %s 0x%x", tmp_path, &dev_id);
816433d6423SLionel Sambuc
817433d6423SLionel Sambuc if (res != 2) {
818433d6423SLionel Sambuc fprintf(stderr, "WARN: could not parse event: %s", event);
819433d6423SLionel Sambuc fprintf(stderr, "WARN: omitting event: %s", event);
820433d6423SLionel Sambuc }
821433d6423SLionel Sambuc
822433d6423SLionel Sambuc strcpy(path, args.path);
823433d6423SLionel Sambuc strcat(path, tmp_path);
824433d6423SLionel Sambuc
825433d6423SLionel Sambuc /* what kind of device is added? */
826433d6423SLionel Sambuc type = determine_type(path);
827433d6423SLionel Sambuc
828433d6423SLionel Sambuc switch (type) {
829433d6423SLionel Sambuc case DEV_TYPE_USB_DEVICE:
830433d6423SLionel Sambuc dbg("USB device added: ommited....");
831433d6423SLionel Sambuc /* ommit usb devices for now */
832433d6423SLionel Sambuc break;
833433d6423SLionel Sambuc case DEV_TYPE_USB_INTF:
834433d6423SLionel Sambuc dbg("USB interface added: (%s, devid: = %d)",path, dev_id);
835433d6423SLionel Sambuc usb_intf_add_event(path, dev_id);
836433d6423SLionel Sambuc return;
837433d6423SLionel Sambuc default:
838433d6423SLionel Sambuc dbg("default");
839433d6423SLionel Sambuc fprintf(stderr, "WARN: ommiting event\n");
840433d6423SLionel Sambuc }
841433d6423SLionel Sambuc } else if (strncmp("REMOVE ", event, 7) == 0) {
842433d6423SLionel Sambuc
843433d6423SLionel Sambuc /* read data from event */
844433d6423SLionel Sambuc res = sscanf(event,"REMOVE %s 0x%x", tmp_path, &dev_id);
845433d6423SLionel Sambuc
846433d6423SLionel Sambuc if (res != 2) {
847433d6423SLionel Sambuc fprintf(stderr, "WARN: could not parse event: %s", event);
848433d6423SLionel Sambuc fprintf(stderr, "WARN: omitting event: %s", event);
849433d6423SLionel Sambuc }
850433d6423SLionel Sambuc
851433d6423SLionel Sambuc usb_intf_remove_event(path, dev_id);
852433d6423SLionel Sambuc
853433d6423SLionel Sambuc #if 0
854433d6423SLionel Sambuc strcpy(path, args.path);
855433d6423SLionel Sambuc strcat(path, tmp_path);
856433d6423SLionel Sambuc
857433d6423SLionel Sambuc /* what kind of device is added? */
858433d6423SLionel Sambuc type = determine_type(path);
859433d6423SLionel Sambuc
860433d6423SLionel Sambuc switch (type) {
861433d6423SLionel Sambuc case DEV_TYPE_USB_DEVICE:
862433d6423SLionel Sambuc /* ommit usb devices for now */
863433d6423SLionel Sambuc break;
864433d6423SLionel Sambuc case DEV_TYPE_USB_INTF:
865433d6423SLionel Sambuc usb_intf_remove_event(path, dev_id);
866433d6423SLionel Sambuc return;
867433d6423SLionel Sambuc default:
868433d6423SLionel Sambuc fprintf(stderr, "WARN: ommiting event\n");
869433d6423SLionel Sambuc }
870433d6423SLionel Sambuc #endif
871433d6423SLionel Sambuc
872433d6423SLionel Sambuc }
873433d6423SLionel Sambuc }
874433d6423SLionel Sambuc
875433d6423SLionel Sambuc /*===========================================================================*
876433d6423SLionel Sambuc * main_loop *
877433d6423SLionel Sambuc *===========================================================================*/
main_loop()878433d6423SLionel Sambuc static void main_loop()
879433d6423SLionel Sambuc {
880433d6423SLionel Sambuc char ev_path[128];
881433d6423SLionel Sambuc char buf[256];
882433d6423SLionel Sambuc int len;
883433d6423SLionel Sambuc FILE* fd;
884433d6423SLionel Sambuc len = strlen(args.path);
885433d6423SLionel Sambuc
886433d6423SLionel Sambuc /* init major numbers */
887433d6423SLionel Sambuc
888433d6423SLionel Sambuc memset(&major_bitmap, 0xff, 16);
889433d6423SLionel Sambuc
890433d6423SLionel Sambuc if (len > 128 - 7 /*len of "events" */) {
891433d6423SLionel Sambuc fprintf(stderr, "pathname to long\n");
892433d6423SLionel Sambuc cleanup();
893433d6423SLionel Sambuc exit(1);
894433d6423SLionel Sambuc }
895433d6423SLionel Sambuc
896433d6423SLionel Sambuc strcpy(ev_path, args.path);
897433d6423SLionel Sambuc strcat(ev_path, "events");
898433d6423SLionel Sambuc
899433d6423SLionel Sambuc
900433d6423SLionel Sambuc while (_run) {
901433d6423SLionel Sambuc
902433d6423SLionel Sambuc char *res;
903433d6423SLionel Sambuc
904433d6423SLionel Sambuc fd = fopen(ev_path, "r");
905433d6423SLionel Sambuc if (fd == NULL) {
906433d6423SLionel Sambuc /*
907433d6423SLionel Sambuc * ENFILE is a temporary failure, often caused by
908433d6423SLionel Sambuc * running the test set. Don't die from that..
909433d6423SLionel Sambuc */
910433d6423SLionel Sambuc if (errno == ENFILE) {
911433d6423SLionel Sambuc usleep(50000);
912433d6423SLionel Sambuc continue;
913433d6423SLionel Sambuc }
914433d6423SLionel Sambuc
915433d6423SLionel Sambuc fprintf(stderr,"devmand error: could not open event "
916433d6423SLionel Sambuc "file %s bailing out\n", ev_path);
917433d6423SLionel Sambuc cleanup();
918433d6423SLionel Sambuc exit(1);
919433d6423SLionel Sambuc }
920433d6423SLionel Sambuc
921433d6423SLionel Sambuc res = fgets(buf, 256, fd);
922433d6423SLionel Sambuc fclose(fd);
923433d6423SLionel Sambuc
924433d6423SLionel Sambuc if (res == NULL) {
925433d6423SLionel Sambuc usleep(50000);
926433d6423SLionel Sambuc continue;
927433d6423SLionel Sambuc }
928433d6423SLionel Sambuc dbg("handle_event: %s", buf);
929433d6423SLionel Sambuc handle_event(buf);
930433d6423SLionel Sambuc }
931433d6423SLionel Sambuc }
932433d6423SLionel Sambuc
933433d6423SLionel Sambuc /*===========================================================================*
934433d6423SLionel Sambuc * display_usage *
935433d6423SLionel Sambuc *===========================================================================*/
display_usage(const char * name)936433d6423SLionel Sambuc static void display_usage(const char *name)
937433d6423SLionel Sambuc {
938433d6423SLionel Sambuc printf("Usage: %s [{-p|--pathname} PATH_TO_SYS}"
939433d6423SLionel Sambuc " [{-d|--config-dir} CONFIG_DIR] [-v|--verbose]"
940433d6423SLionel Sambuc " [[x||--check-config]\n", name);
941433d6423SLionel Sambuc }
942433d6423SLionel Sambuc
943