Linux输入子系统在触摸屏驱动上的实现
Linux输入子系统:事件的编码

Linux输入子系统:事件的编码输入系统协议用类型types和编码codecs来表示输入设备的值并用此来通知用户空间的应用程序。
这篇文档对这些类型和编码进行了说明并且指出什么时候和如何使用这些类型和编码。
一个单一的硬件事件可以产生多个输入事件,每个输入事件包含一个单一数据项的新的数据值。
EV_SYN是一个特别的事件类型,它用来把同一时刻产生的多个输入数据分割为多个数据包。
在下面的描述中,术语事件(event)是指一个涵盖类型,编码和参数值的单一输入事件。
input协议是一个基于状态的协议,只有当相应事件编码对应的参数值发生变化时才会发送该事件。
不过,状态是由Linux的输入子系统进行维护,驱动程序无需维护输入的状态,就算参数值没有变化时向输入子系统发出事件也不会有问题。
用户空间可以用linux/input.h 中定义的EVIOCG*ioctls来获得当前事件编码和参数的状态。
设备的所支持的上报事件种类也可以通过sysfs的class/input/event*/device/capabilities/来获取,设备的特性和可以通过class/input/event*/device/properties来获取。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本文由DroidPhone 翻译:/droidphone Kernel版本:V3.4.10~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Event types:===========types对应于一个相同逻辑输入结构的一组Codes。
每个type都有一组可用的codes用于产生输入事件。
每个type可用的codes的详细信息请参考Codes一节的内容。
Linux内核i.MX51的触摸屏驱动架构

获取校准 3 个点并列方程组 1 得如下:
X A ( X ) B (Y ) C X D1 A ( X T1) B (Y T1) C X D2 A ( X T 2) B (Y T 2) C Y D0 D ( X T 0) E (Y T 0) F
D0 T0 T0
MX51 的触摸屏驱动架构
2012 年 11 月 27 日
※ 任务目标:
分析整理四线电阻屏工作原理,校屏算法及触摸屏驱动架构;
※ 四线电阻屏工作原理:
电阻屏由 x 层和 y 层组成,中间由细小的绝缘层隔开。当触摸屏没有压力时 x 层,y 层 处于断开状态;当有压力时 x 层和 y 层导通,通过 x 层的探针可以侦测出 y 层的电压,通过 y 层的探针可以侦测出 x 层的电压,而通过电压值可以确定触摸点在 x 层和 y 层的位置,从 而得到触摸点在触摸屏上的位置。
D0
A (X
X D 2)(Y T 1 Y T 2) ( X D1 X D 2)(Y T 0 Y T 2)
3/4
B (X C Y
' T0
'
T0
X T 2)( X D1 X D 2) ( X D0 X D 2)( X T 1 X T 2)
(( X T 2)( X D1) ( X T 1)( X D 2)) Y Tቤተ መጻሕፍቲ ባይዱ1 (( X T 0)( X D 2) ( X T 2)( X D0)) Y T 2 (( X T 1)( X D0) ( X T 0)( X D1))
..........................方程组 1
Y Y
D1
D2
S3C2410触摸屏驱动程序原理图

S3C2410触摸屏驱动程序原理图本文介绍了基于三星S3C2410X微处理器,采用SPI接口与ADS7843触摸屏控制器芯片完成触摸屏模块的设计。
具体包括在嵌入式Linux操作系统中的软件驱动开发,采用内核定时器的下半部机制进行了触摸屏硬件中断程序设计,采用16个时钟周期的坐标转换时序,实现触摸点数据采集的方法,给出了坐标采集的流程。
设计完成的触摸屏驱动程序在博创公司教学实验设备UP-NETARM2410-S平台上运行效果良好。
引言随着信息家电和通讯设备的普及,作为与用户交互的终端媒介,触摸屏在生活中得到广泛的应用。
如何在系统中集成触摸屏模块以及在嵌入式操作系统中实现其驱动程序,都成为嵌入式系统设计者需要考虑的问题。
本文主要介绍在三星S3C2410X微处理器的硬件平台上进行基于嵌入式Linux的触摸屏驱动程序设计。
硬件实现方案SPI接口是Motorola推出的一种同步串行接口,采用全双工、四线通信系统,S3C2410X是三星推出的自带触摸屏接口的ARM920T内核芯片,ADS7843为Burr-Brown生产的一款性能优异的触摸屏控制器。
本文采用SPI接口的触摸屏控制器ADS7843外接四线电阻式触摸屏,这种方式最显著的特点是响应速度更快、灵敏度更高,微处理器与触摸屏控制器间的通讯时间大大减少,提高了微处理器的效率。
ADS7843与S3C2410的硬件连接如图1所示,鉴于ADS7843差分工作模式的优点,在硬件电路中将其配置为差分模式。
图1触摸屏输入系统示意图嵌入式Linux系统下的驱动程序设备驱动程序是Linux内核的重要组成部分,控制了操作系统和硬件设备之间的交互。
Linux 的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,成为设备文件。
应用程序可以打开、关闭、读写这些设备文件,对设备的操作就像操作普通的数据文件一样简便。
为开发便利、提高效率,本设计采用可安装模块方式开发调试触摸屏驱动程序。
linux iio子系统介绍

LINUX工业I/O 子系统翻译:tekkamanninjaIIO概述●工业I/O子系统旨在提供那些在某种意义上作为模数转换器(ADC)的设备支持。
●属于这类型的设备如下:o ADCs(模数转换器)o加速度传感器o陀螺仪o IMUs(惯性测量单位)o电容-数字转换器(CDCs)o压力、温度和光线传感器。
●此子系统的目的在于填补那些分类时处在hwmon(硬件监视器)和输入子系统之间的设备类型。
●hwmon(硬件监视器)直接使用低采样率的传感器,应用于(散热)风扇速度控制和温度测量。
●输入子系统,顾名思义,它是专注于(人机交互)输入设备的:o键盘o鼠标o触摸屏o操纵杆●在某些情况下,这些外设和IIO之间的相当大的重叠。
●典型的(IIO类)设备是通过SPI或I2C连接的。
●尽管典型的DMA操作设备,例如与高速同步串口(McBSP, SPORT) 或高速同步并口(EPI, PPI) 连接的外设也可以属于这个子系统。
●因为后来的非SPI或I2C总线,一般不通过Linux总线驱动来抽象,而是属于处理器平台相关的实现。
•IIO子系统概述IIO(框架)的功能●基本的设备注册和处理●通过sysfs中简单的polled访问设备通道。
●(基于)事件的chrdevs(字符设备)o这些特性和输入子系统非常类似:都为硬件触发的事件提供一个到用户空间的通路。
这些事件包括门限检测、自由落体检测和更加复杂的动作检测。
这些事件本身一般是非常简单的,只是一个事件代码和一个时间戳。
任何与事件关联的数据必须可以通过轮询来访问。
注意:一个给定的设备可能有一个或者多个事件通道。
这些事件(的触发)可以通过sysfs接口来开启和关闭(如果可能)。
●硬件缓冲支持●一些新近的传感器在片内集成了fifo(先入先出)/ ring(环形)缓冲区。
●他们极大地减轻了宿主CPU基于其内部采用时钟来缓存相关大量采样数据上的负担。
●每个环形缓冲通常有一个事件chrdev(字符设备)(与上述普遍的设备类似) 来传递事件(例如缓冲已经填满50% )和一个可访问的chrdev(字符设备)来读回这些缓冲中的裸数据。
文档:、linux-308内核I2C触摸屏移植

Linux3.0.8平台搭建移植文档——I2C触摸屏移植1.I2C子系统goodix电容屏采用I2C接口与处理器连接,我们要首先确保linux内核拥有对I2C子系统的支持,下面我们从子系统的配置和电容屏驱动两个方面进行移植修改1)配置I2C子系统支持#make menuconfigDevice Drivers ---><*> I2C support --->[*] Enable compatibility bits for old user-space (NEW)<*> I2C device interface< > I2C bus multiplexing support (NEW)[*] Autoselect pertinent helper modules (NEW)I2C Hardware Bus support --->进入I2C Hardware Bus support选项,选中以下内容:*** I2C system bus drivers (mostly embedded / system-on-chip) ***< > Synopsys DesignWare (NEW)<*> GPIO-based bitbanging I2C< > OpenCores I2C Controller (NEW)< > PCA9564/PCA9665 as platform device (NEW)<*> S3C2410 I2C Driver< > Simtec Generic I2C interface (NEW)...2.GOODIX电容屏移植1)添加goodix电容屏驱动将“goodix_touch.c”文件copy到drivers/input/touchscreen/目录下,并将"goodix_touch.h"、"goodix_queue.h"文件copy到include/linux/目录下,并修改Kconfig文件及Makefile文件支持触摸屏驱动的配置和编译#vi driver/input/touchscreen/Kconfig在config TOUCHSCREEN_TPS6507X选项的后面添加以下内容:config TOUCHSCREEN_GOODIXtristate "GOODIX based touchscreen"depends on I2ChelpIt is a android driver to support Gooidx's touchscreen whose nameis guitar on s5pv210 platform. The touchscreen can support multi-touch not more than two fingers.Say Y here to enable the driver for the touchscreen on theS5V SMDK board.If unsure, say N.To compile this driver as a module, choose M here:the module will be called goodix_touch.ko.#vi driver/input/touchscreen/Makefile在文件最后添加如下内容:obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_touch.o2)添加i2c_board_info资源(电容屏)#vi arch/arm/mach-s5pv210/mach-smdkv210.c在smdkv210_i2c_devs0结构体数组定义中添加以下内容:...{ I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */ { I2C_BOARD_INFO("wm8580", 0x1b), },{I2C_BOARD_INFO("Goodix-TS", 0x55),.irq = IRQ_EINT(4),},...3)配置电容屏选项#make menuconfigDevice Drivers --->Input device support --->...[*] Touchscreens ---><*> GOODIX based touchscreen4)make将在arch/arm/boot/下生成编译好的可执行程序zImage下载到开发板即可,执行命令“cat /dev/input/event0”,然后用手触摸屏幕会在终端看到输出打印的乱码信息,表示移植成功,如果没有打印信息或没有“/dev/input/event0”这个设备说明移植失败。
史上最详细的触摸屏驱动分析

/*触摸屏驱动程序及分析*/#include <linux/errno.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/init.h>#include <linux/serio.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/clk.h>#include <asm/io.h>#include <asm/irq.h>#include <plat/regs-adc.h>#include <mach/regs-gpio.h>/* For ts.dev.id.version */#define S3C2410TSVERSION 0x0101#define WAIT4INT(x) (((x)<<8) | \S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \S3C2410_ADCTSC_XY_PST(3))#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))static char *s3c2410ts_name = "s3c2410 TouchScreen";static struct input_dev *dev;static long xp;static long yp;static int count;extern struct semaphore ADC_LOCK;static int OwnADC = 0;static void __iomem *base_addr;/*把GPG12~15 设置为保留模式*/static inline void s3c2410_ts_connect(void){s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);}/*求坐标的平均值,报告坐标,当还是按下状态时,再次调用ADC转换,如果抬起则让触摸屏设置为等待中断模式*/static void touch_timer_fire(unsigned long data){unsigned long data0;unsigned long data1;int updown;/*用于读取ADCDA T数据*/data0 = ioread32(base_addr+S3C2410_ADCDA T0);data1 = ioread32(base_addr+S3C2410_ADCDA T1);/*判断是按下还是送开*/updown = (!(data0 & S3C2410_ADCDA T0_UPDOWN)) && (!(data1 & S3C2410_ADCDA T0_UPDOWN));/*如果按下*/if (updown) {if (count != 0) {/*转换四次后进行事件汇报*/long tmp;tmp = xp;xp = yp;yp = tmp;/* 求平均值*/xp >>= 2;yp >>= 2;/* 报告x、y的绝对坐标值*/input_report_abs(dev, ABS_X, xp);input_report_abs(dev, ABS_Y, yp);/* 报告按键事件,键值为1(代表触摸屏对应的按键被按下) */input_report_key(dev, BTN_TOUCH, 1);/* 报告触摸屏的状态,1表明触摸屏被按下*/input_report_abs(dev, ABS_PRESSURE, 1);/* 同步*/input_sync(dev);}xp = 0;yp = 0;count = 0;/*自动X/Y轴坐标转换模式的设置,自动地进行X轴和Y轴的转换操作,随后产生相应的INT_ADC中断通知转换完毕*/iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);/*如果还没有启动ADC或者ADC转换四次完毕后则启动ADC*/iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);} else {count = 0;/* 如果触摸笔是弹起状态,则提出报告,并让触摸屏处于等待触摸的阶段*//* 报告按键事件,键值为0(代表触摸屏对应的按键被释放) */input_report_key(dev, BTN_TOUCH, 0);/* 报告触摸屏的状态,0表明触摸屏未被按下*/input_report_abs(dev, ABS_PRESSURE, 0);/*同步*/input_sync(dev);/* 设置触摸屏为等待中断模式,等待触摸笔按下*/iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);if (OwnADC) {OwnADC = 0;up(&ADC_LOCK);}}}static struct timer_list touch_timer =TIMER_INITIALIZER(touch_timer_fire, 0, 0);/*当触摸按下时,产生INT_TC中断,会进入到stylus_updown中断处理函数当有中断产生时,会使OwnADC=1,然后读取数据,并判断是抬起还是按下,按下则调用touch_timer_fire()函数,抬起则释放锁,并使OwnADC=0*/static irqreturn_t stylus_updown(int irq, void *dev_id){unsigned long data0;unsigned long data1;int updown;/*注意在触摸屏驱动模块中,这个ADC_LOCK的作用是保证任何时候都只有一个驱动程序使用ADC的中断线,因为在mini2440的adc模块中也会使用到ADC,这样只有拥有了这个锁,才能进入到启动ADC代码部分,注意尽管LDD3中说过信号量因为休眠不适合使用在ISR中,但down_trylock是一个例外,它不会休眠*/if (down_trylock(&ADC_LOCK) == 0) {OwnADC = 1;//获取ADC转换的数据data0 = ioread32(base_addr+S3C2410_ADCDA T0);data1 = ioread32(base_addr+S3C2410_ADCDA T1);updown = (!(data0 & S3C2410_ADCDA T0_UPDOWN)) && (!(data1 & S3C2410_ADCDA T0_UPDOWN));/*判断目前触摸笔的状态updown = 1 触摸笔按下;updown = 0 触摸笔弹起;*/if (updown) {//当触摸笔按下时touch_timer_fire(0); /*这是一个定时器函数,当然在这里只是作为普通函数调用,用来启动ADC*/} else {//当笔弹起时,释放锁OwnADC = 0;up(&ADC_LOCK);}}return IRQ_HANDLED;}/*INT_ADC 中断处理函数读取四次AD转换的值,然后求和,超过四次后执行touch_time_fire()函数*/static irqreturn_t stylus_action(int irq, void *dev_id){unsigned long data0;unsigned long data1;if (OwnADC) {data0 = ioread32(base_addr+S3C2410_ADCDA T0);data1 = ioread32(base_addr+S3C2410_ADCDA T1);xp += data0 & S3C2410_ADCDA T0_XPDA TA_MASK;yp += data1 & S3C2410_ADCDA T1_YPDA TA_MASK;count++;if (count < (1<<2)) { /*如果小于四次重新启动ADC转换*/iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);iowrite32(ioread32(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_STAR T, base_addr+S3C2410_ADCCON);} else {/*如果超过四次,启动1个时间滴答的定时器,停止ADC,然后调用定时器处理函数touch_timer_fire进行数据上报*/mod_timer(&touch_timer, jiffies+1);iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);}}return IRQ_HANDLED;}static struct clk *adc_clock;/*初始化主要做的工作为:1、获取ADC时钟并使时钟使能2、申请IO虚拟地址3、设置ADCCON,ADCDLY,ACDTSC4、申请input设备5、设置input事件类型,事件值,X,Y坐标的最大最小值6、中断申请7、注册input设备*/static int __init s3c2410ts_init(void){struct input_dev *input_dev; //定义input结构体指针/*获取时钟,触摸屏是挂载在APB BUS上的外围设备,需要时钟控制,见数据手册第7章*/adc_clock = clk_get(NULL, "adc");if (!adc_clock) {//如果时钟获取失败时printk(KERN_ERR "failed to get adc clock source\n");return -ENOENT;}//时钟使能clk_enable(adc_clock);/*I/O内存不要直接进行访问的,最好对其进行映射*/base_addr=ioremap(S3C2410_PA_ADC,0x20);if (base_addr == NULL) {printk(KERN_ERR "Failed to remap register block\n");return -ENOMEM;}/* Configure GPIOs 把YPON,YMON,XPON,XMOND都设置成11,保留模式*/s3c2410_ts_connect();/*使能预分频和设置分频系数S3C2410_ADCCON_PRSCEN:使AD转换使能,是ADCCON的第14位PRSCENS3C2410_ADCCON_PRSCVL(0xFF):预分频系数,取值为0~255:,AD时钟=PCLK/(PRSCVL+1),且必须小于1/5的PCKL*/iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);/*设置ADC延时,在等待中断模式下表示产生INT_TC的间隔时间,ADC转换周期等待定时器*/iowrite32(0xffff, base_addr+S3C2410_ADCDLY);/*ADCTSC = 0xd3 ,将触摸屏置为等待中断模式,等待触摸屏被按下产生INT_TC中断*/iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);/* 以下配置2.6内核划分出来的输入设备*//* 分配一个input输入设备*/input_dev = input_allocate_device();if (!input_dev) {//分配input输入设备不成功时printk(KERN_ERR "Unable to allocate the input device !!\n");return -ENOMEM;}dev = input_dev;/*evbit字段用来定义该输入设备可以支持的(产生和响应)的事件的类型,触摸屏设置为支持同步(EN_SYN)、按键(EN_KEY)、绝对坐标(EV_ABS)事件*/dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);/* 设置所支持的按键(键值),触摸屏可以看成只有一个按键的设备*/dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);/* 设置绝对坐标x的最小最大值(0-0x3FF) */input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0);/* 设置绝对坐标y的最小最大值(0-0x3FF) */input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);dev->name = s3c2410ts_name;dev->id.bustype = BUS_RS232;dev->id.vendor = 0xDEAD;dev->id.product = 0xBEEF;dev->id.version = S3C2410TSVERSION;/*INT_TC, INT_ADC中断注册,问题:两种中断的产生时机?哪种中断会先产生?答案:INT_TC会先产生,并不断的产生*//* Get irqs *///中断处理函数if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM, "s3c2410_action", dev)) {printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");iounmap(base_addr);return -EIO;}if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,"s3c2410_action", dev)) {printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");iounmap(base_addr);return -EIO;}printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);/* All went ok, so register to the input system *//*注册输入设备*/input_register_device(dev);return 0;}/*主要完成:1、中断的释放2、注销input设备3、释放虚拟内存*/static void __exit s3c2410ts_exit(void){disable_irq(IRQ_ADC);disable_irq(IRQ_TC);free_irq(IRQ_TC,dev);free_irq(IRQ_ADC,dev);if (adc_clock) {clk_disable(adc_clock);clk_put(adc_clock);adc_clock = NULL;}input_unregister_device(dev);iounmap(base_addr);}module_init(s3c2410ts_init);module_exit(s3c2410ts_exit);MODULE_LICENSE("GPL");。
linux设备驱动程序的设计与实现

linux设备驱动程序的设计与实现
Linux设备驱动程序的设计与实现是一个涉及底层系统编程和硬件交互的复杂过程。
下面是一个简单的步骤指南,以帮助你开始设计和实现Linux设备驱动程序:
1. 了解硬件:首先,你需要熟悉你要驱动的硬件设备的规格和特性。
这包括硬件的内存空间、I/O端口、中断请求等。
2. 选择驱动程序模型:Linux支持多种设备驱动程序模型,包括字符设备、块设备、网络设备等。
根据你的硬件设备和需求,选择合适的驱动程序模型。
3. 编写Makefile:Makefile是一个文本文件,用于描述如何编译和链接你的设备驱动程序。
它告诉Linux内核构建系统如何找到并编译你的代码。
4. 编写设备驱动程序:在Linux内核源代码树中创建一个新的驱动程序模块,并编写相应的C代码。
这包括设备注册、初始化和卸载函数,以及支持读写和配置硬件的函数。
5. 测试和调试:编译你的设备驱动程序,并将其加载到运行中的Linux内核中。
使用各种测试工具和方法来验证驱动程序的正确性和稳定性。
6. 文档和发布:编写清晰的文档,描述你的设备驱动程序的用途、用法和已知问题。
发布你的代码以供其他人使
用和改进。
kernel下的uinput机制_示例及概述说明

kernel下的uinput机制示例及概述说明1. 引言1.1 概述在计算机领域中,uinput(user input)机制是一种通过模拟输入设备来实现对系统的控制和操作的方法。
它在kernel中被广泛应用,可以创建虚拟的输入设备,并向系统注入用户自定义的输入事件。
通过uinput机制,我们可以模拟鼠标、键盘、触摸屏等各种输入设备的行为,使得用户或开发者能够以编程的方式进行各种操作和测试。
1.2 文章结构本文将就kernel下的uinput机制进行详细介绍与示例演示。
首先,在"2. uinput机制的原理与用途"部分中,我们将解释什么是uinput机制以及它在系统中起到的作用,进而探讨其背后的实现原理和所涉及到的应用领域。
接着,在"3. 示例:通过uinput模拟输入设备的创建和操作"部分中,我们将会给出具体示例,演示如何使用uinput机制来创建虚拟输入设备,并对其进行模拟操作。
随后,在"4. kernel中uinput机制的相关配置和API接口介绍"部分中,我们将详细介绍如何配置kernel以支持uinput机制,并提供相关API接口的介绍和使用示例。
最后,在"5. 结论与展望"部分中,我们将对uinput机制进行总结回顾,并探讨目前存在的问题以及未来的发展趋势。
1.3 目的本文旨在全面介绍kernel下的uinput机制,帮助读者了解其原理和用途,并提供具体示例和配置指南,使得读者能够深入理解并应用该机制,从而满足各种自动化测试、模拟操作等需求。
同时,对于开发者来说,该文章也提供了一个参考和指导,以便他们在实际项目中更好地利用uinput机制来实现相关功能。
2. uinput机制的原理与用途2.1 什么是uinput机制uinput(User Input)机制是Linux内核中的一个子系统,用于模拟和生成输入事件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
以 X 轴为例, 当手指去触摸屏幕时, 将吸收相应 位置的声波能量, 声波信号将衰 减, 此 X 轴声波接收 器接收到的波形在时间 t 上形成一个缺口, 通过确24 作者简介: 於琪建 ( 1983- ) , 男, 浙江台州人, 主要从事电子信息系统集成方面的研究. E-m ai:l q ijian1115@ yahoo. com. cn 通信联系人: 张海峰, 男, 副教授, 硕士生导师. E-ma i:l hfzhang0811@ hdu. edu. cn
图 2 file_operations, file, inode关联过程
4 L inux设备模型与输入子系统
L inux 2. 6 内核的一个重要特色是提供了统一的 内核设备模型, 以适应 / 系统的拓扑结构越来越复杂, 智能电源管理、热插拔以及即插即用的支持要求也越 来越高 0的趋势。
简单地说, L inux 设 备模型是基 于内核对 象 kobject来实现的。借助内核对象 kobject机制, 内核通过 / sys向用户控件输出设备的各类信息, 方便了设备的管 理。 / sys是 sysfs文件系统, 它是一个类似于 proc文件 系统的特殊文件系统, 用于将系统中的设备组织成层 次结构, 并向用户模式程序提供关于内核数据结构的 详细信息。
3 L inux字符设备驱动框架
设备驱动程序是操作系统内核和底层硬件之间的 接口。设备驱动程序为上层应用程序屏蔽了硬件的细 节。 L inux系统中设备驱动程序的设计核心思想是: 像 操作普通文件一样对硬件设备进行操作, 它提供了相 应文件 操作函数 的入口点, 如 open( )、read ( ) 、w r ite ( ) 、re lease( ) 等 [ 3-4] 。
图 3 Inpu t子系统层次结构
可以完成触摸屏驱动程序的设计。 D r iver 驱动 层主 要实 现向 内 核注 册 输 入 设备 以 实
现输入设备模型, 并提供将触摸屏采集到的数据上报 Inpu t核心 层的 方法 。 5. 1 输入设备的注册与注销
D r iver 驱动 层通 过调 用如 下 接口 函 数 来 向输 入 子 系统中注册和注销输入设备:
5 触摸屏驱动程序的实现
输入子系统的 3层驱动结构中, Input核心层与 Event处理层已由内核实现, 故采用设备模型与输入子 系统机制, 以简化设备驱动程序的设计。现在只需实 现 Driver驱动层, 即通过调用内核提供的接口函数, 就
# 34#
机电工程
第 26卷
冲区, 而后应用程序根据触摸屏的坐标进行数据校准 ( 坐标转换 ) , 最终光标显示在触摸笔所指的正确的位 置上。
(S choo l of E lectronics Inform ation, H angzhou D ianzi University, H angzhou 310018, Ch ina) Abstrac t: A im ing at simp lify ing the design of traditiona l L inux dr iver and contr ibuting to m anagem ent and m ain tenance o f the dr ive mode,l us ing the input subsystem based on ke rne l ob jec t, the L inux dev ice dr iverps fram ew ork was fu lfilled. The traditiona l m ethod concerned w ith the inte rfaces of file operations w as im proved. The me thod o f only reporting the input event to the L inux system was proposed. T he dr iver w as successfully deve loped. T he test resu lts indicate tha t the driver w orks w el,l and it can control the touch screen prec isely. K ey word s: dev ice dr ive r; dev ice mode;l input subsy stem; touch screen
0引 言
在嵌入式系统中, 触摸屏具有轻便、反应速度快、 节省空间、易于交流等优点, 成为了最简单、方便、自然 的一种人机交互方式。目前, 触摸屏有 4种类型: 电阻 式触摸屏、电容感应式触摸屏、红外线式触摸屏以及表 面声波式触摸屏。它们的实现材料不同, 但在实现原 理上都是一致的。
本研究主要实现 在嵌入式 ARM ( S3C2440) 下的 触摸屏驱动程序, 由于 S3C2440芯片上已有触摸屏的 接口, 为触摸屏驱动的实现创造了条件。
输入子系统 [ 5] 就是借助于 kobject机制 [ 6] 建立起 来的一种设备模型。如图 3所示, 具体由 D river驱动 层、Input核心层、Event处理层 3部分组成。 D river驱 动层主要将输入设备的数据或信息上报给 Input核心 层; Input核心层由 / driver / input / inpu.t c及相关头文件 实现, 它对下提供了 D river驱动层的接口, 对上提供了 Event处理层的接口; Event处理层提供文件操作方法, 它负 责 将数 据 放 到 设备 缓 冲 区, 用 户 程 序 ( 如 M in iGU I) 打开设备节点, 读取缓冲区数据。
L inux设备驱动程序可分为字符设备驱动程序、块 设备驱动程序和网络设备驱动程序, 本研究中触摸屏 设备为字符设备。
字符设备驱动程 序涉及到 3 个重要的数 据结构 体, 即 file_operations, file, inode。它们之间的关系及 其主要结构成员如图 2所示。
用户空间的应用程序要实现对设备文件的操作, 就是对位于 / dev下 的设备文件进行操作。这 些设备 文件在内核中就由 inode结构表示。当用 L inux 系统 提供的 open方法打开一个设备节点文件的时候, 就会 有表示该文件描述符 fd的 file结构指向这个 inode结 构, 具体实现方式是经过 dentry结构体 ( 目录结构体 ) 产生关联。可以有多个文件 描述符指向 inode结 构, 也就是一个设备文件可以按不同的方式打开多次。
( 1) input_reg ister_device( ); ( 2) input_unreg ister_dev ice( ) 。 以上两个函数调用的参数为 input_dev结构体 ( 在 dr iver/ input / inpu.t h中定义 )。注册完成之后, 内核为 输入设备在 Event处理层关联了相应的文件操作方法 ( 在 / driver/ input / tsdev. c中实现 )。这样, 当设备成功 注册后, 就会在 / dev 下生成相应的设备文件, 从而形 成 L inux 设备驱动程序基本框架。 5. 2 触摸屏驱动实现过程 如图 4所示, 首先触摸屏处于等待中断模式 上。 当触摸笔按 下的时候, 触摸屏将 产生一个 中断 INT _ TC。然后触摸屏将触发进入 X /Y 轴单独转化模式, 也 就是当 X 模式转换完成之后, 将产生一个 INT _ADC 中 断, 此时将进入 Y 模式转换, 当 Y 模式转换完成后, 将 又会产生一个 INT _ADC 中断。此时, 进入中断程序, 将分别取得 X 坐标值与 Y 坐标值。然 后驱动程序调 用接口函数 inpu t_report_abs( ), 将取得的值上报给 Inpu t核 心层 。
第 3期
於琪建, 等: L inux 输入子系统在触摸屏驱动上的实现
# 33#
2 S3C2440触摸屏接口
S3C2440芯片支持触摸屏的接口, 其包含触摸屏 控制器、4个外部场效应管及 1个外部电压源, 具体连 接可见芯片手册上的 ADC 和触摸屏接口操作框图 [ 1] 。
该触摸屏接口有 4种工作模式 [ 2 ] : ( 1) 正常转换模式: 用于通用 A /D转化; ( 2) 单独 X /Y 转化模式: 先进行 X 模式转换, 等 X 坐标转换完成之后, 产生 ADC中断, 然后进入 Y 模式转 换, 将 Y 坐标转换完成之后, 又产生一次 ADC中断; ( 3) X /Y 自动转换模式: 触摸屏自动地转换 X 坐 标和 Y 坐标; ( 4) 等待中断模式: 一般触摸屏开始工作后, 将处 于此模式。只有当触摸笔按下时, 触摸屏控制器才产 生一个 INT _TC 中断信号。 触摸屏接口工作模式涉及到 S3C2440 的 A /D 寄 存器主要有 4 个: ADC 控制寄存器、ADC 触摸控制寄 存器、ADC 开始延迟 寄存器、ADC 数据 转化寄存 器。 所得坐标将存入 ADC数据转化寄存器中。
第 26卷第 3期 2009年 3月
机电 工程
M echan ical& E lectrical Eng inee ring M agazine
V o.l 26 N o. 3 M a r. 2009
L inux输入子系统在触摸屏驱动上的实现
於琪建, 张海峰
(杭州电子科技大学 电子信息学院, 浙江 杭州 310018)
图 4 D river驱动层与 Input核心层关联
Input核心层找出对应的事件处理函数, 由 Event 处理层将数据放到设备缓冲区, 如图 5所示。上层驱 动处理函数将在 应用程序 ( 如 M in iGU I) 调用驱 动的 read函数时, 将设备缓冲区的数据拷贝到用户程序缓
摘 要: 为了简化传统 L inux 驱动程序设计及便于对驱动模块的管理与维护, 采用了基于内核对象的输
入子系统, 完成了 L inux设备驱动框架, 改进了传统基于文件操作接口的驱动程序设计方法, 提出了只