1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <getopt.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <lib.h>
7 #include <sys/stat.h>
8 #include <dirent.h>
9 #include <assert.h>
10 #include <signal.h>
11 #include <minix/dmap.h>
12 #include <minix/paths.h>
13 #include "usb_driver.h"
14 #include "proto.h"
15
16 #define DEVMAN_TYPE_NAME "dev_type"
17 #define PATH_LEN 256
18 #define INVAL_MAJOR -1
19 #define MAX_CONFIG_DIRS 4
20
21 static void main_loop();
22 static void handle_event();
23 static void cleanup();
24 static void parse_config();
25 static void display_usage();
26 static enum dev_type determine_type(char *path);
27 static int get_major();
28 static void create_pid_file();
29 static void put_major(int major);
30 static struct devmand_usb_driver* match_usb_driver(struct usb_device_id *id);
31 static struct devmand_driver_instance *find_instance(int dev_id);
32
33 #define dbg(fmt, ... ) \
34 if (args.verbose) \
35 printf("%8s:%4d: %13s()| "fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )
36
37 static LIST_HEAD(usb_driver_head, devmand_usb_driver) drivers =
38 LIST_HEAD_INITIALIZER(drivers);
39 static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
40 LIST_HEAD_INITIALIZER(instances);
41
42
43 static int _run = 1;
44 struct global_args {
45 char *path;
46 char *config_dirs[MAX_CONFIG_DIRS];
47 int config_dir_count ;
48 int major_offset;
49 int verbose;
50 int check_config;
51 };
52
53 enum dev_type {
54 DEV_TYPE_USB_DEVICE,
55 DEV_TYPE_USB_INTF,
56 DEV_TYPE_UNKOWN
57 };
58
59 extern FILE *yyin;
60
61 static struct global_args args = {
62 .path = NULL,
63 .config_dirs = {NULL,NULL,NULL,NULL},
64 .config_dir_count = 0,
65 .major_offset = USB_BASE_MAJOR,
66 .verbose = 0,
67 .check_config = 0};
68
69 static struct option options[] =
70 {
71 {"dir" , required_argument, NULL, 'd'},
72 {"path", required_argument, NULL, 'p'},
73 {"verbose", required_argument, NULL, 'v'},
74 {"check-config", no_argument, NULL, 'x'},
75 {0,0,0,0} /* terminating entry */
76 };
77
78 static char major_bitmap[16]; /* can store up to 128 major number states */
79
80
81 /*===========================================================================*
82 * run_upscript *
83 *===========================================================================*/
run_upscript(struct devmand_driver_instance * inst)84 int run_upscript(struct devmand_driver_instance *inst)
85 {
86 char cmdl[1024];
87 cmdl[0] = 0;
88 int ret;
89
90 assert(inst->drv->upscript);
91 assert(inst->label);
92
93 snprintf(cmdl, 1024, "%s up %s %d %d",
94 inst->drv->upscript, inst->label, inst->major, inst->dev_id);
95 dbg("Running Upscript: \"%s\"", cmdl);
96 ret = system(cmdl);
97 if (ret != 0) {
98 return EINVAL;
99 }
100 return 0;
101 }
102
103 /*===========================================================================*
104 * run_cleanscript *
105 *===========================================================================*/
run_cleanscript(struct devmand_usb_driver * drv)106 int run_cleanscript(struct devmand_usb_driver *drv)
107 {
108 char cmdl[1024];
109 cmdl[0] = 0;
110 int ret;
111
112 assert(drv->upscript);
113 assert(drv->devprefix);
114
115 snprintf(cmdl, 1024, "%s clean %s ",
116 drv->upscript, drv->devprefix);
117 dbg("Running Upscript: \"%s\"", cmdl);
118 ret = system(cmdl);
119
120 if (ret != 0) {
121 return EINVAL;
122 }
123
124 return 0;
125 }
126
127
128 /*===========================================================================*
129 * run_downscript *
130 *===========================================================================*/
run_downscript(struct devmand_driver_instance * inst)131 int run_downscript(struct devmand_driver_instance *inst)
132 {
133 char cmdl[1024];
134 cmdl[0] = 0;
135 int ret;
136
137 assert(inst->drv->downscript);
138 assert(inst->label);
139
140 snprintf(cmdl, 1024, "%s down %s %d",
141 inst->drv->downscript, inst->label, inst->major);
142
143 dbg("Running Upscript: \"%s\"", cmdl);
144
145 ret = system(cmdl);
146
147 if (ret != 0) {
148 return EINVAL;
149 }
150
151 return 0;
152 }
153
154
155 /*===========================================================================*
156 * stop_driver *
157 *===========================================================================*/
stop_driver(struct devmand_driver_instance * inst)158 int stop_driver(struct devmand_driver_instance *inst)
159 {
160 char cmdl[1024];
161 cmdl[0] = 0;
162 int ret;
163
164 assert(inst->label);
165
166 snprintf(cmdl, 1024, "%s down %s %d",
167 _PATH_MINIX_SERVICE, inst->label, inst->dev_id);
168 dbg("executing minix-service: \"%s\"", cmdl);
169 ret = system(cmdl);
170 if (ret != 0)
171 {
172 return EINVAL;
173 }
174 printf("Stopped driver %s with label %s for device %d.\n",
175 inst->drv->binary, inst->label, inst->dev_id);
176
177 return 0;
178 }
179
180
181 /*===========================================================================*
182 * start_driver *
183 *===========================================================================*/
start_driver(struct devmand_driver_instance * inst)184 int start_driver(struct devmand_driver_instance *inst)
185 {
186 char cmdl[1024];
187 cmdl[0] = 0;
188 int ret;
189
190 /* generate label */
191 ret = snprintf(inst->label, 32, "%s%d", inst->drv->devprefix,
192 inst->dev_id);
193 if (ret < 0 || ret > DEVMAND_DRIVER_LABEL_LEN) {
194 dbg("label too long");
195 return ENOMEM;
196 }
197
198 assert(inst->drv->binary);
199 assert(inst->label);
200
201 snprintf(cmdl, 1024, "%s up %s -major %d -devid %d -label %s",
202 _PATH_MINIX_SERVICE, inst->drv->binary, inst->major, inst->dev_id,
203 inst->label);
204 dbg("executing minix-service: \"%s\"", cmdl);
205
206 ret = system(cmdl);
207
208 if (ret != 0) {
209 return EINVAL;
210 }
211
212 printf("Started driver %s with label %s for device %d.\n",
213 inst->drv->binary, inst->label, inst->dev_id);
214
215 return 0;
216 }
217
218 /*===========================================================================*
219 * find_instance *
220 *===========================================================================*/
221 static struct devmand_driver_instance *
find_instance(int dev_id)222 find_instance(int dev_id)
223 {
224 struct devmand_driver_instance *inst;
225
226 LIST_FOREACH(inst, &instances, list) {
227 if (inst->dev_id == dev_id) {
228 return inst;
229 }
230 }
231 return NULL;
232 }
233
234 /*===========================================================================*
235 * match_usb_driver *
236 *===========================================================================*/
237 static int
match_usb_id(struct devmand_usb_match_id * mid,struct usb_device_id * id)238 match_usb_id(struct devmand_usb_match_id *mid, struct usb_device_id *id)
239 {
240 int res = 1;
241 unsigned long match = mid->match_flags;
242 struct usb_device_id *_id = &mid->match_id;
243
244 if (match & USB_MATCH_ID_VENDOR)
245 if (id->idVendor != _id->idVendor) res = 0;
246 if (match & USB_MATCH_ID_PRODUCT)
247 if (id->idProduct != _id->idProduct) res = 0;
248 if (match & USB_MATCH_BCD_DEVICE)
249 if (id->bcdDevice != _id->bcdDevice) res = 0;
250 if (match & USB_MATCH_DEVICE_PROTOCOL)
251 if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
252 if (match & USB_MATCH_DEVICE_SUBCLASS)
253 if (id->bDeviceSubClass != _id->bDeviceSubClass) res = 0;
254 if (match & USB_MATCH_DEVICE_PROTOCOL)
255 if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
256 if (match & USB_MATCH_INTERFACE_CLASS)
257 if (id->bInterfaceClass != _id->bInterfaceClass) res = 0;
258 if (match & USB_MATCH_INTERFACE_SUBCLASS)
259 if (id->bInterfaceSubClass != _id->bInterfaceSubClass) res = 0;
260 if (match & USB_MATCH_INTERFACE_PROTOCOL)
261 if (id->bInterfaceProtocol != _id->bInterfaceProtocol) res = 0;
262
263 if (match == 0UL) {
264 res = 0;
265 }
266
267 return res;
268 }
269
270 /*===========================================================================*
271 * match_usb_driver *
272 *===========================================================================*/
273 static struct devmand_usb_driver*
match_usb_driver(struct usb_device_id * id)274 match_usb_driver(struct usb_device_id *id)
275 {
276 struct devmand_usb_driver *driver;
277 struct devmand_usb_match_id *mid;
278
279 LIST_FOREACH(driver, &drivers, list) {
280 LIST_FOREACH(mid, &driver->ids, list) {
281 if (match_usb_id(mid, id)) {
282 return driver;
283 }
284 }
285 }
286 return NULL;
287 }
288
289 /*===========================================================================*
290 * add_usb_match_id *
291 *===========================================================================*/
add_usb_driver(char * name)292 struct devmand_usb_driver * add_usb_driver(char *name)
293 {
294 struct devmand_usb_driver *udrv = (struct devmand_usb_driver*)
295 malloc(sizeof(struct devmand_usb_driver));
296
297 LIST_INSERT_HEAD(&drivers, udrv, list);
298 LIST_INIT(&udrv->ids);
299
300 udrv->name = name;
301 return udrv;
302 }
303
304 /*===========================================================================*
305 * add_usb_match_id *
306 *===========================================================================*/
307 struct devmand_usb_match_id *
add_usb_match_id(struct devmand_usb_driver * drv)308 add_usb_match_id
309 (struct devmand_usb_driver *drv)
310 {
311 struct devmand_usb_match_id *id = (struct devmand_usb_match_id*)
312 malloc(sizeof(struct devmand_usb_match_id));
313
314 memset(id, 0, sizeof(struct devmand_usb_match_id));
315
316 LIST_INSERT_HEAD(&drv->ids, id, list);
317
318 return id;
319 }
320
321
322 /*===========================================================================*
323 * parse_config *
324 *===========================================================================*/
parse_config()325 static void parse_config()
326 {
327 int i, status, error;
328 struct stat stats;
329 char * dirname;
330
331 DIR * dir;
332 struct dirent entry;
333 struct dirent *result;
334 char config_file[PATH_MAX];
335
336 dbg("Parsing configuration directories... ");
337 /* Next parse the configuration directories */
338 for(i=0; i < args.config_dir_count; i++){
339 dirname = args.config_dirs[i];
340 dbg("Parsing config dir %s ", dirname);
341 status = stat(dirname,&stats);
342 if (status == -1){
343 error = errno;
344 dbg("Failed to read directory '%s':%s (skipping) \n",
345 dirname,strerror(error));
346 continue;
347 }
348 if (!S_ISDIR(stats.st_mode)){
349 dbg("Parse configuration skipping %s "
350 "(not a directory) \n",dirname);
351 continue;
352 }
353 dir = opendir(dirname);
354 if (dir == NULL){
355 error = errno;
356 dbg("Parse configuration failed to read dir '%s'"
357 "(skipping) :%s\n",dirname, strerror(error));
358 continue;
359 }
360 while( (status = readdir_r(dir,&entry,&result)) == 0 ){
361 if (result == NULL){ /* last entry */
362 closedir(dir);
363 break;
364 }
365
366 /* concatenate dir and file name to open it */
367 snprintf(config_file,PATH_MAX, "%s/%s",
368 dirname,entry.d_name);
369 status = stat(config_file, &stats);
370 if (status == -1){
371 error = errno;
372 dbg("Parse configuration Failed to stat file "
373 "'%s': %s (skipping)\n", config_file,
374 strerror(error));
375 }
376 if (S_ISREG(stats.st_mode)){
377 dbg("Parsing file %s",config_file);
378 yyin = fopen(config_file, "r");
379
380 if (yyin == NULL) {
381 dbg("Can not open config file:"
382 " %d.\n", errno);
383 }
384 yyparse();
385 dbg("Done.");
386 fclose(yyin);
387 }
388 }
389 }
390 dbg("Parsing configuration directories done... ");
391
392 }
393
394 /*===========================================================================*
395 * cleanup *
396 *===========================================================================*/
cleanup()397 static void cleanup() {
398 struct devmand_driver_instance *inst;
399 /* destroy fifo */
400 dbg("cleaning up... ");
401 /* quit all running drivers */
402 LIST_FOREACH(inst, &instances, list) {
403 dbg("stopping driver %s", inst->label);
404 if(inst->drv->downscript) {
405 run_downscript (inst);
406 }
407 stop_driver(inst);
408 }
409 unlink("/var/run/devmand.pid");
410 }
411
sig_int(int sig)412 static void sig_int(int sig) {
413 dbg("devman: Received SIGINT... cleaning up.");
414 _run = 0;
415 }
416
417 /*===========================================================================*
418 * create_pid_file *
419 *===========================================================================*/
create_pid_file()420 void create_pid_file()
421 {
422 FILE *fd;
423
424 fd = fopen("/var/run/devmand.pid", "r");
425 if(fd) {
426 fprintf(stderr, "devmand: /var/run/devmand.pid exists... "
427 "another devmand running?\n");
428 fclose(fd);
429 exit(1);
430 } else {
431 fd = fopen("/var/run/devmand.pid","w");
432 fprintf(fd, "%d", getpid());
433 fclose(fd);
434 }
435 }
436
437 /*===========================================================================*
438 * main *
439 *===========================================================================*/
main(int argc,char * argv[])440 int main(int argc, char *argv[])
441 {
442 int opt, optindex;
443 struct devmand_usb_driver *driver;
444
445
446 /* get command line arguments */
447 while ((opt = getopt_long(argc, argv, "d:p:vxh?", options, &optindex))
448 != -1) {
449 switch (opt) {
450 case 'd':/* config directory */
451 if (args.config_dir_count >= MAX_CONFIG_DIRS){
452 fprintf(stderr,"Parse arguments: Maximum"
453 " of %i configuration directories"
454 " reached skipping directory '%s'\n"
455 , MAX_CONFIG_DIRS, optarg);
456 break;
457 }
458 args.config_dirs[args.config_dir_count] = optarg;
459 args.config_dir_count++;
460 break;
461 case 'p': /* sysfs path */
462 args.path = optarg;
463 break;
464 case 'v': /* verbose */
465 args.verbose = 1;
466 break;
467 case 'x': /* check config */
468 args.check_config = 1;
469 break;
470 case 'h': /* help */
471 case '?': /* help */
472 default:
473 display_usage(argv[0]);
474 return 0;
475 }
476 }
477
478
479 /* is path set? */
480 if (args.path == NULL) {
481 args.path = "/sys/";
482 }
483
484 /* is the configuration directory set? */
485 if (args.config_dir_count == 0) {
486 dbg("Using default configuration directory");
487 args.config_dirs[0] = "/etc/devmand";
488 args.config_dir_count = 1;
489 }
490
491 /* If we only check the configuration run and exit imediately */
492 if (args.check_config == 1){
493 fprintf(stdout, "Only parsing configuration\n");
494 parse_config();
495 exit(0);
496 }
497
498 create_pid_file();
499
500 parse_config();
501 LIST_FOREACH(driver, &drivers, list) {
502 if (driver->upscript) {
503 run_cleanscript(driver);
504 }
505 }
506
507 signal(SIGINT, sig_int);
508
509 main_loop();
510
511 cleanup();
512
513 return 0;
514 }
515
516 /*===========================================================================*
517 * determine_type *
518 *===========================================================================*/
determine_type(char * path)519 static enum dev_type determine_type (char *path)
520 {
521 FILE * fd;
522 char *mypath;
523 char buf[256];
524 int res;
525
526 mypath = (char *) calloc(1, strlen(path)+strlen(DEVMAN_TYPE_NAME)+1);
527
528 if (mypath == NULL) {
529 fprintf(stderr, "ERROR: out of mem\n");
530 cleanup();
531 exit(1);
532 }
533
534 strcat(mypath, path);
535 strcat(mypath, DEVMAN_TYPE_NAME);
536
537 fd = fopen(mypath, "r");
538 free(mypath);
539
540 if (fd == NULL) {
541 fprintf(stderr, "WARN: could not open %s\n", mypath);
542 return DEV_TYPE_UNKOWN;
543 }
544
545 res = fscanf(fd , "%255s\n", buf);
546 fclose(fd);
547
548 if (res != 1) {
549 fprintf(stderr, "WARN: could not parse %s\n", mypath);
550 return DEV_TYPE_UNKOWN;
551 }
552
553 if (strcmp(buf, "USB_DEV") == 0) {
554 return DEV_TYPE_USB_DEVICE;
555 } else if (strcmp(buf, "USB_INTF") == 0) {
556 return DEV_TYPE_USB_INTF;
557 }
558
559 return DEV_TYPE_UNKOWN;
560 }
561
562 /*===========================================================================*
563 * read_hex_uint *
564 *===========================================================================*/
read_hex_uint(char * base_path,char * name,unsigned int * val)565 static int read_hex_uint(char *base_path, char *name, unsigned int* val )
566 {
567 char my_path[PATH_LEN];
568 FILE *fd;
569 memset(my_path,0,PATH_LEN);
570 int ret = 0;
571
572 strcat(my_path, base_path);
573 strcat(my_path, name);
574
575 fd = fopen(my_path, "r");
576
577 if (fd == NULL) {
578 fprintf(stderr, "WARN: could not open %s\n", my_path);
579 return EEXIST;
580 } else if (fscanf(fd, "0x%x\n", val ) != 1) {
581 fprintf(stderr, "WARN: could not parse %s\n", my_path);
582 ret = EINVAL;
583 }
584 fclose(fd);
585
586 return ret;
587 }
588
589 /*===========================================================================*
590 * get_major *
591 *===========================================================================*/
get_major()592 static int get_major() {
593 int i, ret = args.major_offset;
594
595 for (i=0; i < 16; i++) {
596 int j;
597 for (j = 0; j < 8; j++ ) {
598 if ((major_bitmap[i] & (1 << j))) {
599 major_bitmap[i] &= !(1 << j);
600 return ret;
601 }
602 ret++;
603 }
604 }
605 return INVAL_MAJOR;
606 }
607
608 /*===========================================================================*
609 * put_major *
610 *===========================================================================*/
put_major(int major)611 static void put_major(int major) {
612 int i;
613 major -= args.major_offset;
614 assert(major >= 0);
615
616 for (i=0; i < 16; i++) {
617 int j;
618 for (j = 0; j < 8; j++ ) {
619 if (major==0) {
620 assert(!(major_bitmap[i] & (1 <<j)));
621 major_bitmap[i] |= (1 << j);
622 return;
623 }
624 major--;
625 }
626 }
627 }
628
629 /*===========================================================================*
630 * generate_usb_device_id *
631 *===========================================================================*/
632 static struct usb_device_id *
generate_usb_device_id(char * path,int is_interface)633 generate_usb_device_id(char * path, int is_interface)
634 {
635 struct usb_device_id *ret;
636 int res;
637 unsigned int val;
638
639 ret = (struct usb_device_id *)
640 calloc(1,sizeof (struct usb_device_id));
641
642 if (is_interface) {
643
644 res = read_hex_uint(path, "../idVendor", &val);
645 if (res) goto err;
646 ret->idVendor = val;
647
648 res = read_hex_uint(path, "../idProduct", &val);
649 if (res) goto err;
650 ret->idProduct = val;
651 #if 0
652 res = read_hex_uint(path, "../bcdDevice", &val);
653 if (res) goto err;
654 ret->bcdDevice = val;
655 #endif
656 res = read_hex_uint(path, "../bDeviceClass", &val);
657 if (res) goto err;
658 ret->bDeviceClass = val;
659
660 res = read_hex_uint(path, "../bDeviceSubClass", &val);
661 if (res) goto err;
662 ret->bDeviceSubClass = val;
663
664 res = read_hex_uint(path, "../bDeviceProtocol", &val);
665 if (res) goto err;
666 ret->bDeviceProtocol = val;
667
668 res = read_hex_uint(path, "/bInterfaceClass", &val);
669 if (res) goto err;
670 ret->bInterfaceClass = val;
671
672 res = read_hex_uint(path, "/bInterfaceSubClass", &val);
673 if (res) goto err;
674 ret->bInterfaceSubClass = val;
675
676 res = read_hex_uint(path, "/bInterfaceProtocol", &val);
677 if (res) goto err;
678 ret->bInterfaceProtocol = val;
679 }
680
681 return ret;
682
683 err:
684 free(ret);
685 return NULL;
686 }
687
688 /*===========================================================================*
689 * usb_intf_add_even *
690 *===========================================================================*/
usb_intf_add_event(char * path,int dev_id)691 static void usb_intf_add_event(char *path, int dev_id)
692 {
693 struct usb_device_id *id;
694 struct devmand_usb_driver *drv;
695 struct devmand_driver_instance *drv_inst;
696 int major, ret;
697
698 /* generate usb_match_id */
699 id = generate_usb_device_id(path,TRUE);
700 if (id == NULL) {
701 fprintf(stderr, "WARN: could not create usb_device id...\n"
702 " ommiting event\n");
703 free(id);
704 return;
705 }
706
707 /* find suitable driver */
708 drv = match_usb_driver(id);
709 free (id);
710
711 if (drv == NULL) {
712 dbg("INFO: could not find a suitable driver for %s", path);
713 return;
714 }
715
716 /* create instance */
717 drv_inst = (struct devmand_driver_instance *)
718 calloc(1,sizeof(struct devmand_driver_instance));
719
720 if (drv_inst == NULL) {
721 fprintf(stderr, "ERROR: out of memory");
722 return; /* maybe better quit here. */
723 }
724
725
726 /* allocate inode number, if device files needed */
727 major = get_major();
728 if (major == INVAL_MAJOR) {
729 fprintf(stderr, "WARN: ran out of major numbers\n"
730 " cannot start driver %s for %s\n",
731 drv->name, path);
732 return;
733 }
734
735 drv_inst->major = major;
736 drv_inst->drv = drv;
737 drv_inst->dev_id = dev_id;
738
739
740 /* start driver (invoke minix-service) */
741 start_driver(drv_inst);
742
743 /*
744 * run the up action
745 *
746 * An up action can be any executable. Before running it devmand
747 * will set certain environment variables so the script can configure
748 * the device (or generate device files, etc). See up_action() for that.
749 */
750 if (drv->upscript) {
751 ret = run_upscript(drv_inst);
752 if (ret) {
753 stop_driver(drv_inst);
754 fprintf(stderr, "devmand: warning, could not run up_action\n");
755 free(drv_inst);
756 return;
757 }
758 }
759
760 LIST_INSERT_HEAD(&instances,drv_inst,list);
761 }
762
763 /*===========================================================================*
764 * usb_intf_remove_event *
765 *===========================================================================*/
usb_intf_remove_event(char * path,int dev_id)766 static void usb_intf_remove_event(char *path, int dev_id)
767 {
768 struct devmand_driver_instance *inst;
769 struct devmand_usb_driver *drv;
770 int ret;
771
772 /* find the driver instance */
773 inst = find_instance(dev_id);
774
775 if (inst == NULL) {
776 dbg("No driver running for id: %d", dev_id);
777 return;
778 }
779 drv = inst->drv;
780
781 /* run the down script */
782 if (drv->downscript) {
783 ret = run_downscript(inst);
784 if (ret) {
785 fprintf(stderr, "WARN: error running up_action");
786 }
787 }
788
789 /* stop the driver */
790 stop_driver(inst);
791
792 /* free major */
793 put_major(inst->major);
794
795 /* free instance */
796 LIST_REMOVE(inst,list);
797 free(inst);
798 }
799
800 /*===========================================================================*
801 * handle_event *
802 *===========================================================================*/
handle_event(char * event)803 static void handle_event(char *event)
804 {
805 enum dev_type type;
806 char path[PATH_LEN];
807 char tmp_path[PATH_LEN];
808 int dev_id, res;
809
810 path[0]=0;
811
812 if (strncmp("ADD ", event, 4) == 0) {
813
814 /* read data from event */
815 res = sscanf(event, "ADD %s 0x%x", tmp_path, &dev_id);
816
817 if (res != 2) {
818 fprintf(stderr, "WARN: could not parse event: %s", event);
819 fprintf(stderr, "WARN: omitting event: %s", event);
820 }
821
822 strcpy(path, args.path);
823 strcat(path, tmp_path);
824
825 /* what kind of device is added? */
826 type = determine_type(path);
827
828 switch (type) {
829 case DEV_TYPE_USB_DEVICE:
830 dbg("USB device added: ommited....");
831 /* ommit usb devices for now */
832 break;
833 case DEV_TYPE_USB_INTF:
834 dbg("USB interface added: (%s, devid: = %d)",path, dev_id);
835 usb_intf_add_event(path, dev_id);
836 return;
837 default:
838 dbg("default");
839 fprintf(stderr, "WARN: ommiting event\n");
840 }
841 } else if (strncmp("REMOVE ", event, 7) == 0) {
842
843 /* read data from event */
844 res = sscanf(event,"REMOVE %s 0x%x", tmp_path, &dev_id);
845
846 if (res != 2) {
847 fprintf(stderr, "WARN: could not parse event: %s", event);
848 fprintf(stderr, "WARN: omitting event: %s", event);
849 }
850
851 usb_intf_remove_event(path, dev_id);
852
853 #if 0
854 strcpy(path, args.path);
855 strcat(path, tmp_path);
856
857 /* what kind of device is added? */
858 type = determine_type(path);
859
860 switch (type) {
861 case DEV_TYPE_USB_DEVICE:
862 /* ommit usb devices for now */
863 break;
864 case DEV_TYPE_USB_INTF:
865 usb_intf_remove_event(path, dev_id);
866 return;
867 default:
868 fprintf(stderr, "WARN: ommiting event\n");
869 }
870 #endif
871
872 }
873 }
874
875 /*===========================================================================*
876 * main_loop *
877 *===========================================================================*/
main_loop()878 static void main_loop()
879 {
880 char ev_path[128];
881 char buf[256];
882 int len;
883 FILE* fd;
884 len = strlen(args.path);
885
886 /* init major numbers */
887
888 memset(&major_bitmap, 0xff, 16);
889
890 if (len > 128 - 7 /*len of "events" */) {
891 fprintf(stderr, "pathname to long\n");
892 cleanup();
893 exit(1);
894 }
895
896 strcpy(ev_path, args.path);
897 strcat(ev_path, "events");
898
899
900 while (_run) {
901
902 char *res;
903
904 fd = fopen(ev_path, "r");
905 if (fd == NULL) {
906 /*
907 * ENFILE is a temporary failure, often caused by
908 * running the test set. Don't die from that..
909 */
910 if (errno == ENFILE) {
911 usleep(50000);
912 continue;
913 }
914
915 fprintf(stderr,"devmand error: could not open event "
916 "file %s bailing out\n", ev_path);
917 cleanup();
918 exit(1);
919 }
920
921 res = fgets(buf, 256, fd);
922 fclose(fd);
923
924 if (res == NULL) {
925 usleep(50000);
926 continue;
927 }
928 dbg("handle_event: %s", buf);
929 handle_event(buf);
930 }
931 }
932
933 /*===========================================================================*
934 * display_usage *
935 *===========================================================================*/
display_usage(const char * name)936 static void display_usage(const char *name)
937 {
938 printf("Usage: %s [{-p|--pathname} PATH_TO_SYS}"
939 " [{-d|--config-dir} CONFIG_DIR] [-v|--verbose]"
940 " [[x||--check-config]\n", name);
941 }
942
943