驱动usb鼠标产生键盘信息

实际上跟我之前写的简单的usb鼠标驱动分析 这个驱动的区别在于, 输入子系统向input core提交不同的信息, 这样就会有不同的消息输出了, 也就是我们把鼠标按键提交的信息改为 键盘按键的信息,  这样就写完了....

具体代码如下:

#include <linux/kernel.h>

#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "zhutoubenben"
#define DRIVER_DESC "u s b ..."

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

struct usb_device_id my_usb_table[] = {
        { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
          USB_INTERFACE_PROTOCOL_MOUSE) },
        {}
};

struct my_mouse_dev {
        struct usb_device* usb_dev;
        struct input_dev*  input_dev;
        struct urb *       urb;
        signed char *      data;
        dma_addr_t         data_dma;
};

int my_usb_mouse_open(struct input_dev *dev){
        struct my_mouse_dev* mouse_dev = input_get_drvdata( dev);
        mouse_dev->urb->dev = mouse_dev->usb_dev;
        if(usb_submit_urb(mouse_dev->urb,GFP_ATOMIC)){
                return -EIO;
        }
        return 0;
}

void my_usb_mouse_close(struct input_dev *dev){
        struct my_mouse_dev *mouse = input_get_drvdata(dev);
        usb_kill_urb(mouse->urb);
}

/*******  鼠标事件发生 调用的函数
  由下方的probe中的 usb_fill_int_urb()决定
  ******/
static void usb_mouse_irq(struct urb *urb){
        struct my_mouse_dev* mouse = urb->context;
        struct input_dev*    dev   = mouse->input_dev;
        signed char *        data  = mouse->data;
        static char pre_data = '\0';  // 存储上一次的按键信息
        switch(urb->status){
        case 0:     //  成功
                break;
        case -ECONNRESET:	/* unlink */
        case -ENOENT:
        case -ESHUTDOWN:
                return;
        default:		/* error */
                goto resubmit;
        }
        //data[0]: bit0-左键, 1-按下, 0-松开
        //         bit1-右键, 1-按下, 0-松开
        //         bit2-中键, 1-按下, 0-松开
        if(pre_data != data[0] ){
                if(((pre_data & (1<<0)) != (data[0] & (1<<0)))){  //  bit0-左键
                        input_event(dev, EV_KEY, KEY_L, data[0] & 0x01);
                        input_sync(dev);
                }
                if(((pre_data & (1<<1)) != (data[0] & (1<<1)))){  //  bit1-右键
                        input_event(dev, EV_KEY, KEY_R, data[0] & 0x02);
                        input_sync(dev);
                }
                if( ((pre_data & (1<<2)) != (data[0] & (1<<2)))){  //   bit2-中键,
                        input_event(dev, EV_KEY, KEY_ENTER, data[0] & 0x01<<2);
                        input_sync(dev);
                }
                pre_data = data[0];// 存储本次信息, 下次进来的时候就能够当做比较
        }


resubmit:
        usb_submit_urb (urb, GFP_ATOMIC);//  提交
        /*   URB处理流程
            (1)USB设备驱动程序创建并初始化一个访问特定USB设备特定端点的urb,并提交给USB core
            (2)USR core提交该urb到到USB主控制器驱动程序。
            (3)USB主控制器驱动程序根据该urb描述的信息,来访问usb设备
            (4)当设备访问结束后,USB主的控制器驱动程序通知USB设备驱动程序。
          */
        // 此次应加上判断返回的状态是否成功....
}

static int my_usb_probe(struct usb_interface *intf,const struct usb_device_id *id){

        int retval = -ENOMEM;
        struct my_mouse_dev *mouse;
        struct input_dev *input_dev;

        struct usb_endpoint_descriptor *endpoint;  /* 端点描述符 */
        struct usb_host_interface *host_intf;      /* 接口设置描述 */
        struct usb_device *dev = interface_to_usbdev(intf);  /* 设备描述 usb_device */
        int pipe; // 管道
        int maxp;
        host_intf = intf->cur_altsetting;// 获取当前的接口配置
        if(1!=host_intf->desc.bNumEndpoints){
                return -ENODEV;
        }
        endpoint = &host_intf->endpoint[0].desc;
        if (!usb_endpoint_is_int_in(endpoint)){
                return -ENODEV;/* 根据HID规范,鼠标唯一的端点应为中断端点 */
        }

        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);/* 生成中断接收管道 */

        /* 返回该端点能够传输的最大的包长度,鼠标的返回的最大数据包为4个字节。*/
        maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

        mouse = kzalloc(sizeof(struct my_mouse_dev),GFP_KERNEL);

        input_dev = input_allocate_device();
        if(!mouse || !input_dev){
                goto fail0;
        }
        mouse->data = usb_buffer_alloc(dev,8,GFP_ATOMIC,&mouse->data_dma);
        if(!mouse->data){
                printk("usb_buffer_alloc error \n ");
                goto fail1;
        }
        mouse->urb = usb_alloc_urb(0,GFP_KERNEL);
        if(!mouse->urb){
                printk("usb_alloc_urb error \n ");
                goto fail2;
        }
        mouse->usb_dev= dev;
        mouse->input_dev = input_dev;
    usb_fill_int_urb(mouse->urb,dev,pipe,mouse->data,(maxp > 8 ? 8 : maxp),
                                                  usb_mouse_irq, mouse, endpoint->bInterval);
    mouse->urb->transfer_dma = mouse->data_dma;
    mouse->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;// 当不使用DMA

        /*   input 子系统部分 */
        input_dev->dev.parent = &intf->dev;
        input_dev->evbit[0]  = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);//  支持事件: 按键 ,  重复

        set_bit(KEY_L, input_dev->keybit);    //能产生按键L事件
        set_bit(KEY_R, input_dev->keybit);    //能产生按键R事件
        set_bit(KEY_ENTER, input_dev->keybit);//能产生ENTER

        input_set_drvdata(input_dev,mouse); //  设置私有数据
        input_dev->open = my_usb_mouse_open;
        input_dev->close = my_usb_mouse_close;

        retval = input_register_device(mouse->input_dev);
        if (retval){
                printk("input_register_device error \n ");
                goto fail3;
        }

        usb_set_intfdata(intf, mouse);//  设置私有数据
        return 0;

fail3:
        usb_free_urb(mouse->urb);
fail2:
        usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
fail1:
        input_free_device(input_dev);
fail0:
        kfree(mouse);
        return retval;

}

static void my_usb_disconnect (struct usb_interface *intf){
        struct my_mouse_dev* mouse = usb_get_intfdata (intf);

        usb_set_intfdata(intf, NULL);
        if (mouse) {
                usb_kill_urb(mouse->urb);                   /* 结束 urb 生命周期 */
                input_unregister_device(mouse->input_dev);  /* 将鼠标设备从输入子系统中注销 */
                input_free_device(mouse->input_dev);        /* 释放存放鼠标事件的存储空间 */
                usb_free_urb(mouse->urb);                   /* 释放 urb 存储空间 */
                usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);/* 释放存放鼠标事件的 data 存储空间 */
                kfree(mouse);
        }
        printk("device %x disconnect ... \n",interface_to_usbdev(intf)->descriptor.idVendor);
}

static struct usb_driver my_usb_driver = {
        .name =		"my_usb_driver",
        .probe =	my_usb_probe,
        .disconnect =	my_usb_disconnect,
        .id_table =	my_usb_table,
};

static int __init my_usb_mouse_init(void){
        int result;
        result = usb_register(&my_usb_driver);
        if (result)
                err("usb_register failed. Error number %d", result);
        return result;
}

static void __exit my_usb_mouse_exit(void){
        usb_deregister(&my_usb_driver);
}
module_init(my_usb_mouse_init);
module_exit(my_usb_mouse_exit);



实验步骤:

insmod驱动, cat  /dev/event0 

按下鼠标中 左 右  分别有信息输出.....

不过是乱码...╮(╯﹏╰)╭

当然你也可以使用 hexdump /dev/event0 查看十六进制的数据...

也可以写个input的应用程序读出数据.....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值