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