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/* View/edit this file with tab stops set to 4 */ 27 28#ifdef HAVE_XORG_CONFIG_H 29#include <xorg-config.h> 30#endif 31 32#include <string.h> 33#include "os.h" 34#include "xf86Parser.h" 35#include "xf86tokens.h" 36#include "Configint.h" 37 38extern LexRec val; 39 40static 41xf86ConfigSymTabRec InputClassTab[] = 42{ 43 {ENDSECTION, "endsection"}, 44 {IDENTIFIER, "identifier"}, 45 {OPTION, "option"}, 46 {DRIVER, "driver"}, 47 {MATCH_PRODUCT, "matchproduct"}, 48 {MATCH_VENDOR, "matchvendor"}, 49 {MATCH_DEVICE_PATH, "matchdevicepath"}, 50 {MATCH_OS, "matchos"}, 51 {MATCH_PNPID, "matchpnpid"}, 52 {MATCH_USBID, "matchusbid"}, 53 {MATCH_DRIVER, "matchdriver"}, 54 {MATCH_TAG, "matchtag"}, 55 {MATCH_IS_KEYBOARD, "matchiskeyboard"}, 56 {MATCH_IS_POINTER, "matchispointer"}, 57 {MATCH_IS_JOYSTICK, "matchisjoystick"}, 58 {MATCH_IS_TABLET, "matchistablet"}, 59 {MATCH_IS_TOUCHPAD, "matchistouchpad"}, 60 {MATCH_IS_TOUCHSCREEN, "matchistouchscreen"}, 61 {-1, ""}, 62}; 63 64#define CLEANUP xf86freeInputClassList 65 66#define TOKEN_SEP "|" 67 68static void 69add_group_entry(struct list *head, char **values) 70{ 71 xf86MatchGroup *group; 72 73 group = malloc(sizeof(*group)); 74 if (group) { 75 group->values = values; 76 list_add(&group->entry, head); 77 } 78} 79 80XF86ConfInputClassPtr 81xf86parseInputClassSection(void) 82{ 83 int has_ident = FALSE; 84 int token; 85 86 parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec) 87 88 /* Initialize MatchGroup lists */ 89 list_init(&ptr->match_product); 90 list_init(&ptr->match_vendor); 91 list_init(&ptr->match_device); 92 list_init(&ptr->match_os); 93 list_init(&ptr->match_pnpid); 94 list_init(&ptr->match_usbid); 95 list_init(&ptr->match_driver); 96 list_init(&ptr->match_tag); 97 98 while ((token = xf86getToken(InputClassTab)) != ENDSECTION) { 99 switch (token) { 100 case COMMENT: 101 ptr->comment = xf86addComment(ptr->comment, val.str); 102 break; 103 case IDENTIFIER: 104 if (xf86getSubToken(&(ptr->comment)) != STRING) 105 Error(QUOTE_MSG, "Identifier"); 106 if (has_ident == TRUE) 107 Error(MULTIPLE_MSG, "Identifier"); 108 ptr->identifier = val.str; 109 has_ident = TRUE; 110 break; 111 case DRIVER: 112 if (xf86getSubToken(&(ptr->comment)) != STRING) 113 Error(QUOTE_MSG, "Driver"); 114 if (strcmp(val.str, "keyboard") == 0) { 115 ptr->driver = strdup("kbd"); 116 free(val.str); 117 } 118 else 119 ptr->driver = val.str; 120 break; 121 case OPTION: 122 ptr->option_lst = xf86parseOption(ptr->option_lst); 123 break; 124 case MATCH_PRODUCT: 125 if (xf86getSubToken(&(ptr->comment)) != STRING) 126 Error(QUOTE_MSG, "MatchProduct"); 127 add_group_entry(&ptr->match_product, 128 xstrtokenize(val.str, TOKEN_SEP)); 129 break; 130 case MATCH_VENDOR: 131 if (xf86getSubToken(&(ptr->comment)) != STRING) 132 Error(QUOTE_MSG, "MatchVendor"); 133 add_group_entry(&ptr->match_vendor, 134 xstrtokenize(val.str, TOKEN_SEP)); 135 break; 136 case MATCH_DEVICE_PATH: 137 if (xf86getSubToken(&(ptr->comment)) != STRING) 138 Error(QUOTE_MSG, "MatchDevicePath"); 139 add_group_entry(&ptr->match_device, 140 xstrtokenize(val.str, TOKEN_SEP)); 141 break; 142 case MATCH_OS: 143 if (xf86getSubToken(&(ptr->comment)) != STRING) 144 Error(QUOTE_MSG, "MatchOS"); 145 add_group_entry(&ptr->match_os, 146 xstrtokenize(val.str, TOKEN_SEP)); 147 break; 148 case MATCH_PNPID: 149 if (xf86getSubToken(&(ptr->comment)) != STRING) 150 Error(QUOTE_MSG, "MatchPnPID"); 151 add_group_entry(&ptr->match_pnpid, 152 xstrtokenize(val.str, TOKEN_SEP)); 153 break; 154 case MATCH_USBID: 155 if (xf86getSubToken(&(ptr->comment)) != STRING) 156 Error(QUOTE_MSG, "MatchUSBID"); 157 add_group_entry(&ptr->match_usbid, 158 xstrtokenize(val.str, TOKEN_SEP)); 159 break; 160 case MATCH_DRIVER: 161 if (xf86getSubToken(&(ptr->comment)) != STRING) 162 Error(QUOTE_MSG, "MatchDriver"); 163 add_group_entry(&ptr->match_driver, 164 xstrtokenize(val.str, TOKEN_SEP)); 165 break; 166 case MATCH_TAG: 167 if (xf86getSubToken(&(ptr->comment)) != STRING) 168 Error(QUOTE_MSG, "MatchTag"); 169 add_group_entry(&ptr->match_tag, 170 xstrtokenize(val.str, TOKEN_SEP)); 171 break; 172 case MATCH_IS_KEYBOARD: 173 if (xf86getSubToken(&(ptr->comment)) != STRING) 174 Error(QUOTE_MSG, "MatchIsKeyboard"); 175 ptr->is_keyboard.set = xf86getBoolValue(&ptr->is_keyboard.val, 176 val.str); 177 if (!ptr->is_keyboard.set) 178 Error(BOOL_MSG, "MatchIsKeyboard"); 179 break; 180 case MATCH_IS_POINTER: 181 if (xf86getSubToken(&(ptr->comment)) != STRING) 182 Error(QUOTE_MSG, "MatchIsPointer"); 183 ptr->is_pointer.set = xf86getBoolValue(&ptr->is_pointer.val, 184 val.str); 185 if (!ptr->is_pointer.set) 186 Error(BOOL_MSG, "MatchIsPointer"); 187 break; 188 case MATCH_IS_JOYSTICK: 189 if (xf86getSubToken(&(ptr->comment)) != STRING) 190 Error(QUOTE_MSG, "MatchIsJoystick"); 191 ptr->is_joystick.set = xf86getBoolValue(&ptr->is_joystick.val, 192 val.str); 193 if (!ptr->is_joystick.set) 194 Error(BOOL_MSG, "MatchIsJoystick"); 195 break; 196 case MATCH_IS_TABLET: 197 if (xf86getSubToken(&(ptr->comment)) != STRING) 198 Error(QUOTE_MSG, "MatchIsTablet"); 199 ptr->is_tablet.set = xf86getBoolValue(&ptr->is_tablet.val, 200 val.str); 201 if (!ptr->is_tablet.set) 202 Error(BOOL_MSG, "MatchIsTablet"); 203 break; 204 case MATCH_IS_TOUCHPAD: 205 if (xf86getSubToken(&(ptr->comment)) != STRING) 206 Error(QUOTE_MSG, "MatchIsTouchpad"); 207 ptr->is_touchpad.set = xf86getBoolValue(&ptr->is_touchpad.val, 208 val.str); 209 if (!ptr->is_touchpad.set) 210 Error(BOOL_MSG, "MatchIsTouchpad"); 211 break; 212 case MATCH_IS_TOUCHSCREEN: 213 if (xf86getSubToken(&(ptr->comment)) != STRING) 214 Error(QUOTE_MSG, "MatchIsTouchscreen"); 215 ptr->is_touchscreen.set = xf86getBoolValue(&ptr->is_touchscreen.val, 216 val.str); 217 if (!ptr->is_touchscreen.set) 218 Error(BOOL_MSG, "MatchIsTouchscreen"); 219 break; 220 case EOF_TOKEN: 221 Error(UNEXPECTED_EOF_MSG, NULL); 222 break; 223 default: 224 Error(INVALID_KEYWORD_MSG, xf86tokenString ()); 225 break; 226 } 227 } 228 229 if (!has_ident) 230 Error(NO_IDENT_MSG, NULL); 231 232#ifdef DEBUG 233 printf("InputClass section parsed\n"); 234#endif 235 236 return ptr; 237} 238 239void 240xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) 241{ 242 const xf86MatchGroup *group; 243 char * const *cur; 244 245 while (ptr) { 246 fprintf(cf, "Section \"InputClass\"\n"); 247 if (ptr->comment) 248 fprintf(cf, "%s", ptr->comment); 249 if (ptr->identifier) 250 fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier); 251 if (ptr->driver) 252 fprintf(cf, "\tDriver \"%s\"\n", ptr->driver); 253 254 list_for_each_entry(group, &ptr->match_product, entry) { 255 fprintf(cf, "\tMatchProduct \""); 256 for (cur = group->values; *cur; cur++) 257 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 258 *cur); 259 fprintf(cf, "\"\n"); 260 } 261 list_for_each_entry(group, &ptr->match_vendor, entry) { 262 fprintf(cf, "\tMatchVendor \""); 263 for (cur = group->values; *cur; cur++) 264 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 265 *cur); 266 fprintf(cf, "\"\n"); 267 } 268 list_for_each_entry(group, &ptr->match_device, entry) { 269 fprintf(cf, "\tMatchDevicePath \""); 270 for (cur = group->values; *cur; cur++) 271 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 272 *cur); 273 fprintf(cf, "\"\n"); 274 } 275 list_for_each_entry(group, &ptr->match_os, entry) { 276 fprintf(cf, "\tMatchOS \""); 277 for (cur = group->values; *cur; cur++) 278 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 279 *cur); 280 fprintf(cf, "\"\n"); 281 } 282 list_for_each_entry(group, &ptr->match_pnpid, entry) { 283 fprintf(cf, "\tMatchPnPID \""); 284 for (cur = group->values; *cur; cur++) 285 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 286 *cur); 287 fprintf(cf, "\"\n"); 288 } 289 list_for_each_entry(group, &ptr->match_usbid, entry) { 290 fprintf(cf, "\tMatchUSBID \""); 291 for (cur = group->values; *cur; cur++) 292 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 293 *cur); 294 fprintf(cf, "\"\n"); 295 } 296 list_for_each_entry(group, &ptr->match_driver, entry) { 297 fprintf(cf, "\tMatchDriver \""); 298 for (cur = group->values; *cur; cur++) 299 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 300 *cur); 301 fprintf(cf, "\"\n"); 302 } 303 list_for_each_entry(group, &ptr->match_tag, entry) { 304 fprintf(cf, "\tMatchTag \""); 305 for (cur = group->values; *cur; cur++) 306 fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP, 307 *cur); 308 fprintf(cf, "\"\n"); 309 } 310 311 if (ptr->is_keyboard.set) 312 fprintf(cf, "\tIsKeyboard \"%s\"\n", 313 ptr->is_keyboard.val ? "yes" : "no"); 314 if (ptr->is_pointer.set) 315 fprintf(cf, "\tIsPointer \"%s\"\n", 316 ptr->is_pointer.val ? "yes" : "no"); 317 if (ptr->is_joystick.set) 318 fprintf(cf, "\tIsJoystick \"%s\"\n", 319 ptr->is_joystick.val ? "yes" : "no"); 320 if (ptr->is_tablet.set) 321 fprintf(cf, "\tIsTablet \"%s\"\n", 322 ptr->is_tablet.val ? "yes" : "no"); 323 if (ptr->is_touchpad.set) 324 fprintf(cf, "\tIsTouchpad \"%s\"\n", 325 ptr->is_touchpad.val ? "yes" : "no"); 326 if (ptr->is_touchscreen.set) 327 fprintf(cf, "\tIsTouchscreen \"%s\"\n", 328 ptr->is_touchscreen.val ? "yes" : "no"); 329 xf86printOptionList(cf, ptr->option_lst, 1); 330 fprintf(cf, "EndSection\n\n"); 331 ptr = ptr->list.next; 332 } 333} 334 335void 336xf86freeInputClassList (XF86ConfInputClassPtr ptr) 337{ 338 XF86ConfInputClassPtr prev; 339 340 while (ptr) { 341 xf86MatchGroup *group, *next; 342 char **list; 343 344 TestFree(ptr->identifier); 345 TestFree(ptr->driver); 346 347 list_for_each_entry_safe(group, next, &ptr->match_product, entry) { 348 list_del(&group->entry); 349 for (list = group->values; *list; list++) 350 free(*list); 351 free(group); 352 } 353 list_for_each_entry_safe(group, next, &ptr->match_vendor, entry) { 354 list_del(&group->entry); 355 for (list = group->values; *list; list++) 356 free(*list); 357 free(group); 358 } 359 list_for_each_entry_safe(group, next, &ptr->match_device, entry) { 360 list_del(&group->entry); 361 for (list = group->values; *list; list++) 362 free(*list); 363 free(group); 364 } 365 list_for_each_entry_safe(group, next, &ptr->match_os, entry) { 366 list_del(&group->entry); 367 for (list = group->values; *list; list++) 368 free(*list); 369 free(group); 370 } 371 list_for_each_entry_safe(group, next, &ptr->match_pnpid, entry) { 372 list_del(&group->entry); 373 for (list = group->values; *list; list++) 374 free(*list); 375 free(group); 376 } 377 list_for_each_entry_safe(group, next, &ptr->match_usbid, entry) { 378 list_del(&group->entry); 379 for (list = group->values; *list; list++) 380 free(*list); 381 free(group); 382 } 383 list_for_each_entry_safe(group, next, &ptr->match_driver, entry) { 384 list_del(&group->entry); 385 for (list = group->values; *list; list++) 386 free(*list); 387 free(group); 388 } 389 list_for_each_entry_safe(group, next, &ptr->match_tag, entry) { 390 list_del(&group->entry); 391 for (list = group->values; *list; list++) 392 free(*list); 393 free(group); 394 } 395 396 TestFree(ptr->comment); 397 xf86optionListFree(ptr->option_lst); 398 399 prev = ptr; 400 ptr = ptr->list.next; 401 free(prev); 402 } 403} 404