一、usbmouse_as_key.c

/*
 * drivers\hid\usbhid\usbmouse.c
 */

#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>

static struct input_dev *uk_dev;
static char *usb_buf;
static dma_addr_t usb_buf_phys;
static int len;
static struct urb *uk_urb;

static struct usb_device_id usbmouse_as_key_id_table [] = {
    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
        USB_INTERFACE_PROTOCOL_MOUSE) },
    //{USB_DEVICE(0x1234,0x5678)},
    { }    /* Terminating entry */
};

static void usbmouse_as_key_irq(struct urb *urb)
{
    static unsigned char pre_val;
#if 0    
    int i;
    static int cnt = 0;
    printk("data cnt %d: ", ++cnt);
    for (i = 0; i < len; i++)
    {
        printk("%02x ", usb_buf[i]);
    }
    printk("\n");
#endif
    /* USB鼠标数据含义
     * data[0]: bit0-左键, 1-按下, 0-松开
     *          bit1-右键, 1-按下, 0-松开
     *          bit2-中键, 1-按下, 0-松开
     *
     */
    if ((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
    {
        /* 左键发生了变化 */
        input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
        input_sync(uk_dev);
    }

if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
    {
        /* 右键发生了变化 */
        input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
        input_sync(uk_dev);
    }

if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
    {
        /* 中键发生了变化 */
        input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);
        input_sync(uk_dev);
    }
    
    pre_val = usb_buf[0];

/* 重新提交urb */
    usb_submit_urb(uk_urb, GFP_KERNEL);
}

static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;
    int pipe;
    
    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc;

/* a. 分配一个input_dev */
    uk_dev = input_allocate_device();
    
    /* b. 设置 */
    /* b.1 能产生哪类事件 */
    set_bit(EV_KEY, uk_dev->evbit);
    set_bit(EV_REP, uk_dev->evbit);
    
    /* b.2 能产生哪些事件 */
    set_bit(KEY_L, uk_dev->keybit);
    set_bit(KEY_S, uk_dev->keybit);
    set_bit(KEY_ENTER, uk_dev->keybit);
    
    /* c. 注册 */
    input_register_device(uk_dev);
    
    /* d. 硬件相关操作 */
    /* 数据传输3要素: 源,目的,长度 */
    /* 源: USB设备的某个端点 */
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

/* 长度: */
    len = endpoint->wMaxPacketSize;

/* 目的: */
    usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);

/* 使用"3要素" */
    /* 分配usb request block */
    uk_urb = usb_alloc_urb(0, GFP_KERNEL);
    /* 使用"3要素设置urb" */
    usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
    uk_urb->transfer_dma = usb_buf_phys;
    uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

/* 使用URB */
    usb_submit_urb(uk_urb, GFP_KERNEL);
    
    return 0;
}

static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
    struct usb_device *dev = interface_to_usbdev(intf);

//printk("disconnect usbmouse!\n");
    usb_kill_urb(uk_urb);
    usb_free_urb(uk_urb);

usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
    input_unregister_device(uk_dev);
    input_free_device(uk_dev);
}

/* 1. 分配/设置usb_driver */
static struct usb_driver usbmouse_as_key_driver = {
    .name        = "usbmouse_as_key_",
    .probe        = usbmouse_as_key_probe,
    .disconnect    = usbmouse_as_key_disconnect,
    .id_table    = usbmouse_as_key_id_table,
};

static int usbmouse_as_key_init(void)
{
    /* 2. 注册 */
    usb_register(&usbmouse_as_key_driver);
    return 0;
}

static void usbmouse_as_key_exit(void)
{
    usb_deregister(&usbmouse_as_key_driver);    
}

module_init(usbmouse_as_key_init);
module_exit(usbmouse_as_key_exit);

MODULE_LICENSE("GPL");

二、Makefile

KERN_DIR = /work/system/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    += usbmouse_as_key.o

USB设备驱动程序学习笔记(二)的更多相关文章

  1. USB设备驱动程序学习笔记(一)

    现象:把USB设备接到PC1. 右下角弹出"发现android phone"2. 跳出一个对话框,提示你安装驱动程序 问1. 既然还没有"驱动程序",为何能知道 ...

  2. USB驱动程序之USB总线驱动程序学习笔记

    USB总线驱动程序的作用 1. 识别USB设备 1.1 分配地址 1.2 并告诉USB设备(set address) 1.3 发出命令获取描述符 描述符的信息可以在include\linux\usb\ ...

  3. USB设备类学习笔记

    usb audio class 版本目前有3个版本  分别是1.0,2.0,3.0:1.0针对各个厂家的设备具有不同的描述符,而2.0则将它们统一简化,3.0则是最新的,还没有与2.0作进一步比较:因 ...

  4. 基于STM32的USB枚举过程学习笔记

    源:基于STM32的USB枚举过程学习笔记 基于STM32的USB枚举过程学习笔记(一) 基于STM32的USB枚举过程学习笔记(二) 基于STM32的USB枚举过程学习笔记(三) 基于STM32的U ...

  5. Linux设备驱动程序学习----目录

    目录 设备驱动程序简介 1.设备驱动程序简介 构造和运行模块 2.内核模块和应用程序的对比 3.模块编译和装载 4.模块的内核符号表  5.模块初始化和关闭  6.模块参数  7.用户空间编写驱动程序 ...

  6. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78516 ...

  7. Linux设备驱动程序学习之分配内存

    内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...

  8. USB设备驱动程序(一)

    USB驱动编程原理: 当我们把USB设备插入USB口时会提示需要安装相对应的驱动,如USB鼠标.USB键盘等,这些电脑自己自身已经自带有相对于的驱动程序, 当电脑检查到该USB设备类型相同就去帮你安装 ...

  9. 微信小程序学习笔记二 数据绑定 + 事件绑定

    微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...

随机推荐

  1. Redis学习(2)-redis安装

    安装redis需要先从官网下载的源码进行编译,编译依赖GCC环境,如果没有GCC环境,需要安装GCC. yum install gcc-c++ 步骤1:上传 将Windows下下载的压缩文件上传Lin ...

  2. apache并发测试工具ab为什么测不准

    apache并发测试工具ab为什么测不准 发表于2年前(2013-03-21 12:13)   阅读(1146) | 评论(1) 1人收藏此文章, 我要收藏 赞0 3月21日 深圳 OSC 源创会正在 ...

  3. 域名无法解析 Linux临时或永久修改DNS

    最近给VPS重装了系统,因为服务商不提供DHCP,所以只好手动设置IP和DNS Server.悲催的是系统重装的时候忘记了输入DNS Server,最后导致进去系统后,各种域名无法解析. Linux中 ...

  4. java中写sql语句的小小细节

    来源于:http://www.cnblogs.com/reine98/p/6180472.html 看如下一条sql语句 1 2 3 4 5 6 String sql="SELECT * F ...

  5. shell脚本死循环判断nginx日志reqest_time时间大于3秒是否增加,若增加发送相关日志信息到开发人员

    #!/bin/bash while [ 1 ] do pre_request_time_count=`cat /var/log/nginx/access.log |awk '{print $NF}'| ...

  6. ios block常见的错误(三)——并发编程的block引用

    在一些技术型的企业里面,有关block面试笔试题,将会问得很深,如下例子: 请问DemoObj的对象能否正确释放,为什么? //DemoObj.m @interface DemoObj() @prop ...

  7. SQL plus连接远程Oralce数据库

    如果要连接远程数据库,传统的一定可行的方法是在本地装一个oracle,然后使用“Network Configuration Assistant”配置,之后用PL/SQL Dev连接 oracle官网上 ...

  8. HDUOJ-----2838Cow Sorting(组合树状数组)

    Cow Sorting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. Spring MVC+Mybatis 执行存储过程,使用Map进行参数的传递

    研究了一天mybatis如何执行存储过程,基本了解了ORM的设计思想,在map层面进行对象关系映射有两种思路. 根据不同的业务使用不同的思路: 一.实体类和数据库映射,就是将数据库中的字段和java实 ...

  10. view变化监听器ViewTreeObserver介绍

      A view tree observer is used to register listeners that canbe notified of global changes in the vi ...