Date: Fri, 26 Sep 2003 18:47:30 +0200 (CEST) From: "Walter C. Pelissero" <walter@pelissero.de> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/57255: usbd and multi-function devices Message-ID: <200309261647.h8QGlU7E075829@hyde.home.loc> Resent-Message-ID: <200309261710.h8QHAEeW042196@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 57255 >Category: bin >Synopsis: usbd and multi-function devices >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Sep 26 10:10:14 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Walter C. Pelissero >Release: FreeBSD 4.9-PRERELEASE i386 >Organization: >Environment: System: FreeBSD hyde.home.loc 4.9-PRERELEASE FreeBSD 4.9-PRERELEASE #3: Sun Sep 21 21:01:59 CEST 2003 root@hyde.home.loc:/.amd_mnt/daemon/host/usr/warehouse/src/sys/compile/PCG-XG9 i386 >Description: Usbd, as it is, lacks proper support for USB devices implementing multiple functionalities (docking stations and such). If the usbd behaviour was amended to execute all the entries in usbd.conf that match a certain device it would simplify things a bit. An example. If an USB device provides keyboard and mouse interface, you are now required to write a specific entry in usbd.conf so that on matching of that particular manufacturer and product id, usbd should execute two actions to enable keyboard and mouse. If usbd was made able to execute for all the device types implemented the corresponding entry in usbd.conf, nothing would need to be added to usbd.conf (provided actions matching ukbd and ums are already there). This approach has also the advantage of making the name of the device available to the actions, which is not possible in the case of a single entry serving multiple devices. That is, if you match manufacturer and product id, what is the name of the mouse device to use in the action? >How-To-Repeat: >Fix: The following patch will change the behaviour of usbd so that if an entry matching manufacture/product is not available, all the entries matching the implemented devices will be executed. The old behaviour is retained with the command line -s flag. --- usbd.c.orig Sun Aug 31 17:24:14 2003 +++ usbd.c Sun Aug 31 17:08:19 2003 @@ -102,6 +102,7 @@ int lineno; int verbose = 0; /* print message on what it is doing */ +int single_action = 0; typedef struct event_name_s { int type; /* event number (from usb.h) */ @@ -204,8 +205,7 @@ void print_event __P((struct usb_event *event)); void print_action __P((action_t *action, int i)); void print_actions __P((void)); -int find_action __P((struct usb_device_info *devinfo, - action_match_t *action_match)); +void execute_command __P((char *cmd)); void @@ -674,37 +674,19 @@ int -match_devname(action_t *action, struct usb_device_info *devinfo) +match_devname(regex_t *regex, char *name) { - int i; - regmatch_t match; - int error; - - for (i = 0; i < USB_MAX_DEVNAMES; i++) { - if (devinfo->udi_devnames[i][0] == '\0') - break; - - error = regexec(&action->devname_regex, devinfo->udi_devnames[i], - 1, &match, 0); - if (error == 0) { - if (verbose >= 2) - printf("%s: %s matches %s\n", __progname, - devinfo->udi_devnames[i], action->devname); - return(i); - } - } - - return(-1); + return regexec(regex, name, 0, 0, 0) == 0; } - -int -find_action(struct usb_device_info *devinfo, action_match_t *action_match) +void +execute_actions (struct usb_device_info *devinfo, int event_type) { action_t *action; char *devname = NULL; - int match = -1; + int i; + for (i = 0; i < USB_MAX_DEVNAMES && devinfo->udi_devnames[i][0] != '\0'; i++) { STAILQ_FOREACH(action, &actions, next) { if ((action->vendor == WILDCARD_INT || action->vendor == devinfo->udi_vendorNo) && @@ -719,15 +701,15 @@ (action->protocol == WILDCARD_INT || action->protocol == devinfo->udi_protocol) && (action->devname == WILDCARD_STRING || - (match = match_devname(action, devinfo)) != -1)) { - /* found match !*/ - + match_devname(&action->devname_regex, devinfo->udi_devnames[i]))) { + if (verbose >= 2) + print_action(action, 0); /* Find a devname for pretty printing. Either * the matched one or otherwise, if there is only * one devname for that device, use that. */ - if (match >= 0) - devname = devinfo->udi_devnames[match]; + if (action->devname != WILDCARD_STRING) + devname = devinfo->udi_devnames[i]; else if (devinfo->udi_devnames[0][0] != '\0' && devinfo->udi_devnames[1][0] == '\0') /* if we have exactly 1 device name */ @@ -742,16 +724,37 @@ printf("\n"); } - action_match->action = action; - action_match->devname = devname; + if (devname) { + int error; + if (verbose >= 2) + printf("%s: Setting DEVNAME='%s'\n", + __progname, devname); + error = setenv("DEVNAME", devname, 1); + if (error) + fprintf(stderr, "%s: setenv(\"DEVNAME\", + \"%s\",1) failed, %s\n", + __progname, devname, strerror(errno)); + } - return(1); + if (USB_EVENT_IS_ATTACH(event_type) && action->attach) + execute_command(action->attach); + if (USB_EVENT_IS_DETACH(event_type) && action->detach) + execute_command(action->detach); + /* We are done if either we are + * running in single action mode or we + * didn't match the device name, that + * is, we have a catch-all entry for + * the particular USB device. */ + if (single_action || action->devname == WILDCARD_STRING) + return; + /* get on to the next device name */ + break; + } } } - - return(0); } + void execute_command(char *cmd) { @@ -881,30 +884,7 @@ break; case USB_EVENT_DEVICE_ATTACH: case USB_EVENT_DEVICE_DETACH: - if (find_action(&event.u.ue_device, &action_match) == 0) - /* nothing found */ - break; - - if (verbose >= 2) - print_action(action_match.action, 0); - - if (action_match.devname) { - if (verbose >= 2) - printf("%s: Setting DEVNAME='%s'\n", - __progname, action_match.devname); - - error = setenv("DEVNAME", action_match.devname, 1); - if (error) - fprintf(stderr, "%s: setenv(\"DEVNAME\", \"%s\",1) failed, %s\n", - __progname, action_match.devname, strerror(errno)); - } - - if (USB_EVENT_IS_ATTACH(event.ue_type) && - action_match.action->attach) - execute_command(action_match.action->attach); - if (USB_EVENT_IS_DETACH(event.ue_type) && - action_match.action->detach) - execute_command(action_match.action->detach); + execute_actions(&event.u.ue_device, event.ue_type); break; case USB_EVENT_DRIVER_ATTACH: if (verbose) @@ -944,7 +924,7 @@ } } - while ((ch = getopt(argc, argv, "c:def:nt:v")) != -1) { + while ((ch = getopt(argc, argv, "c:def:nst:v")) != -1) { switch(ch) { case 'c': configfile = strdup(optarg); @@ -965,6 +945,9 @@ break; case 'n': handle_events = 0; + break; + case 's': + single_action = 1; break; case 't': itimeout = atoi(optarg); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309261647.h8QGlU7E075829>