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 free(xf86_lex_val.str); 195 xf86_lex_val.str = NULL; 196 break; 197 case IDENTIFIER: 198 if (xf86getSubToken(&(ptr->comment)) != STRING) 199 Error(QUOTE_MSG, "Identifier"); 200 if (has_ident == TRUE) 201 Error(MULTIPLE_MSG, "Identifier"); 202 ptr->identifier = xf86_lex_val.str; 203 has_ident = TRUE; 204 break; 205 case DRIVER: 206 if (xf86getSubToken(&(ptr->comment)) != STRING) 207 Error(QUOTE_MSG, "Driver"); 208 if (strcmp(xf86_lex_val.str, "keyboard") == 0) { 209 ptr->driver = strdup("kbd"); 210 free(xf86_lex_val.str); 211 } 212 else 213 ptr->driver = xf86_lex_val.str; 214 break; 215 case OPTION: 216 ptr->option_lst = xf86parseOption(ptr->option_lst); 217 break; 218 case NOMATCH_PRODUCT: 219 matchtype = MATCH_NEGATED; 220 /* fallthrough */ 221 case MATCH_PRODUCT: 222 if (xf86getSubToken(&(ptr->comment)) != STRING) 223 Error(QUOTE_MSG, "MatchProduct"); 224 add_group_entry(&ptr->match_product, 225 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 226 matchtype); 227 free(xf86_lex_val.str); 228 break; 229 case NOMATCH_VENDOR: 230 matchtype = MATCH_NEGATED; 231 /* fallthrough */ 232 case MATCH_VENDOR: 233 if (xf86getSubToken(&(ptr->comment)) != STRING) 234 Error(QUOTE_MSG, "MatchVendor"); 235 add_group_entry(&ptr->match_vendor, 236 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 237 matchtype); 238 free(xf86_lex_val.str); 239 break; 240 case NOMATCH_DEVICE_PATH: 241 matchtype = MATCH_NEGATED; 242 /* fallthrough */ 243 case MATCH_DEVICE_PATH: 244 if (xf86getSubToken(&(ptr->comment)) != STRING) 245 Error(QUOTE_MSG, "MatchDevicePath"); 246 add_group_entry(&ptr->match_device, 247 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 248 matchtype); 249 free(xf86_lex_val.str); 250 break; 251 case NOMATCH_OS: 252 matchtype = MATCH_NEGATED; 253 /* fallthrough */ 254 case MATCH_OS: 255 if (xf86getSubToken(&(ptr->comment)) != STRING) 256 Error(QUOTE_MSG, "MatchOS"); 257 add_group_entry(&ptr->match_os, xstrtokenize(xf86_lex_val.str, 258 TOKEN_SEP), 259 matchtype); 260 free(xf86_lex_val.str); 261 break; 262 case NOMATCH_PNPID: 263 matchtype = MATCH_NEGATED; 264 /* fallthrough */ 265 case MATCH_PNPID: 266 if (xf86getSubToken(&(ptr->comment)) != STRING) 267 Error(QUOTE_MSG, "MatchPnPID"); 268 add_group_entry(&ptr->match_pnpid, 269 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 270 matchtype); 271 free(xf86_lex_val.str); 272 break; 273 case NOMATCH_USBID: 274 matchtype = MATCH_NEGATED; 275 /* fallthrough */ 276 case MATCH_USBID: 277 if (xf86getSubToken(&(ptr->comment)) != STRING) 278 Error(QUOTE_MSG, "MatchUSBID"); 279 add_group_entry(&ptr->match_usbid, 280 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 281 matchtype); 282 free(xf86_lex_val.str); 283 break; 284 case NOMATCH_DRIVER: 285 matchtype = MATCH_NEGATED; 286 /* fallthrough */ 287 case MATCH_DRIVER: 288 if (xf86getSubToken(&(ptr->comment)) != STRING) 289 Error(QUOTE_MSG, "MatchDriver"); 290 add_group_entry(&ptr->match_driver, 291 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 292 matchtype); 293 free(xf86_lex_val.str); 294 break; 295 case NOMATCH_TAG: 296 matchtype = MATCH_NEGATED; 297 /* fallthrough */ 298 case MATCH_TAG: 299 if (xf86getSubToken(&(ptr->comment)) != STRING) 300 Error(QUOTE_MSG, "MatchTag"); 301 add_group_entry(&ptr->match_tag, xstrtokenize(xf86_lex_val.str, 302 TOKEN_SEP), 303 matchtype); 304 free(xf86_lex_val.str); 305 break; 306 case NOMATCH_LAYOUT: 307 matchtype = MATCH_NEGATED; 308 /* fallthrough */ 309 case MATCH_LAYOUT: 310 if (xf86getSubToken(&(ptr->comment)) != STRING) 311 Error(QUOTE_MSG, "MatchLayout"); 312 add_group_entry(&ptr->match_layout, 313 xstrtokenize(xf86_lex_val.str, TOKEN_SEP), 314 matchtype); 315 free(xf86_lex_val.str); 316 break; 317 case MATCH_IS_KEYBOARD: 318 if (xf86getSubToken(&(ptr->comment)) != STRING) 319 Error(QUOTE_MSG, "MatchIsKeyboard"); 320 ptr->is_keyboard.set = xf86getBoolValue(&ptr->is_keyboard.val, 321 xf86_lex_val.str); 322 free(xf86_lex_val.str); 323 if (!ptr->is_keyboard.set) 324 Error(BOOL_MSG, "MatchIsKeyboard"); 325 break; 326 case MATCH_IS_POINTER: 327 if (xf86getSubToken(&(ptr->comment)) != STRING) 328 Error(QUOTE_MSG, "MatchIsPointer"); 329 ptr->is_pointer.set = xf86getBoolValue(&ptr->is_pointer.val, 330 xf86_lex_val.str); 331 free(xf86_lex_val.str); 332 if (!ptr->is_pointer.set) 333 Error(BOOL_MSG, "MatchIsPointer"); 334 break; 335 case MATCH_IS_JOYSTICK: 336 if (xf86getSubToken(&(ptr->comment)) != STRING) 337 Error(QUOTE_MSG, "MatchIsJoystick"); 338 ptr->is_joystick.set = xf86getBoolValue(&ptr->is_joystick.val, 339 xf86_lex_val.str); 340 free(xf86_lex_val.str); 341 if (!ptr->is_joystick.set) 342 Error(BOOL_MSG, "MatchIsJoystick"); 343 break; 344 case MATCH_IS_TABLET: 345 if (xf86getSubToken(&(ptr->comment)) != STRING) 346 Error(QUOTE_MSG, "MatchIsTablet"); 347 ptr->is_tablet.set = xf86getBoolValue(&ptr->is_tablet.val, xf86_lex_val.str); 348 free(xf86_lex_val.str); 349 if (!ptr->is_tablet.set) 350 Error(BOOL_MSG, "MatchIsTablet"); 351 break; 352 case MATCH_IS_TABLET_PAD: 353 if (xf86getSubToken(&(ptr->comment)) != STRING) 354 Error(QUOTE_MSG, "MatchIsTabletPad"); 355 ptr->is_tablet_pad.set = xf86getBoolValue(&ptr->is_tablet_pad.val, xf86_lex_val.str); 356 free(xf86_lex_val.str); 357 if (!ptr->is_tablet_pad.set) 358 Error(BOOL_MSG, "MatchIsTabletPad"); 359 break; 360 case MATCH_IS_TOUCHPAD: 361 if (xf86getSubToken(&(ptr->comment)) != STRING) 362 Error(QUOTE_MSG, "MatchIsTouchpad"); 363 ptr->is_touchpad.set = xf86getBoolValue(&ptr->is_touchpad.val, 364 xf86_lex_val.str); 365 free(xf86_lex_val.str); 366 if (!ptr->is_touchpad.set) 367 Error(BOOL_MSG, "MatchIsTouchpad"); 368 break; 369 case MATCH_IS_TOUCHSCREEN: 370 if (xf86getSubToken(&(ptr->comment)) != STRING) 371 Error(QUOTE_MSG, "MatchIsTouchscreen"); 372 ptr->is_touchscreen.set = xf86getBoolValue(&ptr->is_touchscreen.val, 373 xf86_lex_val.str); 374 free(xf86_lex_val.str); 375 if (!ptr->is_touchscreen.set) 376 Error(BOOL_MSG, "MatchIsTouchscreen"); 377 break; 378 case EOF_TOKEN: 379 Error(UNEXPECTED_EOF_MSG); 380 break; 381 default: 382 Error(INVALID_KEYWORD_MSG, xf86tokenString()); 383 break; 384 } 385 } 386 387 if (!has_ident) 388 Error(NO_IDENT_MSG); 389 390#ifdef DEBUG 391 printf("InputClass section parsed\n"); 392#endif 393 394 return ptr; 395} 396 397void 398xf86printInputClassSection(FILE * cf, XF86ConfInputClassPtr ptr) 399{ 400 const xf86MatchGroup *group; 401 char *const *cur; 402 403 while (ptr) { 404 fprintf(cf, "Section \"InputClass\"\n"); 405 if (ptr->comment) 406 fprintf(cf, "%s", ptr->comment); 407 if (ptr->identifier) 408 fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier); 409 if (ptr->driver) 410 fprintf(cf, "\tDriver \"%s\"\n", ptr->driver); 411 412 xorg_list_for_each_entry(group, &ptr->match_product, entry) { 413 fprintf(cf, "\tMatchProduct \""); 414 for (cur = group->values; *cur; cur++) 415 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 416 *cur); 417 fprintf(cf, "\"\n"); 418 } 419 xorg_list_for_each_entry(group, &ptr->match_vendor, entry) { 420 fprintf(cf, "\tMatchVendor \""); 421 for (cur = group->values; *cur; cur++) 422 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 423 *cur); 424 fprintf(cf, "\"\n"); 425 } 426 xorg_list_for_each_entry(group, &ptr->match_device, entry) { 427 fprintf(cf, "\tMatchDevicePath \""); 428 for (cur = group->values; *cur; cur++) 429 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 430 *cur); 431 fprintf(cf, "\"\n"); 432 } 433 xorg_list_for_each_entry(group, &ptr->match_os, entry) { 434 fprintf(cf, "\tMatchOS \""); 435 for (cur = group->values; *cur; cur++) 436 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 437 *cur); 438 fprintf(cf, "\"\n"); 439 } 440 xorg_list_for_each_entry(group, &ptr->match_pnpid, entry) { 441 fprintf(cf, "\tMatchPnPID \""); 442 for (cur = group->values; *cur; cur++) 443 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 444 *cur); 445 fprintf(cf, "\"\n"); 446 } 447 xorg_list_for_each_entry(group, &ptr->match_usbid, entry) { 448 fprintf(cf, "\tMatchUSBID \""); 449 for (cur = group->values; *cur; cur++) 450 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 451 *cur); 452 fprintf(cf, "\"\n"); 453 } 454 xorg_list_for_each_entry(group, &ptr->match_driver, entry) { 455 fprintf(cf, "\tMatchDriver \""); 456 for (cur = group->values; *cur; cur++) 457 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 458 *cur); 459 fprintf(cf, "\"\n"); 460 } 461 xorg_list_for_each_entry(group, &ptr->match_tag, entry) { 462 fprintf(cf, "\tMatchTag \""); 463 for (cur = group->values; *cur; cur++) 464 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 465 *cur); 466 fprintf(cf, "\"\n"); 467 } 468 xorg_list_for_each_entry(group, &ptr->match_layout, entry) { 469 fprintf(cf, "\tMatchLayout \""); 470 for (cur = group->values; *cur; cur++) 471 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 472 *cur); 473 fprintf(cf, "\"\n"); 474 } 475 476 if (ptr->is_keyboard.set) 477 fprintf(cf, "\tIsKeyboard \"%s\"\n", 478 ptr->is_keyboard.val ? "yes" : "no"); 479 if (ptr->is_pointer.set) 480 fprintf(cf, "\tIsPointer \"%s\"\n", 481 ptr->is_pointer.val ? "yes" : "no"); 482 if (ptr->is_joystick.set) 483 fprintf(cf, "\tIsJoystick \"%s\"\n", 484 ptr->is_joystick.val ? "yes" : "no"); 485 if (ptr->is_tablet.set) 486 fprintf(cf, "\tIsTablet \"%s\"\n", 487 ptr->is_tablet.val ? "yes" : "no"); 488 if (ptr->is_tablet_pad.set) 489 fprintf(cf, "\tIsTabletPad \"%s\"\n", 490 ptr->is_tablet_pad.val ? "yes" : "no"); 491 if (ptr->is_touchpad.set) 492 fprintf(cf, "\tIsTouchpad \"%s\"\n", 493 ptr->is_touchpad.val ? "yes" : "no"); 494 if (ptr->is_touchscreen.set) 495 fprintf(cf, "\tIsTouchscreen \"%s\"\n", 496 ptr->is_touchscreen.val ? "yes" : "no"); 497 xf86printOptionList(cf, ptr->option_lst, 1); 498 fprintf(cf, "EndSection\n\n"); 499 ptr = ptr->list.next; 500 } 501} 502