On Fri, Mar 25, 2005 at 09:40:48AM -0800, Greg KH wrote: > On Fri, Mar 25, 2005 at 10:43:01AM +0300, Roman Kagan wrote: > > > > The patch expects a matching change in scripts/mod/file2alias.c I sent > > > > to linux-hotplug-devel list a few days ago (i.e. puts > > > > bcdDevice in MODNAME as dXXXX, rather that dlXXXXdhXXXX). > > > > > > I changed this back, as this change doesn't seem to have gone anywhere. > > > > It was sent to linux-hotplug-devel and cc to you on Feb. 26, as I > > thought it was up to you to include it. Has it got lost and should I > > resend it, or should I better send it to another list? I think it's > > worth merging as the current scheme bites everybody with nontrivial > > bcdDevice range. > > Ok, care to resend it? I saw a lot of different patches floating > around, and didn't know which one was the decided apon best fix.
Sure, here you are. This is the latest version of the patch I sent on Feb 26. Erik van Konijnenburg reviewed it and was OK with it (Erik mind adding your Signed-off-by?), so it's "decided upon best" by the two of us :) Roman. ================================= The attached patch fixes the longstanding problem with USB bcdDevice numeric ranges incorrectly converted into patterns for MODULE_ALIAS generation. Previously it put both the lower and the upper limits into the pattern, dlXdhY, making it impossible to fnmatch against except for a few special cases, like dl*dh* or dlXdhX. The patch makes it generate multiple MODULE_ALIAS lines covering the whole range with fnmatch-able patterns. E.g. for a range between 0x0001 and 0xa345 it gives the following patterns: 000[123456789ABCDEF]* 00[123456789ABCDEF]* 0[123456789ABCDEF]* [123456789]* A[012]* A3[0123]* A34[012345]* Since bcdDevice is 2 bytes wide = 4 digits in hex representation, the max no. of patters is 2 * 4 - 1 = 7. Explicit lists of allowed characters inside brackets are used to avoid dependencies on locale collation order with patterns using a dash, like [3-B]. The patch uses "d" prefix for bcdDevice; the most common (and almost the only working) case of dl*dh* becomes d* and thus continues to work. Please consider applying. Roman. Signed-off-by: Roman Kagan <[EMAIL PROTECTED]> scripts/mod/file2alias.c | 112 +++++++++++++++++++++++++++++++++++++---------- 1 files changed, 89 insertions(+), 23 deletions(-) --- linux-2.6.11-rc4/scripts/mod/file2alias.c.orig 2005-02-13 06:06:23.000000000 +0300 +++ linux-2.6.11-rc4/scripts/mod/file2alias.c 2005-02-26 19:15:49.769160544 +0300 @@ -47,32 +47,34 @@ do { sprintf(str + strlen(str), "*"); \ } while(0) -/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */ -static int do_usb_entry(const char *filename, - struct usb_device_id *id, char *alias) +/* USB is special because the bcdDevice can be matched against a numeric range */ +/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ +static void do_usb_entry(struct usb_device_id *id, + unsigned int bcdDevice_initial, int bcdDevice_initial_digits, + unsigned char range_lo, unsigned char range_hi, + struct module *mod) { - id->match_flags = TO_NATIVE(id->match_flags); - id->idVendor = TO_NATIVE(id->idVendor); - id->idProduct = TO_NATIVE(id->idProduct); - id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo); - id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi); - - /* - * Some modules (visor) have empty slots as placeholder for - * run-time specification that results in catch-all alias - */ - if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) - return 1; - + static const char hexdigits[] = "0123456789ABCDEF"; + char alias[500]; strcpy(alias, "usb:"); ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, id->idVendor); ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT, id->idProduct); - ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO, - id->bcdDevice_lo); - ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI, - id->bcdDevice_hi); + + strcat(alias, "d"); + if (bcdDevice_initial_digits) + sprintf(alias + strlen(alias), "%0*X", + bcdDevice_initial_digits, bcdDevice_initial); + if (range_lo == range_hi) + strncat(alias, hexdigits + range_lo, 1); + else if (range_lo > 0x0 || range_hi < 0xf) { + strcat(alias, "["); + strncat(alias, hexdigits + range_lo, range_hi - range_lo + 1); + strcat(alias, "]"); + } + strcat(alias, "*"); + ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass); ADD(alias, "dsc", @@ -90,7 +92,71 @@ static int do_usb_entry(const char *file ADD(alias, "ip", id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, id->bInterfaceProtocol); - return 1; + + /* Always end in a wildcard, for future extension */ + if (alias[strlen(alias)-1] != '*') + strcat(alias, "*"); + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"%s\");\n", alias); +} + +static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) +{ + unsigned int devlo, devhi; + unsigned char chi, clo; + int ndigits; + + id->match_flags = TO_NATIVE(id->match_flags); + id->idVendor = TO_NATIVE(id->idVendor); + id->idProduct = TO_NATIVE(id->idProduct); + + devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? + TO_NATIVE(id->bcdDevice_lo) : 0x0U; + devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? + TO_NATIVE(id->bcdDevice_hi) : ~0x0U; + + /* + * Some modules (visor) have empty slots as placeholder for + * run-time specification that results in catch-all alias + */ + if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) + return; + + /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ + for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { + clo = devlo & 0xf; + chi = devhi & 0xf; + devlo >>= 4; + devhi >>= 4; + + if (devlo == devhi || !ndigits) { + do_usb_entry(id, devlo, ndigits, clo, chi, mod); + break; + } + + if (clo != 0x0) + do_usb_entry(id, devlo++, ndigits, clo, 0xf, mod); + + if (chi != 0xf) + do_usb_entry(id, devhi--, ndigits, 0x0, chi, mod); + } +} + +static void do_usb_table(void *symval, unsigned long size, + struct module *mod) +{ + unsigned int i; + const unsigned long id_size = sizeof(struct usb_device_id); + + if (size % id_size || size < id_size) { + fprintf(stderr, "*** Warning: %s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); + } + /* Leave last one: it's the terminator. */ + size -= id_size; + + for (i = 0; i < size; i += id_size) + do_usb_entry_multi(symval + i, mod); } /* Looks like: ieee1394:venNmoNspNverN */ @@ -262,8 +328,8 @@ void handle_moddevtable(struct module *m do_table(symval, sym->st_size, sizeof(struct pci_device_id), do_pci_entry, mod); else if (sym_is(symname, "__mod_usb_device_table")) - do_table(symval, sym->st_size, sizeof(struct usb_device_id), - do_usb_entry, mod); + /* special case to handle bcdDevice ranges */ + do_usb_table(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_ieee1394_device_table")) do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), do_ieee1394_entry, mod); ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel