1 /*
2 * Copyright (c) 2009 Dan Nicholson
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #ifdef HAVE_XORG_CONFIG_H
27 #include <xorg-config.h>
28 #endif
29
30 #include <string.h>
31 #include "os.h"
32 #include "xf86Parser.h"
33 #include "xf86tokens.h"
34 #include "Configint.h"
35
36
37 static const xf86ConfigSymTabRec InputClassTab[] = {
38 {ENDSECTION, "endsection"},
39 {IDENTIFIER, "identifier"},
40 {OPTION, "option"},
41 {DRIVER, "driver"},
42 {MATCH_PRODUCT, "matchproduct"},
43 {MATCH_VENDOR, "matchvendor"},
44 {MATCH_DEVICE_PATH, "matchdevicepath"},
45 {MATCH_OS, "matchos"},
46 {MATCH_PNPID, "matchpnpid"},
47 {MATCH_USBID, "matchusbid"},
48 {MATCH_DRIVER, "matchdriver"},
49 {MATCH_TAG, "matchtag"},
50 {MATCH_LAYOUT, "matchlayout"},
51 {MATCH_IS_KEYBOARD, "matchiskeyboard"},
52 {MATCH_IS_POINTER, "matchispointer"},
53 {MATCH_IS_JOYSTICK, "matchisjoystick"},
54 {MATCH_IS_TABLET, "matchistablet"},
55 {MATCH_IS_TABLET_PAD, "matchistabletpad"},
56 {MATCH_IS_TOUCHPAD, "matchistouchpad"},
57 {MATCH_IS_TOUCHSCREEN, "matchistouchscreen"},
58 {NOMATCH_PRODUCT, "nomatchproduct"},
59 {NOMATCH_VENDOR, "nomatchvendor"},
60 {NOMATCH_DEVICE_PATH, "nomatchdevicepath"},
61 {NOMATCH_OS, "nomatchos"},
62 {NOMATCH_PNPID, "nomatchpnpid"},
63 {NOMATCH_USBID, "nomatchusbid"},
64 {NOMATCH_DRIVER, "nomatchdriver"},
65 {NOMATCH_TAG, "nomatchtag"},
66 {NOMATCH_LAYOUT, "nomatchlayout"},
67 {-1, ""},
68 };
69
70 static void
xf86freeInputClassList(XF86ConfInputClassPtr ptr)71 xf86freeInputClassList(XF86ConfInputClassPtr ptr)
72 {
73 XF86ConfInputClassPtr prev;
74
75 while (ptr) {
76 xf86MatchGroup *group, *next;
77 char **list;
78
79 TestFree(ptr->identifier);
80 TestFree(ptr->driver);
81
82 xorg_list_for_each_entry_safe(group, next, &ptr->match_product, entry) {
83 xorg_list_del(&group->entry);
84 for (list = group->values; *list; list++)
85 free(*list);
86 free(group);
87 }
88 xorg_list_for_each_entry_safe(group, next, &ptr->match_vendor, entry) {
89 xorg_list_del(&group->entry);
90 for (list = group->values; *list; list++)
91 free(*list);
92 free(group);
93 }
94 xorg_list_for_each_entry_safe(group, next, &ptr->match_device, entry) {
95 xorg_list_del(&group->entry);
96 for (list = group->values; *list; list++)
97 free(*list);
98 free(group);
99 }
100 xorg_list_for_each_entry_safe(group, next, &ptr->match_os, entry) {
101 xorg_list_del(&group->entry);
102 for (list = group->values; *list; list++)
103 free(*list);
104 free(group);
105 }
106 xorg_list_for_each_entry_safe(group, next, &ptr->match_pnpid, entry) {
107 xorg_list_del(&group->entry);
108 for (list = group->values; *list; list++)
109 free(*list);
110 free(group);
111 }
112 xorg_list_for_each_entry_safe(group, next, &ptr->match_usbid, entry) {
113 xorg_list_del(&group->entry);
114 for (list = group->values; *list; list++)
115 free(*list);
116 free(group);
117 }
118 xorg_list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
119 xorg_list_del(&group->entry);
120 for (list = group->values; *list; list++)
121 free(*list);
122 free(group);
123 }
124 xorg_list_for_each_entry_safe(group, next, &ptr->match_tag, entry) {
125 xorg_list_del(&group->entry);
126 for (list = group->values; *list; list++)
127 free(*list);
128 free(group);
129 }
130 xorg_list_for_each_entry_safe(group, next, &ptr->match_layout, entry) {
131 xorg_list_del(&group->entry);
132 for (list = group->values; *list; list++)
133 free(*list);
134 free(group);
135 }
136
137 TestFree(ptr->comment);
138 xf86optionListFree(ptr->option_lst);
139
140 prev = ptr;
141 ptr = ptr->list.next;
142 free(prev);
143 }
144 }
145
146 #define CLEANUP xf86freeInputClassList
147
148 #define TOKEN_SEP "|"
149
150 enum MatchType {
151 MATCH_NORMAL,
152 MATCH_NEGATED,
153 };
154
155 static void
add_group_entry(struct xorg_list * head,char ** values,enum MatchType type)156 add_group_entry(struct xorg_list *head, char **values, enum MatchType type)
157 {
158 xf86MatchGroup *group;
159
160 group = malloc(sizeof(*group));
161 if (group) {
162 group->is_negated = (type == MATCH_NEGATED);
163 group->values = values;
164 xorg_list_add(&group->entry, head);
165 }
166 }
167
168 XF86ConfInputClassPtr
xf86parseInputClassSection(void)169 xf86parseInputClassSection(void)
170 {
171 int has_ident = FALSE;
172 int token;
173 enum MatchType matchtype;
174
175 parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec)
176
177 /* Initialize MatchGroup lists */
178 xorg_list_init(&ptr->match_product);
179 xorg_list_init(&ptr->match_vendor);
180 xorg_list_init(&ptr->match_device);
181 xorg_list_init(&ptr->match_os);
182 xorg_list_init(&ptr->match_pnpid);
183 xorg_list_init(&ptr->match_usbid);
184 xorg_list_init(&ptr->match_driver);
185 xorg_list_init(&ptr->match_tag);
186 xorg_list_init(&ptr->match_layout);
187
188 while ((token = xf86getToken(InputClassTab)) != ENDSECTION) {
189 matchtype = MATCH_NORMAL;
190
191 switch (token) {
192 case COMMENT:
193 ptr->comment = xf86addComment(ptr->comment, xf86_lex_val.str);
194 break;
195 case IDENTIFIER:
196 if (xf86getSubToken(&(ptr->comment)) != STRING)
197 Error(QUOTE_MSG, "Identifier");
198 if (has_ident == TRUE)
199 Error(MULTIPLE_MSG, "Identifier");
200 ptr->identifier = xf86_lex_val.str;
201 has_ident = TRUE;
202 break;
203 case DRIVER:
204 if (xf86getSubToken(&(ptr->comment)) != STRING)
205 Error(QUOTE_MSG, "Driver");
206 if (strcmp(xf86_lex_val.str, "keyboard") == 0) {
207 ptr->driver = strdup("kbd");
208 free(xf86_lex_val.str);
209 }
210 else
211 ptr->driver = xf86_lex_val.str;
212 break;
213 case OPTION:
214 ptr->option_lst = xf86parseOption(ptr->option_lst);
215 break;
216 case NOMATCH_PRODUCT:
217 matchtype = MATCH_NEGATED;
218 /* fallthrough */
219 case MATCH_PRODUCT:
220 if (xf86getSubToken(&(ptr->comment)) != STRING)
221 Error(QUOTE_MSG, "MatchProduct");
222 add_group_entry(&ptr->match_product,
223 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
224 matchtype);
225 free(xf86_lex_val.str);
226 break;
227 case NOMATCH_VENDOR:
228 matchtype = MATCH_NEGATED;
229 /* fallthrough */
230 case MATCH_VENDOR:
231 if (xf86getSubToken(&(ptr->comment)) != STRING)
232 Error(QUOTE_MSG, "MatchVendor");
233 add_group_entry(&ptr->match_vendor,
234 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
235 matchtype);
236 free(xf86_lex_val.str);
237 break;
238 case NOMATCH_DEVICE_PATH:
239 matchtype = MATCH_NEGATED;
240 /* fallthrough */
241 case MATCH_DEVICE_PATH:
242 if (xf86getSubToken(&(ptr->comment)) != STRING)
243 Error(QUOTE_MSG, "MatchDevicePath");
244 add_group_entry(&ptr->match_device,
245 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
246 matchtype);
247 free(xf86_lex_val.str);
248 break;
249 case NOMATCH_OS:
250 matchtype = MATCH_NEGATED;
251 /* fallthrough */
252 case MATCH_OS:
253 if (xf86getSubToken(&(ptr->comment)) != STRING)
254 Error(QUOTE_MSG, "MatchOS");
255 add_group_entry(&ptr->match_os, xstrtokenize(xf86_lex_val.str,
256 TOKEN_SEP),
257 matchtype);
258 free(xf86_lex_val.str);
259 break;
260 case NOMATCH_PNPID:
261 matchtype = MATCH_NEGATED;
262 /* fallthrough */
263 case MATCH_PNPID:
264 if (xf86getSubToken(&(ptr->comment)) != STRING)
265 Error(QUOTE_MSG, "MatchPnPID");
266 add_group_entry(&ptr->match_pnpid,
267 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
268 matchtype);
269 free(xf86_lex_val.str);
270 break;
271 case NOMATCH_USBID:
272 matchtype = MATCH_NEGATED;
273 /* fallthrough */
274 case MATCH_USBID:
275 if (xf86getSubToken(&(ptr->comment)) != STRING)
276 Error(QUOTE_MSG, "MatchUSBID");
277 add_group_entry(&ptr->match_usbid,
278 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
279 matchtype);
280 free(xf86_lex_val.str);
281 break;
282 case NOMATCH_DRIVER:
283 matchtype = MATCH_NEGATED;
284 /* fallthrough */
285 case MATCH_DRIVER:
286 if (xf86getSubToken(&(ptr->comment)) != STRING)
287 Error(QUOTE_MSG, "MatchDriver");
288 add_group_entry(&ptr->match_driver,
289 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
290 matchtype);
291 free(xf86_lex_val.str);
292 break;
293 case NOMATCH_TAG:
294 matchtype = MATCH_NEGATED;
295 /* fallthrough */
296 case MATCH_TAG:
297 if (xf86getSubToken(&(ptr->comment)) != STRING)
298 Error(QUOTE_MSG, "MatchTag");
299 add_group_entry(&ptr->match_tag, xstrtokenize(xf86_lex_val.str,
300 TOKEN_SEP),
301 matchtype);
302 free(xf86_lex_val.str);
303 break;
304 case NOMATCH_LAYOUT:
305 matchtype = MATCH_NEGATED;
306 /* fallthrough */
307 case MATCH_LAYOUT:
308 if (xf86getSubToken(&(ptr->comment)) != STRING)
309 Error(QUOTE_MSG, "MatchLayout");
310 add_group_entry(&ptr->match_layout,
311 xstrtokenize(xf86_lex_val.str, TOKEN_SEP),
312 matchtype);
313 free(xf86_lex_val.str);
314 break;
315 case MATCH_IS_KEYBOARD:
316 if (xf86getSubToken(&(ptr->comment)) != STRING)
317 Error(QUOTE_MSG, "MatchIsKeyboard");
318 ptr->is_keyboard.set = xf86getBoolValue(&ptr->is_keyboard.val,
319 xf86_lex_val.str);
320 free(xf86_lex_val.str);
321 if (!ptr->is_keyboard.set)
322 Error(BOOL_MSG, "MatchIsKeyboard");
323 break;
324 case MATCH_IS_POINTER:
325 if (xf86getSubToken(&(ptr->comment)) != STRING)
326 Error(QUOTE_MSG, "MatchIsPointer");
327 ptr->is_pointer.set = xf86getBoolValue(&ptr->is_pointer.val,
328 xf86_lex_val.str);
329 free(xf86_lex_val.str);
330 if (!ptr->is_pointer.set)
331 Error(BOOL_MSG, "MatchIsPointer");
332 break;
333 case MATCH_IS_JOYSTICK:
334 if (xf86getSubToken(&(ptr->comment)) != STRING)
335 Error(QUOTE_MSG, "MatchIsJoystick");
336 ptr->is_joystick.set = xf86getBoolValue(&ptr->is_joystick.val,
337 xf86_lex_val.str);
338 free(xf86_lex_val.str);
339 if (!ptr->is_joystick.set)
340 Error(BOOL_MSG, "MatchIsJoystick");
341 break;
342 case MATCH_IS_TABLET:
343 if (xf86getSubToken(&(ptr->comment)) != STRING)
344 Error(QUOTE_MSG, "MatchIsTablet");
345 ptr->is_tablet.set = xf86getBoolValue(&ptr->is_tablet.val, xf86_lex_val.str);
346 free(xf86_lex_val.str);
347 if (!ptr->is_tablet.set)
348 Error(BOOL_MSG, "MatchIsTablet");
349 break;
350 case MATCH_IS_TABLET_PAD:
351 if (xf86getSubToken(&(ptr->comment)) != STRING)
352 Error(QUOTE_MSG, "MatchIsTabletPad");
353 ptr->is_tablet_pad.set = xf86getBoolValue(&ptr->is_tablet_pad.val, xf86_lex_val.str);
354 free(xf86_lex_val.str);
355 if (!ptr->is_tablet_pad.set)
356 Error(BOOL_MSG, "MatchIsTabletPad");
357 break;
358 case MATCH_IS_TOUCHPAD:
359 if (xf86getSubToken(&(ptr->comment)) != STRING)
360 Error(QUOTE_MSG, "MatchIsTouchpad");
361 ptr->is_touchpad.set = xf86getBoolValue(&ptr->is_touchpad.val,
362 xf86_lex_val.str);
363 free(xf86_lex_val.str);
364 if (!ptr->is_touchpad.set)
365 Error(BOOL_MSG, "MatchIsTouchpad");
366 break;
367 case MATCH_IS_TOUCHSCREEN:
368 if (xf86getSubToken(&(ptr->comment)) != STRING)
369 Error(QUOTE_MSG, "MatchIsTouchscreen");
370 ptr->is_touchscreen.set = xf86getBoolValue(&ptr->is_touchscreen.val,
371 xf86_lex_val.str);
372 free(xf86_lex_val.str);
373 if (!ptr->is_touchscreen.set)
374 Error(BOOL_MSG, "MatchIsTouchscreen");
375 break;
376 case EOF_TOKEN:
377 Error(UNEXPECTED_EOF_MSG);
378 break;
379 default:
380 Error(INVALID_KEYWORD_MSG, xf86tokenString());
381 break;
382 }
383 }
384
385 if (!has_ident)
386 Error(NO_IDENT_MSG);
387
388 #ifdef DEBUG
389 printf("InputClass section parsed\n");
390 #endif
391
392 return ptr;
393 }
394
395 void
xf86printInputClassSection(FILE * cf,XF86ConfInputClassPtr ptr)396 xf86printInputClassSection(FILE * cf, XF86ConfInputClassPtr ptr)
397 {
398 const xf86MatchGroup *group;
399 char *const *cur;
400
401 while (ptr) {
402 fprintf(cf, "Section \"InputClass\"\n");
403 if (ptr->comment)
404 fprintf(cf, "%s", ptr->comment);
405 if (ptr->identifier)
406 fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
407 if (ptr->driver)
408 fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
409
410 xorg_list_for_each_entry(group, &ptr->match_product, entry) {
411 fprintf(cf, "\tMatchProduct \"");
412 for (cur = group->values; *cur; cur++)
413 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
414 *cur);
415 fprintf(cf, "\"\n");
416 }
417 xorg_list_for_each_entry(group, &ptr->match_vendor, entry) {
418 fprintf(cf, "\tMatchVendor \"");
419 for (cur = group->values; *cur; cur++)
420 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
421 *cur);
422 fprintf(cf, "\"\n");
423 }
424 xorg_list_for_each_entry(group, &ptr->match_device, entry) {
425 fprintf(cf, "\tMatchDevicePath \"");
426 for (cur = group->values; *cur; cur++)
427 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
428 *cur);
429 fprintf(cf, "\"\n");
430 }
431 xorg_list_for_each_entry(group, &ptr->match_os, entry) {
432 fprintf(cf, "\tMatchOS \"");
433 for (cur = group->values; *cur; cur++)
434 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
435 *cur);
436 fprintf(cf, "\"\n");
437 }
438 xorg_list_for_each_entry(group, &ptr->match_pnpid, entry) {
439 fprintf(cf, "\tMatchPnPID \"");
440 for (cur = group->values; *cur; cur++)
441 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
442 *cur);
443 fprintf(cf, "\"\n");
444 }
445 xorg_list_for_each_entry(group, &ptr->match_usbid, entry) {
446 fprintf(cf, "\tMatchUSBID \"");
447 for (cur = group->values; *cur; cur++)
448 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
449 *cur);
450 fprintf(cf, "\"\n");
451 }
452 xorg_list_for_each_entry(group, &ptr->match_driver, entry) {
453 fprintf(cf, "\tMatchDriver \"");
454 for (cur = group->values; *cur; cur++)
455 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
456 *cur);
457 fprintf(cf, "\"\n");
458 }
459 xorg_list_for_each_entry(group, &ptr->match_tag, entry) {
460 fprintf(cf, "\tMatchTag \"");
461 for (cur = group->values; *cur; cur++)
462 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
463 *cur);
464 fprintf(cf, "\"\n");
465 }
466 xorg_list_for_each_entry(group, &ptr->match_layout, entry) {
467 fprintf(cf, "\tMatchLayout \"");
468 for (cur = group->values; *cur; cur++)
469 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
470 *cur);
471 fprintf(cf, "\"\n");
472 }
473
474 if (ptr->is_keyboard.set)
475 fprintf(cf, "\tIsKeyboard \"%s\"\n",
476 ptr->is_keyboard.val ? "yes" : "no");
477 if (ptr->is_pointer.set)
478 fprintf(cf, "\tIsPointer \"%s\"\n",
479 ptr->is_pointer.val ? "yes" : "no");
480 if (ptr->is_joystick.set)
481 fprintf(cf, "\tIsJoystick \"%s\"\n",
482 ptr->is_joystick.val ? "yes" : "no");
483 if (ptr->is_tablet.set)
484 fprintf(cf, "\tIsTablet \"%s\"\n",
485 ptr->is_tablet.val ? "yes" : "no");
486 if (ptr->is_tablet_pad.set)
487 fprintf(cf, "\tIsTabletPad \"%s\"\n",
488 ptr->is_tablet_pad.val ? "yes" : "no");
489 if (ptr->is_touchpad.set)
490 fprintf(cf, "\tIsTouchpad \"%s\"\n",
491 ptr->is_touchpad.val ? "yes" : "no");
492 if (ptr->is_touchscreen.set)
493 fprintf(cf, "\tIsTouchscreen \"%s\"\n",
494 ptr->is_touchscreen.val ? "yes" : "no");
495 xf86printOptionList(cf, ptr->option_lst, 1);
496 fprintf(cf, "EndSection\n\n");
497 ptr = ptr->list.next;
498 }
499 }
500