diff options
-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); |