Commits

Anonymous committed 3cf5266

builtin: move usb-db, pci-db to builtins

Comments (0)

Files changed (10)

 	rules/rules.d/60-persistent-input.rules \
 	rules/rules.d/60-persistent-alsa.rules \
 	rules/rules.d/60-persistent-storage.rules \
+	rules/rules.d/75-net-description.rules \
+	rules/rules.d/75-tty-description.rules \
+	rules/rules.d/78-sound-card.rules \
 	rules/rules.d/80-drivers.rules \
 	rules/rules.d/95-udev-late.rules
 
 	udev/udev-builtin.c \
 	udev/udev-builtin-blkid.c \
 	udev/udev-builtin-firmware.c \
+	udev/udev-builtin-hwdb.c \
 	udev/udev-builtin-input_id.c \
 	udev/udev-builtin-kmod.c \
 	udev/udev-builtin-path_id.c \
 
 udev_common_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
-	-DFIRMWARE_PATH="$(FIRMWARE_PATH)"
+	-DFIRMWARE_PATH="$(FIRMWARE_PATH)" \
+	-DUSB_DATABASE=\"$(USB_DATABASE)\" -DPCI_DATABASE=\"$(PCI_DATABASE)\"
 
 udev_udevd_SOURCES = \
 	$(udev_common_sources) \
 UNINSTALL_EXEC_HOOKS += libgudev-uninstall-move-hook
 endif
 
-if ENABLE_HWDB
-# ------------------------------------------------------------------------------
-# usb/pci-db - read vendor/device string database
-# ------------------------------------------------------------------------------
-extras_usb_db_usb_db_SOURCES = extras/usb-db/usb-db.c
-extras_usb_db_usb_db_CPPFLAGS = $(AM_CPPFLAGS) -DUSB_DATABASE=\"$(USB_DATABASE)\" -DBUILD_FOR_USB
-extras_usb_db_usb_db_LDADD = libudev/libudev-private.la
-libexec_PROGRAMS += extras/usb-db/usb-db
-dist_udevrules_DATA += \
-	rules/rules.d/75-net-description.rules \
-	rules/rules.d/75-tty-description.rules \
-	rules/rules.d/78-sound-card.rules
-
-extras_usb_db_pci_db_SOURCES = extras/usb-db/usb-db.c
-extras_usb_db_pci_db_CPPFLAGS = $(AM_CPPFLAGS) -DPCI_DATABASE=\"$(PCI_DATABASE)\" -DBUILD_FOR_PCI
-extras_usb_db_pci_db_LDADD = libudev/libudev-private.la
-libexec_PROGRAMS += extras/usb-db/pci-db
-endif
-
 if ENABLE_KEYMAP
 # ------------------------------------------------------------------------------
 # keymap - map custom hardware's multimedia keys
 AC_PATH_PROG([XSLTPROC], [xsltproc])
 
 AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([POSIX RT library not found])])
+
 PKG_CHECK_MODULES(BLKID, blkid >= 2.20)
+
 PKG_CHECK_MODULES(KMOD, libkmod >= 2)
 
+if test "x$cross_compiling" = "xno" ; then
+	AC_CHECK_FILES([/usr/share/pci.ids], [pciids=/usr/share/pci.ids])
+	AC_CHECK_FILES([/usr/share/hwdata/pci.ids], [pciids=/usr/share/hwdata/pci.ids])
+	AC_CHECK_FILES([/usr/share/misc/pci.ids], [pciids=/usr/share/misc/pci.ids])
+fi
+
+AC_ARG_WITH(usb-ids-path,
+	[AS_HELP_STRING([--with-usb-ids-path=DIR], [Path to usb.ids file])],
+	[USB_DATABASE=${withval}],
+	[if test -n "$usbids" ; then
+		USB_DATABASE="$usbids"
+	else
+		PKG_CHECK_MODULES(USBUTILS, usbutils >= 0.82)
+		AC_SUBST([USB_DATABASE], [$($PKG_CONFIG --variable=usbids usbutils)])
+	fi])
+AC_MSG_CHECKING([for USB database location])
+AC_MSG_RESULT([$USB_DATABASE])
+AC_SUBST(USB_DATABASE)
+
+AC_ARG_WITH(pci-ids-path,
+	[AS_HELP_STRING([--with-pci-ids-path=DIR], [Path to pci.ids file])],
+	[PCI_DATABASE=${withval}],
+	[if test -n "$pciids" ; then
+		PCI_DATABASE="$pciids"
+	else
+		AC_MSG_ERROR([pci.ids not found, try --with-pci-ids-path=])
+	fi])
+AC_MSG_CHECKING([for PCI database location])
+AC_MSG_RESULT([$PCI_DATABASE])
+AC_SUBST(PCI_DATABASE)
+
 AC_ARG_WITH([rootprefix],
 	AS_HELP_STRING([--with-rootprefix=DIR], [rootfs directory prefix for config files and kernel modules]),
 	[], [with_rootprefix=$prefix])
 AM_CONDITIONAL([ENABLE_GUDEV], [test "x$enable_gudev" = "xyes"])
 
 # ------------------------------------------------------------------------------
-# usb/pci-db - read vendor/device string database
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([hwdb],
-	AS_HELP_STRING([--disable-hwdb], [disable hardware database support @<:@default=enabled@:>@]),
-	[], [enable_hwdb=yes])
-AS_IF([test "x$enable_hwdb" = "xyes"], [
-	if test "x$cross_compiling" = "xno" ; then
-		AC_CHECK_FILES([/usr/share/pci.ids], [pciids=/usr/share/pci.ids])
-		AC_CHECK_FILES([/usr/share/hwdata/pci.ids], [pciids=/usr/share/hwdata/pci.ids])
-		AC_CHECK_FILES([/usr/share/misc/pci.ids], [pciids=/usr/share/misc/pci.ids])
-	fi
-
-	AC_ARG_WITH(usb-ids-path,
-		[AS_HELP_STRING([--with-usb-ids-path=DIR], [Path to usb.ids file])],
-		[USB_DATABASE=${withval}],
-		[if test -n "$usbids" ; then
-			USB_DATABASE="$usbids"
-		else
-			PKG_CHECK_MODULES(USBUTILS, usbutils >= 0.82)
-			AC_SUBST([USB_DATABASE], [$($PKG_CONFIG --variable=usbids usbutils)])
-		fi])
-	AC_MSG_CHECKING([for USB database location])
-	AC_MSG_RESULT([$USB_DATABASE])
-	AC_SUBST(USB_DATABASE)
-
-	AC_ARG_WITH(pci-ids-path,
-		[AS_HELP_STRING([--with-pci-ids-path=DIR], [Path to pci.ids file])],
-		[PCI_DATABASE=${withval}],
-		[if test -n "$pciids" ; then
-			PCI_DATABASE="$pciids"
-		else
-			AC_MSG_ERROR([pci.ids not found, try --with-pci-ids-path=])
-		fi])
-	AC_MSG_CHECKING([for PCI database location])
-	AC_MSG_RESULT([$PCI_DATABASE])
-	AC_SUBST(PCI_DATABASE)
-])
-AM_CONDITIONAL([ENABLE_HWDB], [test "x$enable_hwdb" = "xyes"])
-
-# ------------------------------------------------------------------------------
 # keymap - map custom hardware's multimedia keys
 # ------------------------------------------------------------------------------
 AC_ARG_ENABLE([keymap],
 	include_prefix:		${INCLUDE_PREFIX}
 	systemdsystemunitdir:	${systemdsystemunitdir}
 	firmware path:		${FIRMWARE_PATH}
+	usb.ids:		${USB_DATABASE}
+	pci.ids:		${PCI_DATABASE}
 
 	compiler:		${CC}
 	cflags:			${CFLAGS}
 	gudev:			${enable_gudev}
 	gintrospection:		${enable_introspection}
 	keymap:			${enable_keymap}
-	hwdb:			${enable_hwdb}
-	  usb.ids:		${USB_DATABASE}
-	  pci.ids:		${PCI_DATABASE}
 	mtd_probe:		${enable_mtd_probe}
 	rule_generator:		${enable_rule_generator}
 	udev_acl:		${enable_udev_acl}

extras/usb-db/.gitignore

-usb-db
-pci-db

extras/usb-db/usb-db.c

-/*
- * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
- *
- * 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:
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <inttypes.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <libudev.h>
-
-#if defined(BUILD_FOR_USB)
-# define DATABASE USB_DATABASE
-# define SUBSYSTEM "usb"
-# define DEVTYPE "usb_device"
-# define VENDOR_ATTR "idVendor"
-# define PRODUCT_ATTR "idProduct"
-#elif defined(BUILD_FOR_PCI)
-# define DATABASE PCI_DATABASE
-# define SUBSYSTEM "pci"
-# define DEVTYPE NULL
-# define VENDOR_ATTR "vendor"
-# define PRODUCT_ATTR "device"
-#else
-# error "Are you havin' a laugh?"
-#endif
-
-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,
-	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(
-	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, "r"))) {
-		fprintf(stderr, "Failed to open database file "DATABASE": %s\n", strerror(errno));
-		return -1;
-	}
-
-	for (;;) {
-		size_t n;
-
-		if (line) {
-			free(line);
-			line = NULL;
-		}
-
-		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, SUBSYSTEM, DEVTYPE);
-}
-
-int main(int argc, char*argv[]) {
-
-	struct udev *udev = NULL;
-	int ret = 1;
-	char *sp;
-	struct udev_device *dev = NULL, *parent = NULL;
-	uint16_t vid = 0, pid = 0;
-	char *vendor = NULL, *product = NULL;
-
-	if (argc < 2) {
-		fprintf(stderr, "Need to pass sysfs path.\n");
-		goto finish;
-	}
-
-	if (!(udev = udev_new()))
-		goto finish;
-
-	if (asprintf(&sp, "%s%s", udev_get_sys_path(udev), argv[1]) < 0) {
-		fprintf(stderr, "Failed to allocate sysfs path.\n");
-		goto finish;
-	}
-
-	dev = udev_device_new_from_syspath(udev, sp);
-	free(sp);
-
-	if (!dev) {
-		fprintf(stderr, "Failed to access %s.\n", argv[1]);
-		goto finish;
-	}
-
-	parent = find_device(dev, SUBSYSTEM, DEVTYPE);
-	if (!parent) {
-		fprintf(stderr, "Failed to find device.\n");
-		goto finish;
-	}
-
-	if (get_vid_pid(parent, &vid, &pid) < 0)
-		goto finish;
-
-	if (lookup_vid_pid(vid, pid, &vendor, &product) < 0)
-		goto finish;
-
-	if (vendor)
-		printf("ID_VENDOR_FROM_DATABASE=%s\n", vendor);
-
-	if (product)
-		printf("ID_MODEL_FROM_DATABASE=%s\n", product);
-
-	ret = 0;
-
-finish:
-	udev_device_unref(dev);
-	udev_unref(udev);
-	free(vendor);
-	free(product);
-
-	return ret;
-}

rules/rules.d/75-net-description.rules

 SUBSYSTEM!="net", GOTO="net_end"
 
 SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id"
-SUBSYSTEMS=="usb", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{program}="usb-db %p"
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb-db"
 SUBSYSTEMS=="usb", ATTRS{idVendor}!="", ATTRS{idProduct}!="", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}"
 SUBSYSTEMS=="usb", GOTO="net_end"
 
-SUBSYSTEMS=="pci", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{program}="pci-db %p"
+SUBSYSTEMS=="pci", IMPORT{builtin}="pci-db"
 SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
 
 LABEL="net_end"

rules/rules.d/75-tty-description.rules

 SUBSYSTEM!="tty", GOTO="tty_end"
 
 SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id"
-SUBSYSTEMS=="usb", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{program}="usb-db %p"
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb-db"
 SUBSYSTEMS=="usb", ATTRS{idVendor}!="", ATTRS{idProduct}!="", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}"
 SUBSYSTEMS=="usb", GOTO="tty_end"
 
-SUBSYSTEMS=="pci", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{program}="pci-db %p"
+SUBSYSTEMS=="pci", IMPORT{builtin}="pci-db"
 SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
 
 LABEL="tty_end"

rules/rules.d/78-sound-card.rules

 ENV{SOUND_INITIALIZED}="1"
 
 SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
-SUBSYSTEMS=="usb", ENV{ID_VENDOR_FROM_DATABASE}=="", IMPORT{program}="usb-db %p"
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb-db"
 SUBSYSTEMS=="usb", GOTO="skip_pci"
 
-SUBSYSTEMS=="pci", ENV{ID_VENDOR_FROM_DATABASE}=="", IMPORT{program}="pci-db %p"
+SUBSYSTEMS=="pci", IMPORT{builtin}="pci-db"
 SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
 
 LABEL="skip_pci"

udev/udev-builtin-hwdb.c

+/*
+ * 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 (line) {
+			free(line);
+			line = NULL;
+		}
+
+		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,
+};

udev/udev-builtin.c

 	[UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id,
 	[UDEV_BUILTIN_KMOD] = &udev_builtin_kmod,
 	[UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id,
+	[UDEV_BUILTIN_PCI_DB] = &udev_builtin_pci_db,
+	[UDEV_BUILTIN_USB_DB] = &udev_builtin_usb_db,
 	[UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id,
 };
 
 	UDEV_BUILTIN_INPUT_ID,
 	UDEV_BUILTIN_KMOD,
 	UDEV_BUILTIN_PATH_ID,
+	UDEV_BUILTIN_PCI_DB,
+	UDEV_BUILTIN_USB_DB,
 	UDEV_BUILTIN_USB_ID,
 	UDEV_BUILTIN_MAX
 };
 extern const struct udev_builtin udev_builtin_input_id;
 extern const struct udev_builtin udev_builtin_kmod;
 extern const struct udev_builtin udev_builtin_path_id;
+extern const struct udev_builtin udev_builtin_pci_db;
+extern const struct udev_builtin udev_builtin_usb_db;
 extern const struct udev_builtin udev_builtin_usb_id;
 int udev_builtin_init(struct udev *udev);
 void udev_builtin_exit(struct udev *udev);