历史上的今天
今天是:2024年12月25日(星期三)
2020年12月25日 | I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之声卡驱动移植
2020-12-25 来源:eefocus
前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了“输入子系统”的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。
输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份:
#include #include #include #include #include #include static struct input_dev *buttons_dev; static struct timer_list timer; struct button_desc* button_desc = NULL; struct button_desc{ char* name; unsigned int pin; unsigned int irq; unsigned int val; }; static struct button_desc buttons_desc[8] = { [0] = { .name = "S1", .pin = S5PV210_GPH0(0), .irq = IRQ_EINT(0), .val = KEY_L, }, [1] = { .name = "S2", .pin = S5PV210_GPH0(1), .irq = IRQ_EINT(1), .val = KEY_S, }, [2] = { .name = "S3", .pin = S5PV210_GPH0(2), .irq = IRQ_EINT(2), .val = KEY_C, }, [3] = { .name = "S4", .pin = S5PV210_GPH0(3), .irq = IRQ_EINT(3), .val = KEY_ENTER, }, [4] = { .name = "S5", .pin = S5PV210_GPH0(4), .irq = IRQ_EINT(4), .val = KEY_LEFTCTRL, }, [5] = { .name = "S6", .pin = S5PV210_GPH0(5), .irq = IRQ_EINT(5), .val = KEY_MINUS, }, [6] = { .name = "S7", .pin = S5PV210_GPH2(6), .irq = IRQ_EINT(22), .val = KEY_CAPSLOCK, }, [7] = { .name = "S8", .pin = S5PV210_GPH2(7), .irq = IRQ_EINT(23), .val = KEY_SPACE, }, }; static void timer_function(unsigned long data){ if(button_desc == NULL) return; if(gpio_get_value(button_desc->pin)){ input_event(buttons_dev, EV_KEY, button_desc->val, 0); } else{ input_event(buttons_dev, EV_KEY, button_desc->val, 1); } input_sync(buttons_dev); } static irqreturn_t irq_handler(int irq, void *devid){ button_desc = (struct button_desc*)devid; mod_timer(&timer, jiffies + HZ/100); return IRQ_RETVAL(IRQ_HANDLED); } static int buttons_init(void){ int i; buttons_dev = input_allocate_device(); if(buttons_dev == NULL){ printk(KERN_ERR "Error: allocate input device failed!n"); return -ENOMEM; } __set_bit(EV_KEY, buttons_dev->evbit); __set_bit(EV_REP, buttons_dev->evbit); __set_bit(KEY_L, buttons_dev->keybit); __set_bit(KEY_S, buttons_dev->keybit); __set_bit(KEY_C, buttons_dev->keybit); __set_bit(KEY_SPACE, buttons_dev->keybit); __set_bit(KEY_MINUS, buttons_dev->keybit); __set_bit(KEY_ENTER, buttons_dev->keybit); __set_bit(KEY_LEFTCTRL, buttons_dev->keybit); __set_bit(KEY_CAPSLOCK, buttons_dev->keybit); printk("1n"); if(input_register_device(buttons_dev)){ goto error_1; } printk("2n"); init_timer(&timer); timer.function = timer_function; add_timer(&timer); printk("3n"); for(i = 0; i != 8; ++i){ if(request_irq(buttons_desc[i].irq, irq_handler, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, buttons_desc[i].name, &buttons_desc[i])){ goto error_2; } } printk("4n"); return 0; error_2: for(--i; i >= 0; --i){ free_irq(buttons_desc[i].irq, &buttons_desc[i]); } input_unregister_device(buttons_dev); error_1: input_free_device(buttons_dev); return -EBUSY; } static void buttons_exit(void){ int i; for(i = 0; i != 8; ++i){ free_irq(buttons_desc[i].irq, &buttons_desc[i]); } input_unregister_device(buttons_dev); input_free_device(buttons_dev); } module_init(buttons_init); module_exit(buttons_exit); MODULE_LICENSE("GPL"); 很显然,基于输入子系统的按键驱动比起直接编写的字符驱动设备要简单的多,不过按键消抖还是要加的,上面的代码加上了按键消抖。
史海拾趣
|
1 TL431的简介 德州仪器公司(TI)生产的TL431是一是一个有良好的热稳定性能的三端可调分流基准源。它的输出电压用两个电阻就可以任意地设置到从Vref(2.5V)到36V范围内的任何值(如图2)。该器件的典型动态阻抗为0.2Ω,在很多应用中可 ...… 查看全部问答> |
|
共8章,很全面包括altera和xilinx,两个公司的FPGA和相关软件都涉及到,软件操作,语法点,编码风格,还有专门一章涉及实例,源程序附带! 文件列表为: 1.1可编程逻辑器件概述.ppt 1.2 FPGA的设计方法与要求.ppt 1.3 FPGA的设计流程.ppt 1.3 ...… 查看全部问答> |
|
想在ce下做一个com server(exe),然后多个com client(exe)访问server服务,但是CoCreateInstance总取不上接口:( 看见Microsoft Windows CE 5.0 、Windows Mobile 6 SDK 上对CoCreateInstance的第三个参数DWORD dwClsContext,有如下描述: ...… 查看全部问答> |
|
config.status: error: cannot find input file: config.h.in [root@localhost ntop-3.2]# make cd . && /bin/sh ./missing --run echo cd && /bin/sh /ntop-3.2/config.status config.h config.status: creating config.h config.status: error: cannot find input file: config.h.in make: * ...… 查看全部问答> |
|
为啥WinCE5.0帮助上说流驱动的Init函数应该声明为DWORD XXX_Init(LPCTSTR pContext, DWORD dwBusContext);但是时间的串口初始化声明却是为HANDLE COM_Init(ULONG Identifier);到底是怎么回事? 难道两种都可以存在??… 查看全部问答> |
|
20131218 C风格字符串处理模块 这是顺着之前那个 malloc/realloc 内存在函数之间传递 的 帖子的后续。 采用了重新封装一个结构体,虽然相较于 C++,必须自己调用 在地位上 类似于 Cpp类的 ...… 查看全部问答> |
|
职场中的人际隔阂和矛盾均与自尊心有关。伤害了自尊心就等于伤害了感情,所以善待自尊心成了职场生存中的一门大学问。把自己对自尊心的要求平等地与以他人,那么至少可以减少不必要的情感伤害,同事之间的关系自然可以融洽甚至是和睦。 ...… 查看全部问答> |




