1/* 2 * Copyright © 2018 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "config.h" 25 26/* This has the hallmarks of a library to make it re-usable from the tests 27 * and from the list-quirks tool. It doesn't have all of the features from a 28 * library you'd expect though 29 */ 30 31#undef NDEBUG /* You don't get to disable asserts here */ 32#include <assert.h> 33#include <stdlib.h> 34#include <libudev.h> 35#include <dirent.h> 36#include <fnmatch.h> 37#include <libgen.h> 38#ifdef __FreeBSD__ 39#include <kenv.h> 40#endif 41 42#include "libinput-versionsort.h" 43#include "libinput-util.h" 44 45#include "quirks.h" 46 47/* Custom logging so we can have detailed output for the tool but minimal 48 * logging for libinput itself. */ 49#define qlog_debug(ctx_, ...) quirk_log_msg((ctx_), QLOG_NOISE, __VA_ARGS__) 50#define qlog_info(ctx_, ...) quirk_log_msg((ctx_), QLOG_INFO, __VA_ARGS__) 51#define qlog_error(ctx_, ...) quirk_log_msg((ctx_), QLOG_ERROR, __VA_ARGS__) 52#define qlog_parser(ctx_, ...) quirk_log_msg((ctx_), QLOG_PARSER_ERROR, __VA_ARGS__) 53 54enum property_type { 55 PT_UINT, 56 PT_INT, 57 PT_STRING, 58 PT_BOOL, 59 PT_DIMENSION, 60 PT_RANGE, 61 PT_DOUBLE, 62 PT_TUPLES, 63 PT_UINT_ARRAY, 64}; 65 66struct quirk_array { 67 union { 68 uint32_t u[32]; 69 } data; 70 size_t nelements; 71}; 72 73/** 74 * Generic value holder for the property types we support. The type 75 * identifies which value in the union is defined and we expect callers to 76 * already know which type yields which value. 77 */ 78struct property { 79 size_t refcount; 80 struct list link; /* struct sections.properties */ 81 82 enum quirk id; 83 enum property_type type; 84 union { 85 bool b; 86 uint32_t u; 87 int32_t i; 88 char *s; 89 double d; 90 struct quirk_dimensions dim; 91 struct quirk_range range; 92 struct quirk_tuples tuples; 93 struct quirk_array array; 94 } value; 95}; 96 97enum match_flags { 98 M_NAME = bit(0), 99 M_BUS = bit(1), 100 M_VID = bit(2), 101 M_PID = bit(3), 102 M_DMI = bit(4), 103 M_UDEV_TYPE = bit(5), 104 M_DT = bit(6), 105 M_VERSION = bit(7), 106 107 M_LAST = M_VERSION, 108}; 109 110enum bustype { 111 BT_UNKNOWN, 112 BT_USB, 113 BT_BLUETOOTH, 114 BT_PS2, 115 BT_RMI, 116 BT_I2C, 117 BT_SPI, 118}; 119 120enum udev_type { 121 UDEV_MOUSE = bit(1), 122 UDEV_POINTINGSTICK = bit(2), 123 UDEV_TOUCHPAD = bit(3), 124 UDEV_TABLET = bit(4), 125 UDEV_TABLET_PAD = bit(5), 126 UDEV_JOYSTICK = bit(6), 127 UDEV_KEYBOARD = bit(7), 128}; 129 130/** 131 * Contains the combined set of matches for one section or the values for 132 * one device. 133 * 134 * bits defines which fields are set, the rest is zero. 135 */ 136struct match { 137 uint32_t bits; 138 139 char *name; 140 enum bustype bus; 141 uint32_t vendor; 142 uint32_t product; 143 uint32_t version; 144 145 char *dmi; /* dmi modalias with preceding "dmi:" */ 146 147 /* We can have more than one type set, so this is a bitfield */ 148 uint32_t udev_type; 149 150 char *dt; /* device tree compatible (first) string */ 151}; 152 153/** 154 * Represents one section in the .quirks file. 155 */ 156struct section { 157 struct list link; 158 159 bool has_match; /* to check for empty sections */ 160 bool has_property; /* to check for empty sections */ 161 162 char *name; /* the [Section Name] */ 163 struct match match; 164 struct list properties; 165}; 166 167/** 168 * The struct returned to the caller. It contains the 169 * properties for a given device. 170 */ 171struct quirks { 172 size_t refcount; 173 struct list link; /* struct quirks_context.quirks */ 174 175 /* These are not ref'd, just a collection of pointers */ 176 struct property **properties; 177 size_t nproperties; 178 179 /* Special properties for AttrEventCode and AttrInputCode, these are 180 * owned by us, not the section */ 181 struct list floating_properties; 182}; 183 184/** 185 * Quirk matching context, initialized once with quirks_init_subsystem() 186 */ 187struct quirks_context { 188 size_t refcount; 189 190 libinput_log_handler log_handler; 191 enum quirks_log_type log_type; 192 struct libinput *libinput; /* for logging */ 193 194 char *dmi; 195 char *dt; 196 197 struct list sections; 198 199 /* list of quirks handed to libinput, just for bookkeeping */ 200 struct list quirks; 201}; 202 203LIBINPUT_ATTRIBUTE_PRINTF(3, 0) 204static inline void 205quirk_log_msg_va(struct quirks_context *ctx, 206 enum quirks_log_priorities priority, 207 const char *format, 208 va_list args) 209{ 210 switch (priority) { 211 /* We don't use this if we're logging through libinput */ 212 default: 213 case QLOG_NOISE: 214 case QLOG_PARSER_ERROR: 215 if (ctx->log_type == QLOG_LIBINPUT_LOGGING) 216 return; 217 break; 218 case QLOG_DEBUG: /* These map straight to libinput priorities */ 219 case QLOG_INFO: 220 case QLOG_ERROR: 221 break; 222 } 223 224 ctx->log_handler(ctx->libinput, 225 (enum libinput_log_priority)priority, 226 format, 227 args); 228} 229 230LIBINPUT_ATTRIBUTE_PRINTF(3, 4) 231static inline void 232quirk_log_msg(struct quirks_context *ctx, 233 enum quirks_log_priorities priority, 234 const char *format, 235 ...) 236{ 237 va_list args; 238 239 va_start(args, format); 240 quirk_log_msg_va(ctx, priority, format, args); 241 va_end(args); 242 243} 244 245const char * 246quirk_get_name(enum quirk q) 247{ 248 switch(q) { 249 case QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD: return "ModelALPSSerialTouchpad"; 250 case QUIRK_MODEL_APPLE_TOUCHPAD: return "ModelAppleTouchpad"; 251 case QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON: return "ModelAppleTouchpadOneButton"; 252 case QUIRK_MODEL_BOUNCING_KEYS: return "ModelBouncingKeys"; 253 case QUIRK_MODEL_CHROMEBOOK: return "ModelChromebook"; 254 case QUIRK_MODEL_CLEVO_W740SU: return "ModelClevoW740SU"; 255 case QUIRK_MODEL_DELL_CANVAS_TOTEM: return "ModelDellCanvasTotem"; 256 case QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD: return "ModelHPPavilionDM4Touchpad"; 257 case QUIRK_MODEL_HP_ZBOOK_STUDIO_G3: return "ModelHPZBookStudioG3"; 258 case QUIRK_MODEL_INVERT_HORIZONTAL_SCROLLING: return "ModelInvertHorizontalScrolling"; 259 case QUIRK_MODEL_LENOVO_SCROLLPOINT: return "ModelLenovoScrollPoint"; 260 case QUIRK_MODEL_LENOVO_T450_TOUCHPAD: return "ModelLenovoT450Touchpad"; 261 case QUIRK_MODEL_LENOVO_X1GEN6_TOUCHPAD: return "ModelLenovoX1Gen6Touchpad"; 262 case QUIRK_MODEL_LENOVO_X230: return "ModelLenovoX230"; 263 case QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD: return "ModelSynapticsSerialTouchpad"; 264 case QUIRK_MODEL_SYSTEM76_BONOBO: return "ModelSystem76Bonobo"; 265 case QUIRK_MODEL_SYSTEM76_GALAGO: return "ModelSystem76Galago"; 266 case QUIRK_MODEL_SYSTEM76_KUDU: return "ModelSystem76Kudu"; 267 case QUIRK_MODEL_TABLET_MODE_NO_SUSPEND: return "ModelTabletModeNoSuspend"; 268 case QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE: return "ModelTabletModeSwitchUnreliable"; 269 case QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER: return "ModelTouchpadVisibleMarker"; 270 case QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS: return "ModelTouchpadPhantomClicks"; 271 case QUIRK_MODEL_TRACKBALL: return "ModelTrackball"; 272 case QUIRK_MODEL_WACOM_TOUCHPAD: return "ModelWacomTouchpad"; 273 case QUIRK_MODEL_PRESSURE_PAD: return "ModelPressurePad"; 274 275 case QUIRK_ATTR_SIZE_HINT: return "AttrSizeHint"; 276 case QUIRK_ATTR_TOUCH_SIZE_RANGE: return "AttrTouchSizeRange"; 277 case QUIRK_ATTR_PALM_SIZE_THRESHOLD: return "AttrPalmSizeThreshold"; 278 case QUIRK_ATTR_LID_SWITCH_RELIABILITY: return "AttrLidSwitchReliability"; 279 case QUIRK_ATTR_KEYBOARD_INTEGRATION: return "AttrKeyboardIntegration"; 280 case QUIRK_ATTR_TRACKPOINT_INTEGRATION: return "AttrPointingStickIntegration"; 281 case QUIRK_ATTR_TPKBCOMBO_LAYOUT: return "AttrTPKComboLayout"; 282 case QUIRK_ATTR_PRESSURE_RANGE: return "AttrPressureRange"; 283 case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: return "AttrPalmPressureThreshold"; 284 case QUIRK_ATTR_RESOLUTION_HINT: return "AttrResolutionHint"; 285 case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: return "AttrTrackpointMultiplier"; 286 case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: return "AttrThumbPressureThreshold"; 287 case QUIRK_ATTR_USE_VELOCITY_AVERAGING: return "AttrUseVelocityAveraging"; 288 case QUIRK_ATTR_TABLET_SMOOTHING: return "AttrTabletSmoothing"; 289 case QUIRK_ATTR_THUMB_SIZE_THRESHOLD: return "AttrThumbSizeThreshold"; 290 case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp"; 291 case QUIRK_ATTR_EVENT_CODE: return "AttrEventCode"; 292 case QUIRK_ATTR_INPUT_PROP: return "AttrInputProp"; 293 default: 294 abort(); 295 } 296} 297 298static inline const char * 299matchflagname(enum match_flags f) 300{ 301 switch(f) { 302 case M_NAME: return "MatchName"; break; 303 case M_BUS: return "MatchBus"; break; 304 case M_VID: return "MatchVendor"; break; 305 case M_PID: return "MatchProduct"; break; 306 case M_VERSION: return "MatchVersion"; break; 307 case M_DMI: return "MatchDMIModalias"; break; 308 case M_UDEV_TYPE: return "MatchUdevType"; break; 309 case M_DT: return "MatchDeviceTree"; break; 310 default: 311 abort(); 312 } 313} 314 315static inline struct property * 316property_new(void) 317{ 318 struct property *p; 319 320 p = zalloc(sizeof *p); 321 p->refcount = 1; 322 list_init(&p->link); 323 324 return p; 325} 326 327static inline struct property * 328property_ref(struct property *p) 329{ 330 assert(p->refcount > 0); 331 p->refcount++; 332 return p; 333} 334 335static inline struct property * 336property_unref(struct property *p) 337{ 338 /* Note: we don't cleanup here, that is a separate call so we 339 can abort if we haven't cleaned up correctly. */ 340 assert(p->refcount > 0); 341 p->refcount--; 342 343 return NULL; 344} 345 346/* Separate call so we can verify that the caller unrefs the property 347 * before shutting down the subsystem. 348 */ 349static inline void 350property_cleanup(struct property *p) 351{ 352 /* If we get here, the quirks must've been removed already */ 353 property_unref(p); 354 assert(p->refcount == 0); 355 356 list_remove(&p->link); 357 if (p->type == PT_STRING) 358 free(p->value.s); 359 free(p); 360} 361 362/** 363 * Return the system DMI info in modalias format. 364 */ 365#ifdef __linux__ 366static inline char * 367init_dmi_linux(void) 368{ 369 struct udev *udev; 370 struct udev_device *udev_device; 371 const char *modalias = NULL; 372 char *copy = NULL; 373 const char *syspath = "/sys/devices/virtual/dmi/id"; 374 375 udev = udev_new(); 376 if (!udev) 377 return NULL; 378 379 udev_device = udev_device_new_from_syspath(udev, syspath); 380 if (udev_device) 381 modalias = udev_device_get_property_value(udev_device, 382 "MODALIAS"); 383 384 /* Not sure whether this could ever really fail, if so we should 385 * open the sysfs file directly. But then udev wouldn't have failed, 386 * so... */ 387 if (!modalias) 388 modalias = "dmi:*"; 389 390 copy = safe_strdup(modalias); 391 392 udev_device_unref(udev_device); 393 udev_unref(udev); 394 395 return copy; 396} 397#endif 398 399#ifdef __FreeBSD__ 400static inline char * 401init_dmi_freebsd(void) 402{ 403#define LEN (KENV_MVALLEN + 1) 404 char *modalias; 405 char bios_vendor[LEN], bios_version[LEN], bios_date[LEN]; 406 char sys_vendor[LEN], product_name[LEN], product_version[LEN]; 407 char board_vendor[LEN], board_name[LEN], board_version[LEN]; 408 char chassis_vendor[LEN], chassis_type[LEN], chassis_version[LEN]; 409 int chassis_type_num = 0x2; 410 411 kenv(KENV_GET, "smbios.bios.vendor", bios_vendor, LEN); 412 kenv(KENV_GET, "smbios.bios.version", bios_version, LEN); 413 kenv(KENV_GET, "smbios.bios.reldate", bios_date, LEN); 414 kenv(KENV_GET, "smbios.system.maker", sys_vendor, LEN); 415 kenv(KENV_GET, "smbios.system.product", product_name, LEN); 416 kenv(KENV_GET, "smbios.system.version", product_version, LEN); 417 kenv(KENV_GET, "smbios.planar.maker", board_vendor, LEN); 418 kenv(KENV_GET, "smbios.planar.product", board_name, LEN); 419 kenv(KENV_GET, "smbios.planar.version", board_version, LEN); 420 kenv(KENV_GET, "smbios.chassis.vendor", chassis_vendor, LEN); 421 kenv(KENV_GET, "smbios.chassis.type", chassis_type, LEN); 422 kenv(KENV_GET, "smbios.chassis.version", chassis_version, LEN); 423#undef LEN 424 425 if (strcmp(chassis_type, "Desktop") == 0) 426 chassis_type_num = 0x3; 427 else if (strcmp(chassis_type, "Portable") == 0) 428 chassis_type_num = 0x8; 429 else if (strcmp(chassis_type, "Laptop") == 0) 430 chassis_type_num = 0x9; 431 else if (strcmp(chassis_type, "Notebook") == 0) 432 chassis_type_num = 0xA; 433 else if (strcmp(chassis_type, "Tablet") == 0) 434 chassis_type_num = 0x1E; 435 else if (strcmp(chassis_type, "Convertible") == 0) 436 chassis_type_num = 0x1F; 437 else if (strcmp(chassis_type, "Detachable") == 0) 438 chassis_type_num = 0x20; 439 440 xasprintf(&modalias, 441 "dmi:bvn%s:bvr%s:bd%s:svn%s:pn%s:pvr%s:rvn%s:rn%s:rvr%s:cvn%s:ct%d:cvr%s:", 442 bios_vendor, bios_version, bios_date, sys_vendor, product_name, 443 product_version, board_vendor, board_name, board_version, chassis_vendor, 444 chassis_type_num, chassis_version); 445 446 return modalias; 447} 448#endif 449 450static inline char * 451init_dmi(void) 452{ 453 if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) 454 return safe_strdup("dmi:"); 455 456#if defined(__linux__) 457 return init_dmi_linux(); 458#elif defined(__FreeBSD__) 459 return init_dmi_freebsd(); 460#else 461 return NULL; 462#endif 463} 464 465/** 466 * Return the dt compatible string 467 */ 468static inline char * 469init_dt(void) 470{ 471 char compatible[1024]; 472 char *copy = NULL; 473 const char *syspath = "/sys/firmware/devicetree/base/compatible"; 474 FILE *fp; 475 476 if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) 477 return safe_strdup(""); 478 479 fp = fopen(syspath, "r"); 480 if (!fp) 481 return NULL; 482 483 /* devicetree/base/compatible has multiple null-terminated entries 484 but we only care about the first one here, so strdup is enough */ 485 if (fgets(compatible, sizeof(compatible), fp)) { 486 copy = safe_strdup(compatible); 487 } 488 489 fclose(fp); 490 491 return copy; 492} 493 494static inline struct section * 495section_new(const char *path, const char *name) 496{ 497 struct section *s = zalloc(sizeof(*s)); 498 499 char *path_dup = safe_strdup(path); 500 xasprintf(&s->name, "%s (%s)", name, basename(path_dup)); 501 free(path_dup); 502 list_init(&s->link); 503 list_init(&s->properties); 504 505 return s; 506} 507 508static inline void 509section_destroy(struct section *s) 510{ 511 struct property *p; 512 513 free(s->name); 514 free(s->match.name); 515 free(s->match.dmi); 516 free(s->match.dt); 517 518 list_for_each_safe(p, &s->properties, link) 519 property_cleanup(p); 520 521 assert(list_empty(&s->properties)); 522 523 list_remove(&s->link); 524 free(s); 525} 526 527static inline bool 528parse_hex(const char *value, unsigned int *parsed) 529{ 530 return strneq(value, "0x", 2) && 531 safe_atou_base(value, parsed, 16) && 532 strspn(value, "0123456789xABCDEF") == strlen(value) && 533 *parsed <= 0xFFFF; 534} 535 536/** 537 * Parse a MatchFooBar=banana line. 538 * 539 * @param section The section struct to be filled in 540 * @param key The MatchFooBar part of the line 541 * @param value The banana part of the line. 542 * 543 * @return true on success, false otherwise. 544 */ 545static bool 546parse_match(struct quirks_context *ctx, 547 struct section *s, 548 const char *key, 549 const char *value) 550{ 551 int rc = false; 552 553#define check_set_bit(s_, bit_) { \ 554 if ((s_)->match.bits & (bit_)) goto out; \ 555 (s_)->match.bits |= (bit_); \ 556 } 557 558 assert(strlen(value) >= 1); 559 560 if (streq(key, "MatchName")) { 561 check_set_bit(s, M_NAME); 562 s->match.name = safe_strdup(value); 563 } else if (streq(key, "MatchBus")) { 564 check_set_bit(s, M_BUS); 565 if (streq(value, "usb")) 566 s->match.bus = BT_USB; 567 else if (streq(value, "bluetooth")) 568 s->match.bus = BT_BLUETOOTH; 569 else if (streq(value, "ps2")) 570 s->match.bus = BT_PS2; 571 else if (streq(value, "rmi")) 572 s->match.bus = BT_RMI; 573 else if (streq(value, "i2c")) 574 s->match.bus = BT_I2C; 575 else if (streq(value, "spi")) 576 s->match.bus = BT_SPI; 577 else 578 goto out; 579 } else if (streq(key, "MatchVendor")) { 580 unsigned int vendor; 581 582 check_set_bit(s, M_VID); 583 if (!parse_hex(value, &vendor)) 584 goto out; 585 586 s->match.vendor = vendor; 587 } else if (streq(key, "MatchProduct")) { 588 unsigned int product; 589 590 check_set_bit(s, M_PID); 591 if (!parse_hex(value, &product)) 592 goto out; 593 594 s->match.product = product; 595 } else if (streq(key, "MatchVersion")) { 596 unsigned int version; 597 598 check_set_bit(s, M_VERSION); 599 if (!parse_hex(value, &version)) 600 goto out; 601 602 s->match.version = version; 603 } else if (streq(key, "MatchDMIModalias")) { 604 check_set_bit(s, M_DMI); 605 if (!strneq(value, "dmi:", 4)) { 606 qlog_parser(ctx, 607 "%s: MatchDMIModalias must start with 'dmi:'\n", 608 s->name); 609 goto out; 610 } 611 s->match.dmi = safe_strdup(value); 612 } else if (streq(key, "MatchUdevType")) { 613 check_set_bit(s, M_UDEV_TYPE); 614 if (streq(value, "touchpad")) 615 s->match.udev_type = UDEV_TOUCHPAD; 616 else if (streq(value, "mouse")) 617 s->match.udev_type = UDEV_MOUSE; 618 else if (streq(value, "pointingstick")) 619 s->match.udev_type = UDEV_POINTINGSTICK; 620 else if (streq(value, "keyboard")) 621 s->match.udev_type = UDEV_KEYBOARD; 622 else if (streq(value, "joystick")) 623 s->match.udev_type = UDEV_JOYSTICK; 624 else if (streq(value, "tablet")) 625 s->match.udev_type = UDEV_TABLET; 626 else if (streq(value, "tablet-pad")) 627 s->match.udev_type = UDEV_TABLET_PAD; 628 else 629 goto out; 630 } else if (streq(key, "MatchDeviceTree")) { 631 check_set_bit(s, M_DT); 632 s->match.dt = safe_strdup(value); 633 } else { 634 qlog_error(ctx, "Unknown match key '%s'\n", key); 635 goto out; 636 } 637 638#undef check_set_bit 639 s->has_match = true; 640 rc = true; 641out: 642 return rc; 643} 644 645/** 646 * Parse a ModelFooBar=1 line. 647 * 648 * @param section The section struct to be filled in 649 * @param key The ModelFooBar part of the line 650 * @param value The value after the =, must be 1 or 0. 651 * 652 * @return true on success, false otherwise. 653 */ 654static bool 655parse_model(struct quirks_context *ctx, 656 struct section *s, 657 const char *key, 658 const char *value) 659{ 660 bool b; 661 enum quirk q = QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD; 662 663 assert(strneq(key, "Model", 5)); 664 665 if (!parse_boolean_property(value, &b)) 666 return false; 667 668 do { 669 if (streq(key, quirk_get_name(q))) { 670 struct property *p = property_new(); 671 p->id = q, 672 p->type = PT_BOOL; 673 p->value.b = b; 674 list_append(&s->properties, &p->link); 675 s->has_property = true; 676 return true; 677 } 678 } while (++q < _QUIRK_LAST_MODEL_QUIRK_); 679 680 qlog_error(ctx, "Unknown key %s in %s\n", key, s->name); 681 682 return false; 683} 684 685/** 686 * Parse a AttrFooBar=banana line. 687 * 688 * @param section The section struct to be filled in 689 * @param key The AttrFooBar part of the line 690 * @param value The banana part of the line. 691 * 692 * Value parsing depends on the attribute type. 693 * 694 * @return true on success, false otherwise. 695 */ 696static inline bool 697parse_attr(struct quirks_context *ctx, 698 struct section *s, 699 const char *key, 700 const char *value) 701{ 702 struct property *p = property_new(); 703 bool rc = false; 704 struct quirk_dimensions dim; 705 struct quirk_range range; 706 unsigned int v; 707 bool b; 708 double d; 709 710 if (streq(key, quirk_get_name(QUIRK_ATTR_SIZE_HINT))) { 711 p->id = QUIRK_ATTR_SIZE_HINT; 712 if (!parse_dimension_property(value, &dim.x, &dim.y)) 713 goto out; 714 p->type = PT_DIMENSION; 715 p->value.dim = dim; 716 rc = true; 717 } else if (streq(key, quirk_get_name(QUIRK_ATTR_TOUCH_SIZE_RANGE))) { 718 p->id = QUIRK_ATTR_TOUCH_SIZE_RANGE; 719 if (!parse_range_property(value, &range.upper, &range.lower)) 720 goto out; 721 p->type = PT_RANGE; 722 p->value.range = range; 723 rc = true; 724 } else if (streq(key, quirk_get_name(QUIRK_ATTR_PALM_SIZE_THRESHOLD))) { 725 p->id = QUIRK_ATTR_PALM_SIZE_THRESHOLD; 726 if (!safe_atou(value, &v)) 727 goto out; 728 p->type = PT_UINT; 729 p->value.u = v; 730 rc = true; 731 } else if (streq(key, quirk_get_name(QUIRK_ATTR_LID_SWITCH_RELIABILITY))) { 732 p->id = QUIRK_ATTR_LID_SWITCH_RELIABILITY; 733 if (!streq(value, "reliable") && 734 !streq(value, "write_open") && 735 !streq(value, "unreliable")) 736 goto out; 737 p->type = PT_STRING; 738 p->value.s = safe_strdup(value); 739 rc = true; 740 } else if (streq(key, quirk_get_name(QUIRK_ATTR_KEYBOARD_INTEGRATION))) { 741 p->id = QUIRK_ATTR_KEYBOARD_INTEGRATION; 742 if (!streq(value, "internal") && !streq(value, "external")) 743 goto out; 744 p->type = PT_STRING; 745 p->value.s = safe_strdup(value); 746 rc = true; 747 } else if (streq(key, quirk_get_name(QUIRK_ATTR_TRACKPOINT_INTEGRATION))) { 748 p->id = QUIRK_ATTR_TRACKPOINT_INTEGRATION; 749 if (!streq(value, "internal") && !streq(value, "external")) 750 goto out; 751 p->type = PT_STRING; 752 p->value.s = safe_strdup(value); 753 rc = true; 754 } else if (streq(key, quirk_get_name(QUIRK_ATTR_TPKBCOMBO_LAYOUT))) { 755 p->id = QUIRK_ATTR_TPKBCOMBO_LAYOUT; 756 if (!streq(value, "below")) 757 goto out; 758 p->type = PT_STRING; 759 p->value.s = safe_strdup(value); 760 rc = true; 761 } else if (streq(key, quirk_get_name(QUIRK_ATTR_PRESSURE_RANGE))) { 762 p->id = QUIRK_ATTR_PRESSURE_RANGE; 763 if (!parse_range_property(value, &range.upper, &range.lower)) 764 goto out; 765 p->type = PT_RANGE; 766 p->value.range = range; 767 rc = true; 768 } else if (streq(key, quirk_get_name(QUIRK_ATTR_PALM_PRESSURE_THRESHOLD))) { 769 p->id = QUIRK_ATTR_PALM_PRESSURE_THRESHOLD; 770 if (!safe_atou(value, &v)) 771 goto out; 772 p->type = PT_UINT; 773 p->value.u = v; 774 rc = true; 775 } else if (streq(key, quirk_get_name(QUIRK_ATTR_RESOLUTION_HINT))) { 776 p->id = QUIRK_ATTR_RESOLUTION_HINT; 777 if (!parse_dimension_property(value, &dim.x, &dim.y)) 778 goto out; 779 p->type = PT_DIMENSION; 780 p->value.dim = dim; 781 rc = true; 782 } else if (streq(key, quirk_get_name(QUIRK_ATTR_TRACKPOINT_MULTIPLIER))) { 783 p->id = QUIRK_ATTR_TRACKPOINT_MULTIPLIER; 784 if (!safe_atod(value, &d)) 785 goto out; 786 p->type = PT_DOUBLE; 787 p->value.d = d; 788 rc = true; 789 } else if (streq(key, quirk_get_name(QUIRK_ATTR_USE_VELOCITY_AVERAGING))) { 790 p->id = QUIRK_ATTR_USE_VELOCITY_AVERAGING; 791 if (!parse_boolean_property(value, &b)) 792 goto out; 793 p->type = PT_BOOL; 794 p->value.b = b; 795 rc = true; 796 } else if (streq(key, quirk_get_name(QUIRK_ATTR_TABLET_SMOOTHING))) { 797 p->id = QUIRK_ATTR_TABLET_SMOOTHING; 798 if (!parse_boolean_property(value, &b)) 799 goto out; 800 p->type = PT_BOOL; 801 p->value.b = b; 802 rc = true; 803 } else if (streq(key, quirk_get_name(QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD))) { 804 p->id = QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD; 805 if (!safe_atou(value, &v)) 806 goto out; 807 p->type = PT_UINT; 808 p->value.u = v; 809 rc = true; 810 } else if (streq(key, quirk_get_name(QUIRK_ATTR_THUMB_SIZE_THRESHOLD))) { 811 p->id = QUIRK_ATTR_THUMB_SIZE_THRESHOLD; 812 if (!safe_atou(value, &v)) 813 goto out; 814 p->type = PT_UINT; 815 p->value.u = v; 816 rc = true; 817 } else if (streq(key, quirk_get_name(QUIRK_ATTR_MSC_TIMESTAMP))) { 818 p->id = QUIRK_ATTR_MSC_TIMESTAMP; 819 if (!streq(value, "watch")) 820 goto out; 821 p->type = PT_STRING; 822 p->value.s = safe_strdup(value); 823 rc = true; 824 } else if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE))) { 825 struct input_event events[32]; 826 size_t nevents = ARRAY_LENGTH(events); 827 828 p->id = QUIRK_ATTR_EVENT_CODE; 829 830 if (!parse_evcode_property(value, events, &nevents) || 831 nevents == 0) 832 goto out; 833 834 for (size_t i = 0; i < nevents; i++) { 835 p->value.tuples.tuples[i].first = events[i].type; 836 p->value.tuples.tuples[i].second = events[i].code; 837 p->value.tuples.tuples[i].third = events[i].value; 838 } 839 p->value.tuples.ntuples = nevents; 840 p->type = PT_TUPLES; 841 842 rc = true; 843 } else if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP))) { 844 struct input_prop props[INPUT_PROP_CNT]; 845 size_t nprops = ARRAY_LENGTH(props); 846 847 p->id = QUIRK_ATTR_INPUT_PROP; 848 849 if (!parse_input_prop_property(value, props, &nprops) || 850 nprops == 0) 851 goto out; 852 853 for (size_t i = 0; i < nprops; i++) { 854 p->value.tuples.tuples[i].first = props[i].prop; 855 p->value.tuples.tuples[i].second = props[i].enabled; 856 } 857 858 p->value.tuples.ntuples = nprops; 859 p->type = PT_TUPLES; 860 861 rc = true; 862 } else { 863 qlog_error(ctx, "Unknown key %s in %s\n", key, s->name); 864 } 865out: 866 if (rc) { 867 list_append(&s->properties, &p->link); 868 s->has_property = true; 869 } else { 870 property_cleanup(p); 871 } 872 return rc; 873} 874 875/** 876 * Parse a single line, expected to be in the format Key=value. Anything 877 * else will be rejected with a failure. 878 * 879 * Our data files can only have Match, Model and Attr, so let's check for 880 * those too. 881 */ 882static bool 883parse_value_line(struct quirks_context *ctx, struct section *s, const char *line) 884{ 885 bool rc = false; 886 887 size_t nelem; 888 char **strv = strv_from_string(line, "=", &nelem); 889 if (!strv || nelem != 2) 890 goto out; 891 892 const char *key = strv[0]; 893 const char *value = strv[1]; 894 if (strlen(key) == 0 || strlen(value) == 0) 895 goto out; 896 897 /* Whatever the value is, it's not supposed to be in quotes */ 898 if (value[0] == '"' || value[0] == '\'') 899 goto out; 900 901 if (strneq(key, "Match", 5)) 902 rc = parse_match(ctx, s, key, value); 903 else if (strneq(key, "Model", 5)) 904 rc = parse_model(ctx, s, key, value); 905 else if (strneq(key, "Attr", 4)) 906 rc = parse_attr(ctx, s, key, value); 907 else 908 qlog_error(ctx, "Unknown value prefix %s\n", line); 909out: 910 strv_free(strv); 911 return rc; 912} 913 914static inline bool 915parse_file(struct quirks_context *ctx, const char *path) 916{ 917 enum state { 918 STATE_SECTION, 919 STATE_MATCH, 920 STATE_MATCH_OR_VALUE, 921 STATE_VALUE_OR_SECTION, 922 STATE_ANY, 923 }; 924 FILE *fp; 925 char line[512]; 926 bool rc = false; 927 enum state state = STATE_SECTION; 928 struct section *section = NULL; 929 int lineno = -1; 930 931 qlog_debug(ctx, "%s\n", path); 932 933 /* Not using open_restricted here, if we can't access 934 * our own data files, our installation is screwed up. 935 */ 936 fp = fopen(path, "r"); 937 if (!fp) { 938 /* If the file doesn't exist that's fine. Only way this can 939 * happen is for the custom override file, all others are 940 * provided by scandir so they do exist. Short of races we 941 * don't care about. */ 942 if (errno == ENOENT) 943 return true; 944 945 qlog_error(ctx, "%s: failed to open file\n", path); 946 goto out; 947 } 948 949 while (fgets(line, sizeof(line), fp)) { 950 char *comment; 951 952 lineno++; 953 954 comment = strstr(line, "#"); 955 if (comment) { 956 /* comment points to # but we need to remove the 957 * preceding whitespaces too */ 958 comment--; 959 while (comment >= line) { 960 if (*comment != ' ' && *comment != '\t') 961 break; 962 comment--; 963 } 964 *(comment + 1) = '\0'; 965 } else { /* strip the trailing newline */ 966 comment = strstr(line, "\n"); 967 if (comment) 968 *comment = '\0'; 969 } 970 if (strlen(line) == 0) 971 continue; 972 973 /* We don't use quotes for strings, so we really don't want 974 * erroneous trailing whitespaces */ 975 switch (line[strlen(line) - 1]) { 976 case ' ': 977 case '\t': 978 qlog_parser(ctx, 979 "%s:%d: Trailing whitespace '%s'\n", 980 path, lineno, line); 981 goto out; 982 } 983 984 switch (line[0]) { 985 case '\0': 986 case '\n': 987 case '#': 988 break; 989 /* white space not allowed */ 990 case ' ': 991 case '\t': 992 qlog_parser(ctx, "%s:%d: Preceding whitespace '%s'\n", 993 path, lineno, line); 994 goto out; 995 /* section title */ 996 case '[': 997 if (line[strlen(line) - 1] != ']') { 998 qlog_parser(ctx, "%s:%d: Closing ] missing '%s'\n", 999 path, lineno, line); 1000 goto out; 1001 } 1002 1003 if (state != STATE_SECTION && 1004 state != STATE_VALUE_OR_SECTION) { 1005 qlog_parser(ctx, "%s:%d: expected section before %s\n", 1006 path, lineno, line); 1007 goto out; 1008 } 1009 if (section && 1010 (!section->has_match || !section->has_property)) { 1011 qlog_parser(ctx, "%s:%d: previous section %s was empty\n", 1012 path, lineno, section->name); 1013 goto out; /* Previous section was empty */ 1014 } 1015 1016 state = STATE_MATCH; 1017 section = section_new(path, line); 1018 list_append(&ctx->sections, §ion->link); 1019 break; 1020 default: 1021 /* entries must start with A-Z */ 1022 if (line[0] < 'A' || line[0] > 'Z') { 1023 qlog_parser(ctx, "%s:%d: Unexpected line %s\n", 1024 path, lineno, line); 1025 goto out; 1026 } 1027 switch (state) { 1028 case STATE_SECTION: 1029 qlog_parser(ctx, "%s:%d: expected [Section], got %s\n", 1030 path, lineno, line); 1031 goto out; 1032 case STATE_MATCH: 1033 if (!strneq(line, "Match", 5)) { 1034 qlog_parser(ctx, "%s:%d: expected MatchFoo=bar, have %s\n", 1035 path, lineno, line); 1036 goto out; 1037 } 1038 state = STATE_MATCH_OR_VALUE; 1039 break; 1040 case STATE_MATCH_OR_VALUE: 1041 if (!strneq(line, "Match", 5)) 1042 state = STATE_VALUE_OR_SECTION; 1043 break; 1044 case STATE_VALUE_OR_SECTION: 1045 if (strneq(line, "Match", 5)) { 1046 qlog_parser(ctx, "%s:%d: expected value or [Section], have %s\n", 1047 path, lineno, line); 1048 goto out; 1049 } 1050 break; 1051 case STATE_ANY: 1052 break; 1053 } 1054 1055 if (!parse_value_line(ctx, section, line)) { 1056 qlog_parser(ctx, "%s:%d: failed to parse %s\n", 1057 path, lineno, line); 1058 goto out; 1059 } 1060 break; 1061 } 1062 } 1063 1064 if (!section) { 1065 qlog_parser(ctx, "%s: is an empty file\n", path); 1066 goto out; 1067 } 1068 1069 if ((!section->has_match || !section->has_property)) { 1070 qlog_parser(ctx, "%s:%d: previous section %s was empty\n", 1071 path, lineno, section->name); 1072 goto out; /* Previous section was empty */ 1073 } 1074 1075 rc = true; 1076out: 1077 if (fp) 1078 fclose(fp); 1079 1080 return rc; 1081} 1082 1083static int 1084is_data_file(const struct dirent *dir) { 1085 return strendswith(dir->d_name, ".quirks"); 1086} 1087 1088static inline bool 1089parse_files(struct quirks_context *ctx, const char *data_path) 1090{ 1091 struct dirent **namelist; 1092 int ndev = -1; 1093 int idx = 0; 1094 1095 ndev = scandir(data_path, &namelist, is_data_file, versionsort); 1096 if (ndev <= 0) { 1097 qlog_error(ctx, 1098 "%s: failed to find data files\n", 1099 data_path); 1100 return false; 1101 } 1102 1103 for (idx = 0; idx < ndev; idx++) { 1104 char path[PATH_MAX]; 1105 1106 snprintf(path, 1107 sizeof(path), 1108 "%s/%s", 1109 data_path, 1110 namelist[idx]->d_name); 1111 1112 if (!parse_file(ctx, path)) 1113 break; 1114 } 1115 1116 for (int i = 0; i < ndev; i++) 1117 free(namelist[i]); 1118 free(namelist); 1119 1120 return idx == ndev; 1121} 1122 1123struct quirks_context * 1124quirks_init_subsystem(const char *data_path, 1125 const char *override_file, 1126 libinput_log_handler log_handler, 1127 struct libinput *libinput, 1128 enum quirks_log_type log_type) 1129{ 1130 struct quirks_context *ctx = zalloc(sizeof *ctx); 1131 1132 assert(data_path); 1133 1134 ctx->refcount = 1; 1135 ctx->log_handler = log_handler; 1136 ctx->log_type = log_type; 1137 ctx->libinput = libinput; 1138 list_init(&ctx->quirks); 1139 list_init(&ctx->sections); 1140 1141 qlog_debug(ctx, "%s is data root\n", data_path); 1142 1143 ctx->dmi = init_dmi(); 1144 ctx->dt = init_dt(); 1145 if (!ctx->dmi && !ctx->dt) 1146 goto error; 1147 1148 if (!parse_files(ctx, data_path)) 1149 goto error; 1150 1151 if (override_file && !parse_file(ctx, override_file)) 1152 goto error; 1153 1154 return ctx; 1155 1156error: 1157 quirks_context_unref(ctx); 1158 return NULL; 1159} 1160 1161struct quirks_context * 1162quirks_context_ref(struct quirks_context *ctx) 1163{ 1164 assert(ctx->refcount > 0); 1165 ctx->refcount++; 1166 1167 return ctx; 1168} 1169 1170struct quirks_context * 1171quirks_context_unref(struct quirks_context *ctx) 1172{ 1173 struct section *s; 1174 1175 if (!ctx) 1176 return NULL; 1177 1178 assert(ctx->refcount >= 1); 1179 ctx->refcount--; 1180 1181 if (ctx->refcount > 0) 1182 return NULL; 1183 1184 /* Caller needs to clean up before calling this */ 1185 assert(list_empty(&ctx->quirks)); 1186 1187 list_for_each_safe(s, &ctx->sections, link) { 1188 section_destroy(s); 1189 } 1190 1191 free(ctx->dmi); 1192 free(ctx->dt); 1193 free(ctx); 1194 1195 return NULL; 1196} 1197 1198static struct quirks * 1199quirks_new(void) 1200{ 1201 struct quirks *q; 1202 1203 q = zalloc(sizeof *q); 1204 q->refcount = 1; 1205 q->nproperties = 0; 1206 list_init(&q->link); 1207 list_init(&q->floating_properties); 1208 1209 return q; 1210} 1211 1212struct quirks * 1213quirks_unref(struct quirks *q) 1214{ 1215 if (!q) 1216 return NULL; 1217 1218 /* We don't really refcount, but might 1219 * as well have the API in place */ 1220 assert(q->refcount == 1); 1221 1222 for (size_t i = 0; i < q->nproperties; i++) { 1223 property_unref(q->properties[i]); 1224 } 1225 1226 /* Floating properties are owned by our quirks context, need to be 1227 * cleaned up here */ 1228 struct property *p; 1229 list_for_each_safe(p, &q->floating_properties, link) { 1230 property_cleanup(p); 1231 } 1232 1233 list_remove(&q->link); 1234 free(q->properties); 1235 free(q); 1236 1237 return NULL; 1238} 1239 1240/** 1241 * Searches for the udev property on this device and its parent devices. 1242 * 1243 * @return the value of the property or NULL 1244 */ 1245static const char * 1246udev_prop(struct udev_device *device, const char *prop) 1247{ 1248 struct udev_device *d = device; 1249 const char *value = NULL; 1250 1251 do { 1252 value = udev_device_get_property_value(d, prop); 1253 d = udev_device_get_parent(d); 1254 } while (value == NULL && d != NULL); 1255 1256 return value; 1257} 1258 1259static inline void 1260match_fill_name(struct match *m, 1261 struct udev_device *device) 1262{ 1263 const char *str = udev_prop(device, "NAME"); 1264 size_t slen; 1265 1266 if (!str) 1267 return; 1268 1269 /* udev NAME is in quotes, strip them */ 1270 if (str[0] == '"') 1271 str++; 1272 1273 m->name = safe_strdup(str); 1274 slen = strlen(m->name); 1275 if (slen > 1 && 1276 m->name[slen - 1] == '"') 1277 m->name[slen - 1] = '\0'; 1278 1279 m->bits |= M_NAME; 1280} 1281 1282static inline void 1283match_fill_bus_vid_pid(struct match *m, 1284 struct udev_device *device) 1285{ 1286 const char *str; 1287 unsigned int product, vendor, bus, version; 1288 1289 str = udev_prop(device, "PRODUCT"); 1290 if (!str) 1291 return; 1292 1293 /* ID_VENDOR_ID/ID_PRODUCT_ID/ID_BUS aren't filled in for virtual 1294 * devices so we have to resort to PRODUCT */ 1295 if (sscanf(str, "%x/%x/%x/%x", &bus, &vendor, &product, &version) != 4) 1296 return; 1297 1298 m->product = product; 1299 m->vendor = vendor; 1300 m->version = version; 1301 m->bits |= M_PID|M_VID|M_VERSION; 1302 switch (bus) { 1303 case BUS_USB: 1304 m->bus = BT_USB; 1305 m->bits |= M_BUS; 1306 break; 1307 case BUS_BLUETOOTH: 1308 m->bus = BT_BLUETOOTH; 1309 m->bits |= M_BUS; 1310 break; 1311 case BUS_I8042: 1312 m->bus = BT_PS2; 1313 m->bits |= M_BUS; 1314 break; 1315 case BUS_RMI: 1316 m->bus = BT_RMI; 1317 m->bits |= M_BUS; 1318 break; 1319 case BUS_I2C: 1320 m->bus = BT_I2C; 1321 m->bits |= M_BUS; 1322 break; 1323 case BUS_SPI: 1324 m->bus = BT_SPI; 1325 m->bits |= M_BUS; 1326 break; 1327 default: 1328 break; 1329 } 1330} 1331 1332static inline void 1333match_fill_udev_type(struct match *m, 1334 struct udev_device *device) 1335{ 1336 struct ut_map { 1337 const char *prop; 1338 enum udev_type flag; 1339 } mappings[] = { 1340 { "ID_INPUT_MOUSE", UDEV_MOUSE }, 1341 { "ID_INPUT_POINTINGSTICK", UDEV_POINTINGSTICK }, 1342 { "ID_INPUT_TOUCHPAD", UDEV_TOUCHPAD }, 1343 { "ID_INPUT_TABLET", UDEV_TABLET }, 1344 { "ID_INPUT_TABLET_PAD", UDEV_TABLET_PAD }, 1345 { "ID_INPUT_JOYSTICK", UDEV_JOYSTICK }, 1346 { "ID_INPUT_KEYBOARD", UDEV_KEYBOARD }, 1347 { "ID_INPUT_KEY", UDEV_KEYBOARD }, 1348 }; 1349 1350 ARRAY_FOR_EACH(mappings, map) { 1351 if (udev_prop(device, map->prop)) 1352 m->udev_type |= map->flag; 1353 } 1354 m->bits |= M_UDEV_TYPE; 1355} 1356 1357static inline void 1358match_fill_dmi_dt(struct match *m, char *dmi, char *dt) 1359{ 1360 if (dmi) { 1361 m->dmi = dmi; 1362 m->bits |= M_DMI; 1363 } 1364 1365 if (dt) { 1366 m->dt = dt; 1367 m->bits |= M_DT; 1368 } 1369} 1370 1371static struct match * 1372match_new(struct udev_device *device, 1373 char *dmi, char *dt) 1374{ 1375 struct match *m = zalloc(sizeof *m); 1376 1377 match_fill_name(m, device); 1378 match_fill_bus_vid_pid(m, device); 1379 match_fill_dmi_dt(m, dmi, dt); 1380 match_fill_udev_type(m, device); 1381 return m; 1382} 1383 1384static void 1385match_free(struct match *m) 1386{ 1387 /* dmi and dt are global */ 1388 free(m->name); 1389 free(m); 1390} 1391 1392static void 1393quirk_merge_event_codes(struct quirks_context *ctx, 1394 struct quirks *q, 1395 const struct property *property) 1396{ 1397 for (size_t i = 0; i < q->nproperties; i++) { 1398 struct property *p = q->properties[i]; 1399 1400 if (p->id != property->id) 1401 continue; 1402 1403 /* We have a duplicated property, merge in with ours */ 1404 size_t offset = p->value.tuples.ntuples; 1405 size_t max = ARRAY_LENGTH(p->value.tuples.tuples); 1406 for (size_t j = 0; j < property->value.tuples.ntuples; j++) { 1407 if (offset + j >= max) 1408 break; 1409 p->value.tuples.tuples[offset + j] = property->value.tuples.tuples[j]; 1410 p->value.tuples.ntuples++; 1411 } 1412 return; 1413 } 1414 1415 /* First time we add AttrEventCode: create a new property. 1416 * Unlike the other properties, this one isn't part of a section, it belongs 1417 * to the quirks */ 1418 struct property *newprop = property_new(); 1419 newprop->id = property->id; 1420 newprop->type = property->type; 1421 newprop->value.tuples = property->value.tuples; 1422 /* Caller responsible for pre-allocating space */ 1423 q->properties[q->nproperties++] = property_ref(newprop); 1424 list_append(&q->floating_properties, &newprop->link); 1425} 1426 1427static void 1428quirk_apply_section(struct quirks_context *ctx, 1429 struct quirks *q, 1430 const struct section *s) 1431{ 1432 struct property *p; 1433 size_t nprops = 0; 1434 void *tmp; 1435 1436 list_for_each(p, &s->properties, link) { 1437 nprops++; 1438 } 1439 1440 nprops += q->nproperties; 1441 tmp = realloc(q->properties, nprops * sizeof(p)); 1442 if (!tmp) 1443 return; 1444 1445 q->properties = tmp; 1446 list_for_each(p, &s->properties, link) { 1447 qlog_debug(ctx, "property added: %s from %s\n", 1448 quirk_get_name(p->id), s->name); 1449 1450 /* All quirks but AttrEventCode and AttrInputProp 1451 * simply overwrite each other, so we can just append the 1452 * matching property and, later when checking the quirk, pick 1453 * the last one in the array. 1454 * 1455 * The event codes/input props are special because they're lists 1456 * that may *partially* override each other, e.g. a section may 1457 * enable BTN_LEFT and BTN_RIGHT but a later section may disable 1458 * only BTN_RIGHT. This should result in BTN_LEFT force-enabled 1459 * and BTN_RIGHT force-disabled. 1460 * 1461 * To hack around this, those are the only ones where only ever 1462 * have one struct property in the list (not owned by a section) 1463 * and we simply merge any extra sections onto that. 1464 */ 1465 if (p->id == QUIRK_ATTR_EVENT_CODE || 1466 p->id == QUIRK_ATTR_INPUT_PROP) 1467 quirk_merge_event_codes(ctx, q, p); 1468 else 1469 q->properties[q->nproperties++] = property_ref(p); 1470 } 1471} 1472 1473static bool 1474quirk_match_section(struct quirks_context *ctx, 1475 struct quirks *q, 1476 struct section *s, 1477 struct match *m, 1478 struct udev_device *device) 1479{ 1480 uint32_t matched_flags = 0x0; 1481 1482 for (uint32_t flag = 0x1; flag <= M_LAST; flag <<= 1) { 1483 uint32_t prev_matched_flags = matched_flags; 1484 /* section doesn't have this bit set, continue */ 1485 if ((s->match.bits & flag) == 0) 1486 continue; 1487 1488 /* Couldn't fill in this bit for the match, so we 1489 * do not match on it */ 1490 if ((m->bits & flag) == 0) { 1491 qlog_debug(ctx, 1492 "%s wants %s but we don't have that\n", 1493 s->name, matchflagname(flag)); 1494 continue; 1495 } 1496 1497 /* now check the actual matching bit */ 1498 switch (flag) { 1499 case M_NAME: 1500 if (fnmatch(s->match.name, m->name, 0) == 0) 1501 matched_flags |= flag; 1502 break; 1503 case M_BUS: 1504 if (m->bus == s->match.bus) 1505 matched_flags |= flag; 1506 break; 1507 case M_VID: 1508 if (m->vendor == s->match.vendor) 1509 matched_flags |= flag; 1510 break; 1511 case M_PID: 1512 if (m->product == s->match.product) 1513 matched_flags |= flag; 1514 break; 1515 case M_VERSION: 1516 if (m->version == s->match.version) 1517 matched_flags |= flag; 1518 break; 1519 case M_DMI: 1520 if (fnmatch(s->match.dmi, m->dmi, 0) == 0) 1521 matched_flags |= flag; 1522 break; 1523 case M_DT: 1524 if (fnmatch(s->match.dt, m->dt, 0) == 0) 1525 matched_flags |= flag; 1526 break; 1527 case M_UDEV_TYPE: 1528 if (s->match.udev_type & m->udev_type) 1529 matched_flags |= flag; 1530 break; 1531 default: 1532 abort(); 1533 } 1534 1535 if (prev_matched_flags != matched_flags) { 1536 qlog_debug(ctx, 1537 "%s matches for %s\n", 1538 s->name, 1539 matchflagname(flag)); 1540 } 1541 } 1542 1543 if (s->match.bits == matched_flags) { 1544 qlog_debug(ctx, "%s is full match\n", s->name); 1545 quirk_apply_section(ctx, q, s); 1546 } 1547 1548 return true; 1549} 1550 1551struct quirks * 1552quirks_fetch_for_device(struct quirks_context *ctx, 1553 struct udev_device *udev_device) 1554{ 1555 struct quirks *q = NULL; 1556 struct section *s; 1557 struct match *m; 1558 1559 if (!ctx) 1560 return NULL; 1561 1562 qlog_debug(ctx, "%s: fetching quirks\n", 1563 udev_device_get_devnode(udev_device)); 1564 1565 q = quirks_new(); 1566 1567 m = match_new(udev_device, ctx->dmi, ctx->dt); 1568 1569 list_for_each(s, &ctx->sections, link) { 1570 quirk_match_section(ctx, q, s, m, udev_device); 1571 } 1572 1573 match_free(m); 1574 1575 if (q->nproperties == 0) { 1576 quirks_unref(q); 1577 return NULL; 1578 } 1579 1580 list_insert(&ctx->quirks, &q->link); 1581 1582 return q; 1583} 1584 1585static inline struct property * 1586quirk_find_prop(struct quirks *q, enum quirk which) 1587{ 1588 /* Run backwards to only handle the last one assigned */ 1589 for (ssize_t i = q->nproperties - 1; i >= 0; i--) { 1590 struct property *p = q->properties[i]; 1591 if (p->id == which) 1592 return p; 1593 } 1594 1595 return NULL; 1596} 1597 1598bool 1599quirks_has_quirk(struct quirks *q, enum quirk which) 1600{ 1601 return quirk_find_prop(q, which) != NULL; 1602} 1603 1604bool 1605quirks_get_int32(struct quirks *q, enum quirk which, int32_t *val) 1606{ 1607 struct property *p; 1608 1609 if (!q) 1610 return false; 1611 1612 p = quirk_find_prop(q, which); 1613 if (!p) 1614 return false; 1615 1616 assert(p->type == PT_INT); 1617 *val = p->value.i; 1618 1619 return true; 1620} 1621 1622bool 1623quirks_get_uint32(struct quirks *q, enum quirk which, uint32_t *val) 1624{ 1625 struct property *p; 1626 1627 if (!q) 1628 return false; 1629 1630 p = quirk_find_prop(q, which); 1631 if (!p) 1632 return false; 1633 1634 assert(p->type == PT_UINT); 1635 *val = p->value.u; 1636 1637 return true; 1638} 1639 1640bool 1641quirks_get_double(struct quirks *q, enum quirk which, double *val) 1642{ 1643 struct property *p; 1644 1645 if (!q) 1646 return false; 1647 1648 p = quirk_find_prop(q, which); 1649 if (!p) 1650 return false; 1651 1652 assert(p->type == PT_DOUBLE); 1653 *val = p->value.d; 1654 1655 return true; 1656} 1657 1658bool 1659quirks_get_string(struct quirks *q, enum quirk which, char **val) 1660{ 1661 struct property *p; 1662 1663 if (!q) 1664 return false; 1665 1666 p = quirk_find_prop(q, which); 1667 if (!p) 1668 return false; 1669 1670 assert(p->type == PT_STRING); 1671 *val = p->value.s; 1672 1673 return true; 1674} 1675 1676bool 1677quirks_get_bool(struct quirks *q, enum quirk which, bool *val) 1678{ 1679 struct property *p; 1680 1681 if (!q) 1682 return false; 1683 1684 p = quirk_find_prop(q, which); 1685 if (!p) 1686 return false; 1687 1688 assert(p->type == PT_BOOL); 1689 *val = p->value.b; 1690 1691 return true; 1692} 1693 1694bool 1695quirks_get_dimensions(struct quirks *q, 1696 enum quirk which, 1697 struct quirk_dimensions *val) 1698{ 1699 struct property *p; 1700 1701 if (!q) 1702 return false; 1703 1704 p = quirk_find_prop(q, which); 1705 if (!p) 1706 return false; 1707 1708 assert(p->type == PT_DIMENSION); 1709 *val = p->value.dim; 1710 1711 return true; 1712} 1713 1714bool 1715quirks_get_range(struct quirks *q, 1716 enum quirk which, 1717 struct quirk_range *val) 1718{ 1719 struct property *p; 1720 1721 if (!q) 1722 return false; 1723 1724 p = quirk_find_prop(q, which); 1725 if (!p) 1726 return false; 1727 1728 assert(p->type == PT_RANGE); 1729 *val = p->value.range; 1730 1731 return true; 1732} 1733 1734bool 1735quirks_get_tuples(struct quirks *q, 1736 enum quirk which, 1737 const struct quirk_tuples **tuples) 1738{ 1739 struct property *p; 1740 1741 if (!q) 1742 return false; 1743 1744 p = quirk_find_prop(q, which); 1745 if (!p) 1746 return false; 1747 1748 assert(p->type == PT_TUPLES); 1749 *tuples = &p->value.tuples; 1750 1751 return true; 1752} 1753 1754bool 1755quirks_get_uint32_array(struct quirks *q, 1756 enum quirk which, 1757 const uint32_t **array, 1758 size_t *nelements) 1759{ 1760 struct property *p; 1761 1762 if (!q) 1763 return false; 1764 1765 p = quirk_find_prop(q, which); 1766 if (!p) 1767 return false; 1768 1769 assert(p->type == PT_UINT_ARRAY); 1770 *array = p->value.array.data.u; 1771 *nelements = p->value.array.nelements; 1772 1773 return true; 1774} 1775