mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-24 00:50:42 +01:00
quirks: add support for Uniq matching
Same as MatchName but matches on the UNIQ udev property instead. This is needed for some Huion, Gaomon and other tablet devices that only differentiate each other through the Uniq string which contains the firmware version. Closes #997 Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1006>
This commit is contained in:
parent
e72ee0b1c8
commit
a2f0cc35c5
2 changed files with 102 additions and 1 deletions
38
src/quirks.c
38
src/quirks.c
|
|
@ -103,8 +103,9 @@ enum match_flags {
|
|||
M_UDEV_TYPE = bit(5),
|
||||
M_DT = bit(6),
|
||||
M_VERSION = bit(7),
|
||||
M_UNIQ = bit(8),
|
||||
|
||||
M_LAST = M_VERSION,
|
||||
M_LAST = M_UNIQ,
|
||||
};
|
||||
|
||||
enum bustype {
|
||||
|
|
@ -137,6 +138,7 @@ struct match {
|
|||
uint32_t bits;
|
||||
|
||||
char *name;
|
||||
char *uniq;
|
||||
enum bustype bus;
|
||||
uint32_t vendor;
|
||||
uint32_t product;
|
||||
|
|
@ -307,6 +309,7 @@ matchflagname(enum match_flags f)
|
|||
case M_DMI: return "MatchDMIModalias"; break;
|
||||
case M_UDEV_TYPE: return "MatchUdevType"; break;
|
||||
case M_DT: return "MatchDeviceTree"; break;
|
||||
case M_UNIQ: return "MatchUniq"; break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
|
@ -512,6 +515,7 @@ section_destroy(struct section *s)
|
|||
|
||||
free(s->name);
|
||||
free(s->match.name);
|
||||
free(s->match.uniq);
|
||||
free(s->match.dmi);
|
||||
free(s->match.dt);
|
||||
|
||||
|
|
@ -560,6 +564,9 @@ parse_match(struct quirks_context *ctx,
|
|||
if (streq(key, "MatchName")) {
|
||||
check_set_bit(s, M_NAME);
|
||||
s->match.name = safe_strdup(value);
|
||||
} else if (streq(key, "MatchUniq")) {
|
||||
check_set_bit(s, M_UNIQ);
|
||||
s->match.uniq = safe_strdup(value);
|
||||
} else if (streq(key, "MatchBus")) {
|
||||
check_set_bit(s, M_BUS);
|
||||
if (streq(value, "usb"))
|
||||
|
|
@ -1279,6 +1286,29 @@ match_fill_name(struct match *m,
|
|||
m->bits |= M_NAME;
|
||||
}
|
||||
|
||||
static inline void
|
||||
match_fill_uniq(struct match *m,
|
||||
struct udev_device *device)
|
||||
{
|
||||
const char *str = udev_prop(device, "UNIQ");
|
||||
size_t slen;
|
||||
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
/* udev uniq is in quotes, strip them */
|
||||
if (str[0] == '"')
|
||||
str++;
|
||||
|
||||
m->uniq = safe_strdup(str);
|
||||
slen = strlen(m->uniq);
|
||||
if (slen > 1 &&
|
||||
m->uniq[slen - 1] == '"')
|
||||
m->uniq[slen - 1] = '\0';
|
||||
|
||||
m->bits |= M_UNIQ;
|
||||
}
|
||||
|
||||
static inline void
|
||||
match_fill_bus_vid_pid(struct match *m,
|
||||
struct udev_device *device)
|
||||
|
|
@ -1375,6 +1405,7 @@ match_new(struct udev_device *device,
|
|||
struct match *m = zalloc(sizeof *m);
|
||||
|
||||
match_fill_name(m, device);
|
||||
match_fill_uniq(m, device);
|
||||
match_fill_bus_vid_pid(m, device);
|
||||
match_fill_dmi_dt(m, dmi, dt);
|
||||
match_fill_udev_type(m, device);
|
||||
|
|
@ -1386,6 +1417,7 @@ match_free(struct match *m)
|
|||
{
|
||||
/* dmi and dt are global */
|
||||
free(m->name);
|
||||
free(m->uniq);
|
||||
free(m);
|
||||
}
|
||||
|
||||
|
|
@ -1500,6 +1532,10 @@ quirk_match_section(struct quirks_context *ctx,
|
|||
if (fnmatch(s->match.name, m->name, 0) == 0)
|
||||
matched_flags |= flag;
|
||||
break;
|
||||
case M_UNIQ:
|
||||
if (fnmatch(s->match.uniq, m->uniq, 0) == 0)
|
||||
matched_flags |= flag;
|
||||
break;
|
||||
case M_BUS:
|
||||
if (m->bus == s->match.bus)
|
||||
matched_flags |= flag;
|
||||
|
|
|
|||
|
|
@ -759,6 +759,69 @@ START_TEST(quirks_parse_name_invalid)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_uniq)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=1235\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=abc\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=*foo\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=foo*\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=foo[]\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section Uniq]\n"
|
||||
"MatchUniq=*foo*\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_uniq_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchUniq=\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_udev)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
|
|
@ -1532,6 +1595,8 @@ TEST_COLLECTION(quirks)
|
|||
litest_add_deviceless(quirks_parse_version_invalid);
|
||||
litest_add_deviceless(quirks_parse_name);
|
||||
litest_add_deviceless(quirks_parse_name_invalid);
|
||||
litest_add_deviceless(quirks_parse_uniq);
|
||||
litest_add_deviceless(quirks_parse_uniq_invalid);
|
||||
litest_add_deviceless(quirks_parse_udev);
|
||||
litest_add_deviceless(quirks_parse_udev_invalid);
|
||||
litest_add_deviceless(quirks_parse_dmi);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue