bin/57255: usbd and multi-function devices
Walter C. Pelissero
walter at pelissero.de
Fri Sep 26 10:10:23 PDT 2003
>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 at 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:
More information about the freebsd-bugs
mailing list