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