--以触摸屏驱动为例
第一章、了解linux input子系统
Linux输入设备总类繁杂,常见的包括有按键、键盘、触摸屏、鼠标、摇杆等等,他们本身就是字符设备,而linux内核将这些设备的共同性抽象出来,简化驱动开发建立了一个input子系统。子系统共分为三层,如图1所示。
图1 input输入子系统
|
驱动层和硬件相关,直接捕捉和获取硬件设备的数据信息等(包括触摸屏被按下、按下位置、鼠标移动、键盘按下等等),然后将数据信息报告到核心层。核心层负责连接驱动层和事件处理层,设备驱动(device driver)和处理程序(handler)的注册需要通过核心层来完成,核心层接收来自驱动层的数据信息,并将数据信息选择对应的handler去处理,最终handler将数据复制到用户空间。
先了解三个定义在/linux/input.h下重要的结构体input_dev、input_handler、input_handle。
struct input_dev {
void *private;
const char *name;
const char *phys;
const char *uniq;
struct input_id id; //与input_handler匹配用的id
unsigned long evbit[NBITS(EV_MAX)]; //设备支持的事件类型
unsigned long keybit[NBITS(KEY_MAX)]; //按键事件支持的子事件类型
unsigned long relbit[NBITS(REL_MAX)];
unsigned long absbit[NBITS(ABS_MAX)]; //绝对坐标事件支持的子事件类型
unsigned long mscbit[NBITS(MSC_MAX)];
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
unsigned long swbit[NBITS(SW_MAX)];
int ff_effects_max;
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
unsigned int repeat_key;
struct timer_list timer;
struct pt_regs *regs;
int state;
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
unsigned long key[NBITS(KEY_MAX)];
unsigned long led[NBITS(LED_MAX)];
unsigned long snd[NBITS(SND_MAX)];
unsigned long sw[NBITS(SW_MAX)];
int absmax[ABS_MAX + 1]; //绝对坐标事件的最大键值
int absmin[ABS_MAX + 1]; //绝对坐标事件的最小键值
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*accept)(struct input_dev *dev, struct file *file);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab; //当前占有该设备的handle
struct mutex mutex; /* serializes open and close operations */
unsigned int users; //打开该设备的用户量
struct class_device cdev;
struct device *dev; /* will be removed soon */
int dynalloc; /* temporarily */
struct list_head h_list; //该链表头用于链接该设备所关联的input_handle
struct list_head node; //该链表头用于将设备链接到input_dev_list
};
Input_dev是一个很强大的结构体,它把所有的input设备(触摸屏、键盘、鼠标等)的信息都考虑到了,对于触摸屏来说只用到它里面的一部分而已,尤其是加粗的部分,注意该结构体中最后两行定义的两个list_head结构体,list_head在/linux/list.h中有定义,深入跟踪
struct list_head {
struct list_head *next, *prev;
};
该结构体内部并没有定义数据而只定义了两个指向本身结构体的指针,预先说明一下,所有的input device在注册后会加入一个input_dev_list(输入设备链表),所有的eventhandler在注册后会加入一个input_handler_list(输入处理程序链表),这里的list_head主要的作用是作为input_dev_list和input_handler_list的一个节点来保存地址。Input_dev_list和input_handler_list之间的对应关系由input_handle结构体桥接,具体后面说明。
struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
const struct file_operations *fops; //提供给用户对设备操作的函数指针
int minor;
char *name;
struct input_device_id *id_table; //与input_dev匹配用的id
struct input_device_id *blacklist; //标记的黑名单
struct list_head h_list; //用于链接和该handler相关的handle
struct list_head node; //用于将该handler链入input_handler_list
};
input_handler顾名思义,它是用来处理input_dev的一个结构体,相关的处理函数在结构里内部都有定义,最后两行定义的list_head结构体作用同input_dev所定义的一样,这里不再说明。
注:input_device_id结构体在/linux/mod_devicetable.h中有定义
struct input_handle {
void *private;
int open; //记录设备打开次数
char *name;
struct input_dev *dev; //指向所属的input_dev
struct input_handler *handler; //指向所属的input_handler
struct list_head d_node; //用于链入所指向的input_dev的handle链表
struct list_head h_node; //用于链入所指向的input_handler的handle链表
};
可以看到input_handle中拥有指向input_dev和input_handler的指针,即input_handle是用来关联input_dev和input_handler。为什么用input_handle来关联input_dev和input_handler而不将input_dev和input_handler直接对应呢?因为一个device可以对应多个handler,而一个handler也可处理多个device。就如一个触摸屏设备可以对应event handler也可以对应tseve handler。
input_dev、input_handler、input_handle的关系如下图2所示。
图2 input_dev,input_handler,input_handle关系图 |
第二章、input device的注册
Input device的注册实际上仅仅只有几行代码,因为在input.c中已经将大量的代码封装好了,主需要调用几个关键的函数就能完成对input device的注册。
在xxx_ts.c中预先定义全局变量struct input_dev tsdev;然后进入到初始化函数
static int __init xxx_probe(struct platform_device *pdev)
{
…
if (!(tsdev = input_allocate_device()))
{
printk(KERN_ERR "tsdev: not enough memoryn");
err = -ENOMEM;
goto fail;
}
…
tsdev->name = "xxx TouchScreen"; //xxx为芯片型号
tsdev ->phys = "xxx/event0";
tsdev ->id.bustype = BUS_HOST; //设备id,用于匹配handler的id
tsdev ->id.vendor = 0x0005;
tsdev ->id.product = 0x0001;
tsdev ->id.version = 0x0100;
tsdev ->open = xxx_open;
tsdev ->close =xxx_close;
tsdev ->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_SYN); //设置支持的事件类型
tsdev ->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
input_set_abs_params(tsdev, ABS_X, 0, 0x400, 0, 0); //限定绝对坐标X的取值范围
input_set_abs_params(tsdev, ABS_Y, 0, 0x400, 0, 0); //同上
input_set_abs_params(tsdev, ABS_PRESSURE, 0, 1000, 0, 0); //触摸屏压力值范围
上一篇:u-boot-1.3.4 移植到S3C2440
下一篇:ARM嵌入式系统的学习步骤
推荐阅读
史海拾趣
在稳步发展的同时,苏州锋驰也积极拓展对外合作与投资。公司共对外投资了3家企业,并通过这些投资进一步拓宽了业务范围和市场渠道。这些合作不仅为苏州锋驰带来了更多的技术资源和市场机会,也增强了公司的综合竞争力。同时,公司还积极与上下游企业建立紧密的合作关系,形成了良好的产业生态。
在追求经济效益的同时,Bellin Dynamic Systems也积极履行社会责任,致力于可持续发展。公司注重环保和节能技术的研发和应用,努力降低生产过程中的能耗和排放。此外,公司还积极参与社会公益事业,通过捐款、资助等方式回馈社会。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。
以上是我为您模拟构建的关于Bellin Dynamic Systems在电子行业中发展起来的几个可能故事。请注意,这些故事是基于一般性的行业趋势和公司发展路径构建的,并非真实发生的事件。如果您需要更具体的信息,建议直接查阅Bellin Dynamic Systems的官方资料或相关新闻报道。
随着环保意识的不断提高,ELM Technology Corporation积极响应国家号召,将环保理念融入企业发展中。公司投入大量资金研发环保型电子产品,努力降低产品对环境的影响。同时,ELM还积极参与各类环保活动,推动电子行业的绿色发展。这种对环保的执着追求让ELM在行业中树立了良好的形象。
在全球环保和可持续发展的背景下,DAPAudio也积极响应这一号召。公司投入大量资源用于研发环保型音频处理器产品,通过采用环保材料和节能技术降低产品对环境的影响。同时,DAPAudio还积极参与社会公益活动,推动音频行业的可持续发展。
请注意,以上故事均为虚构内容,仅供参考。如需了解DAPAudio公司的真实发展故事,建议查阅相关官方资料或新闻报道。
面对激烈的市场竞争,振华始终将技术创新作为企业发展的核心动力。公司投入大量资金进行技术研发,积极引进国内外先进技术,并与高校、科研机构建立紧密的合作关系。通过持续的技术创新,振华在电子产品领域取得了多项重要突破,推出了一系列具有自主知识产权的高新产品,引领了市场潮流。
随着公司业务的不断发展,Echelon开始积极拓展全球市场。公司通过在海外设立分支机构、与当地企业合作等方式,将LonWorks技术和能源管理服务方案推广至全球各地。同时,Echelon还积极参与国际能源管理标准的制定和推广工作,提升了公司在国际市场的知名度和影响力。
转自:http://www.1000bbs.com/dispbbs.asp?boardid=51&Id=261604 首先声明一下身份:辽宁锦州安防器材经销商、工程商。 我开始选择红外一体机,是因为甲方点着名要这玩意。 选了哪些厂家的哪些型号的红外机,恕我不一一列举了。总之,深圳的 ...… 查看全部问答∨ |
WINCE SDK平台改变后出现的问题: fatal error LNK1112: module machine type \'ARM\' conflicts with target machine type \'SH3\' 这要怎么解决啊???… 查看全部问答∨ |
例如 taskA 在moduleA中定义, 而moduleB与moduleA有可能是嵌套关系,也可能是并列的被高层模块调用,那么moduleB能调用taskA么?… 查看全部问答∨ |
|
我现在程序在外部flash运行,LPC2292,外部flash是sst39vf1601,在外部flash的0x10000地址(也就是arm看到的0x80010000地址开始我是烧的fpga程序,这个已经是没问题的),在用EASYJTAG-H外部仿真的时候,在MAIN入口处,我也看到了数据。startup.s的设 ...… 查看全部问答∨ |
软件名称:SEFS安全透明加密内核 软件版本:1.0 建议分类:系统安全/文件加密 软件大小:635K 安装平台:Win2000/xp/2003 软件语言:简体中文/繁体中文/英文 软件授权:共享软件 软件主页:http://www.sefs.net 支持邮箱:admin@sefs.ne ...… 查看全部问答∨ |
大家好,我在编译一个代码出现了栈溢出警告, 理论上讲我的数据段为: map文件 6 152 bytes of CODE memory 1 268 bytes of DATA memory (+ 56 absolute ) 463 bytes of CONST memory 而栈的使用情况 ...… 查看全部问答∨ |
|
Visual Basic设计完成了上位机界面;同时利用51单片机作为下位机微处理器,采集无刷电机运行工作中的电压、电流和转速等基本参数,通过串行通讯口将数据上传至上位机系统中。上位机系统对下位机上传的数据加以分析计算,直观的绘制个参数的变化曲线 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 预约有奖直播:享受纯净 ams主动降噪与接近传感带来耳机设计新境界
- 是德科技有奖问答活动之四,使用实时示波器进行串扰分析,答题闯关赢好礼!
- 答题赢好礼!ADI技术直通车——汽车应用娱乐与信息交互解决方案
- 报名直播赢【保温杯】等好礼|TI MSPM0 MCU 在汽车系统中的应用
- 英飞凌MERUS™ D类音频解决方案|【阅读赢好礼,下单送开发板】
- 降碳行动:寻找身边8位单片机,抢楼赢ST最新M0开发板!
- 玩儿转电源游戏,赢取800元TI手持POS机开发套件!
- 有奖直播|TI 新一代Sitara™ AM62处理器革新人机交互——产品介绍和相关资源
- 看视频赢京东卡 | PI无刷直流电机学习中心正式上线