一、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. vue 常见报错问题

    情况一:http://eslint.org/docs/rules/no-tabs  Unexpected tab character 解决方案:缩进是4个空格,而不是tab,设置indent 情况二 ...

  2. 手动脱NsPacK壳实战

    作者:Fly2015 这里脱壳的程序是吾爱破解培训的作业2,相较于作业1略微要强一点,可是仅仅要掌握了脱壳的ESP定律,脱这个Nspack壳并不难.只是还是蛮有意思的. 1.使用查壳软件对加壳的程序进 ...

  3. cocos2d-x项目101次相遇-安装和环境搭建 -xcode

    cocos2d-x 101次相遇 / 文件夹  1   安装和环境搭建 -xcode  2   Scenes . Director, Layers, Sprites 3   建立图片菜单  4   在 ...

  4. Java 爬虫(获取指定页面中所有的邮箱地址)

    import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.io.In ...

  5. HTTP头返回码分析

    http协议通讯时,在客户端发送请求后(request),服务器端返回的状态码解释(response) http状态码 1**:请求收到,继续处理 2**:操作成功收到,分析.接受           ...

  6. 网线/双绞线上各标识CAT, AWG, PR, UTP/STP/FTP/SFTP的含义

    CAT5, CAT5e, CAT6 表示网线类别, 常见的有 CAT5, CAT5e, CAT6分别表示五类, 超五类, 六类网线 24AWG, 26AWG American Wire Gauge是美 ...

  7. 很幽默的讲解六种Socket IO模型

    很幽默的讲解六种Socket IO模型 本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型二:WSAAsyncSelect ...

  8. Highcharts网页版

    //后台控制器中(SpringMVC) @RequestMapping(value="/getAll",method=RequestMethod.POST) @ResponseBo ...

  9. GitLab Notification Emails

    GitLab has a notification system in place to notify a user of events that are important for the work ...

  10. Android手机在不同分辨率情况下字体自适应大小

    两种解决方法: 一. 1.首先根据不同分辨率获取不同字体大小. 在RES里创建values-480x320/strings.xml 里面设置<dimen name="Text_size ...