diff options
Diffstat (limited to 'scripts/mod/file2alias.c')
| -rw-r--r-- | scripts/mod/file2alias.c | 97 |
1 files changed, 83 insertions, 14 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 62a9025cdcc7..220213e603db 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -104,7 +104,7 @@ static void device_id_check(const char *modname, const char *device_id, | |||
| 104 | static void do_usb_entry(struct usb_device_id *id, | 104 | static void do_usb_entry(struct usb_device_id *id, |
| 105 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, | 105 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, |
| 106 | unsigned char range_lo, unsigned char range_hi, | 106 | unsigned char range_lo, unsigned char range_hi, |
| 107 | struct module *mod) | 107 | unsigned char max, struct module *mod) |
| 108 | { | 108 | { |
| 109 | char alias[500]; | 109 | char alias[500]; |
| 110 | strcpy(alias, "usb:"); | 110 | strcpy(alias, "usb:"); |
| @@ -118,9 +118,22 @@ static void do_usb_entry(struct usb_device_id *id, | |||
| 118 | sprintf(alias + strlen(alias), "%0*X", | 118 | sprintf(alias + strlen(alias), "%0*X", |
| 119 | bcdDevice_initial_digits, bcdDevice_initial); | 119 | bcdDevice_initial_digits, bcdDevice_initial); |
| 120 | if (range_lo == range_hi) | 120 | if (range_lo == range_hi) |
| 121 | sprintf(alias + strlen(alias), "%u", range_lo); | 121 | sprintf(alias + strlen(alias), "%X", range_lo); |
| 122 | else if (range_lo > 0 || range_hi < 9) | 122 | else if (range_lo > 0 || range_hi < max) { |
| 123 | sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi); | 123 | if (range_lo > 0x9 || range_hi < 0xA) |
| 124 | sprintf(alias + strlen(alias), | ||
| 125 | "[%X-%X]", | ||
| 126 | range_lo, | ||
| 127 | range_hi); | ||
| 128 | else { | ||
| 129 | sprintf(alias + strlen(alias), | ||
| 130 | range_lo < 0x9 ? "[%X-9" : "[%X", | ||
| 131 | range_lo); | ||
| 132 | sprintf(alias + strlen(alias), | ||
| 133 | range_hi > 0xA ? "a-%X]" : "%X]", | ||
| 134 | range_lo); | ||
| 135 | } | ||
| 136 | } | ||
| 124 | if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) | 137 | if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) |
| 125 | strcat(alias, "*"); | 138 | strcat(alias, "*"); |
| 126 | 139 | ||
| @@ -147,10 +160,49 @@ static void do_usb_entry(struct usb_device_id *id, | |||
| 147 | "MODULE_ALIAS(\"%s\");\n", alias); | 160 | "MODULE_ALIAS(\"%s\");\n", alias); |
| 148 | } | 161 | } |
| 149 | 162 | ||
| 163 | /* Handles increment/decrement of BCD formatted integers */ | ||
| 164 | /* Returns the previous value, so it works like i++ or i-- */ | ||
| 165 | static unsigned int incbcd(unsigned int *bcd, | ||
| 166 | int inc, | ||
| 167 | unsigned char max, | ||
| 168 | size_t chars) | ||
| 169 | { | ||
| 170 | unsigned int init = *bcd, i, j; | ||
| 171 | unsigned long long c, dec = 0; | ||
| 172 | |||
| 173 | /* If bcd is not in BCD format, just increment */ | ||
| 174 | if (max > 0x9) { | ||
| 175 | *bcd += inc; | ||
| 176 | return init; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Convert BCD to Decimal */ | ||
| 180 | for (i=0 ; i < chars ; i++) { | ||
| 181 | c = (*bcd >> (i << 2)) & 0xf; | ||
| 182 | c = c > 9 ? 9 : c; /* force to bcd just in case */ | ||
| 183 | for (j=0 ; j < i ; j++) | ||
| 184 | c = c * 10; | ||
| 185 | dec += c; | ||
| 186 | } | ||
| 187 | |||
| 188 | /* Do our increment/decrement */ | ||
| 189 | dec += inc; | ||
| 190 | *bcd = 0; | ||
| 191 | |||
| 192 | /* Convert back to BCD */ | ||
| 193 | for (i=0 ; i < chars ; i++) { | ||
| 194 | for (c=1,j=0 ; j < i ; j++) | ||
| 195 | c = c * 10; | ||
| 196 | c = (dec / c) % 10; | ||
| 197 | *bcd += c << (i << 2); | ||
| 198 | } | ||
| 199 | return init; | ||
| 200 | } | ||
| 201 | |||
| 150 | static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | 202 | static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) |
| 151 | { | 203 | { |
| 152 | unsigned int devlo, devhi; | 204 | unsigned int devlo, devhi; |
| 153 | unsigned char chi, clo; | 205 | unsigned char chi, clo, max; |
| 154 | int ndigits; | 206 | int ndigits; |
| 155 | 207 | ||
| 156 | id->match_flags = TO_NATIVE(id->match_flags); | 208 | id->match_flags = TO_NATIVE(id->match_flags); |
| @@ -162,6 +214,17 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | |||
| 162 | devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? | 214 | devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? |
| 163 | TO_NATIVE(id->bcdDevice_hi) : ~0x0U; | 215 | TO_NATIVE(id->bcdDevice_hi) : ~0x0U; |
| 164 | 216 | ||
| 217 | /* Figure out if this entry is in bcd or hex format */ | ||
| 218 | max = 0x9; /* Default to decimal format */ | ||
| 219 | for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) { | ||
| 220 | clo = (devlo >> (ndigits << 2)) & 0xf; | ||
| 221 | chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; | ||
| 222 | if (clo > max || chi > max) { | ||
| 223 | max = 0xf; | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 165 | /* | 228 | /* |
| 166 | * Some modules (visor) have empty slots as placeholder for | 229 | * Some modules (visor) have empty slots as placeholder for |
| 167 | * run-time specification that results in catch-all alias | 230 | * run-time specification that results in catch-all alias |
| @@ -173,21 +236,27 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | |||
| 173 | for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { | 236 | for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { |
| 174 | clo = devlo & 0xf; | 237 | clo = devlo & 0xf; |
| 175 | chi = devhi & 0xf; | 238 | chi = devhi & 0xf; |
| 176 | if (chi > 9) /* it's bcd not hex */ | 239 | if (chi > max) /* If we are in bcd mode, truncate if necessary */ |
| 177 | chi = 9; | 240 | chi = max; |
| 178 | devlo >>= 4; | 241 | devlo >>= 4; |
| 179 | devhi >>= 4; | 242 | devhi >>= 4; |
| 180 | 243 | ||
| 181 | if (devlo == devhi || !ndigits) { | 244 | if (devlo == devhi || !ndigits) { |
| 182 | do_usb_entry(id, devlo, ndigits, clo, chi, mod); | 245 | do_usb_entry(id, devlo, ndigits, clo, chi, max, mod); |
| 183 | break; | 246 | break; |
| 184 | } | 247 | } |
| 185 | 248 | ||
| 186 | if (clo > 0) | 249 | if (clo > 0x0) |
| 187 | do_usb_entry(id, devlo++, ndigits, clo, 9, mod); | 250 | do_usb_entry(id, |
| 188 | 251 | incbcd(&devlo, 1, max, | |
| 189 | if (chi < 9) | 252 | sizeof(id->bcdDevice_lo) * 2), |
| 190 | do_usb_entry(id, devhi--, ndigits, 0, chi, mod); | 253 | ndigits, clo, max, max, mod); |
| 254 | |||
| 255 | if (chi < max) | ||
| 256 | do_usb_entry(id, | ||
| 257 | incbcd(&devhi, -1, max, | ||
| 258 | sizeof(id->bcdDevice_lo) * 2), | ||
| 259 | ndigits, 0x0, chi, max, mod); | ||
| 191 | } | 260 | } |
| 192 | } | 261 | } |
| 193 | 262 | ||
| @@ -735,7 +804,7 @@ static inline int sym_is(const char *symbol, const char *name) | |||
| 735 | match = strstr(symbol, name); | 804 | match = strstr(symbol, name); |
| 736 | if (!match) | 805 | if (!match) |
| 737 | return 0; | 806 | return 0; |
| 738 | return match[strlen(symbol)] == '\0'; | 807 | return match[strlen(name)] == '\0'; |
| 739 | } | 808 | } |
| 740 | 809 | ||
| 741 | static void do_table(void *symval, unsigned long size, | 810 | static void do_table(void *symval, unsigned long size, |
