OK6410之USB设备驱动程序

发布者:sokaku最新更新时间:2018-10-11 来源: 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分层分离(总线-驱动-设备模型)

推荐阅读最新更新时间:2024-03-16 16:15

OK6410裸机程序---hello world
上面已经解决 了几个问题。 现在我们的状态:可以在PC - OK6410 之间进行tftp传输,确定了一下可用的地址 空间,下面我们来说一下printf调试 、 因为没有jlink,只能用printf调试,你也许会问,我们自己实现printf么?答曰:不是,我们只是弄个hello world,何必那么认真呢? printf函数是uboot 实现的,我们只需要调用就行了。当然了,这个首先得到你uboot 的printf函数地址。这需要你自己编译 uboot,因为每个人 的printf函数地址不一定一样。查看System.map文件 ,找到printf地址。就行了。 调用时我们可以这样用: void (*show)(char*,
[单片机]
51单片机I2C总线驱动程序
SI2I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。 I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 一.I2C系统结构 每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。 二.数据位的有效性规定 I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 三.字节传送与应答 每一个字节必须保证是8位长度。数据传送时,
[单片机]
51单片机I2C总线<font color='red'>驱动程序</font>
STM32组合设备实现USB转双串口
串口及其中断初始化 void USART1Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
[单片机]
基于IEEEl394b总线双向数据传输设备驱动程序设计
  介绍了基于IEEEl394b总线双向数据传输系统PC机端设备驱动程序。结合IEEEl394b总线规范,以Windows环境为例详细介绍了利用Fir-eAPI SDK开发IEEE1394b设备驱动程序的设计原理、实现方法。   现有的大部分数据传输接口总线造价比较高,且难以满足实际运用中对传输速率的要求,成了阻碍整个系统性能提高的一大屏障。IEEE-1394是现今最高速的串行总线接口之一,IEEE1394lb更是在原有IEEE1394的基础上速度更快,支持距离更长,在实时批量数据传输方面有广泛的应用前景。   基于1394传输系统设备驱动文献,大部分都是基于IEEE1394a的,而IEEE1394b以其更高的速度展现出了更大的
[嵌入式]
基于MSP430的ADS7841驱动程序
师姐(博士)反向设计了ADS7841芯片。为了测试其稳定性和精度,所以帮忙写了这个驱动程序。最初是师兄用FPGA写的,但读出来的数据差距太大,所以我就用430单片机帮忙搞了一个!但这个程序调试的并不顺利,简直就是痛苦,我昨天中午和晚上都没吃饭!首先碰到I/O口坏的情况,还有就是这个芯片的 DATASHEET关于读数的说明是错的,害人不浅!据datasheet解释是等待busy信号为低才开始读数,其实这个时候已经晚了,会漏掉一位。所有上面这些问题我是借助逻辑分析仪看出来的,把抓出来的时序一点点的分析,终于发现了读数方面DATASHEET的漏洞。还有就是她没提写数据和读数据分别应该在时钟的什么沿触发。实在让人郁闷~!~正常应该在下降沿写
[单片机]
vxworks嵌入式操作系统下串行设备驱动程序开发思路
    1. 概 述     我们在基于vxworks嵌入式操作系统开发产品时,经常会根据自行设计的硬件电路开发专用的驱动程序。Vxworks下的驱动程序根据设备的不同特性,,大体可分为:char driver、serial driver、bLOCk driver、end driver、scsi driver等类型,其中以char driver最简单,最基础,以serial driver最常用。掌握驱动程序的基本工作流程,无论对我们开发上层的应用还是自己编写相应的驱动程序,都很有帮助。本文主要以i8250串口驱动程序为例,介绍一下串行驱动程序编写的基本思路。     驱动程序,简而言之就是对具体的硬件设备进行管理和服务的程
[单片机]
vxworks嵌入式操作系统下串行<font color='red'>设备</font><font color='red'>驱动程序</font>开发思路
烧写OK6410裸板方法汇总
1. 用DNW下载到SRAM 中运行: 下载到SRAM 中不会破坏开发板中现有文件与程序,但是掉电后教程中所下载的文件将丢失。 ①、串口线与USB device 线连接电脑和开发板。设置开发板为nandflash 启动; ②、打开 DNW 软件,设置好串口端口,波特率设置为:115200,设置USB Prot: Download Address:0x57e00000 。打开 DNW 串口(Serial Port - Connect); ③、启动开发板,在 DNW 窗口中迅速敲击空格键进入Uboot 状态; ④、在 DNW 窗口中输入:dnw 0x50008000 ,这一句设置下载的地址。如果你的电脑是首次使用 DNW 下载,会提示
[单片机]
OK6410裸机学习之串口实验
start.S文件: .globl _start _start: // 硬件相关的设置 // Peri port setup ldr r0, =0x70000000 orr r0, r0, #0x13 mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) // 关看门狗 // 往WTCON(0x7E004000)写0 ldr r0, =0x7E004000 mov r1, #0 str r1, // 设置栈 ldr sp, =8*1024 // 设置时钟 bl clock_init bl main
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved