首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Char转换为kernel Keycode (用于uinput使用)

将Char转换为kernel Keycode (用于uinput使用)
EN

Stack Overflow用户
提问于 2017-01-19 18:12:26
回答 1查看 1.2K关注 0票数 1

我正在尝试做一个在Debian Stretch上使用uinput的虚拟键盘,我可以给它输入字符串,比如"Toto !",键盘会写下这个字符串。然而,我坚持从C字符到键盘处理的键码的转换。我没有使用event-codes.h中定义的宏,因为我希望我的解决方案在计算机的区域设置上工作,并且宏是围绕美国键盘定义的。

下面是使用uinput创建的设备:

代码语言:javascript
复制
int setup_uinput_device(){
/* Temporary variable */
    int i=0;
/* Open the input device */
    uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
    if (fcntl(uinp_fd, F_GETFD) == -1)
    {
        printf("Unable to open /dev/uinput\n");
        return -1;
    }
    memset(&uinp,0,sizeof(uinp)); /* Intialize the uInput device to NULL */
    strncpy(uinp.name, "Custom Keyboard", UINPUT_MAX_NAME_SIZE);
    uinp.id.bustype = BUS_USB;
    // Setup the uinput device
    ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
    ioctl(uinp_fd, UI_SET_EVBIT, EV_REL);
    ioctl(uinp_fd, UI_SET_EVBIT, EV_REP);
    for (i=0; i < 256; i++) {
        ioctl(uinp_fd, UI_SET_KEYBIT, i);
    }
    /* Create input device into input sub-system */
    write(uinp_fd, &uinp, sizeof(uinp));
    if (ioctl(uinp_fd, UI_DEV_CREATE))
    {
        printf("Unable to create UINPUT device.\n");
        return -1;
    }
    return 0;
}

我已经尝试过使用X11库的解决方案,如下面的链接所示:Convert ASCII character to x11 keycode不幸的是,我使用uinput创建的键盘采用的键码与X11使用的键码不同。(我想我的键盘采用的键码与使用dumpkeys命令得到的键码相同)。当然可以将X11键码转换为(内核?)键盘可以正确解释的键码,但我希望保持较低的依赖项数量。

我现在正在尝试使用linux.h中描述的EVIOCGKEYCODE,但我很难理解它是如何工作的,我认为它做的与我真正想要的相反。

下面是一个例子:

代码语言:javascript
复制
int main(int argc, char *argv[]) {
    setup_uinput_device();
    struct input_keymap_entry mapping;
    int i =0;
    /* Set the max value at 130 just for the purpose of testing */    
    for (i=0; i<130; i++) {
        mapping.scancode[0] = i;
        if(ioctl(fd, EVIOCGKEYCODE_V2, mapping)) {
            perror("evdev ioctl");
        }
        printf("Scancode= %d, Keycode = %d\n",
               mapping.scancode[0], mapping.keycode);
    }
    /* Simple function to destroy the device */
    destroy_uinput_device();
    return 0;
} 

我得到以下错误:"evdev ioctl: Invalid argument“。我在某处读到过,这是PS2键盘使用的一种旧方法,所以这可能是它不起作用的许多原因之一。

我考虑的最后一个解决方案是在表或映射中解析dumpkeys的结果,以便稍后使用,但我认为我会遇到性能问题,并且我不想重新创建可能已经存在的东西。

有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-09 17:41:49

因此,经过多次尝试,我终于理解了内核使用的键码与X11使用的键码减去8是一样的。

我首先要管理编码。我使用了以下代码来管理多字节编码字符(如used ):

代码语言:javascript
复制
    char *str = "Test €";
    size_t mbslen; /* Number of multibyte characters in source */
    wchar_t *wcs; /* Pointer to converted wide character string */
    wchar_t *wp;
    setlocale(LC_ALL, "");

    mbslen = mbstowcs(NULL, str, 0);
    if (mbslen == (size_t) -1) {
            perror("mbstowcs");
            exit(ERROR_FAILURE);
    }

    wcs = calloc(mbslen + 1, sizeof(wchar_t));
    if (wcs == NULL) {
            perror("calloc");
            exit(ERROR_FAILURE);
    }

    /* Convert the multibyte character string in str to a wide character string */
    if (mbstowcs(wcs, str, mbslen + 1) == (size_t) -1) {
            perror("mbstowcs");
            exit(ERROR_FAILURE);
    }

然后使用这个conversion table from ucs to keysym,根据我在原始问题中提供的example,我成功地将一个widechar数组转换为其相应的键码序列。

最后一步是在我的uinput键盘上输入X11键码减8。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41739121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档