我想从包含如下数据的文本文件中读取按钮映射:

DPAD_LEFT = 105
DPAD_RIGHT = 106
DPAD_UP = 103
DPAD_DOWN = 108

右边的部分实际上是evdev键码(在 <linux/input.h> 中定义)。

这很难读,所以我希望能够有这样的文件:
DPAD_LEFT = KEY_LEFT
DPAD_RIGHT = KEY_RIGHT
DPAD_UP = KEY_UP
DPAD_DOWN = KEY_DOWN

但是我目前无法将它们转换回原位:
char[256] keyname;
some_method_to_read(&keyname, "DPAD_LEFT");
//keyname now contains "KEY_LEFT"

如何获取相应的键码(例如105)?有没有标准的方法可以做到这一点?

编辑:我现在唯一能想到的方法就是复制源代码中的所有键码并将它们放在数组或映射中,就像 evtest utility一样。但是有很多键码,这对我来说似乎有些过大了。另外,这有时可能与<input/linux.h>中定义的键码不同步。
std::map<string, int> keynames;
#define MAP_KEYCODE(keycode) keynames[#keycode] = keycode

MAP_KEYCODE(KEY_LEFT);
MAP_KEYCODE(KEY_RIGHT);
MAP_KEYCODE(KEY_UP);
MAP_KEYCODE(KEY_DOWN);
// [...]

最佳答案

让您的程序从配置文件中读取名称到代码的映射,例如/usr/share/yourprogram/keycodes和/或$HOME/.yourprogram/keycodes

记录任何人都可以使用其/usr/include/linux/input.h重新生成该文件-并自己重新生成初始文件-例如

awk '$2 ~ /^KEY_/ { code[$2] = $3 }
     END {
       for (name in code)
         if (code[name] ~ /^KEY_/)
           code[name] = code[code[name]];
       for (name in code)
         if (code[name] !~ /KEY_/)
           printf "%-24s %s\n", name, code[name]
     }' /usr/include/linux/input.h | sort

您可能需要自己添加KEY_CNT(它的值比KEY_MAX多一个),因为上述脚本不执行数学运算,仅直接使用别名。

为了描述名称到代码的映射,我将使用
struct keycode {
    struct keycode *next;
    unsigned int    code;
    unsigned int    hash;
    unsigned char   namelen;
    char            name[];
};

哈希是一个简单的哈希,例如djb2,
unsigned int djb2(const char *const str, const size_t len)
{
    unsigned int result = 5831U;
    size_t       i;
    for (i = 0; i < len; i++)
        result = result * 33U ^ (unsigned int)str[i];
    return result;
}

在当前定义的键控代码中,只有KEY_CUTKEY_F15映射到相同的djb2哈希,即1857856141。(如果您使用31U而不是33U,则当前集将没有冲突,但这并不能证明将来会发生冲突。最好已经发生一次冲突,因此您可以测试它是否正确处理。)

读取配置文件的函数可以通过将新代码添加到单链列表之前来返回代码。
int read_keycodes(const char *const filename,
                  struct keycode **list);

如果您位于该列表的前面,则稍后应忽略相同名称的重新定义。这样,如果先阅读系统范围的配置,然后再阅读用户特定的配置,则用户特定的配置可以覆盖系统范围的配置。

读取所有键码映射后,您将构建一个哈希表,类似于
struct keytab {
    unsigned int     size; /* index = hash % size */
    struct keycode **slot;
};

(在构建哈希表时,请舍弃其确切名称已存在于 key 表中的 key 代码。这样,以后的定义将覆盖先前的定义。)

这样,您只需要计算要查找的名称的哈希值,然后在您的keytab结构中探测链接列表。首先比较散列,然后比较长度;如果两者都匹配,最后执行strcmp()。这样,查找将非常快,并且实现起来也相对简单。使用当前的键码,对于strcmp()KEY_F15,您只需要对慢速KEY_CUT进行两次;对于其他所有代码,一个strcmp()就足够了。

问题?

关于c - 有没有办法从字符串获取evdev键码?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32059363/

10-11 19:30