svn commit: r223534 - head/tools/tools/bus_autoconf
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jun 25 13:44:06 UTC 2011
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 ***
More information about the svn-src-all
mailing list