Add a code-based name lookup function

Two new function pairs:
	libevdev_event_code_from_code_name()
	libevdev_event_type_from_code_name()

	libevdev_event_code_from_code_name_n()
	libevdev_event_type_from_code_name_n()

These functions look up event codes/types by the name of the event code only,
removing the need to figure out what event type an event code has. So if all
you have is "BTN_TOUCH", you can now look up the type and code for that,
without having to check the prefix yourself to guess at the type.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2019-03-19 11:44:33 +10:00
parent 76662deeff
commit 9fe185dd3d
4 changed files with 227 additions and 0 deletions

View file

@ -184,3 +184,46 @@ libevdev_property_from_name_n(const char *name, size_t len)
return entry ? (int)entry->value : -1;
}
LIBEVDEV_EXPORT int
libevdev_event_code_from_code_name(const char *name)
{
return libevdev_event_code_from_code_name_n(name, strlen(name));
}
LIBEVDEV_EXPORT int
libevdev_event_code_from_code_name_n(const char *name, size_t len)
{
const struct name_entry *entry;
struct name_lookup lookup;
/* now look up the name @name and return the constant */
lookup.name = name;
lookup.len = len;
entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
return entry ? (int)entry->value : -1;
}
LIBEVDEV_EXPORT int
libevdev_event_type_from_code_name(const char *name)
{
return libevdev_event_type_from_code_name_n(name, strlen(name));
}
LIBEVDEV_EXPORT int
libevdev_event_type_from_code_name_n(const char *name, size_t len)
{
const struct name_entry *entry;
struct name_lookup lookup;
/* First look up if the name exists, we dont' want to return a valid
* type for an invalid code name */
lookup.name = name;
lookup.len = len;
entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
return entry ? type_from_prefix(name, len) : -1;
}

View file

@ -2174,6 +2174,84 @@ int libevdev_event_code_from_name_n(unsigned int type, const char *name,
int libevdev_event_value_from_name(unsigned int type, unsigned int code,
const char *name);
/**
* @ingroup misc
*
* Look up an event type for a event code name. For example, the name
* "ABS_Y" returns EV_ABS. For the lookup to succeed, the name must be
* unique, which is the case for all #defines as of kernel 5.0 and likely to
* be the case in the future.
*
* This is equivalent to libevdev_event_type_from_name() but takes the code
* name instead of the type name.
*
* @param name A non-NULL string describing an input-event value
* ("ABS_X", "REL_Y", "KEY_A", ...)
*
* @return The given event code for the name or -1 if not found.
*/
int
libevdev_event_type_from_code_name(const char *name);
/**
* @ingroup misc
*
* Look up an event type for a event code name. For example, the name
* "ABS_Y" returns EV_ABS. For the lookup to succeed, the name must be
* unique, which is the case for all #defines as of kernel 5.0 and likely to
* be the case in the future.
*
* This is equivalent to libevdev_event_type_from_name_n() but takes the code
* name instead of the type name.
*
* @param name A non-NULL string describing an input-event value
* ("ABS_X", "REL_Y", "KEY_A", ...)
* @param len The length of the passed string excluding any terminating 0
* character.
*
* @return The given event code for the name or -1 if not found.
*/
int
libevdev_event_type_from_code_name_n(const char *name, size_t len);
/**
* @ingroup misc
*
* Look up an event code by its name. For example, the name "ABS_Y" returns
* 1. For the lookup to succeed, the name must be unique, which is the case
* for all #defines as of kernel 5.0 and likely to be the case in the future.
*
* This is equivalent to libevdev_event_code_from_name() without the need
* for knowing the event type.
*
* @param name A non-NULL string describing an input-event value
* ("ABS_X", "REL_Y", "KEY_A", ...)
*
* @return The given event code for the name or -1 if not found.
*/
int
libevdev_event_code_from_code_name(const char *name);
/**
* @ingroup misc
*
* Look up an event code by its name. For example, the name "ABS_Y" returns
* 1. For the lookup to succeed, the name must be unique, which is the case
* for all #defines as of kernel 5.0 and likely to be the case in the future.
*
* This is equivalent to libevdev_event_code_from_name_n() without the need
* for knowing the event type.
*
* @param name A non-NULL string describing an input-event value
* ("ABS_X", "REL_Y", "KEY_A", ...)
* @param len The length of the passed string excluding any terminating 0
* character.
*
* @return The given event code for the name or -1 if not found.
*/
int
libevdev_event_code_from_code_name_n(const char *name, size_t len);
/**
* @ingroup misc
*

View file

@ -121,3 +121,13 @@ global:
local:
*;
} LIBEVDEV_1_3;
LIBEVDEV_1_7 {
global:
libevdev_event_code_from_code_name;
libevdev_event_code_from_code_name_n;
libevdev_event_type_from_code_name;
libevdev_event_type_from_code_name_n;
local:
*;
} LIBEVDEV_1_6;

View file

@ -55,6 +55,41 @@ START_TEST(test_type_names_invalid)
}
END_TEST
START_TEST(test_type_name_lookup)
{
ck_assert_int_eq(libevdev_event_type_from_code_name("SYN_REPORT"), EV_SYN);
ck_assert_int_eq(libevdev_event_type_from_code_name("KEY_A"), EV_KEY);
ck_assert_int_eq(libevdev_event_type_from_code_name("REL_Z"), EV_REL);
ck_assert_int_eq(libevdev_event_type_from_code_name("ABS_Z"), EV_ABS);
ck_assert_int_eq(libevdev_event_type_from_code_name("MSC_SERIAL"), EV_MSC);
ck_assert_int_eq(libevdev_event_type_from_code_name("SND_TONE"), EV_SND);
ck_assert_int_eq(libevdev_event_type_from_code_name("SW_TABLET_MODE"), EV_SW);
ck_assert_int_eq(libevdev_event_type_from_code_name("LED_CHARGING"), EV_LED);
ck_assert_int_eq(libevdev_event_type_from_code_name("REP_PERIOD"), EV_REP);
ck_assert_int_eq(libevdev_event_type_from_code_name("FF_SPRING"), EV_FF);
ck_assert_int_eq(libevdev_event_type_from_code_name("FF_STATUS_STOPPED"), EV_FF_STATUS);
ck_assert_int_eq(libevdev_event_type_from_code_name_n("KEY_1zzzzz", 5), EV_KEY);
ck_assert_int_eq(libevdev_event_type_from_code_name_n("ABS_Zooom", 5), EV_ABS);
ck_assert_int_eq(libevdev_event_type_from_code_name("KEY_MAX"), EV_KEY);
ck_assert_int_eq(libevdev_event_type_from_code_name("REL_MAX"), EV_REL);
ck_assert_int_eq(libevdev_event_type_from_code_name("ABS_MAX"), EV_ABS);
}
END_TEST
START_TEST(test_type_name_lookup_invalid)
{
ck_assert_int_eq(libevdev_event_type_from_name("SYN_REPORTED"), -1);
ck_assert_int_eq(libevdev_event_type_from_name("syn_blah"), -1);
ck_assert_int_eq(libevdev_event_type_from_name("SYN_"), -1);
ck_assert_int_eq(libevdev_event_type_from_name("KEY_BANANA"), -1);
ck_assert_int_eq(libevdev_event_type_from_name_n("KEY_BA", 6), -1);
ck_assert_int_eq(libevdev_event_type_from_name_n("KEY_BLAH", 8), -1);
}
END_TEST
START_TEST(test_code_names)
{
ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_REPORT"), SYN_REPORT);
@ -78,6 +113,30 @@ START_TEST(test_code_names)
}
END_TEST
START_TEST(test_code_name_lookup)
{
/* Same as test_code_names() but without the type */
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_REPORT"), SYN_REPORT);
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_X"), ABS_X);
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_A"), BTN_A);
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_A"), KEY_A);
ck_assert_int_eq(libevdev_event_code_from_code_name("REL_X"), REL_X);
ck_assert_int_eq(libevdev_event_code_from_code_name("MSC_RAW"), MSC_RAW);
ck_assert_int_eq(libevdev_event_code_from_code_name("LED_KANA"), LED_KANA);
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_BELL"), SND_BELL);
ck_assert_int_eq(libevdev_event_code_from_code_name("REP_DELAY"), REP_DELAY);
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_DROPPED"), SYN_DROPPED);
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_RESERVED"), KEY_RESERVED);
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_0"), BTN_0);
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_0"), KEY_0);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_GAIN"), FF_GAIN);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_MAX"), FF_STATUS_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_PEN_INSERTED"), SW_PEN_INSERTED);
ck_assert_int_eq(libevdev_event_code_from_code_name_n("ABS_YXZ", 5), ABS_Y);
}
END_TEST
START_TEST(test_code_names_invalid)
{
ck_assert_int_eq(libevdev_event_code_from_name(EV_MAX, "MAX_FAKE"), -1);
@ -99,6 +158,28 @@ START_TEST(test_code_names_invalid)
}
END_TEST
START_TEST(test_code_name_lookup_invalid)
{
/* Same as test_code_names_invalid() but without the type */
ck_assert_int_eq(libevdev_event_code_from_code_name("MAX_FAKE"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("CNT_FAKE"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("PWR_SOMETHING"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("EV_ABS"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_XY"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_GAMEPAD"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("BUS_PCI"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("ID_BUS"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_CNT"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_CNT"), -1);
ck_assert_int_eq(libevdev_event_code_from_code_name_n("ABS_X", 4), -1);
}
END_TEST
START_TEST(test_code_names_max)
{
ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_MAX"), SYN_MAX);
@ -111,6 +192,17 @@ START_TEST(test_code_names_max)
ck_assert_int_eq(libevdev_event_code_from_name(EV_SND, "SND_MAX"), SND_MAX);
ck_assert_int_eq(libevdev_event_code_from_name(EV_REP, "REP_MAX"), REP_MAX);
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_MAX"), FF_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_MAX"), SYN_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_MAX"), KEY_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("REL_MAX"), REL_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_MAX"), ABS_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("MSC_MAX"), MSC_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_MAX"), SW_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("LED_MAX"), LED_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_MAX"), SND_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("REP_MAX"), REP_MAX);
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_MAX"), FF_MAX);
}
END_TEST
@ -175,11 +267,15 @@ TEST_SUITE(event_code_suite)
TCase *tc = tcase_create("type tests");
tcase_add_test(tc, test_type_names);
tcase_add_test(tc, test_type_names_invalid);
tcase_add_test(tc, test_type_name_lookup);
tcase_add_test(tc, test_type_name_lookup_invalid);
suite_add_tcase(s, tc);
tc = tcase_create("code tests");
tcase_add_test(tc, test_code_names);
tcase_add_test(tc, test_code_name_lookup);
tcase_add_test(tc, test_code_names_invalid);
tcase_add_test(tc, test_code_name_lookup_invalid);
tcase_add_test(tc, test_code_names_max);
suite_add_tcase(s, tc);