diff options
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/file2alias.c | 111 |
1 files changed, 88 insertions, 23 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index d54b52d3bb6f..32197efe67ed 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -47,32 +47,31 @@ do { \ | |||
| 47 | sprintf(str + strlen(str), "*"); \ | 47 | sprintf(str + strlen(str), "*"); \ |
| 48 | } while(0) | 48 | } while(0) |
| 49 | 49 | ||
| 50 | /* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */ | 50 | /* USB is special because the bcdDevice can be matched against a numeric range */ |
| 51 | static int do_usb_entry(const char *filename, | 51 | /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ |
| 52 | struct usb_device_id *id, char *alias) | 52 | static void do_usb_entry(struct usb_device_id *id, |
| 53 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, | ||
| 54 | unsigned char range_lo, unsigned char range_hi, | ||
| 55 | struct module *mod) | ||
| 53 | { | 56 | { |
| 54 | id->match_flags = TO_NATIVE(id->match_flags); | 57 | char alias[500]; |
| 55 | id->idVendor = TO_NATIVE(id->idVendor); | ||
| 56 | id->idProduct = TO_NATIVE(id->idProduct); | ||
| 57 | id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo); | ||
| 58 | id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Some modules (visor) have empty slots as placeholder for | ||
| 62 | * run-time specification that results in catch-all alias | ||
| 63 | */ | ||
| 64 | if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) | ||
| 65 | return 1; | ||
| 66 | |||
| 67 | strcpy(alias, "usb:"); | 58 | strcpy(alias, "usb:"); |
| 68 | ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, | 59 | ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, |
| 69 | id->idVendor); | 60 | id->idVendor); |
| 70 | ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT, | 61 | ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT, |
| 71 | id->idProduct); | 62 | id->idProduct); |
| 72 | ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO, | 63 | |
| 73 | id->bcdDevice_lo); | 64 | strcat(alias, "d"); |
| 74 | ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI, | 65 | if (bcdDevice_initial_digits) |
| 75 | id->bcdDevice_hi); | 66 | sprintf(alias + strlen(alias), "%0*X", |
| 67 | bcdDevice_initial_digits, bcdDevice_initial); | ||
| 68 | if (range_lo == range_hi) | ||
| 69 | sprintf(alias + strlen(alias), "%u", range_lo); | ||
| 70 | else if (range_lo > 0 || range_hi < 9) | ||
| 71 | sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi); | ||
| 72 | if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) | ||
| 73 | strcat(alias, "*"); | ||
| 74 | |||
| 76 | ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, | 75 | ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, |
| 77 | id->bDeviceClass); | 76 | id->bDeviceClass); |
| 78 | ADD(alias, "dsc", | 77 | ADD(alias, "dsc", |
| @@ -90,7 +89,73 @@ static int do_usb_entry(const char *filename, | |||
| 90 | ADD(alias, "ip", | 89 | ADD(alias, "ip", |
| 91 | id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, | 90 | id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, |
| 92 | id->bInterfaceProtocol); | 91 | id->bInterfaceProtocol); |
| 93 | return 1; | 92 | |
| 93 | /* Always end in a wildcard, for future extension */ | ||
| 94 | if (alias[strlen(alias)-1] != '*') | ||
| 95 | strcat(alias, "*"); | ||
| 96 | buf_printf(&mod->dev_table_buf, | ||
| 97 | "MODULE_ALIAS(\"%s\");\n", alias); | ||
| 98 | } | ||
| 99 | |||
| 100 | static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | ||
| 101 | { | ||
| 102 | unsigned int devlo, devhi; | ||
| 103 | unsigned char chi, clo; | ||
| 104 | int ndigits; | ||
| 105 | |||
| 106 | id->match_flags = TO_NATIVE(id->match_flags); | ||
| 107 | id->idVendor = TO_NATIVE(id->idVendor); | ||
| 108 | id->idProduct = TO_NATIVE(id->idProduct); | ||
| 109 | |||
| 110 | devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? | ||
| 111 | TO_NATIVE(id->bcdDevice_lo) : 0x0U; | ||
| 112 | devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? | ||
| 113 | TO_NATIVE(id->bcdDevice_hi) : ~0x0U; | ||
| 114 | |||
| 115 | /* | ||
| 116 | * Some modules (visor) have empty slots as placeholder for | ||
| 117 | * run-time specification that results in catch-all alias | ||
| 118 | */ | ||
| 119 | if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) | ||
| 120 | return; | ||
| 121 | |||
| 122 | /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ | ||
| 123 | for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { | ||
| 124 | clo = devlo & 0xf; | ||
| 125 | chi = devhi & 0xf; | ||
| 126 | if (chi > 9) /* it's bcd not hex */ | ||
| 127 | chi = 9; | ||
| 128 | devlo >>= 4; | ||
| 129 | devhi >>= 4; | ||
| 130 | |||
| 131 | if (devlo == devhi || !ndigits) { | ||
| 132 | do_usb_entry(id, devlo, ndigits, clo, chi, mod); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (clo > 0) | ||
| 137 | do_usb_entry(id, devlo++, ndigits, clo, 9, mod); | ||
| 138 | |||
| 139 | if (chi < 9) | ||
| 140 | do_usb_entry(id, devhi--, ndigits, 0, chi, mod); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | static void do_usb_table(void *symval, unsigned long size, | ||
| 145 | struct module *mod) | ||
| 146 | { | ||
| 147 | unsigned int i; | ||
| 148 | const unsigned long id_size = sizeof(struct usb_device_id); | ||
| 149 | |||
| 150 | if (size % id_size || size < id_size) { | ||
| 151 | fprintf(stderr, "*** Warning: %s ids %lu bad size " | ||
| 152 | "(each on %lu)\n", mod->name, size, id_size); | ||
| 153 | } | ||
| 154 | /* Leave last one: it's the terminator. */ | ||
| 155 | size -= id_size; | ||
| 156 | |||
| 157 | for (i = 0; i < size; i += id_size) | ||
| 158 | do_usb_entry_multi(symval + i, mod); | ||
| 94 | } | 159 | } |
| 95 | 160 | ||
| 96 | /* Looks like: ieee1394:venNmoNspNverN */ | 161 | /* Looks like: ieee1394:venNmoNspNverN */ |
| @@ -280,8 +345,8 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
| 280 | do_table(symval, sym->st_size, sizeof(struct pci_device_id), | 345 | do_table(symval, sym->st_size, sizeof(struct pci_device_id), |
| 281 | do_pci_entry, mod); | 346 | do_pci_entry, mod); |
| 282 | else if (sym_is(symname, "__mod_usb_device_table")) | 347 | else if (sym_is(symname, "__mod_usb_device_table")) |
| 283 | do_table(symval, sym->st_size, sizeof(struct usb_device_id), | 348 | /* special case to handle bcdDevice ranges */ |
| 284 | do_usb_entry, mod); | 349 | do_usb_table(symval, sym->st_size, mod); |
| 285 | else if (sym_is(symname, "__mod_ieee1394_device_table")) | 350 | else if (sym_is(symname, "__mod_ieee1394_device_table")) |
| 286 | do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), | 351 | do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), |
| 287 | do_ieee1394_entry, mod); | 352 | do_ieee1394_entry, mod); |
