4 * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details:
26 #if defined(BUILD_FOR_USB)
27 # define DATABASE USB_DATABASE
28 # define SUBSYSTEM "usb"
29 # define DEVTYPE "usb_device"
30 # define VENDOR_ATTR "idVendor"
31 # define PRODUCT_ATTR "idProduct"
32 #elif defined(BUILD_FOR_PCI)
33 # define DATABASE PCI_DATABASE
34 # define SUBSYSTEM "pci"
36 # define VENDOR_ATTR "vendor"
37 # define PRODUCT_ATTR "device"
39 # error "Are you havin' a laugh?"
42 static int get_id_attr(
43 struct udev_device *parent,
50 if (!(t = udev_device_get_sysattr_value(parent, name))) {
51 fprintf(stderr, "%s lacks %s.\n", udev_device_get_syspath(parent), name);
55 if (!strncmp(t, "0x", 2))
58 if (sscanf(t, "%04x", &u) != 1 || u > 0xFFFFU) {
59 fprintf(stderr, "Failed to parse %s on %s.\n", name, udev_device_get_syspath(parent));
63 *value = (uint16_t) u;
67 static int get_vid_pid(
68 struct udev_device *parent,
72 if (get_id_attr(parent, VENDOR_ATTR, vid) < 0)
75 fprintf(stderr, "Invalid vendor id.\n");
79 if (get_id_attr(parent, PRODUCT_ATTR, pid) < 0)
85 static void rstrip(char *n) {
88 for (i = strlen(n); i > 0 && isspace(n[i-1]); i--)
92 #define HEXCHARS "0123456789abcdefABCDEF"
93 #define WHITESPACE " \t\n\r"
95 static int lookup_vid_pid(
103 int found_vendor = 0;
106 *vendor = *product = NULL;
108 if (!(f = fopen(DATABASE, "r"))) {
109 fprintf(stderr, "Failed to open database file "DATABASE": %s\n", strerror(errno));
121 if (getline(&line, &n, f) < 0)
126 if (line[0] == '#' || line[0] == 0)
129 if (strspn(line, HEXCHARS) == 4) {
135 if (sscanf(line, "%04x", &u) == 1 && u == vid) {
139 t += strspn(t, WHITESPACE);
141 if (!(*vendor = strdup(t))) {
142 fprintf(stderr, "Out of memory.\n");
152 if (found_vendor && line[0] == '\t' && strspn(line+1, HEXCHARS) == 4) {
155 if (sscanf(line+1, "%04x", &u) == 1 && u == pid) {
159 t += strspn(t, WHITESPACE);
161 if (!(*product = strdup(t))) {
162 fprintf(stderr, "Out of memory.\n");
181 *product = *vendor = NULL;
187 static struct udev_device *find_device(struct udev_device *dev, const char *subsys, const char *devtype)
191 str = udev_device_get_subsystem(dev);
194 if (strcmp(str, subsys) != 0)
197 if (devtype != NULL) {
198 str = udev_device_get_devtype(dev);
201 if (strcmp(str, devtype) != 0)
206 return udev_device_get_parent_with_subsystem_devtype(dev, SUBSYSTEM, DEVTYPE);
209 int main(int argc, char*argv[]) {
211 struct udev *udev = NULL;
214 struct udev_device *dev = NULL, *parent = NULL;
215 uint16_t vid = 0, pid = 0;
216 char *vendor = NULL, *product = NULL;
219 fprintf(stderr, "Need to pass sysfs path.\n");
223 if (!(udev = udev_new()))
226 if (asprintf(&sp, "%s/%s", udev_get_sys_path(udev), argv[1]) < 0) {
227 fprintf(stderr, "Failed to allocate sysfs path.\n");
231 dev = udev_device_new_from_syspath(udev, sp);
235 fprintf(stderr, "Failed to access %s.\n", argv[1]);
239 parent = find_device(dev, SUBSYSTEM, DEVTYPE);
241 fprintf(stderr, "Failed to find device.\n");
245 if (get_vid_pid(parent, &vid, &pid) < 0)
248 if (lookup_vid_pid(vid, pid, &vendor, &product) < 0)
252 printf("ID_VENDOR_FROM_DATABASE=%s\n", vendor);
255 printf("ID_MODEL_FROM_DATABASE=%s\n", product);
260 udev_device_unref(dev);