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