summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--hid.c152
-rw-r--r--libldetect.h20
3 files changed, 175 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 52e5c74..ad040e6 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ libdir = $(prefix)/lib
includedir = $(prefix)/include
binaries = lspcidrake
-lib_objs = common.o modalias.o pciusb.o pci.o usb.o pciclass.o usbclass.o dmi.o
+lib_objs = common.o hid.o modalias.o pciusb.o pci.o usb.o pciclass.o usbclass.o dmi.o sysfs_attr.o sysfs_utils.o
lib_major = libldetect.so.$(LIB_MAJOR)
libraries = libldetect.so $(lib_major) $(lib_major).$(LIB_MINOR) libldetect.a
CFLAGS = -Wall -W -Wstrict-prototypes -Os -fPIC -fvisibility=hidden
@@ -46,6 +46,8 @@ pciusb.o: pciusb.c libldetect.h common.h
pci.o: pci.c libldetect.h common.h
usb.o: usb.c libldetect.h common.h
dmi.o: dmi.c libldetect.h common.h
+sysfs_attr.o: sysfs/sysfs_attr.c sysfs/sysfs.h sysfs/libsysfs.h
+sysfs_utils.o: sysfs/sysfs_utils.c sysfs/sysfs.h sysfs/libsysfs.h
clean:
rm -f *~ *.o pciclass.c usbclass.c $(binaries) $(libraries)
diff --git a/hid.c b/hid.c
new file mode 100644
index 0000000..99870ad
--- /dev/null
+++ b/hid.c
@@ -0,0 +1,152 @@
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <dirent.h>
+#include <fnmatch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sysfs/libsysfs.h"
+#include "libldetect.h"
+#include "common.h"
+
+
+#define HID_BUS_NAME "hid"
+const char *sysfs_hid_path = "/sys/bus/"HID_BUS_NAME"/devices";
+#if 0
+#define DEBUG(args...) printf(args)
+#else
+#define DEBUG(args...)
+#endif
+
+#if 0
+struct module_alias {
+ const char *modalias;
+ const char *module;
+};
+
+static struct module_alias aliasdb[] = { {NULL, NULL} };
+static const char *resolve_modalias(const struct module_alias *aliasdb,
+ const char *alias_name)
+{
+ const struct module_alias *alias = aliasdb;
+
+ while (alias->modalias != NULL) {
+ if (fnmatch(alias->modalias, alias_name, 0) == 0)
+ return alias->module;
+
+ alias++;
+ }
+ return NULL;
+}
+#endif
+
+static char *get_field_value(const char *fields, const char *field_name)
+{
+ char *modalias;
+ char *end;
+
+ modalias = strstr(fields, field_name);
+ if (modalias == NULL)
+ return NULL;
+ end = strchrnul(modalias, '\n');
+
+ return strndup(modalias+strlen(field_name), end - (modalias+strlen(field_name)));
+}
+
+static char *parse_modalias(char *fields)
+{
+ return get_field_value(fields, "MODALIAS=");
+}
+
+static char *parse_name(char *fields)
+{
+ return get_field_value(fields, "HID_NAME=");
+}
+
+static void add_entry(struct hid_entries *entry_list, char *name, char *module)
+{
+
+ struct hid_entry *new_entries;
+
+ new_entries = realloc(entry_list->entries, (entry_list->nb+1)*sizeof(entry_list->entries));
+ if (new_entries != NULL) {
+ new_entries[entry_list->nb].module = module;
+ new_entries[entry_list->nb].text = name;
+ entry_list->entries = new_entries;
+ entry_list->nb++;
+ }
+}
+
+static void parse_device(struct hid_entries *entries, const char *dev)
+{
+ char keyfile[SYSFS_PATH_MAX];
+ char *modalias;
+ char *modname;
+ char *device_name;
+ struct sysfs_attribute *sysfs_attr;
+
+ snprintf(keyfile, sizeof(keyfile)-1, "%s/%s/uevent",
+ sysfs_hid_path, dev);
+ sysfs_attr = sysfs_open_attribute(keyfile);
+ if (!sysfs_attr)
+ return;
+ if (sysfs_read_attribute(sysfs_attr) != 0 || !sysfs_attr->value) {
+ sysfs_close_attribute(sysfs_attr);
+ return;
+ }
+
+ DEBUG("%s: read %s\n", HID_BUS_NAME, sysfs_attr->value);
+
+ modalias = parse_modalias(sysfs_attr->value);
+ if (modalias == NULL)
+ return;
+ DEBUG("%s: modalias is [%s]\n", HID_BUS_NAME, modalias);
+
+ device_name = parse_name(sysfs_attr->value);
+ sysfs_close_attribute(sysfs_attr);
+ if (device_name != NULL)
+ DEBUG("%s: device name is [%s]\n", HID_BUS_NAME, device_name);
+ else
+ device_name = strdup("HID Device");
+
+ modname = modalias_resolve_module(modalias);
+ DEBUG("%s: module name is [%s]\n", HID_BUS_NAME, modname);
+ add_entry(entries, device_name, modname);
+ free(modalias);
+}
+
+
+struct hid_entries hid_probe(void)
+{
+ DIR *dir;
+ struct dirent *dent;
+ struct hid_entries entry_list = {NULL, 0};
+
+ dir = opendir(sysfs_hid_path);
+ if (dir == NULL)
+ goto end_probe;
+
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ if (dent->d_name[0] == '.')
+ continue;
+ DEBUG("%s: device found %s\n", HID_BUS_NAME, dent->d_name);
+ parse_device(&entry_list, dent->d_name);
+ }
+
+end_probe:
+ if (dir)
+ closedir(dir);
+
+ return entry_list;
+}
+
+void hid_entries_free(struct hid_entries *entries)
+{
+ unsigned int i;
+ for (i = 0; i < entries->nb; i++) {
+ free(entries->entries[i].module);
+ free(entries->entries[i].text);
+ }
+ free(entries->entries);
+}
diff --git a/libldetect.h b/libldetect.h
index 6ad02e7..d4d8a5c 100644
--- a/libldetect.h
+++ b/libldetect.h
@@ -71,5 +71,25 @@ extern struct dmi_entries dmi_probe(void);
extern void dmi_entries_free(struct dmi_entries entries);
extern char *dmidecode_file;
+/******************************************************************************/
+/* hid ************************************************************************/
+/******************************************************************************/
+struct hid_entry {
+ unsigned short vendor; /* PCI vendor id */
+ unsigned short product;
+ unsigned short version;
+
+ char *module;
+ char *text;
+};
+struct hid_entries {
+ struct hid_entry *entries;
+ unsigned int nb;
+};
+
+extern struct hid_entries hid_probe(void);
+extern void hid_entries_free(struct hid_entries *entries);
+extern const char *sysfs_hid_path;
+
#endif
#pragma GCC visibility pop