Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7681505
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: 嵌入式

2012-02-10 09:07:53

/*

 *  Copyright (c) 1999-2001 Vojtech Pavlik

 *

 *  USB HIDBP Mouse support

 */

 

/*

 * This program is free software; you can redistribute it and/or modify

 * it under the terms of the GNU General Public License as published by

 * the Free Software Foundation; either version 2 of the License, or

 * (at your option) any later version.

 *

 * This program is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 * GNU General Public License for more details.

 *

 * You should have received a copy of the GNU General Public License

 * along with this program; if not, write to the Free Software

 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 *

 * Should you need to contact me, the author, you can do so either by

 * e-mail - mail your message to , or by paper mail:

 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic

 */

 

#include

#include

#include

#include

#include

#include

 

/* for apple IDs */

#ifdef CONFIG_USB_HID_MODULE

//#include "../hid-ids.h"

#endif

 

/*

 * Version Information

 */

#define DRIVER_VERSION "v1.6"

#define DRIVER_AUTHOR "Vojtech Pavlik "

#define DRIVER_DESC "USB HID Boot Protocol mouse driver"

#define DRIVER_LICENSE "GPL"

 

MODULE_AUTHOR(DRIVER_AUTHOR);

MODULE_DESCRIPTION(DRIVER_DESC);

MODULE_LICENSE(DRIVER_LICENSE);

 

struct usb_mouse {

    char name[128];

    char phys[64];

    struct usb_device *usbdev;

    struct input_dev *dev;

    struct urb *irq;

 

    signed char *data;

    dma_addr_t data_dma;

};

 

static void usb_mouse_irq(struct urb *urb)

{

    struct usb_mouse *mouse = urb->context;

    signed char *data = mouse->data;

    struct input_dev *dev = mouse->dev;

    int status;

 

    switch (urb->status) {

    case 0:            /* success */

        break;

    case -ECONNRESET: /* unlink */

    case -ENOENT:

    case -ESHUTDOWN:

        return;

    /* -EPIPE:  should clear the halt */

    default:       /* error */

        goto resubmit;

    }

 

    input_report_key(dev, BTN_LEFT,   data[0] & 0x01);

    input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);

    input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);

    input_report_key(dev, BTN_SIDE,   data[0] & 0x08);

    input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);

 

    input_report_rel(dev, REL_X,     data[1]);

    input_report_rel(dev, REL_Y,     data[2]);

    input_report_rel(dev, REL_WHEEL, data[3]);

 

    input_sync(dev);

resubmit:

    status = usb_submit_urb (urb, GFP_ATOMIC);

    if (status)

        err ("can't resubmit intr, %s-%s/input0, status %d",

                mouse->usbdev->bus->bus_name,

                mouse->usbdev->devpath, status);

}

 

static int usb_mouse_open(struct input_dev *dev)

{

    struct usb_mouse *mouse = input_get_drvdata(dev);

 

    mouse->irq->dev = mouse->usbdev;

    if (usb_submit_urb(mouse->irq, GFP_KERNEL))

        return -EIO;

 

    return 0;

}

 

static void usb_mouse_close(struct input_dev *dev)

{

    struct usb_mouse *mouse = input_get_drvdata(dev);

 

    usb_kill_urb(mouse->irq);

}

 

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

{

    /* 设备描述 usb_device */

    /* 接口描述 usb_interface */

    struct usb_device *dev = interface_to_usbdev(intf);

   

    /* 接口设置描述 */

    struct usb_host_interface *interface;

   

    /* 端点描述符 */

    struct usb_endpoint_descriptor *endpoint;

   

   

    struct usb_mouse *mouse;

    struct input_dev *input_dev;

    int pipe, maxp;

    int error = -ENOMEM;

 

    /* 获取当前接口设置 */

    interface = intf->cur_altsetting;

 

    /* 根据HID规范,鼠标只有一个端点(不包含0号控制端点)*/

    if (interface->desc.bNumEndpoints != 1)

        return -ENODEV;

 

    /* 获取端点0描述符 */

    endpoint = &interface->endpoint[0].desc;

   

    /* 根据HID规范,鼠标唯一的端点应为中断端点 */

    if (!usb_endpoint_is_int_in(endpoint))

        return -ENODEV;

 

    /* 生成中断管道 */

    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

   

    /* 返回该端点能够传输的最大的包长度,鼠标的返回的最大数据包为4个字节。*/ 

    maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

 

    /* 创建input设备 */

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

    input_dev = input_allocate_device();

    if (!mouse || !input_dev)

        goto fail1;

 

   /* 申请内存空间用于数据传输,data 为指向该空间的地址*/

    mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);

    if (!mouse->data)

        goto fail1;

   

    /* 分配URB */

    mouse->irq = usb_alloc_urb(0, GFP_KERNEL);

    if (!mouse->irq)

        goto fail2;

 

    mouse->usbdev = dev;

    mouse->dev = input_dev;

 

    if (dev->manufacturer)

        strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));

 

    if (dev->product) {

        if (dev->manufacturer)

            strlcat(mouse->name, " ", sizeof(mouse->name));

        strlcat(mouse->name, dev->product, sizeof(mouse->name));

    }

 

    if (!strlen(mouse->name))

        snprintf(mouse->name, sizeof(mouse->name),

             "USB HIDBP Mouse %04x:%04x",

             le16_to_cpu(dev->descriptor.idVendor),

             le16_to_cpu(dev->descriptor.idProduct));

 

    usb_make_path(dev, mouse->phys, sizeof(mouse->phys));

    strlcat(mouse->phys, "/input0", sizeof(mouse->phys));

 

    input_dev->name = mouse->name;

    input_dev->phys = mouse->phys;

    usb_to_input_id(dev, &input_dev->id);

    input_dev->dev.parent = &intf->dev;

 

    input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);

    input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |

        BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);

    input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);

    input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |

        BIT_MASK(BTN_EXTRA);

    input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);

 

    input_set_drvdata(input_dev, mouse);

 

    input_dev->open = usb_mouse_open;

    input_dev->close = usb_mouse_close;

 

    /* 初始化中断URB */

    usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,

             (maxp > 8 ? 8 : maxp),

             usb_mouse_irq, mouse, endpoint->bInterval);

    mouse->irq->transfer_dma = mouse->data_dma;

    mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

 

    error = input_register_device(mouse->dev);

    if (error)

        goto fail3;

 

    usb_set_intfdata(intf, mouse);

    return 0;

 

fail3:

    usb_free_urb(mouse->irq);

fail2:

    usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);

fail1:

    input_free_device(input_dev);

    kfree(mouse);

    return error;

}

 

static void usb_mouse_disconnect(struct usb_interface *intf)

{

    struct usb_mouse *mouse = usb_get_intfdata (intf);

 

    usb_set_intfdata(intf, NULL);

    if (mouse) {

        usb_kill_urb(mouse->irq);

        input_unregister_device(mouse->dev);

        usb_free_urb(mouse->irq);

        usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);

        kfree(mouse);

    }

}

 

static struct usb_device_id usb_mouse_id_table [] = {

    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

        USB_INTERFACE_PROTOCOL_MOUSE) },

    { } /* Terminating entry */

};

 

MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);

 

static struct usb_driver usb_mouse_driver = {

    .name      = "usbmouse",   /* 驱动名 */

    .probe     = usb_mouse_probe, /* 捕获函数 */

    .disconnect   = usb_mouse_disconnect, /* 卸载函数 */

    .id_table  = usb_mouse_id_table, /* 设备列表 */

};

 

static int __init usb_mouse_init(void)

{

    /* 注册鼠标驱动程序 */

    int retval = usb_register(&usb_mouse_driver);

    if (retval == 0)

        printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"

                DRIVER_DESC "\n");

    return retval;

}

 

static void __exit usb_mouse_exit(void)

{

    usb_deregister(&usb_mouse_driver);

}

 

module_init(usb_mouse_init);

module_exit(usb_mouse_exit);

 

源码: usbmouse.rar   

阅读(2922) | 评论(0) | 转发(6) |
给主人留下些什么吧!~~