历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2018年10月11日 | OK6410之USB设备驱动程序

发布者:sokaku 来源: eefocus关键字: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

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

测试部分参考:JZ2440的USB设备驱动程序


关键字:OK6410  USB设备  驱动程序 引用地址:OK6410之USB设备驱动程序

上一篇:OK6410块设备驱动之用内存模拟磁盘
下一篇:OK6410分层分离(总线-驱动-设备模型)

推荐阅读

近日,2018首届 RFC 机器人创始人影响力峰会在上海举行,RFC 全称是中关村双创服务机器人创始人联盟,为目前国内最大的服务机器人联盟。科沃斯机器人作为全球最早的服务机器人研发与生产商之一,凭借二十年的科研实力和产品创新获封“2018服务机器人年度领军企业”大奖,致力于让用户轻松享受由机器人参与的现代智能家居生活。 首届RFC机器人创始人影...
1 RFID天线的应用现状1.1 RFID天线应用的一般要求电子标签天线RFID天线必须足够小; RFID天线提供最大可能的信号和能量给标签的芯片; RFID天线具有鲁棒性; RFID天线非常便宜读写器天线读写器天线既可以与读写器集成在一起,也可以采用分离式;读写器天线设计要求多频段覆盖;应用智能波束扫描天线阵1.2 RFID天线的极化:圆极化1.3 RFID天线的方向...
有爆料消息称华为Mate40系列的海外发布日期为欧洲中部夏令时间10月22日14点,也就是北京时间10月22日20点,华为消费者业务CEO 华为常务董事余承东在其微博证实了这一消息,并公布华为Mate40系列全球线上发布会将于北京时间10月22日20点举办。据已知爆料消息,华为Mate 40系列有4款机型,分别是Mate 40、Mate 40 Pro、Mate 40 Pro+以及Mate40 RS保...
随着宽禁带半导体器件的发展,电力电子器件的开关速度越来越快,工作电压逐渐升高,也使电压探头的性能对电力电子器件暂态电压测量结果的影响程度增大。下面PRBTEK为您分享典型示波器电压探头电路原理:高阻无源探头无源探头具有价格便宜、机械结构坚固、动态范围宽、输入电阻高等优势,因此广泛应用于通用测试场合。常用的无源探头为10倍衰减的高阻无源探...

史海拾趣

问答坊 | AI 解惑

TS201S型DSP引导程序加载方法研究

TS201S型DSP引导程序加载方法研究…

查看全部问答∨

lpc2000 VS s3c44b0

当然这个对比有点不公平,那一个系列来和一款芯片对决。但是在arm中我之使用过着两种。    首先说说中断,s3的中断匪夷所思,看明白了就是调不通,再跑ucos的时候除了定时中断外没有正常工作的中断,用了1周没有任何进展,接着就放弃了 ...…

查看全部问答∨

闻气味找故障

  嗅觉有时候也能帮助我们找到故障的位置。譬如说CRT显示器吧,用鼻子闻一闻,就知道故障出在哪了。   1.酸味    如果有这种味道,一般是内部电容有过热或过压爆裂,电容的酸性气体溢出所致。   2.糊味    一般是显 ...…

查看全部问答∨

我相信这只手能拦截爱国者导弹~~

$(\'swf_cu8\').innerHTML=AC_FL_RunContent(\'width\', \'550\', \'height\', \'400\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', encodeURI(\'http://player.youku.com/player.php/sid/XMTE1MDUxMDcy/v.sw ...…

查看全部问答∨

跪求cadence 15.5安装步骤

:Q&nbsp;各们谁有cadence 15.5安装步骤请与我分享;P…

查看全部问答∨

请问各位大虾

请问各位大虾:如何改写DS18B20的R0和R1这两位??? 还有以9位、10位、11位、12位输出时,如何计算温度值??? 小弟先在这里谢谢哈!!! 本文来自: 电子工程师之家http://www.eehome.cn…

查看全部问答∨

66.5MHZ的CAN时钟频率怎么分出125K的波特率? 

用的是i.mx35自带的CAN接口,CAN时钟采用总线时钟66.5MH,需要除以分频、位时间才能得到125KHZ的波特率。现在问题是分频、位时间分别设置多少? 我算了下无论设置为多少都不能得到整数的125K?   …

查看全部问答∨

怎样复习单片机

马上就要期末考了 ,真不知道怎么去复习。虽然有看一点书,但就是不会归纳知识点。看书没什么重点,而且平常也是看看程序 。…

查看全部问答∨

有谁会uC/OS II

有会uc/os-ii的高手吗?我要做论文 是基于uc/os-ii的串行通信的 有高手会的话 发给我好吗?我邮箱是stefa545@163.com   或者可以给我解释下源代码的也行  实在不懂啊 …

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved