From 8569a28793faad34b2697591bdc6519c28462ca7 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Fri, 3 Apr 2009 17:46:33 +0000 Subject: Add hid device enumerator --- hid.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 hid.c (limited to 'hid.c') 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 +#include +#include +#include +#include +#include + +#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); +} -- cgit v1.2.1