diff options
author | hselasky <hselasky@FreeBSD.org> | 2011-06-24 21:27:33 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2011-06-24 21:27:33 +0000 |
commit | 99e5945c1699988d03ad2ae09d005e3e2b53eca4 (patch) | |
tree | bfe687369996c093137a9d5e1c1c8ffc895eb863 /tools | |
parent | f5e9daf260f37151cc8e3c60b75612ca9ff3352c (diff) | |
download | FreeBSD-src-99e5945c1699988d03ad2ae09d005e3e2b53eca4.zip FreeBSD-src-99e5945c1699988d03ad2ae09d005e3e2b53eca4.tar.gz |
- 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
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/bus_autoconf/bus_autoconf.c | 151 | ||||
-rw-r--r-- | tools/tools/bus_autoconf/bus_autoconf.h | 3 | ||||
-rw-r--r-- | tools/tools/bus_autoconf/bus_autoconf.sh | 63 |
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 38fbd29..3ddab5a 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 a247109..7dbc486 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 4815572..21a4df0 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 |