Skip site navigation (1)Skip section navigation (2)
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>