ok6410linux usb驱动,OK6410之USB设备驱动程序

usb.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"

#include "linux/input.h"

static struct input_dev *mk_dev;

static int len;

static char *buf;

static dma_addr_t buf_phys;

static struct urb *mk_urb;

static struct usb_device_id usb_mk_id_table [] = {

{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

USB_INTERFACE_PROTOCOL_MOUSE) },

//{USB_DEVICE(0x46d, 0xc52f)},

{ }    // Terminating entry

};

// 当USB主机控制器获得鼠标数据后,

// 会调用这个函数

static void uk_callback(struct urb *urb)

{

int i;

static char pre_val;

#if 0

printk("Get datas:\n");

for (i = 0; i < len; i++)

{

printk("x ", buf[i]);

}

printk("\n");

#endif

// 鼠标数据含义:

// buf[0]: bit0-左键, 0-松开, 1-按下

//         bit1-右键, 0-松开, 1-按下

//         bit2-中键, 0-松开, 1-按下

// buf[1],buf[2]构成一个整数, 表示X方向的相对位移

//         >0 : 右移

//         <0 : 左移

// buf[3],buf[4]构成一个整数, 表示Y方向的相对位移

//         >0 : 下移

//         <0 : 上移

// buf[6]: 滚轮

// 确定按键值

// 上报数据

if ((pre_val & (1<<0)) != (buf[0] & (1<<0)))

{

// 左键按下或松开

input_event(mk_dev, EV_KEY, KEY_L, (buf[0] & (1<<0)) ? 1 : 0);

input_sync(mk_dev);

}

if ((pre_val & (1<<1)) != (buf[0] & (1<<1)))

{

// 右键按下或松开

input_event(mk_dev, EV_KEY, KEY_S, (buf[0] & (1<<1)) ? 1 : 0);

input_sync(mk_dev);

}

if ((pre_val & (1<<2)) != (buf[0] & (1<<2)))

{

// 中键按下或松开

input_event(mk_dev, EV_KEY, KEY_ENTER, (buf[0] & (1<<2)) ? 1 : 0);

input_sync(mk_dev);

}

pre_val = buf[0];

// 重新提交URB

usb_submit_urb(mk_urb, GFP_KERNEL);

}

static int usb_mk_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;

static int first = 1;

if (!first)

return -EIO;

first = 0;

// 每一个设备都有端点0

// interface->endpoint[]数组里放"除了端点0外的其他端点"

// interface->endpoint[0]表示"除端点0外的第1个端点"

// interface->endpoint[1]表示"除端点0外的第2个端点"

interface = intf->cur_altsetting;

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

// 1. 分配inputd_dev

mk_dev = input_allocate_device();

// 2. 设置

// 2.1 能产生哪类事件

set_bit(EV_KEY, mk_dev->evbit);

set_bit(EV_REP, mk_dev->evbit);

// 2.2 能产生这类事件里的哪些事件

set_bit(KEY_L, mk_dev->keybit);

set_bit(KEY_S, mk_dev->keybit);

set_bit(KEY_ENTER, mk_dev->keybit);

// 3. 注册

input_register_device(mk_dev);

// 4. 硬件相关的操作:

//    对于GPIO按键, 是request_irq, 在中断处理函数里上报按键

//    对于USB设备, 是使用"USB主机驱动程序提供的函数"发起USB传输获得数据

// 数据传输3要素: 源, 目的, 长度

// A. 源: USB设备的某个端点

// ((PIPE_INTERRUPT << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN)

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

// C. 长度: 这个端点描述符的wMaxPacketSize

len = endpoint->wMaxPacketSize;

// B. 目的: 分配buffer

buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &buf_phys);

// D. 怎么使用这3要素 ?

// 分配URB: USB Reqeust Block

mk_urb = usb_alloc_urb(0, GFP_KERNEL);

// 用3要素填充URB

usb_fill_int_urb(mk_urb, dev, pipe, buf, len, uk_callback, NULL, endpoint->bInterval);

mk_urb->transfer_dma = buf_phys;

mk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

// 使用URB

usb_submit_urb(mk_urb, GFP_KERNEL);

return 0;

}

static void usb_mk_disconnect(struct usb_interface *intf)

{

struct usb_device *dev = interface_to_usbdev(intf);

printk("disconnect usb mouse!!!!!\n");

usb_kill_urb(mk_urb);

usb_free_urb(mk_urb);

usb_buffer_free(dev,len, buf, buf_phys);

input_unregister_device(mk_dev);

input_free_device(mk_dev);

}

// 1. 分配usb_driver

// 2. 设置

static struct usb_driver usb_mk_driver = {

.name        = "usbmk",

.probe       = usb_mk_probe,

.disconnect  = usb_mk_disconnect,

.id_table    = usb_mk_id_table,

};

static int usb_mk_init(void)

{

// 3. 注册

usb_register(&usb_mk_driver);

return 0;

}

static void usb_mk_exit(void)

{

usb_deregister(&usb_mk_driver);

}

module_init(usb_mk_init);

module_exit(usb_mk_exit);

MODULE_LICENSE("GPL");

=====================================================================

Makefile文件:

KERN_DIR = /home/linux/linux-3.0.1

all:

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

clean:

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

rm -rf modules.order

obj-m += usb.o

=====================================================================

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值