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 ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to