aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod/file2alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod/file2alias.c')
-rw-r--r--scripts/mod/file2alias.c95
1 files changed, 82 insertions, 13 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 62a9025cdcc7..6f426afbc522 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,
104static void do_usb_entry(struct usb_device_id *id, 104static 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-- */
165static 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
150static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) 202static 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