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