aboutsummaryrefslogtreecommitdiff
path: root/tools/tools
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2011-06-24 21:27:33 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2011-06-24 21:27:33 +0000
commita433a3d8c910078a69ed8c32fd56f0132bdd5954 (patch)
treebfe687369996c093137a9d5e1c1c8ffc895eb863 /tools/tools
parentb97989d6598263b367646de39f8c4e39f0d8b7dd (diff)
downloadsrc-a433a3d8c910078a69ed8c32fd56f0132bdd5954.tar.gz
src-a433a3d8c910078a69ed8c32fd56f0132bdd5954.zip
- We need to sort all USB device ID's together. Else the matching order will
be wrong. This is required because devd only executes one entry. MFC after: 14 days
Notes
Notes: svn path=/head/; revision=223518
Diffstat (limited to 'tools/tools')
-rw-r--r--tools/tools/bus_autoconf/bus_autoconf.c151
-rw-r--r--tools/tools/bus_autoconf/bus_autoconf.h3
-rw-r--r--tools/tools/bus_autoconf/bus_autoconf.sh63
3 files changed, 163 insertions, 54 deletions
diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c
index 38fbd29760d7..3ddab5a8ebff 100644
--- a/tools/tools/bus_autoconf/bus_autoconf.c
+++ b/tools/tools/bus_autoconf/bus_autoconf.c
@@ -43,15 +43,67 @@
static char *type;
static char *file_name;
-static char *module;
static const char *mode;
+struct usb_info;
+static void usb_dump_sub(struct usb_device_id *, struct usb_info *);
+
+/*
+ * To ensure that the correct USB driver is loaded, the driver having
+ * the most information about the device must be probed first. Then
+ * more generic drivers shall be probed.
+ */
static int
usb_compare(const void *_a, const void *_b)
{
const struct usb_device_id *a = _a;
const struct usb_device_id *b = _b;
+ /* vendor matches first */
+
+ if (a->match_flag_vendor > b->match_flag_vendor)
+ return (-1);
+ if (a->match_flag_vendor < b->match_flag_vendor)
+ return (1);
+
+ /* product matches first */
+
+ if (a->match_flag_product > b->match_flag_product)
+ return (-1);
+ if (a->match_flag_product < b->match_flag_product)
+ return (1);
+
+ /* device class matches first */
+
+ if (a->match_flag_dev_class > b->match_flag_dev_class)
+ return (-1);
+ if (a->match_flag_dev_class < b->match_flag_dev_class)
+ return (1);
+
+ if (a->match_flag_dev_subclass > b->match_flag_dev_subclass)
+ return (-1);
+ if (a->match_flag_dev_subclass < b->match_flag_dev_subclass)
+ return (1);
+
+ /* interface class matches first */
+
+ if (a->match_flag_int_class > b->match_flag_int_class)
+ return (-1);
+ if (a->match_flag_int_class < b->match_flag_int_class)
+ return (1);
+
+ if (a->match_flag_int_subclass > b->match_flag_int_subclass)
+ return (-1);
+ if (a->match_flag_int_subclass < b->match_flag_int_subclass)
+ return (1);
+
+ if (a->match_flag_int_protocol > b->match_flag_int_protocol)
+ return (-1);
+ if (a->match_flag_int_protocol < b->match_flag_int_protocol)
+ return (1);
+
+ /* then sort according to value */
+
if (a->idVendor > b->idVendor)
return (1);
if (a->idVendor < b->idVendor)
@@ -85,7 +137,9 @@ usb_compare(const void *_a, const void *_b)
if (a->bInterfaceProtocol < b->bInterfaceProtocol)
return (-1);
- return (0);
+ /* in the end sort by module name */
+
+ return (strcmp(a->module_name, b->module_name));
}
static void
@@ -105,39 +159,55 @@ static void
usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo)
{
#if USB_HAVE_COMPAT_LINUX
- if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
- id->match_flag_vendor = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
- id->match_flag_product = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
- id->match_flag_dev_lo = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
- id->match_flag_dev_hi = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
- id->match_flag_dev_class = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
- id->match_flag_dev_subclass = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
- id->match_flag_dev_protocol = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
- id->match_flag_int_class = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
- id->match_flag_int_subclass = 1;
- if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
- id->match_flag_int_protocol = 1;
+ if (id->match_flags != 0) {
+ if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
+ id->match_flag_vendor = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
+ id->match_flag_product = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
+ id->match_flag_dev_lo = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
+ id->match_flag_dev_hi = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
+ id->match_flag_dev_class = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+ id->match_flag_dev_subclass = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ id->match_flag_dev_protocol = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
+ id->match_flag_int_class = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
+ id->match_flag_int_subclass = 1;
+ if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+ id->match_flag_int_protocol = 1;
+ id->match_flags = 0;
+ }
#endif
+ if (pinfo != NULL) {
+
+ pinfo->is_iface = id->match_flag_int_class |
+ id->match_flag_int_protocol |
+ id->match_flag_int_subclass;
+
+ pinfo->is_dev = id->match_flag_dev_class |
+ id->match_flag_dev_subclass;
- pinfo->is_iface = id->match_flag_int_class |
- id->match_flag_int_protocol |
- id->match_flag_int_subclass;
+ pinfo->is_vp = id->match_flag_vendor |
+ id->match_flag_product;
- pinfo->is_dev = id->match_flag_dev_class |
- id->match_flag_dev_subclass;
+ pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface;
+ }
+}
- pinfo->is_vp = id->match_flag_vendor |
- id->match_flag_product;
+static char *
+usb_trim(char *ptr)
+{
+ char *end;
- pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface;
+ end = strchr(ptr, ' ');
+ if (end)
+ *end = 0;
+ return (ptr);
}
static uint32_t
@@ -149,7 +219,7 @@ usb_dump(struct usb_device_id *id, uint32_t nid)
usb_dump_sub(id, &info);
if (info.is_any) {
- printf("nomatch 10 {\n"
+ printf("nomatch 32 {\n"
" match \"bus\" \"uhub[0-9]+\";\n"
" match \"mode\" \"%s\";\n", mode);
} else {
@@ -212,7 +282,7 @@ usb_dump(struct usb_device_id *id, uint32_t nid)
id->bInterfaceProtocol);
}
printf(" action \"kldload %s\";\n"
- "};\n\n", module);
+ "};\n\n", usb_trim(id->module_name));
return (n);
}
@@ -239,12 +309,21 @@ usb_parse_and_dump(int f, off_t size)
}
nid = size / sizeof(*id);
+ for (x = 0; x != nid; x++) {
+ /* make sure flag bits are correct */
+ usb_dump_sub(id + x, NULL);
+ /* zero terminate string */
+ id[x].module_name[sizeof(id[0].module_name) - 1] = 0;
+ }
+
usb_sort(id, nid);
for (x = 0; x != nid;)
x += usb_dump(id + x, nid - x);
free(id);
+
+ printf("# %d %s entries processed\n\n", (int)nid, type);
}
static void
@@ -253,7 +332,6 @@ usage(void)
fprintf(stderr,
"bus_autoconf - devd config file generator\n"
" -i <input_binary>\n"
- " -m <module_name>\n"
" -t <structure_type>\n"
" -h show usage\n"
);
@@ -263,7 +341,7 @@ usage(void)
int
main(int argc, char **argv)
{
- const char *params = "i:m:ht:";
+ const char *params = "i:ht:";
int c;
int f;
off_t off;
@@ -276,16 +354,13 @@ main(int argc, char **argv)
case 't':
type = optarg;
break;
- case 'm':
- module = optarg;
- break;
default:
usage();
break;
}
}
- if (type == NULL || module == NULL || file_name == NULL)
+ if (type == NULL || file_name == NULL)
usage();
f = open(file_name, O_RDONLY);
diff --git a/tools/tools/bus_autoconf/bus_autoconf.h b/tools/tools/bus_autoconf/bus_autoconf.h
index a247109b2f7d..7dbc4865d2de 100644
--- a/tools/tools/bus_autoconf/bus_autoconf.h
+++ b/tools/tools/bus_autoconf/bus_autoconf.h
@@ -33,6 +33,9 @@
struct usb_device_id {
+ /* Internal field */
+ char module_name[32];
+
/* Hook for driver specific information */
unsigned long driver_info;
diff --git a/tools/tools/bus_autoconf/bus_autoconf.sh b/tools/tools/bus_autoconf/bus_autoconf.sh
index 4815572261af..21a4df063dd5 100644
--- a/tools/tools/bus_autoconf/bus_autoconf.sh
+++ b/tools/tools/bus_autoconf/bus_autoconf.sh
@@ -29,6 +29,30 @@
OS=FreeBSD
DOLLAR=$
+cleanup()
+{
+ # Cleanup
+ rm -f usb_dual.ids
+ rm -f usb_host.ids
+ rm -f usb_device.ids
+}
+
+usb_format()
+{
+ [ -f ${1} ] || return
+
+ # Split into one and one record
+ split -b 32 ${1} ${1}.
+
+ # Prefix each record by the module name
+ for G in $(ls ${1}.*)
+ do
+ printf "%-32s" ${3} >> ${2}
+ cat ${G} >> ${2}
+ rm -f ${G}
+ done
+}
+
cat <<EOF
#
# ${DOLLAR}${OS}${DOLLAR}
@@ -39,26 +63,33 @@ cat <<EOF
EOF
-for F in $(echo $* | sort)
+# Cleanup
+cleanup
+
+for F in $*
do
+
+# Get module basename
H=$(basename ${F} | sed -e "s/\.ko//g")
# USB Host
-objcopy -j usb_host_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_host -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_host_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_host.ids ${H}
+
# USB Device
-objcopy -j usb_device_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_device -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_device_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_device.ids ${H}
+
# USB Dual mode
-objcopy -j usb_dual_id -O binary ${F} ${F}.ids 2> /dev/null
-[ -f ${F}.ids ] && (
-bus_autoconf -i ${F}.ids -t usb_dual -m ${H} ;
-rm ${F}.ids
-)
+objcopy -j usb_dual_id -O binary ${F} temp.ids 2> /dev/null
+usb_format temp.ids usb_dual.ids ${H}
+
done
+
+# Dump all data
+[ -f usb_dual.ids ] && bus_autoconf -i usb_dual.ids -t usb_dual
+[ -f usb_host.ids ] && bus_autoconf -i usb_host.ids -t usb_host
+[ -f usb_device.ids ] && bus_autoconf -i usb_device.ids -t usb_device
+
+# Cleanup
+cleanup