USB -> PS/2

Walter C. Pelissero walter at pelissero.de
Sun Aug 31 09:12:12 PDT 2003


Just noticed that the patch to usbd.c I proposed yesterday shows an
undesirable behaviour.  That is, usbd executes the actions in
usbd.conf of all matching devices, which is not exactly what I meant
to do.  In fact, usbd should execute for every device name the "best"
matching action in usbd.conf.

Supposed usbd.conf is sorted in a way that the most specific entries
precede the less specific ones, the following patch should do the
trick.

Cheers,

-- 
walter pelissero
http://www.pelissero.de



--- 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);


More information about the freebsd-questions mailing list