Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Jun 2011 21:27:33 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r223518 - head/tools/tools/bus_autoconf
Message-ID:  <201106242127.p5OLRXZa070898@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri Jun 24 21:27:33 2011
New Revision: 223518
URL: http://svn.freebsd.org/changeset/base/223518

Log:
  - We need to sort all USB device ID's together. Else the matching order will
  be wrong. This is required because devd only executes one entry.
  
  MFC after:	14 days

Modified:
  head/tools/tools/bus_autoconf/bus_autoconf.c
  head/tools/tools/bus_autoconf/bus_autoconf.h
  head/tools/tools/bus_autoconf/bus_autoconf.sh

Modified: head/tools/tools/bus_autoconf/bus_autoconf.c
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.c	Fri Jun 24 20:23:50 2011	(r223517)
+++ head/tools/tools/bus_autoconf/bus_autoconf.c	Fri Jun 24 21:27:33 2011	(r223518)
@@ -43,15 +43,67 @@
 
 static char *type;
 static char *file_name;
-static char *module;
 static const char *mode;
 
+struct usb_info;
+static void usb_dump_sub(struct usb_device_id *, struct usb_info *);
+
+/*
+ * To ensure that the correct USB driver is loaded, the driver having
+ * the most information about the device must be probed first. Then
+ * more generic drivers shall be probed.
+ */
 static int
 usb_compare(const void *_a, const void *_b)
 {
 	const struct usb_device_id *a = _a;
 	const struct usb_device_id *b = _b;
 
+	/* vendor matches first */
+
+	if (a->match_flag_vendor > b->match_flag_vendor)
+		return (-1);
+	if (a->match_flag_vendor < b->match_flag_vendor)
+		return (1);
+
+	/* product matches first */
+
+	if (a->match_flag_product > b->match_flag_product)
+		return (-1);
+	if (a->match_flag_product < b->match_flag_product)
+		return (1);
+
+	/* device class matches first */
+
+	if (a->match_flag_dev_class > b->match_flag_dev_class)
+		return (-1);
+	if (a->match_flag_dev_class < b->match_flag_dev_class)
+		return (1);
+
+	if (a->match_flag_dev_subclass > b->match_flag_dev_subclass)
+		return (-1);
+	if (a->match_flag_dev_subclass < b->match_flag_dev_subclass)
+		return (1);
+
+	/* interface class matches first */
+
+	if (a->match_flag_int_class > b->match_flag_int_class)
+		return (-1);
+	if (a->match_flag_int_class < b->match_flag_int_class)
+		return (1);
+
+	if (a->match_flag_int_subclass > b->match_flag_int_subclass)
+		return (-1);
+	if (a->match_flag_int_subclass < b->match_flag_int_subclass)
+		return (1);
+
+	if (a->match_flag_int_protocol > b->match_flag_int_protocol)
+		return (-1);
+	if (a->match_flag_int_protocol < b->match_flag_int_protocol)
+		return (1);
+
+	/* then sort according to value */
+
 	if (a->idVendor > b->idVendor)
 		return (1);
 	if (a->idVendor < b->idVendor)
@@ -85,7 +137,9 @@ usb_compare(const void *_a, const void *
 	if (a->bInterfaceProtocol < b->bInterfaceProtocol)
 		return (-1);
 
-	return (0);
+	/* in the end sort by module name */
+
+	return (strcmp(a->module_name, b->module_name));
 }
 
 static void
@@ -105,39 +159,55 @@ static void
 usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo)
 {
 #if USB_HAVE_COMPAT_LINUX
-	if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
-		id->match_flag_vendor = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
-		id->match_flag_product = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
-		id->match_flag_dev_lo = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
-		id->match_flag_dev_hi = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
-		id->match_flag_dev_class = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
-		id->match_flag_dev_subclass = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
-		id->match_flag_dev_protocol = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
-		id->match_flag_int_class = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
-		id->match_flag_int_subclass = 1;
-	if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
-		id->match_flag_int_protocol = 1;
+	if (id->match_flags != 0) {
+		if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
+			id->match_flag_vendor = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
+			id->match_flag_product = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
+			id->match_flag_dev_lo = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
+			id->match_flag_dev_hi = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
+			id->match_flag_dev_class = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+			id->match_flag_dev_subclass = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+			id->match_flag_dev_protocol = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
+			id->match_flag_int_class = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
+			id->match_flag_int_subclass = 1;
+		if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+			id->match_flag_int_protocol = 1;
+		id->match_flags = 0;
+	}
 #endif
+	if (pinfo != NULL) {
 
-	pinfo->is_iface = id->match_flag_int_class |
-	    id->match_flag_int_protocol |
-	    id->match_flag_int_subclass;
+		pinfo->is_iface = id->match_flag_int_class |
+		    id->match_flag_int_protocol |
+		    id->match_flag_int_subclass;
 
-	pinfo->is_dev = id->match_flag_dev_class |
-	    id->match_flag_dev_subclass;
+		pinfo->is_dev = id->match_flag_dev_class |
+		    id->match_flag_dev_subclass;
 
-	pinfo->is_vp = id->match_flag_vendor |
-	    id->match_flag_product;
+		pinfo->is_vp = id->match_flag_vendor |
+		    id->match_flag_product;
 
-	pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface;
+		pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface;
+	}
+}
+
+static char *
+usb_trim(char *ptr)
+{
+	char *end;
+
+	end = strchr(ptr, ' ');
+	if (end)
+		*end = 0;
+	return (ptr);
 }
 
 static uint32_t
@@ -149,7 +219,7 @@ usb_dump(struct usb_device_id *id, uint3
 	usb_dump_sub(id, &info);
 
 	if (info.is_any) {
-		printf("nomatch 10 {\n"
+		printf("nomatch 32 {\n"
 		    "	match \"bus\" \"uhub[0-9]+\";\n"
 		    "	match \"mode\" \"%s\";\n", mode);
 	} else {
@@ -212,7 +282,7 @@ usb_dump(struct usb_device_id *id, uint3
 		    id->bInterfaceProtocol);
 	}
 	printf("	action \"kldload %s\";\n"
-	    "};\n\n", module);
+	    "};\n\n", usb_trim(id->module_name));
 
 	return (n);
 }
@@ -239,12 +309,21 @@ usb_parse_and_dump(int f, off_t size)
 	}
 	nid = size / sizeof(*id);
 
+	for (x = 0; x != nid; x++) {
+		/* make sure flag bits are correct */
+		usb_dump_sub(id + x, NULL);
+		/* zero terminate string */
+		id[x].module_name[sizeof(id[0].module_name) - 1] = 0;
+	}
+
 	usb_sort(id, nid);
 
 	for (x = 0; x != nid;)
 		x += usb_dump(id + x, nid - x);
 
 	free(id);
+
+	printf("# %d %s entries processed\n\n", (int)nid, type);
 }
 
 static void
@@ -253,7 +332,6 @@ usage(void)
 	fprintf(stderr,
 	    "bus_autoconf - devd config file generator\n"
 	    "	-i <input_binary>\n"
-	    "	-m <module_name>\n"
 	    "	-t <structure_type>\n"
 	    "	-h show usage\n"
 	);
@@ -263,7 +341,7 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-	const char *params = "i:m:ht:";
+	const char *params = "i:ht:";
 	int c;
 	int f;
 	off_t off;
@@ -276,16 +354,13 @@ main(int argc, char **argv)
 		case 't':
 			type = optarg;
 			break;
-		case 'm':
-			module = optarg;
-			break;
 		default:
 			usage();
 			break;
 		}
 	}
 
-	if (type == NULL || module == NULL || file_name == NULL)
+	if (type == NULL || file_name == NULL)
 		usage();
 
 	f = open(file_name, O_RDONLY);

Modified: head/tools/tools/bus_autoconf/bus_autoconf.h
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.h	Fri Jun 24 20:23:50 2011	(r223517)
+++ head/tools/tools/bus_autoconf/bus_autoconf.h	Fri Jun 24 21:27:33 2011	(r223518)
@@ -33,6 +33,9 @@
 
 struct usb_device_id {
 
+	/* Internal field */
+	char	module_name[32];
+
 	/* Hook for driver specific information */
 	unsigned long driver_info;
 

Modified: head/tools/tools/bus_autoconf/bus_autoconf.sh
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.sh	Fri Jun 24 20:23:50 2011	(r223517)
+++ head/tools/tools/bus_autoconf/bus_autoconf.sh	Fri Jun 24 21:27:33 2011	(r223518)
@@ -29,6 +29,30 @@
 OS=FreeBSD
 DOLLAR=$
 
+cleanup()
+{
+   # Cleanup
+   rm -f usb_dual.ids
+   rm -f usb_host.ids
+   rm -f usb_device.ids
+}
+
+usb_format()
+{
+    [ -f ${1} ] || return
+
+    # Split into one and one record
+    split -b 32 ${1} ${1}.
+
+    # Prefix each record by the module name
+    for G in $(ls ${1}.*)
+    do
+      printf "%-32s" ${3} >> ${2}
+      cat ${G} >> ${2}
+      rm -f ${G}
+    done
+}
+
 cat <<EOF
 #
 # ${DOLLAR}${OS}${DOLLAR}
@@ -39,26 +63,33 @@ cat <<EOF
 
 EOF
 
-for F in $(echo $* | sort)
+# Cleanup
+cleanup
+
+for F in $*
 do
+
+# Get module basename
 H=$(basename ${F} | sed -e "s/\.ko//g")
 
 # USB Host
-objcopy -j usb_host_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_host -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_host_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_host.ids ${H}
+
 # USB Device
-objcopy -j usb_device_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_device -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_device_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_device.ids ${H}
+
 # USB Dual mode
-objcopy -j usb_dual_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_dual -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_dual_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_dual.ids ${H}
+
 done
+
+# Dump all data
+[ -f usb_dual.ids ] && bus_autoconf -i usb_dual.ids -t usb_dual
+[ -f usb_host.ids ] && bus_autoconf -i usb_host.ids -t usb_host
+[ -f usb_device.ids ] && bus_autoconf -i usb_device.ids -t usb_device
+
+# Cleanup
+cleanup



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106242127.p5OLRXZa070898>