Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Jun 2011 13:44:05 +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: r223534 - head/tools/tools/bus_autoconf
Message-ID:  <201106251344.p5PDi5BV008829@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Sat Jun 25 13:44:05 2011
New Revision: 223534
URL: http://svn.freebsd.org/changeset/base/223534

Log:
  - Improve bus_autoconf tool.
  - Implement simple and generic language which can
  be used to describe any kind of device ID structures.
  - Fix endian issues.
  - Add an example format file.
  
  Suggested by:	imp @
  MFC after:	14 days

Added:
  head/tools/tools/bus_autoconf/bus_autoconf_format_example.txt   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_load_file.c   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_load_file.h   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_sections.c   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_sections.h   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_usb.c   (contents, props changed)
  head/tools/tools/bus_autoconf/bus_usb.h   (contents, props changed)
Modified:
  head/tools/tools/bus_autoconf/Makefile
  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/Makefile
==============================================================================
--- head/tools/tools/bus_autoconf/Makefile	Sat Jun 25 12:37:06 2011	(r223533)
+++ head/tools/tools/bus_autoconf/Makefile	Sat Jun 25 13:44:05 2011	(r223534)
@@ -36,7 +36,10 @@ PROG=	bus_autoconf
 MAN=
 BINDIR?= /usr/local/bin
 
-SRCS=	bus_autoconf.c
+SRCS+=	bus_autoconf.c
+SRCS+=	bus_load_file.c
+SRCS+=	bus_sections.c
+SRCS+=	bus_usb.c
 
 WARNS=	6
 

Modified: head/tools/tools/bus_autoconf/bus_autoconf.c
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.c	Sat Jun 25 12:37:06 2011	(r223533)
+++ head/tools/tools/bus_autoconf/bus_autoconf.c	Sat Jun 25 13:44:05 2011	(r223534)
@@ -33,306 +33,23 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <sysexits.h>
-#include <err.h>
-#include <fcntl.h>
 #include <string.h>
+#include <err.h>
+#include <sysexits.h>
+#include <unistd.h>
 
 #include "bus_autoconf.h"
-
-static char *type;
-static char *file_name;
-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)
-		return (-1);
-	if (a->idProduct > b->idProduct)
-		return (1);
-	if (a->idProduct < b->idProduct)
-		return (-1);
-	if (a->bDeviceClass > b->bDeviceClass)
-		return (1);
-	if (a->bDeviceClass < b->bDeviceClass)
-		return (-1);
-	if (a->bDeviceSubClass > b->bDeviceSubClass)
-		return (1);
-	if (a->bDeviceSubClass < b->bDeviceSubClass)
-		return (-1);
-	if (a->bDeviceProtocol > b->bDeviceProtocol)
-		return (1);
-	if (a->bDeviceProtocol < b->bDeviceProtocol)
-		return (-1);
-	if (a->bInterfaceClass > b->bInterfaceClass)
-		return (1);
-	if (a->bInterfaceClass < b->bInterfaceClass)
-		return (-1);
-	if (a->bInterfaceSubClass > b->bInterfaceSubClass)
-		return (1);
-	if (a->bInterfaceSubClass < b->bInterfaceSubClass)
-		return (-1);
-	if (a->bInterfaceProtocol > b->bInterfaceProtocol)
-		return (1);
-	if (a->bInterfaceProtocol < b->bInterfaceProtocol)
-		return (-1);
-
-	/* in the end sort by module name */
-
-	return (strcmp(a->module_name, b->module_name));
-}
-
-static void
-usb_sort(struct usb_device_id *id, uint32_t nid)
-{
-	qsort(id, nid, sizeof(*id), &usb_compare);
-}
-
-struct usb_info {
-	uint8_t	is_iface;
-	uint8_t	is_any;
-	uint8_t	is_vp;
-	uint8_t	is_dev;
-};
-
-static void
-usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo)
-{
-#if USB_HAVE_COMPAT_LINUX
-	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_dev = id->match_flag_dev_class |
-		    id->match_flag_dev_subclass;
-
-		pinfo->is_vp = id->match_flag_vendor |
-		    id->match_flag_product;
-
-		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
-usb_dump(struct usb_device_id *id, uint32_t nid)
-{
-	uint32_t n = 1;
-	struct usb_info info;
-
-	usb_dump_sub(id, &info);
-
-	if (info.is_any) {
-		printf("nomatch 32 {\n"
-		    "	match \"bus\" \"uhub[0-9]+\";\n"
-		    "	match \"mode\" \"%s\";\n", mode);
-	} else {
-		return (n);
-	}
-
-	if (id->match_flag_vendor) {
-		printf("	match \"vendor\" \"0x%04x\";\n",
-		    id->idVendor);
-	}
-	if (id->match_flag_product) {
-		uint32_t x;
-
-		if (info.is_any == 1 && info.is_vp == 1) {
-			/* try to join similar entries */
-			while (n < nid) {
-				usb_dump_sub(id + n, &info);
-
-				if (info.is_any != 1 || info.is_vp != 1)
-					break;
-				if (id[n].idVendor != id[0].idVendor)
-					break;
-				n++;
-			}
-			/* restore infos */
-			usb_dump_sub(id, &info);
-		}
-		if (n == 1) {
-			printf("	match \"product\" \"0x%04x\";\n",
-			    id->idProduct);
-		} else {
-			printf("	match \"product\" \"(");
-
-			for (x = 0; x != n; x++) {
-				printf("0x%04x%s", id[x].idProduct,
-				    (x == (n - 1)) ? "" : "|");
-			}
-
-			printf(")\";\n");
-		}
-	}
-	if (id->match_flag_dev_class) {
-		printf("	match \"devclass\" \"0x%02x\";\n",
-		    id->bDeviceClass);
-	}
-	if (id->match_flag_dev_subclass) {
-		printf("	match \"devsubclass\" \"0x%02x\";\n",
-		    id->bDeviceSubClass);
-	}
-	if (id->match_flag_int_class) {
-		printf("	match \"intclass\" \"0x%02x\";\n",
-		    id->bInterfaceClass);
-	}
-	if (id->match_flag_int_subclass) {
-		printf("	match \"intsubclass\" \"0x%02x\";\n",
-		    id->bInterfaceSubClass);
-	}
-	if (id->match_flag_int_protocol) {
-		printf("	match \"intprotocol\" \"0x%02x\";\n",
-		    id->bInterfaceProtocol);
-	}
-	printf("	action \"kldload %s\";\n"
-	    "};\n\n", usb_trim(id->module_name));
-
-	return (n);
-}
-
-static void
-usb_parse_and_dump(int f, off_t size)
-{
-	struct usb_device_id *id;
-	uint32_t nid;
-	uint32_t x;
-
-	if (size % sizeof(struct usb_device_id)) {
-		errx(EX_NOINPUT, "Size is not divisible by %d",
-		    (int)sizeof(struct usb_device_id));
-	}
-	lseek(f, 0, SEEK_SET);
-
-	id = malloc(size);
-	if (id == NULL) {
-		errx(EX_SOFTWARE, "Out of memory");
-	}
-	if (read(f, id, size) != size) {
-		err(EX_NOINPUT, "Cannot read all data");
-	}
-	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);
-}
+#include "bus_sections.h"
+#include "bus_load_file.h"
+#include "bus_usb.h"
 
 static void
 usage(void)
 {
 	fprintf(stderr,
 	    "bus_autoconf - devd config file generator\n"
-	    "	-i <input_binary>\n"
-	    "	-t <structure_type>\n"
+	    "	-i <structure_type,module.ko>\n"
+	    "	-F <format_file>\n"
 	    "	-h show usage\n"
 	);
 	exit(EX_USAGE);
@@ -341,50 +58,68 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-	const char *params = "i:ht:";
+	const char *params = "i:F:h";
+	char *fname;
+	char *section;
+	char *module;
+	char *postfix;
+	uint8_t *ptr;
+	uint32_t len;
 	int c;
-	int f;
-	off_t off;
+	int any_opt = 0;
 
 	while ((c = getopt(argc, argv, params)) != -1) {
 		switch (c) {
 		case 'i':
-			file_name = optarg;
+			fname = optarg;
+			load_file(fname, &ptr, &len);
+
+			module = strchr(fname, ',');
+			if (module == NULL) {
+				errx(EX_USAGE, "Invalid input "
+				    "file name '%s'", fname);
+			}
+			/* split module and section */
+			*module++ = 0;
+
+			/* remove postfix */
+			postfix = strchr(module, '.');
+			if (postfix)
+				*postfix = 0;
+
+			/* get section name */
+			section = fname;
+
+			/* check section type */
+			if (strncmp(section, "usb_", 4) == 0)
+				usb_import_entries(section, module, ptr, len);
+			else
+				errx(EX_USAGE, "Invalid section '%s'", section);
+
+			free(ptr);
+
+			any_opt = 1;
 			break;
-		case 't':
-			type = optarg;
+
+		case 'F':
+			fname = optarg;
+			load_file(fname, &ptr, &len);
+			format_parse_entries(ptr, len);
+			free(ptr);
+
+			any_opt = 1;
 			break;
+
 		default:
 			usage();
 			break;
 		}
 	}
 
-	if (type == NULL || file_name == NULL)
+	if (any_opt == 0)
 		usage();
 
-	f = open(file_name, O_RDONLY);
-	if (f < 0)
-		err(EX_NOINPUT, "Cannot open file '%s'", file_name);
-
-	off = lseek(f, 0, SEEK_END);
-	if (off <= 0)
-		err(EX_NOINPUT, "Cannot seek to end of file");
-
-	if (strcmp(type, "usb_host") == 0) {
-		mode = "host";
-		usb_parse_and_dump(f, off);
-	} else if (strcmp(type, "usb_device") == 0) {
-		mode = "device";
-		usb_parse_and_dump(f, off);
-	} else if (strcmp(type, "usb_dual") == 0) {
-		mode = "(host|device)";
-		usb_parse_and_dump(f, off);
-	} else {
-		err(EX_USAGE, "Unsupported structure type: %s", type);
-	}
-
-	close(f);
+	usb_dump_entries();
 
 	return (0);
 }

Modified: head/tools/tools/bus_autoconf/bus_autoconf.h
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.h	Sat Jun 25 12:37:06 2011	(r223533)
+++ head/tools/tools/bus_autoconf/bus_autoconf.h	Sat Jun 25 13:44:05 2011	(r223534)
@@ -28,59 +28,4 @@
 #ifndef _BUS_AUTOCONF_H_
 #define	_BUS_AUTOCONF_H_
 
-/* Make sure we get the have compat linux definition. */
-#include <dev/usb/usb.h>
-
-struct usb_device_id {
-
-	/* Internal field */
-	char	module_name[32];
-
-	/* Hook for driver specific information */
-	unsigned long driver_info;
-
-	/* Used for product specific matches; the BCD range is inclusive */
-	uint16_t idVendor;
-	uint16_t idProduct;
-	uint16_t bcdDevice_lo;
-	uint16_t bcdDevice_hi;
-
-	/* Used for device class matches */
-	uint8_t	bDeviceClass;
-	uint8_t	bDeviceSubClass;
-	uint8_t	bDeviceProtocol;
-
-	/* Used for interface class matches */
-	uint8_t	bInterfaceClass;
-	uint8_t	bInterfaceSubClass;
-	uint8_t	bInterfaceProtocol;
-
-	/* Select which fields to match against */
-	uint8_t	match_flag_vendor:1;
-	uint8_t	match_flag_product:1;
-	uint8_t	match_flag_dev_lo:1;
-	uint8_t	match_flag_dev_hi:1;
-	uint8_t	match_flag_dev_class:1;
-	uint8_t	match_flag_dev_subclass:1;
-	uint8_t	match_flag_dev_protocol:1;
-	uint8_t	match_flag_int_class:1;
-	uint8_t	match_flag_int_subclass:1;
-	uint8_t	match_flag_int_protocol:1;
-
-#if USB_HAVE_COMPAT_LINUX
-	/* which fields to match against */
-	uint16_t match_flags;
-#define	USB_DEVICE_ID_MATCH_VENDOR              0x0001
-#define	USB_DEVICE_ID_MATCH_PRODUCT             0x0002
-#define	USB_DEVICE_ID_MATCH_DEV_LO              0x0004
-#define	USB_DEVICE_ID_MATCH_DEV_HI              0x0008
-#define	USB_DEVICE_ID_MATCH_DEV_CLASS           0x0010
-#define	USB_DEVICE_ID_MATCH_DEV_SUBCLASS        0x0020
-#define	USB_DEVICE_ID_MATCH_DEV_PROTOCOL        0x0040
-#define	USB_DEVICE_ID_MATCH_INT_CLASS           0x0080
-#define	USB_DEVICE_ID_MATCH_INT_SUBCLASS        0x0100
-#define	USB_DEVICE_ID_MATCH_INT_PROTOCOL        0x0200
-#endif
-};
-
 #endif					/* _BUS_AUTOCONF_H_ */

Modified: head/tools/tools/bus_autoconf/bus_autoconf.sh
==============================================================================
--- head/tools/tools/bus_autoconf/bus_autoconf.sh	Sat Jun 25 12:37:06 2011	(r223533)
+++ head/tools/tools/bus_autoconf/bus_autoconf.sh	Sat Jun 25 13:44:05 2011	(r223534)
@@ -29,30 +29,6 @@
 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}
@@ -63,33 +39,34 @@ cat <<EOF
 
 EOF
 
-# Cleanup
-cleanup
+rm -f bus_autoconf_format.bin
+rm -f bus_autoconf_args.txt
 
 for F in $*
 do
 
-# Get module basename
-H=$(basename ${F} | sed -e "s/\.ko//g")
+G=$(basename ${F})
 
-# USB Host
-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} temp.ids 2> /dev/null
-usb_format temp.ids usb_device.ids ${H}
+# Format information
+objcopy -j bus_autoconf_format -O binary ${F} temp.ids 2> /dev/null
+[ -f temp.ids ] && cat temp.ids >> bus_autoconf_format.bin
+
+# USB Host mode
+objcopy -j usb_host_id -O binary ${F} "usb_host_id,${G}" 2> /dev/null
+[ -f "usb_host_id,${G}" ] && (echo -n " -i usb_host_id,${G}" >> bus_autoconf_args.txt)
+
+# USB Device mode
+objcopy -j usb_device_id -O binary ${F} "usb_device_id,${G}" 2> /dev/null
+[ -f "usb_device_id,${G}" ] && (echo -n " -i usb_device_id,${G}" >> bus_autoconf_args.txt)
 
 # USB Dual mode
-objcopy -j usb_dual_id -O binary ${F} temp.ids 2> /dev/null
-usb_format temp.ids usb_dual.ids ${H}
+objcopy -j usb_dual_id -O binary ${F} "usb_dual_id,${G}" 2> /dev/null
+[ -f "usb_dual_id,${G}" ] && (echo -n " -i usb_dual_id,${G}" >> bus_autoconf_args.txt)
 
 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
+bus_autoconf -F bus_autoconf_format.bin $(cat bus_autoconf_args.txt)
 
 # Cleanup
-cleanup
+rm -f -- bus_autoconf_format.bin $(cat bus_autoconf_args.txt)

Added: head/tools/tools/bus_autoconf/bus_autoconf_format_example.txt
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/bus_autoconf/bus_autoconf_format_example.txt	Sat Jun 25 13:44:05 2011	(r223534)
@@ -0,0 +1,111 @@
+/* $FreeBSD$ */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define	U16_XOR "8"
+#define	U32_XOR "12"
+#define	U64_XOR "56"
+#define	U8_BITFIELD_XOR "7"
+#define	U16_BITFIELD_XOR "15"
+#define	U32_BITFIELD_XOR "31"
+#define	U64_BITFIELD_XOR "63"
+#else
+#define	U16_XOR "0"
+#define	U32_XOR "0"
+#define	U64_XOR "0"
+#define	U8_BITFIELD_XOR "0"
+#define	U16_BITFIELD_XOR "0"
+#define	U32_BITFIELD_XOR "0"
+#define	U64_BITFIELD_XOR "0"
+#endif
+
+#if USB_HAVE_COMPAT_LINUX
+#define	MFL_SIZE "1"
+#else
+#define	MFL_SIZE "0"
+#endif
+
+static const char __section("bus_autoconf_format") __used usb_id_format[] = {
+
+		/*
+		 * Declare three different sections that use the same format.
+		 * All sizes are in bits. Fields cannot be greater than
+		 * 8 bits in size. Bitfields having a size greater than 1
+		 * must fit within the byte in which the bitfield is defined.
+		 */
+
+		"usb_host_id{256,:}"
+		"usb_device_id{256,:}"
+		"usb_dual_id{256,:}"
+
+		/*
+		 * Describe all fields in the usb_device_id structure
+		 * which is found in sys/dev/usb/usbdi.h.
+		 */
+
+#if BITS_PER_LONG == 32 || BITS_PER_LONG == 64
+		"unused{0,8}"
+		"unused{0,8}"
+		"unused{0,8}"
+		"unused{0,8}"
+#if BITS_PER_LONG == 64
+		"unused{0,8}"
+		"unused{0,8}"
+		"unused{0,8}"
+		"unused{0,8}"
+#endif
+#else
+#error "Please update code."
+#endif
+
+		"idVendor[0]{" U16_XOR ",8}"
+		"idVendor[1]{" U16_XOR ",8}"
+		"idProduct[0]{" U16_XOR ",8}"
+		"idProduct[1]{" U16_XOR ",8}"
+		"bcdDevice_lo[0]{" U16_XOR ",8}"
+		"bcdDevice_lo[1]{" U16_XOR ",8}"
+		"bcdDevice_hi[0]{" U16_XOR ",8}"
+		"bcdDevice_hi[1]{" U16_XOR ",8}"
+
+		"bDeviceClass{0,8}"
+		"bDeviceSubClass{0,8}"
+		"bDeviceProtocol{0,8}"
+		"bInterfaceClass{0,8}"
+		"bInterfaceSubClass{0,8}"
+		"bInterfaceProtocol{0,8}"
+
+/* NOTE: On big endian machines bitfields are bitreversed. */
+
+		"mf_vendor{" U8_BITFIELD_XOR ",1}"
+		"mf_product{" U8_BITFIELD_XOR ",1}"
+		"mf_dev_lo{" U8_BITFIELD_XOR ",1}"
+		"mf_dev_hi{" U8_BITFIELD_XOR ",1}"
+
+		"mf_dev_class{" U8_BITFIELD_XOR ",1}"
+		"mf_dev_subclass{" U8_BITFIELD_XOR ",1}"
+		"mf_dev_protocol{" U8_BITFIELD_XOR ",1}"
+		"mf_int_class{" U8_BITFIELD_XOR ",1}"
+
+		"mf_int_subclass{" U8_BITFIELD_XOR ",1}"
+		"mf_int_protocol{" U8_BITFIELD_XOR ",1}"
+		"unused{" U8_BITFIELD_XOR ",6}"
+
+		"mfl_vendor{" U16_XOR "," MFL_SIZE "}"
+		"mfl_product{" U16_XOR "," MFL_SIZE "}"
+		"mfl_dev_lo{" U16_XOR "," MFL_SIZE "}"
+		"mfl_dev_hi{" U16_XOR "," MFL_SIZE "}"
+
+		"mfl_dev_class{" U16_XOR "," MFL_SIZE "}"
+		"mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}"
+		"mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}"
+		"mfl_int_class{" U16_XOR "," MFL_SIZE "}"
+
+		"mfl_int_subclass{" U16_XOR "," MFL_SIZE "}"
+		"mfl_int_protocol{" U16_XOR "," MFL_SIZE "}"
+		"unused{" U16_XOR "," MFL_SIZE "}"
+		"unused{" U16_XOR "," MFL_SIZE "}"
+
+		"unused{" U16_XOR "," MFL_SIZE "}"
+		"unused{" U16_XOR "," MFL_SIZE "}"
+		"unused{" U16_XOR "," MFL_SIZE "}"
+		"unused{" U16_XOR "," MFL_SIZE "}"
+};

Added: head/tools/tools/bus_autoconf/bus_load_file.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/bus_autoconf/bus_load_file.c	Sat Jun 25 13:44:05 2011	(r223534)
@@ -0,0 +1,72 @@
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2011 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <err.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "bus_load_file.h"
+
+void
+load_file(const char *fname, uint8_t **pptr, uint32_t *plen)
+{
+	uint8_t *ptr;
+	uint32_t len;
+	off_t off;
+	int f;
+
+	f = open(fname, O_RDONLY);
+	if (f < 0)
+		err(EX_NOINPUT, "Cannot open file '%s'", fname);
+
+	off = lseek(f, 0, SEEK_END);
+	if (off <= 0)
+		err(EX_NOINPUT, "Cannot seek to end of file");
+
+	if (lseek(f, 0, SEEK_SET) < 0)
+		err(EX_NOINPUT, "Cannot seek to beginning of file");
+
+	len = off;
+	if (len != off)
+		err(EX_NOINPUT, "File '%s' is too big", fname);
+
+	ptr = malloc(len);
+	if (ptr == NULL)
+		errx(EX_SOFTWARE, "Out of memory");
+
+	if (read(f, ptr, len) != len)
+		err(EX_NOINPUT, "Cannot read all data");
+
+	close(f);
+
+	*pptr = ptr;
+	*plen = len;
+}

Added: head/tools/tools/bus_autoconf/bus_load_file.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/bus_autoconf/bus_load_file.h	Sat Jun 25 13:44:05 2011	(r223534)
@@ -0,0 +1,33 @@
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2011 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BUS_LOAD_FILE_H_
+#define	_BUS_LOAD_FILE_H_
+
+void	load_file(const char *, uint8_t **, uint32_t *);
+
+#endif					/* _BUS_LOAD_FILE_H_ */

Added: head/tools/tools/bus_autoconf/bus_sections.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/bus_autoconf/bus_sections.c	Sat Jun 25 13:44:05 2011	(r223534)
@@ -0,0 +1,223 @@
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2011 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sysexits.h>
+#include <err.h>
+#include <string.h>
+
+#include <sys/queue.h>
+
+#include "bus_sections.h"
+
+#define	MAX_STRING	64
+
+struct format_info;
+typedef TAILQ_HEAD(,format_info) format_info_head_t;
+typedef TAILQ_ENTRY(format_info) format_info_entry_t;
+
+static format_info_head_t format_head = TAILQ_HEAD_INITIALIZER(format_head);
+
+struct format_info {
+	format_info_entry_t entry;
+	format_info_head_t fields;
+	char	name[MAX_STRING];
+	uint16_t bit_offset;
+	uint16_t bit_size;
+};
+
+static struct format_info *
+format_info_new(char *pstr, uint16_t bo, uint16_t bs)
+{
+	struct format_info *pfi;
+
+	pfi = malloc(sizeof(*pfi));
+	if (pfi == NULL)
+		errx(EX_SOFTWARE, "Out of memory.");
+
+	memset(pfi, 0, sizeof(*pfi));
+
+	TAILQ_INIT(&pfi->fields);
+
+	strlcpy(pfi->name, pstr, sizeof(pfi->name));
+	pfi->bit_offset = bo;
+	pfi->bit_size = bs;
+	return (pfi);
+}
+
+static const struct format_info *
+format_get_section(const char *section)
+{
+	const struct format_info *psub;
+	static const struct format_info *psub_last;
+	static const char *psub_cache;
+
+	if (psub_cache && strcmp(psub_cache, section) == 0)
+		return (psub_last);
+
+	TAILQ_FOREACH(psub, &format_head, entry) {
+		if (strcmp(section, psub->name) == 0) {
+			psub_cache = section;
+			psub_last = psub;
+			return (psub);
+		}
+	}
+	warnx("Section '%s' not found", section);
+	psub_cache = section;
+	psub_last = psub;
+	return (NULL);
+}
+
+uint16_t
+format_get_section_size(const char *section)
+{
+	const struct format_info *pfi;
+
+	pfi = format_get_section(section);
+	if (pfi == NULL)
+		return (0);
+
+	return ((pfi->bit_offset + 7) / 8);
+}
+
+
+uint8_t
+format_get_field(const char *section, const char *field,
+    const uint8_t *ptr, uint16_t size)
+{
+	const struct format_info *pfi;
+	const struct format_info *psub;
+	uint16_t rem;
+	uint16_t off;
+	uint16_t sz;
+
+	pfi = format_get_section(section);
+	if (pfi == NULL)
+		return (0);
+
+	/* skip until we find the fields */
+	while (pfi && TAILQ_FIRST(&pfi->fields) == NULL)
+		pfi = TAILQ_NEXT(pfi, entry);
+
+	if (pfi == NULL)
+		return (0);
+
+	TAILQ_FOREACH(psub, &pfi->fields, entry) {
+		if (strcmp(field, psub->name) == 0) {
+
+			/* range check */
+			if (((psub->bit_offset + psub->bit_size) / 8) > size)
+				return (0);
+
+			/* compute byte offset */
+			rem = psub->bit_offset & 7;
+			off = psub->bit_offset / 8;
+			sz = psub->bit_size;
+
+			/* extract bit-field */
+			return ((ptr[off] >> rem) & ((1 << sz) - 1));
+		}
+	}
+	warnx("Field '%s' not found in '%s'", field, pfi->name);
+	return (0);
+}
+
+void
+format_parse_entries(const uint8_t *ptr, uint32_t len)
+{
+	static const char *command_list = "012345678:";
+	const char *cmd;
+	struct format_info *pfi;
+	struct format_info *pfi_last = NULL;
+	char linebuf[3][MAX_STRING];
+	uint32_t off = 0;
+	uint16_t bit_offset = 0;
+	uint8_t state = 0;
+	uint8_t cmd_index;
+	int c;
+
+	/*
+	 * The format we are parsing:
+	 * <string>{string,string}<next_string>{...}
+	 */
+	while (len--) {
+		c = *(ptr++);
+
+		/* skip some characters */
+		if (c == 0 || c == '\n' || c == '\r' || c == ' ' || c == '\t')
+			continue;
+
+		/* accumulate non-field delimiters */
+		if (strchr("{,}", c) == NULL) {
+			if (off < (MAX_STRING - 1)) {
+				linebuf[state][off] = c;
+				off++;
+			}
+			continue;
+		}
+		/* parse keyword */
+		linebuf[state][off] = 0;
+		off = 0;
+		state++;
+		if (state == 3) {
+			/* check for command in command list */
+			cmd = strchr(command_list, linebuf[2][0]);
+			if (cmd != NULL)
+				cmd_index = cmd - command_list;
+			else
+				cmd_index = 255;
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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