Add a code-based name lookup function
authorPeter Hutterer <peter.hutterer@who-t.net>
Tue, 19 Mar 2019 01:44:33 +0000 (11:44 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 21 Mar 2019 00:55:32 +0000 (00:55 +0000)
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>
libevdev/libevdev-names.c
libevdev/libevdev.h
libevdev/libevdev.sym
test/test-event-codes.c

index 6d06df3..82abddc 100644 (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;
+}
index 198b684..3027d2e 100644 (file)
@@ -2177,6 +2177,84 @@ int libevdev_event_value_from_name(unsigned int type, unsigned int code,
 /**
  * @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
+ *
  * Look up an event value by its type, code and name. Event values start
  * with a fixed prefix followed by their name (eg., "MT_TOOL_PALM"). The
  * prefix must be included in the name. It returns the constant assigned
index 7dd0c20..d034669 100644 (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;
index 643b537..b4e6d02 100644 (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);