string: factorize skip_spaces and export it to be generally available
[safe/jmp/linux-2.6] / scripts / mod / file2alias.c
index 4eea60b..6f426af 100644 (file)
@@ -104,7 +104,7 @@ static void device_id_check(const char *modname, const char *device_id,
 static void do_usb_entry(struct usb_device_id *id,
                         unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
                         unsigned char range_lo, unsigned char range_hi,
-                        struct module *mod)
+                        unsigned char max, struct module *mod)
 {
        char alias[500];
        strcpy(alias, "usb:");
@@ -118,9 +118,22 @@ static void do_usb_entry(struct usb_device_id *id,
                sprintf(alias + strlen(alias), "%0*X",
                        bcdDevice_initial_digits, bcdDevice_initial);
        if (range_lo == range_hi)
-               sprintf(alias + strlen(alias), "%u", range_lo);
-       else if (range_lo > 0 || range_hi < 9)
-               sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi);
+               sprintf(alias + strlen(alias), "%X", range_lo);
+       else if (range_lo > 0 || range_hi < max) {
+               if (range_lo > 0x9 || range_hi < 0xA)
+                       sprintf(alias + strlen(alias),
+                               "[%X-%X]",
+                               range_lo,
+                               range_hi);
+               else {
+                       sprintf(alias + strlen(alias),
+                               range_lo < 0x9 ? "[%X-9" : "[%X",
+                               range_lo);
+                       sprintf(alias + strlen(alias),
+                               range_hi > 0xA ? "a-%X]" : "%X]",
+                               range_lo);
+               }
+       }
        if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
                strcat(alias, "*");
 
@@ -147,10 +160,49 @@ static void do_usb_entry(struct usb_device_id *id,
                   "MODULE_ALIAS(\"%s\");\n", alias);
 }
 
+/* Handles increment/decrement of BCD formatted integers */
+/* Returns the previous value, so it works like i++ or i-- */
+static unsigned int incbcd(unsigned int *bcd,
+                          int inc,
+                          unsigned char max,
+                          size_t chars)
+{
+       unsigned int init = *bcd, i, j;
+       unsigned long long c, dec = 0;
+
+       /* If bcd is not in BCD format, just increment */
+       if (max > 0x9) {
+               *bcd += inc;
+               return init;
+       }
+
+       /* Convert BCD to Decimal */
+       for (i=0 ; i < chars ; i++) {
+               c = (*bcd >> (i << 2)) & 0xf;
+               c = c > 9 ? 9 : c; /* force to bcd just in case */
+               for (j=0 ; j < i ; j++)
+                       c = c * 10;
+               dec += c;
+       }
+
+       /* Do our increment/decrement */
+       dec += inc;
+       *bcd  = 0;
+
+       /* Convert back to BCD */
+       for (i=0 ; i < chars ; i++) {
+               for (c=1,j=0 ; j < i ; j++)
+                       c = c * 10;
+               c = (dec / c) % 10;
+               *bcd += c << (i << 2);
+       }
+       return init;
+}
+
 static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
 {
        unsigned int devlo, devhi;
-       unsigned char chi, clo;
+       unsigned char chi, clo, max;
        int ndigits;
 
        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)
        devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
                TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
 
+       /* Figure out if this entry is in bcd or hex format */
+       max = 0x9; /* Default to decimal format */
+       for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+               clo = (devlo >> (ndigits << 2)) & 0xf;
+               chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
+               if (clo > max || chi > max) {
+                       max = 0xf;
+                       break;
+               }
+       }
+
        /*
         * Some modules (visor) have empty slots as placeholder for
         * 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)
        for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
                clo = devlo & 0xf;
                chi = devhi & 0xf;
-               if (chi > 9)    /* it's bcd not hex */
-                       chi = 9;
+               if (chi > max)  /* If we are in bcd mode, truncate if necessary */
+                       chi = max;
                devlo >>= 4;
                devhi >>= 4;
 
                if (devlo == devhi || !ndigits) {
-                       do_usb_entry(id, devlo, ndigits, clo, chi, mod);
+                       do_usb_entry(id, devlo, ndigits, clo, chi, max, mod);
                        break;
                }
 
-               if (clo > 0)
-                       do_usb_entry(id, devlo++, ndigits, clo, 9, mod);
-
-               if (chi < 9)
-                       do_usb_entry(id, devhi--, ndigits, 0, chi, mod);
+               if (clo > 0x0)
+                       do_usb_entry(id,
+                                    incbcd(&devlo, 1, max,
+                                           sizeof(id->bcdDevice_lo) * 2),
+                                    ndigits, clo, max, max, mod);
+
+               if (chi < max)
+                       do_usb_entry(id,
+                                    incbcd(&devhi, -1, max,
+                                           sizeof(id->bcdDevice_lo) * 2),
+                                    ndigits, 0x0, chi, max, mod);
        }
 }
 
@@ -641,7 +710,7 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
        id->vendor = TO_NATIVE(id->vendor);
 
        strcpy(alias, "virtio:");
-       ADD(alias, "d", 1, id->device);
+       ADD(alias, "d", id->device != VIRTIO_DEV_ANY_ID, id->device);
        ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
 
        add_wildcard(alias);
@@ -657,6 +726,15 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
        return 1;
 }
 
+/* Looks like: spi:S */
+static int do_spi_entry(const char *filename, struct spi_device_id *id,
+                       char *alias)
+{
+       sprintf(alias, SPI_MODULE_PREFIX "%s", id->name);
+
+       return 1;
+}
+
 static const struct dmifield {
        const char *prefix;
        int field;
@@ -710,6 +788,14 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
        strcat(alias, ":");
        return 1;
 }
+
+static int do_platform_entry(const char *filename,
+                            struct platform_device_id *id, char *alias)
+{
+       sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name);
+       return 1;
+}
+
 /* Ignore any prefix, eg. some architectures prepend _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -845,10 +931,18 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct i2c_device_id), "i2c",
                         do_i2c_entry, mod);
+       else if (sym_is(symname, "__mod_spi_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct spi_device_id), "spi",
+                        do_spi_entry, mod);
        else if (sym_is(symname, "__mod_dmi_device_table"))
                do_table(symval, sym->st_size,
                         sizeof(struct dmi_system_id), "dmi",
                         do_dmi_entry, mod);
+       else if (sym_is(symname, "__mod_platform_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct platform_device_id), "platform",
+                        do_platform_entry, mod);
        free(zeros);
 }