string: factorize skip_spaces and export it to be generally available
[safe/jmp/linux-2.6] / scripts / mod / file2alias.c
index 473f94e..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);
        }
 }
 
@@ -206,6 +275,21 @@ static void do_usb_table(void *symval, unsigned long size,
                do_usb_entry_multi(symval + i, mod);
 }
 
+/* Looks like: hid:bNvNpN */
+static int do_hid_entry(const char *filename,
+                            struct hid_device_id *id, char *alias)
+{
+       id->bus = TO_NATIVE(id->bus);
+       id->vendor = TO_NATIVE(id->vendor);
+       id->product = TO_NATIVE(id->product);
+
+       sprintf(alias, "hid:b%04X", id->bus);
+       ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
+       ADD(alias, "p", id->product != HID_ANY_ID, id->product);
+
+       return 1;
+}
+
 /* Looks like: ieee1394:venNmoNspNverN */
 static int do_ieee1394_entry(const char *filename,
                             struct ieee1394_device_id *id, char *alias)
@@ -352,11 +436,17 @@ static void do_pnp_device_entry(void *symval, unsigned long size,
 
        for (i = 0; i < count; i++) {
                const char *id = (char *)devs[i].id;
+               char acpi_id[sizeof(devs[0].id)];
+               int j;
 
                buf_printf(&mod->dev_table_buf,
                           "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+
+               /* fix broken pnp bus lowercasing */
+               for (j = 0; j < sizeof(acpi_id); j++)
+                       acpi_id[j] = toupper(id[j]);
                buf_printf(&mod->dev_table_buf,
-                          "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
+                          "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
        }
 }
 
@@ -402,10 +492,17 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
                        /* add an individual alias for every device entry */
                        if (!dup) {
+                               char acpi_id[sizeof(card->devs[0].id)];
+                               int k;
+
                                buf_printf(&mod->dev_table_buf,
                                           "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+
+                               /* fix broken pnp bus lowercasing */
+                               for (k = 0; k < sizeof(acpi_id); k++)
+                                       acpi_id[k] = toupper(id[k]);
                                buf_printf(&mod->dev_table_buf,
-                                          "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
+                                          "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
                        }
                }
        }
@@ -613,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);
@@ -629,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;
@@ -682,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)
 {
@@ -745,6 +859,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
        else if (sym_is(symname, "__mod_usb_device_table"))
                /* special case to handle bcdDevice ranges */
                do_usb_table(symval, sym->st_size, mod);
+       else if (sym_is(symname, "__mod_hid_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct hid_device_id), "hid",
+                        do_hid_entry, mod);
        else if (sym_is(symname, "__mod_ieee1394_device_table"))
                do_table(symval, sym->st_size,
                         sizeof(struct ieee1394_device_id), "ieee1394",
@@ -813,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);
 }