InputClass.c revision 1b5d61b8
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
37static 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
70static void
71xf86freeInputClassList(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
150enum MatchType {
151    MATCH_NORMAL,
152    MATCH_NEGATED,
153};
154
155static void
156add_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
168XF86ConfInputClassPtr
169xf86parseInputClassSection(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
395void
396xf86printInputClassSection(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