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