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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 * 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 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* 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 *===========================================================================*/ 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 * 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 *===========================================================================*/ 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 *===========================================================================*/ 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 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 * 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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 *===========================================================================*/ 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