1 |
#include <sys/types.h> |
2 |
#include <dirent.h> |
3 |
#include <fnmatch.h> |
4 |
#include <stdio.h> |
5 |
#include <stdlib.h> |
6 |
#include <string.h> |
7 |
|
8 |
#include "libsysfs.h" |
9 |
#include "libldetect.h" |
10 |
#include "common.h" |
11 |
|
12 |
|
13 |
#define HID_BUS_NAME "hid" |
14 |
const char *sysfs_hid_path = "/sys/bus/"HID_BUS_NAME"/devices"; |
15 |
#if 0 |
16 |
#define DEBUG(args...) printf(args) |
17 |
#else |
18 |
#define DEBUG(args...) |
19 |
#endif |
20 |
|
21 |
#if 0 |
22 |
struct module_alias { |
23 |
const char *modalias; |
24 |
const char *module; |
25 |
}; |
26 |
|
27 |
static struct module_alias aliasdb[] = { {NULL, NULL} }; |
28 |
static const char *resolve_modalias(const struct module_alias *aliasdb, |
29 |
const char *alias_name) |
30 |
{ |
31 |
const struct module_alias *alias = aliasdb; |
32 |
|
33 |
while (alias->modalias != NULL) { |
34 |
if (fnmatch(alias->modalias, alias_name, 0) == 0) |
35 |
return alias->module; |
36 |
|
37 |
alias++; |
38 |
} |
39 |
return NULL; |
40 |
} |
41 |
#endif |
42 |
|
43 |
static char *get_field_value(const char *fields, const char *field_name) |
44 |
{ |
45 |
char *modalias; |
46 |
char *end; |
47 |
|
48 |
modalias = strstr(fields, field_name); |
49 |
if (modalias == NULL) |
50 |
return NULL; |
51 |
end = strchr(modalias, '\n'); |
52 |
if (end == NULL) |
53 |
end = modalias + strlen(modalias); |
54 |
|
55 |
return strndup(modalias+strlen(field_name), end - (modalias+strlen(field_name))); |
56 |
} |
57 |
|
58 |
static char *parse_modalias(char *fields) |
59 |
{ |
60 |
return get_field_value(fields, "MODALIAS="); |
61 |
} |
62 |
|
63 |
static char *parse_name(char *fields) |
64 |
{ |
65 |
return get_field_value(fields, "HID_NAME="); |
66 |
} |
67 |
|
68 |
static void add_entry(struct hid_entries *entry_list, char *name, char *module) |
69 |
{ |
70 |
|
71 |
struct hid_entry *new_entries; |
72 |
|
73 |
new_entries = realloc(entry_list->entries, (entry_list->nb+1)*sizeof(*(entry_list->entries))); |
74 |
if (new_entries != NULL) { |
75 |
new_entries[entry_list->nb].module = module; |
76 |
new_entries[entry_list->nb].text = name; |
77 |
entry_list->entries = new_entries; |
78 |
entry_list->nb++; |
79 |
} |
80 |
} |
81 |
|
82 |
static void parse_device(struct hid_entries *entries, const char *dev) |
83 |
{ |
84 |
char keyfile[SYSFS_PATH_MAX]; |
85 |
char *modalias; |
86 |
char *modname; |
87 |
char *device_name; |
88 |
struct sysfs_attribute *sysfs_attr; |
89 |
|
90 |
snprintf(keyfile, sizeof(keyfile)-1, "%s/%s/uevent", |
91 |
sysfs_hid_path, dev); |
92 |
sysfs_attr = sysfs_open_attribute(keyfile); |
93 |
if (!sysfs_attr) |
94 |
return; |
95 |
if (sysfs_read_attribute(sysfs_attr) != 0 || !sysfs_attr->value) { |
96 |
sysfs_close_attribute(sysfs_attr); |
97 |
return; |
98 |
} |
99 |
|
100 |
DEBUG("%s: read %s\n", HID_BUS_NAME, sysfs_attr->value); |
101 |
|
102 |
modalias = parse_modalias(sysfs_attr->value); |
103 |
if (modalias == NULL) |
104 |
return; |
105 |
DEBUG("%s: modalias is [%s]\n", HID_BUS_NAME, modalias); |
106 |
|
107 |
device_name = parse_name(sysfs_attr->value); |
108 |
sysfs_close_attribute(sysfs_attr); |
109 |
if (device_name != NULL) |
110 |
DEBUG("%s: device name is [%s]\n", HID_BUS_NAME, device_name); |
111 |
else |
112 |
device_name = strdup("HID Device"); |
113 |
|
114 |
modname = modalias_resolve_module(modalias); |
115 |
free(modalias); |
116 |
DEBUG("%s: module name is [%s]\n", HID_BUS_NAME, modname); |
117 |
if (modname != NULL) |
118 |
add_entry(entries, device_name, modname); |
119 |
} |
120 |
|
121 |
|
122 |
struct hid_entries hid_probe(void) |
123 |
{ |
124 |
DIR *dir; |
125 |
struct dirent *dent; |
126 |
struct hid_entries entry_list = {NULL, 0}; |
127 |
|
128 |
dir = opendir(sysfs_hid_path); |
129 |
if (dir == NULL) |
130 |
goto end_probe; |
131 |
|
132 |
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { |
133 |
if (dent->d_name[0] == '.') |
134 |
continue; |
135 |
DEBUG("%s: device found %s\n", HID_BUS_NAME, dent->d_name); |
136 |
parse_device(&entry_list, dent->d_name); |
137 |
} |
138 |
|
139 |
end_probe: |
140 |
if (dir) |
141 |
closedir(dir); |
142 |
|
143 |
return entry_list; |
144 |
} |
145 |
|
146 |
void hid_entries_free(struct hid_entries *entries) |
147 |
{ |
148 |
unsigned int i; |
149 |
for (i = 0; i < entries->nb; i++) { |
150 |
free(entries->entries[i].module); |
151 |
free(entries->entries[i].text); |
152 |
} |
153 |
free(entries->entries); |
154 |
} |