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