mirror of
https://github.com/systemd/systemd.git
synced 2025-03-25 18:50:18 +03:00
usb-db: move from udev-extras
This commit is contained in:
parent
5a92fd9c9b
commit
ccba91c746
20
configure.ac
20
configure.ac
@ -72,6 +72,22 @@ if test "x$enable_extras" = xyes; then
|
||||
PKG_CHECK_MODULES(LIBUSB, libusb >= 0.1.12)
|
||||
AC_SUBST(LIBUSB_CFLAGS)
|
||||
AC_SUBST(LIBUSB_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(USBUTILS, usbutils >= 0.82)
|
||||
AC_SUBST([USB_DATABASE], [$($PKG_CONFIG --variable=usbids usbutils)])
|
||||
|
||||
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])
|
||||
AC_ARG_WITH(pci-ids-path,
|
||||
AS_HELP_STRING([--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_SUBST(PCI_DATABASE)
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_EXTRAS], [test "x$enable_extras" = xyes])
|
||||
|
||||
@ -113,6 +129,7 @@ AC_CONFIG_FILES([
|
||||
extras/v4l_id/Makefile
|
||||
extras/hid2hci/Makefile
|
||||
extras/udev-acl/Makefile
|
||||
extras/usb-db/Makefile
|
||||
extras/gudev/Makefile
|
||||
extras/gudev/gudev-1.0.pc
|
||||
extras/gudev/docs/Makefile
|
||||
@ -144,5 +161,8 @@ AC_MSG_RESULT([
|
||||
extras: ${enable_extras}
|
||||
gintrospection: ${enable_introspection}
|
||||
|
||||
usb.ids: ${USB_DATABASE}
|
||||
pci.ids: ${PCI_DATABASE}
|
||||
|
||||
xsltproc: ${XSLTPROC}
|
||||
])
|
||||
|
@ -17,6 +17,7 @@ SUBDIRS = \
|
||||
if ENABLE_EXTRAS
|
||||
SUBDIRS += \
|
||||
udev-acl \
|
||||
usb-db \
|
||||
hid2hci \
|
||||
gudev
|
||||
endif
|
||||
|
2
extras/usb-db/.gitignore
vendored
Normal file
2
extras/usb-db/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
usb-db
|
||||
pci-db
|
12
extras/usb-db/Makefile.am
Normal file
12
extras/usb-db/Makefile.am
Normal file
@ -0,0 +1,12 @@
|
||||
include $(top_srcdir)/Makefile.am.inc
|
||||
|
||||
udevhomedir = $(udev_prefix)/lib/udev
|
||||
udevhome_PROGRAMS = usb-db pci-db
|
||||
|
||||
usb_db_SOURCES = usb-db.c
|
||||
usb_db_CPPFLAGS = $(AM_CPPFLAGS) -DUSB_DATABASE=\"$(USB_DATABASE)\" -DBUILD_FOR_USB
|
||||
usb_db_LDADD = $(top_builddir)/libudev/libudev.la
|
||||
|
||||
pci_db_SOURCES = $(usb_db_SOURCES)
|
||||
pci_db_CPPFLAGS = $(AM_CPPFLAGS) -DPCI_DATABASE=\"$(PCI_DATABASE)\" -DBUILD_FOR_PCI
|
||||
pci_db_LDADD = $(top_builddir)/libudev/libudev.la
|
266
extras/usb-db/usb-db.c
Normal file
266
extras/usb-db/usb-db.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*-*- linux-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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user