/*
 * usb-db, pci-db - lookup vendor/product database
 *
 * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
 * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
#include <ctype.h>
#include <stdlib.h>

#include "udev.h"

static int get_id_attr(
        struct udev_device *parent,
        const char *name,
        uint16_t *value) {

        const char *t;
        unsigned u;

        if (!(t = udev_device_get_sysattr_value(parent, name))) {
                fprintf(stderr, "%s lacks %s.\n", udev_device_get_syspath(parent), name);
                return -1;
        }

        if (!strncmp(t, "0x", 2))
                t += 2;

        if (sscanf(t, "%04x", &u) != 1 || u > 0xFFFFU) {
                fprintf(stderr, "Failed to parse %s on %s.\n", name, udev_device_get_syspath(parent));
                return -1;
        }

        *value = (uint16_t) u;
        return 0;
}

static int get_vid_pid(
        struct udev_device *parent,
        const char *vendor_attr,
        const char *product_attr,
        uint16_t *vid,
        uint16_t *pid) {

        if (get_id_attr(parent, vendor_attr, vid) < 0)
                return -1;
        else if (*vid <= 0) {
                fprintf(stderr, "Invalid vendor id.\n");
                return -1;
        }

        if (get_id_attr(parent, product_attr, pid) < 0)
                return -1;

        return 0;
}

static void rstrip(char *n) {
        size_t i;

        for (i = strlen(n); i > 0 && isspace(n[i-1]); i--)
                n[i-1] = 0;
}

#define HEXCHARS "0123456789abcdefABCDEF"
#define WHITESPACE " \t\n\r"
static int lookup_vid_pid(const char *database,
                          uint16_t vid, uint16_t pid,
                          char **vendor, char **product)
{

        FILE *f;
        int ret = -1;
        int found_vendor = 0;
        char *line = NULL;

        *vendor = *product = NULL;

        if (!(f = fopen(database, "rme"))) {
                fprintf(stderr, "Failed to open database file '%s': %s\n", database, strerror(errno));
                return -1;
        }

        for (;;) {
                size_t n;

                if (getline(&line, &n, f) < 0)
                        break;

                rstrip(line);

                if (line[0] == '#' || line[0] == 0)
                        continue;

                if (strspn(line, HEXCHARS) == 4) {
                        unsigned u;

                        if (found_vendor)
                                break;

                        if (sscanf(line, "%04x", &u) == 1 && u == vid) {
                                char *t;

                                t = line+4;
                                t += strspn(t, WHITESPACE);

                                if (!(*vendor = strdup(t))) {
                                        fprintf(stderr, "Out of memory.\n");
                                        goto finish;
                                }

                                found_vendor = 1;
                        }

                        continue;
                }

                if (found_vendor && line[0] == '\t' && strspn(line+1, HEXCHARS) == 4) {
                        unsigned u;

                        if (sscanf(line+1, "%04x", &u) == 1 && u == pid) {
                                char *t;

                                t = line+5;
                                t += strspn(t, WHITESPACE);

                                if (!(*product = strdup(t))) {
                                        fprintf(stderr, "Out of memory.\n");
                                        goto finish;
                                }

                                break;
                        }
                }
        }

        ret = 0;

finish:
        free(line);
        fclose(f);

        if (ret < 0) {
                free(*product);
                free(*vendor);

                *product = *vendor = NULL;
        }

        return ret;
}

static struct udev_device *find_device(struct udev_device *dev, const char *subsys, const char *devtype)
{
        const char *str;

        str = udev_device_get_subsystem(dev);
        if (str == NULL)
                goto try_parent;
        if (strcmp(str, subsys) != 0)
                goto try_parent;

        if (devtype != NULL) {
                str = udev_device_get_devtype(dev);
                if (str == NULL)
                        goto try_parent;
                if (strcmp(str, devtype) != 0)
                        goto try_parent;
        }
        return dev;
try_parent:
        return udev_device_get_parent_with_subsystem_devtype(dev, subsys, devtype);
}


static int builtin_db(struct udev_device *dev, bool test,
                      const char *database,
                      const char *vendor_attr, const char *product_attr,
                      const char *subsys, const char *devtype)
{
        struct udev_device *parent;
        uint16_t vid = 0, pid = 0;
        char *vendor = NULL, *product = NULL;

        parent = find_device(dev, subsys, devtype);
        if (!parent) {
                fprintf(stderr, "Failed to find device.\n");
                goto finish;
        }

        if (get_vid_pid(parent, vendor_attr, product_attr, &vid, &pid) < 0)
                goto finish;

        if (lookup_vid_pid(database, vid, pid, &vendor, &product) < 0)
                goto finish;

        if (vendor)
                udev_builtin_add_property(dev, test, "ID_VENDOR_FROM_DATABASE", vendor);
        if (product)
                udev_builtin_add_property(dev, test, "ID_MODEL_FROM_DATABASE", product);

finish:
        free(vendor);
        free(product);
        return 0;
}

static int builtin_usb_db(struct udev_device *dev, int argc, char *argv[], bool test)
{
        return builtin_db(dev, test, USB_DATABASE, "idVendor", "idProduct", "usb", "usb_device");
}

static int builtin_pci_db(struct udev_device *dev, int argc, char *argv[], bool test)
{
        return builtin_db(dev, test, PCI_DATABASE, "vendor", "device", "pci", NULL);
}

const struct udev_builtin udev_builtin_usb_db = {
        .name = "usb-db",
        .cmd = builtin_usb_db,
        .help = "USB vendor/product database",
        .run_once = true,
};

const struct udev_builtin udev_builtin_pci_db = {
        .name = "pci-db",
        .cmd = builtin_pci_db,
        .help = "PCI vendor/product database",
        .run_once = true,
};
