]>
Commit | Line | Data |
---|---|---|
1 | #include <stdio.h> | |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <fcntl.h> | |
6 | #include <sys/stat.h> | |
7 | #include <sys/types.h> | |
8 | #include <linux/input.h> | |
9 | ||
10 | #include "hd.h" | |
11 | #include "hd_int.h" | |
12 | #include "hddb.h" | |
13 | #include "input.h" | |
14 | ||
15 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
16 | * input devs | |
17 | * | |
18 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
19 | */ | |
20 | ||
21 | static void get_input_devices(hd_data_t *hd_data); | |
22 | static char *all_bits(char *str); | |
23 | static int test_bit(char *str, unsigned bit); | |
24 | ||
25 | void hd_scan_input(hd_data_t *hd_data) | |
26 | { | |
27 | if(!hd_probe_feature(hd_data, pr_input)) return; | |
28 | ||
29 | hd_data->module = mod_input; | |
30 | ||
31 | /* some clean-up */ | |
32 | remove_hd_entries(hd_data); | |
33 | ||
34 | PROGRESS(1, 0, "joydev mod"); | |
35 | load_module(hd_data, "joydev"); | |
36 | ||
37 | PROGRESS(1, 1, "evdev mod"); | |
38 | load_module(hd_data, "evdev"); | |
39 | ||
40 | PROGRESS(2, 0, "input"); | |
41 | ||
42 | get_input_devices(hd_data); | |
43 | } | |
44 | ||
45 | ||
46 | #define INP_NAME "N: Name=" | |
47 | #define INP_HANDLERS "H: Handlers=" | |
48 | #define INP_KEY "B: KEY=" | |
49 | #define INP_REL "B: REL=" | |
50 | ||
51 | void get_input_devices(hd_data_t *hd_data) | |
52 | { | |
53 | hd_t *hd; | |
54 | str_list_t *input, *sl, *sl1; | |
55 | char *s; | |
56 | unsigned ok, u; | |
57 | unsigned bus, vendor, product, version; | |
58 | unsigned mouse_buttons, mouse_wheels; | |
59 | char *name = NULL, *handlers = NULL, *key = NULL, *rel = NULL; | |
60 | size_t len; | |
61 | str_list_t *handler_list; | |
62 | hd_dev_num_t dev_num = { type: 'c', range: 1 }; | |
63 | ||
64 | input = read_file("/proc/bus/input/devices", 0, 0); | |
65 | ||
66 | ADD2LOG("----- /proc/bus/input/devices -----\n"); | |
67 | for(sl = input; sl; sl = sl->next) { | |
68 | ADD2LOG(" %s", sl->str); | |
69 | } | |
70 | ADD2LOG("----- /proc/bus/input/devices end -----\n"); | |
71 | ||
72 | for(ok = 0, sl = input; sl; sl = sl->next) { | |
73 | if(*sl->str == '\n') { | |
74 | ADD2LOG("bus = %u, name = %s\n", bus, name); | |
75 | if(handlers) ADD2LOG(" handlers = %s\n", handlers); | |
76 | if(key) ADD2LOG(" key = %s\n", key); | |
77 | if(rel) ADD2LOG(" rel = %s\n", rel); | |
78 | ||
79 | mouse_buttons = 0; | |
80 | if(key) { | |
81 | for(u = BTN_MOUSE; u < BTN_MOUSE + 8; u++) { | |
82 | if(test_bit(key, u)) mouse_buttons++; | |
83 | } | |
84 | } | |
85 | ADD2LOG(" mouse buttons = %u\n", mouse_buttons); | |
86 | ||
87 | mouse_wheels = 0; | |
88 | if(rel) { | |
89 | for(u = REL_HWHEEL; u <= REL_MAX; u++) { | |
90 | if(test_bit(rel, u)) mouse_wheels++; | |
91 | } | |
92 | } | |
93 | ADD2LOG(" mouse wheels = %u\n", mouse_wheels); | |
94 | ||
95 | if(ok && handlers) { | |
96 | handler_list = hd_split(' ', handlers); | |
97 | ||
98 | if(bus == BUS_USB) { | |
99 | s = NULL; | |
100 | for(sl1 = handler_list; sl1; sl1 = sl1->next) { | |
101 | if(sscanf(sl1->str, "mouse%u", &u) == 1) { | |
102 | str_printf(&s, 0, "/dev/input/mouse%u", u); | |
103 | break; | |
104 | } | |
105 | } | |
106 | ||
107 | if(s) { | |
108 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
109 | if(hd->unix_dev_name2 && !strcmp(hd->unix_dev_name2, s)) { | |
110 | hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210); | |
111 | hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons); | |
112 | } | |
113 | } | |
114 | } | |
115 | ||
116 | s = free_mem(s); | |
117 | } | |
118 | else { | |
119 | if(search_str_list(handler_list, "kbd") && test_bit(key, KEY_1)) { | |
120 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
121 | hd->base_class.id = bc_keyboard; | |
122 | hd->sub_class.id = sc_keyboard_kbd; | |
123 | hd->bus.id = bus_ps2; | |
124 | ||
125 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0211); | |
126 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0001); | |
127 | hd->device.name = new_str(name); | |
128 | ||
129 | for(sl1 = handler_list; sl1; sl1 = sl1->next) { | |
130 | if(sscanf(sl1->str, "event%u", &u) == 1) { | |
131 | str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u); | |
132 | dev_num.major = 13; | |
133 | dev_num.minor = 64 + u; | |
134 | hd->unix_dev_num = dev_num; | |
135 | break; | |
136 | } | |
137 | } | |
138 | } | |
139 | else if(strstr(handlers, "mouse")) { | |
140 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
141 | hd->base_class.id = bc_mouse; | |
142 | hd->sub_class.id = sc_mou_ps2; | |
143 | hd->bus.id = bus_ps2; | |
144 | ||
145 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210); | |
146 | hd->device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons); | |
147 | hd->device.name = new_str(name); | |
148 | ||
149 | /* Synaptics/Alps TouchPad */ | |
150 | if(vendor == 2 && (product == 7 || product == 8)) { | |
151 | hd->compat_vendor.id = hd->vendor.id; | |
152 | hd->compat_device.id = hd->device.id; | |
153 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0212); | |
154 | hd->device.id = MAKE_ID(TAG_SPECIAL, product - 6); | |
155 | } | |
156 | ||
157 | hd->unix_dev_name = new_str(DEV_MICE); | |
158 | dev_num.major = 13; | |
159 | dev_num.minor = 63; | |
160 | hd->unix_dev_num = dev_num; | |
161 | ||
162 | for(sl1 = handler_list; sl1; sl1 = sl1->next) { | |
163 | if(sscanf(sl1->str, "mouse%u", &u) == 1) { | |
164 | str_printf(&hd->unix_dev_name2, 0, "/dev/input/mouse%u", u); | |
165 | dev_num.major = 13; | |
166 | dev_num.minor = 32 + u; | |
167 | hd->unix_dev_num2 = dev_num; | |
168 | break; | |
169 | } | |
170 | } | |
171 | ||
172 | } | |
173 | } | |
174 | ||
175 | handler_list = free_str_list(handler_list); | |
176 | } | |
177 | ||
178 | ok = 0; | |
179 | ||
180 | name = free_mem(name); | |
181 | handlers = free_mem(handlers); | |
182 | key = free_mem(key); | |
183 | rel = free_mem(rel); | |
184 | } | |
185 | ||
186 | if(sscanf(sl->str, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x", &bus, &vendor, &product, &version) == 4) { | |
187 | ok = 1; | |
188 | continue; | |
189 | } | |
190 | ||
191 | if(!strncmp(sl->str, INP_NAME, sizeof INP_NAME - 1)) { | |
192 | s = sl->str + sizeof INP_NAME; | |
193 | len = strlen(s); | |
194 | if(len > 2) { | |
195 | name = canon_str(s, len - 2); | |
196 | } | |
197 | continue; | |
198 | } | |
199 | ||
200 | if(!strncmp(sl->str, INP_HANDLERS, sizeof INP_HANDLERS - 1)) { | |
201 | s = sl->str + sizeof INP_HANDLERS - 1; | |
202 | handlers = canon_str(s, strlen(s)); | |
203 | continue; | |
204 | } | |
205 | ||
206 | if(!strncmp(sl->str, INP_KEY, sizeof INP_KEY - 1)) { | |
207 | s = sl->str + sizeof INP_KEY - 1; | |
208 | key = canon_str(s, strlen(s)); | |
209 | key = all_bits(key); | |
210 | continue; | |
211 | } | |
212 | ||
213 | if(!strncmp(sl->str, INP_REL, sizeof INP_REL - 1)) { | |
214 | s = sl->str + sizeof INP_REL - 1; | |
215 | rel = canon_str(s, strlen(s)); | |
216 | rel = all_bits(rel); | |
217 | continue; | |
218 | } | |
219 | } | |
220 | ||
221 | free_str_list(input); | |
222 | ||
223 | } | |
224 | ||
225 | ||
226 | char *all_bits(char *str) | |
227 | { | |
228 | str_list_t *sl, *sl0; | |
229 | char *s = NULL; | |
230 | unsigned u; | |
231 | ||
232 | if(!str) return NULL; | |
233 | ||
234 | sl = sl0 = hd_split(' ', str); | |
235 | for(; sl; sl = sl->next) { | |
236 | u = strtoul(sl->str, NULL, 16); | |
237 | str_printf(&s, -1, "%08x", u); | |
238 | } | |
239 | free_str_list(sl0); | |
240 | free_mem(str); | |
241 | ||
242 | return s; | |
243 | } | |
244 | ||
245 | ||
246 | int test_bit(char *str, unsigned bit) | |
247 | { | |
248 | size_t len, ofs; | |
249 | unsigned u, mask; | |
250 | ||
251 | if(!str) return 0; | |
252 | ||
253 | len = strlen(str); | |
254 | ||
255 | ofs = bit >> 2; | |
256 | mask = 1 << (bit & 3); | |
257 | ||
258 | if(ofs >= len) return 0; | |
259 | ||
260 | ofs = len - ofs - 1; | |
261 | ||
262 | u = str[ofs] >= 'a' ? str[ofs] - 'a' + 10 : str[ofs] - '0'; | |
263 | ||
264 | return (u & mask) ? 1 : 0; | |
265 | } | |
266 | ||
267 |