zoukankan      html  css  js  c++  java
  • 虚拟键盘驱动程序

    虚拟键盘驱动程序
    Saturday, September 12th, 2009 | Author: admin

    转载时请注明出处和作者联系方式
    文章出处:http://www.limodev.cn/blog
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    前段时间写一个程序,要向系统中注入按键事件,我又不想信赖于具体的GUI,就写一个虚拟键盘设备驱动程序,感觉挺好用的,不过后来发现linux其实有一个uinput驱动程序实现了类似的功能。幸好后来才发现uinput这玩意儿,否则就没有机会去写了这个程序了,有时真是宁愿知识面窄一点,这样才有机会重复发明一些轮子,从中获得一些乐趣。

    o 先写一个字符驱动程序。

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/slab.h>
    #include <linux/fs.h>
    #include <linux/errno.h>
    #include <linux/types.h>
    #include <linux/proc_fs.h>
    #include <linux/fcntl.h>    
    #include <linux/aio.h>
    #include <asm/uaccess.h>
    #include <linux/ioctl.h>
    #include <linux/cdev.h>
    #include <linux/input.h>
    int vkeyboard_major = 201;
    module_param(vkeyboard_major, int, 0);
    MODULE_AUTHOR("Li XianJing <xianjimli@hotmail.com>");
    MODULE_LICENSE("GPL");
     
    static struct input_dev* vkeyboard_idev = NULL;
     
    int vkeyboard_open(struct inode* inode, struct file* filp)
    {
        return 0;
    }
     
    int vkeyboard_release(struct inode* inode, struct file* filp)
    {
        return 0;
    }
     
    ssize_t vkeyboard_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos)
    {
        printk(KERN_INFO"%s/n", __func__);
        return count;
    }
     
    struct keyboard_event
    {
        int press;
        int key;
    };
     
    ssize_t vkeyboard_write(struct file* filp, const char __user * buf, size_t count, loff_t* f_pos)
    {
        int ret = 0;
        struct keyboard_event event;
     
        while(ret < count)
        {
            if(copy_from_user(&event, buf + ret, sizeof(event)))
            {
                return -EFAULT;
            }
            ret += sizeof(event);
     
            input_event(vkeyboard_idev, EV_MSC, MSC_SCAN, event.key);
            input_report_key(vkeyboard_idev, event.key, event.press);
            input_sync (vkeyboard_idev);
     
            printk(KERN_INFO"%s p=%d key=%d with scan code/n", __func__, event.press, event.key);
        }
     
        return ret;
    }
     
    static struct file_operations vkeyboard_fops =
    {
        .owner = THIS_MODULE,
        .open    = vkeyboard_open,
        .release = vkeyboard_release,
        .read    = vkeyboard_read,
        .write   = vkeyboard_write,
    };
     
    static int __init vkeyboard_init(void)
    {
        int result = register_chrdev(vkeyboard_major, "vkeyboard", &vkeyboard_fops);
        vkeyboard_input_dev_setup();
     
        return result;
    }
     
    static void __exit vkeyboard_cleanup(void)
    {
        input_unregister_device(vkeyboard_idev);
        unregister_chrdev(vkeyboard_major, "vkeyboard");
     
        return;
    }
     
    module_init(vkeyboard_init);
    module_exit(vkeyboard_cleanup);

    o 再实现一个虚拟输入设备。

    static int vkeyboard_input_dev_open(struct input_dev* idev)
    {
        printk(KERN_INFO"%s/n", __func__);
     
        return 0;
    }
     
    static void vkeyboard_input_dev_close(struct input_dev* idev)
    {
        printk(KERN_INFO"%s/n", __func__);
     
        return;
    }
     
    static int vkeyboard_input_dev_setup(void)
    {
        int ret = 0;
        int i = 0;
        vkeyboard_idev = input_allocate_device();
     
        if(vkeyboard_idev == NULL)
        {
            return -ENOMEM;
        }
     
        vkeyboard_idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_MSC);
        vkeyboard_idev->mscbit[0] = BIT_MASK(MSC_SCAN) | BIT_MASK(MSC_SERIAL) | BIT_MASK(MSC_RAW);
     
        bitmap_fill(vkeyboard_idev->keybit, KEY_MAX);
        bitmap_fill(vkeyboard_idev->relbit, REL_MAX);
        bitmap_fill(vkeyboard_idev->absbit, ABS_MAX);                
     
        vkeyboard_idev->name = "vkeyboard";
        vkeyboard_idev->phys = "vkeyboard/input0";
        vkeyboard_idev->open = vkeyboard_input_dev_open;
        vkeyboard_idev->close = vkeyboard_input_dev_close;
     
        for(i = 32; i < KEY_MAX; i++)
        {
            input_set_capability(vkeyboard_idev, EV_KEY, i);
        }
        __set_bit(EV_KEY, vkeyboard_idev->evbit);
     
        ret = input_register_device(vkeyboard_idev);
     
        return ret;
    }

    o Makefile

    obj-m := vkeyboard.o

    KDIR := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)

    default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
    install:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
    clean:
        rm -f *.mod.c *.ko *.o Module.markers  modules.order  Module.symvers

    加载模块后,向/dev/vkeyboard里写入要注入的事件,事件将会转发到/dev/input/eventX输入设备文件里,系统会从这里自动读取事件。

  • 相关阅读:
    打印九九乘法表
    PAT (Basic Level) Practice (中文) 1091 N-自守数 (15分)
    PAT (Basic Level) Practice (中文)1090 危险品装箱 (25分) (单身狗进阶版 使用map+ vector+数组标记)
    PAT (Basic Level) Practice (中文) 1088 三人行 (20分)
    PAT (Basic Level) Practice (中文) 1087 有多少不同的值 (20分)
    PAT (Basic Level) Practice (中文)1086 就不告诉你 (15分)
    PAT (Basic Level) Practice (中文) 1085 PAT单位排行 (25分) (map搜索+set排序+并列进行排行)
    PAT (Basic Level) Practice (中文) 1083 是否存在相等的差 (20分)
    PAT (Basic Level) Practice (中文) 1082 射击比赛 (20分)
    PAT (Basic Level) Practice (中文) 1081 检查密码 (15分)
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167489.html
Copyright © 2011-2022 走看看