历史上的今天
返回首页

历史上的今天

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

正在发生

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

2018-10-11 来源:eefocus

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设备驱动程序


推荐阅读

史海拾趣

ERNI公司的发展小趣事

近年来,ERNI不断加大研发投入,致力于推出更多创新产品和技术。他们不仅继续深耕连接器领域,还拓展了背板、子系统及整套电机架系统等业务。同时,ERNI还积极为客户提供高性能、自行设计的工具制造、现代器件装配和测试设备等高附加值的服务。这些举措使ERNI在电子行业中的竞争力不断增强,也为公司的未来发展奠定了坚实基础。

以上是关于电子行业里ERNI公司发展起来的相关故事概述。通过这些故事,我们可以看到ERNI如何凭借持续的创新、精湛的技术和全球化的战略在电子行业中取得了辉煌成就。

Cornerstone Sensors公司的发展小趣事

Cornerstone Sensors一直致力于技术创新和产品升级。公司不断投入研发资源,探索传感器技术的新应用和新领域。例如,公司率先推出了具有自校准功能的智能传感器,大大提高了产品的使用便捷性和准确性。此外,Cornerstone Sensors还积极探索物联网、人工智能等新兴技术与传感器的结合点,为行业发展注入了新的活力。

ARBOR公司的发展小趣事

随着全球电子市场的日益繁荣,ARBOR公司开始实施国际化战略。公司在多个国家和地区设立了分支机构,积极与当地企业合作,拓展市场份额。通过不断调整和优化产品线,ARBOR公司的产品逐渐在全球范围内赢得了良好的口碑。国际化战略的实施不仅提升了公司的知名度,也为公司的持续发展奠定了坚实基础。

Amphenol Thermometrics公司的发展小趣事

随着环保意识的日益增强,ARBOR公司积极响应国家号召,致力于绿色电子产品的研发和生产。公司投入大量资金研发环保材料和技术,成功推出了一系列绿色电子产品。这些产品不仅具有优异的性能,还符合环保标准,得到了消费者的广泛认可。ARBOR公司的绿色环保理念也为整个电子行业树立了榜样。

AirBorn公司的发展小趣事

如今,AirBorn已经成为电子连接器行业的领军企业之一。面对未来,AirBorn将继续秉承“创新、质量、服务”的理念,不断提升技术水平和产品质量。同时,公司还将积极拓展新的应用领域和市场,为全球客户提供更加优质、高效的产品和服务。相信在未来的发展中,AirBorn将继续书写辉煌的发展篇章。

请注意,以上故事是基于AirBorn公司的公开信息和一般电子行业的发展趋势创作的,可能并不完全准确或详尽。要了解AirBorn公司的最新发展和详细信息,建议查阅公司官方网站或相关新闻报道。

Circuit Assembly公司的发展小趣事

随着电子行业的竞争日益激烈,AirBorn面临着来自同行的压力和挑战。为了保持领先地位,AirBorn加强了与客户的沟通与合作,深入了解市场需求和变化趋势。同时,公司还加大了对新技术和新材料的研发投入,不断推出具有创新性和竞争力的新产品。这些举措使得AirBorn在激烈的市场竞争中保持了稳健的发展态势。

问答坊 | AI 解惑

51单片机C语言入门教程.pdf

51单片机C语言入门教程.pdf…

查看全部问答>

有个PADS(POWERPCB)视频教程很好

PADS(POWERPCB) 几乎是高速电路板必备的电路板设计软件了. 很多方面比PROTEL优秀, 我找到了一个视频教程, 是BT的, 所以要下载人越多,速度越快, 附件是BT的种子文件, 大家一起下载学习吧.…

查看全部问答>

物理地址到虚拟地址的转换问题?

2440中UART0寄存器对应的物理地址为 0x50000000,对应的虚拟地址在g_oalAddressTable表中为0x91000000 g_oalAddressTable         DCD     0x91000000, 0x50000000,  1     &nb ...…

查看全部问答>

二个程序谁的耗的资源少,效率高?

一个程序主函数中就是一个检测文件是否存在的循环. 另一个程序在主函数中另建一个线程,被建的线程中是一个检测文件是否存在的循环. …

查看全部问答>

求助!是经常被问到的关于显示JPG图片的。

是WINCE5的SDK,用IImagingFactory    IImage接口, 报错是 dcdvDlg.obj : error LNK2001: unresolved external symbol _CLSID_ImagingFactory dcdvDlg.obj : error LNK2001: unresolved external symbol _IID_IImagingFactory 我已 ...…

查看全部问答>

【原创】在VC/eVC中实现VB中的Split函数

VB中,sItem = Split(s, \",\")   CString s; CString sItem[13]; byte pItem; byte p1, p2; s += \",\"; p1 = 0; pItem = 0; for (p2 = 0; p2 < s.GetLength(); p2++) {         if (s.GetAt(p2) == \',\') &nb ...…

查看全部问答>

(转贴)像素和分辨率以及换算

经常会有朋友问到200万高清网络机是多少分辨率,或者1600*1200是多少万像素?今天刚好从网上找到一篇这样的文章,希望对大家有帮助。   1.什么是像素?简单的说,我们通常所说的像素,就是CCD上光电感应元件的数量,一个感光元件经过感光 ...…

查看全部问答>

2010成都物联网峰会展品图片分享

这组图片是三个星期以前拍的,回来之后就马不停蹄的赶项目进度,推迟到现在才发上来。本人拍照水平很菜,加上展品放在玻璃柜里面,拍出来相片实在一般般,大家将就一下。 对这次展会的总体印象是规格高,规模大,在一定程度上反映出了中国物联网 ...…

查看全部问答>

dsp2812 到货了?

请问斑竹,片子到货了吗,还要等多久呢?…

查看全部问答>