aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel McCallum <nathaniel@natemccallum.com>2009-11-18 20:15:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:20 -0500
commit55f49f26821f379c451deb9fd6de8e59afb9b37e (patch)
treec4c4cfd20a6766cd38ec25213124ccc92b48592e
parentafe2dab4f6d32d5650aaba42f2c7ec9c0622f4dd (diff)
USB: handle bcd incrementation in usb modalias generation
This patch fixes a bug when incrementing/decrementing on a BCD formatted integer (i.e. 0x09++ should be 0x10 not 0x0A). It just adds a function for incrementing/decrementing BCD integers by converting to decimal, doing the increment/decrement and then converting back to BCD. Signed-off-by: Nathaniel McCallum <nathaniel@natemccallum.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--scripts/mod/file2alias.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e31f03aaf294..6f426afbc522 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -160,6 +160,45 @@ static void do_usb_entry(struct usb_device_id *id,
160 "MODULE_ALIAS(\"%s\");\n", alias); 160 "MODULE_ALIAS(\"%s\");\n", alias);
161} 161}
162 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
163static 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)
164{ 203{
165 unsigned int devlo, devhi; 204 unsigned int devlo, devhi;
@@ -208,10 +247,16 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
208 } 247 }
209 248
210 if (clo > 0x0) 249 if (clo > 0x0)
211 do_usb_entry(id, devlo++, ndigits, clo, max, max, mod); 250 do_usb_entry(id,
251 incbcd(&devlo, 1, max,
252 sizeof(id->bcdDevice_lo) * 2),
253 ndigits, clo, max, max, mod);
212 254
213 if (chi < max) 255 if (chi < max)
214 do_usb_entry(id, devhi--, ndigits, 0x0, chi, max, mod); 256 do_usb_entry(id,
257 incbcd(&devhi, -1, max,
258 sizeof(id->bcdDevice_lo) * 2),
259 ndigits, 0x0, chi, max, mod);
215 } 260 }
216} 261}
217 262