diff options
author | Christophe Fergeau <cfergeau@mandriva.com> | 2009-04-03 17:46:33 +0000 |
---|---|---|
committer | Christophe Fergeau <cfergeau@mandriva.com> | 2009-04-03 17:46:33 +0000 |
commit | 8569a28793faad34b2697591bdc6519c28462ca7 (patch) | |
tree | b151f68b0fa897e989324fdf860595f1e7bbcdcb | |
parent | c332dcbce4b0030ece7a8bd88ac1bc15980ec47b (diff) | |
download | ldetect-8569a28793faad34b2697591bdc6519c28462ca7.tar ldetect-8569a28793faad34b2697591bdc6519c28462ca7.tar.gz ldetect-8569a28793faad34b2697591bdc6519c28462ca7.tar.bz2 ldetect-8569a28793faad34b2697591bdc6519c28462ca7.tar.xz ldetect-8569a28793faad34b2697591bdc6519c28462ca7.zip |
Add hid device enumerator
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | hid.c | 152 | ||||
-rw-r--r-- | libldetect.h | 20 |
3 files changed, 175 insertions, 1 deletions
@@ -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) @@ -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 |