input core输入事件 矩阵键盘 映射 原理分析

原创 2015年07月08日 11:20:46

//这个是矩阵键盘映射表,使用内核定义的宏KEY()来建立

//#defineKEY(row, col,val) ((((row)& (MATRIX_MAX_ROWS - 1)) << 24) |\

//(((col)& (MATRIX_MAX_COLS - 1)) << 16) |\

//((val)& 0xffff))

//从上面的定义来看KEY用于唯一确认一个值,用于将(row,col,val)转换为一个单一个32位的值。

//这样存储起来,比较节省空间。高高字节用于存储行号,高低字节用于存储列号,低高和低低字节用于保存值。

//如此一来,将二维坐标(x,y)及值val转换为一个单一的32int数据。

//但是取出来的时候还得使用特殊的宏来操作。

//将扫描码映射为内核定义的标准键值,以方便上层应用程序使用。

staticintmx6sl_evk_keymap[] = {

KEY(0,0, KEY_SELECT), //映射矩阵(0,0)处按键为内核标准的KEY_SELECT键码。

KEY(0,1, KEY_BACK),

KEY(0,2, KEY_F1), //映射矩阵(0,2)处按键为内核标准的KEY_F1键码。

KEY(0,3, KEY_F2), //映射矩阵(0,3)处按键为内核标准的KEY_F2键码。

//内核自己定义的键码在linux/input.h中定义。

KEY(1,0, KEY_F3),

KEY(1,1, KEY_F4),

KEY(1,2, KEY_F5),

KEY(1,3, KEY_MENU),


KEY(2,0, KEY_PREVIOUS),

KEY(2,1, KEY_NEXT),

KEY(2,2, KEY_HOME),

KEY(2,3, KEY_NEXT),


KEY(3,0, KEY_UP),

KEY(3,1, KEY_LEFT),

KEY(3,2, KEY_RIGHT),

KEY(3,3, KEY_DOWN),

};

//这个结构体也是内核抽象出来的,定义在linux/input/matrix_keypad.h中。

//structmatrix_keymap_data {

// constuint32_t *keymap;

// unsignedint keymap_size;

//};

staticconststructmatrix_keymap_data mx6sl_evk_map_data__initconst = {

.keymap =mx6sl_evk_keymap,

.keymap_size =ARRAY_SIZE(mx6sl_evk_keymap),

};

//#defineARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

//这里的ARRAY_SIZE宏用于确认数组大小(数组有多少元素)。

//从实现来看就是使用sizeof求出整个数组占用内存大小,然后用sizeof(第一个元素)占用内存大小

//2个数一除就能得到整个数组中元素的个数。

#defineMATRIX_MAX_ROWS 32

#defineMATRIX_MAX_COLS 32


//内核使用一个32位的数据来保存3种信息:行号,列号,键码

//8<31:24>用于保存行号。

//低高8<23:16>用于保存列号。

//16<15:0>用于保存内核定义的键码。

#defineKEY_ROW(k) (((k) >> 24) & 0xff) //32位数据中提取最高8位的行号

#defineKEY_COL(k) (((k) >> 16) & 0xff) //32位数据中提取次高8位的列号

#defineKEY_VAL(k) ((k) & 0xffff) //32位数据中提取低16位的映射的内核定义的键码!


//这个应该用于行列的索引值,可以在映射数组中根据行,列获取下标。

//其中对于row_shift的定义为:

*@row_shift: number of bits to shift row value by to advance to thenext line in the keymap

//大体的意思就是:在keymap中用于移至下一行的值的位数。

//在内核中找到了imx6kpp的驱动,他的定义如下,结合起来,更好理解。

//#defineMAX_MATRIX_KEY_ROWS 8

//#defineMAX_MATRIX_KEY_COLS 8

//#defineMATRIX_ROW_SHIFT 3 //这里就是row_shift了,这里行大小为8,移至下行需要移到8个,所以2^3=8,所以这里

//row_shift就为8了。

#defineMATRIX_SCAN_CODE(row, col, row_shift) (((row) << (row_shift)) +(col))

//从上面的定义来看使用<<左移,所以2<<3=8.感觉这个函数只是将行号和列号组织在了一起而已。


//一般的驱动会有以下的代码,用于向inputcore提供事件。

//这里比较关键的是第3句,使用行列组织在一起的codekeycodes[]数组中提出映射键码,这是怎么做到的呢?


code= MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);

input_event(input_dev,EV_MSC, MSC_SCAN, code);

input_report_key(input_dev,keypad->keycodes[code],matrix_volatile_state[col]& (1 << row));


//来看一下,下面这些代码,分析一下,找出为什么?

input_dev->keycode= keypad->keycodes;

input_dev->keycodesize= sizeof(keypad->keycodes[0]);

input_dev->keycodemax= ARRAY_SIZE(keypad->keycodes);


//其实这里比较关键的,建立了映射关系!

conststructmatrix_keymap_data *keymap_data =pdev->dev.platform_data;//从平台设备中拿到映射表。


matrix_keypad_build_keymap(keymap_data,MATRIX_ROW_SHIFT,

keypad->keycodes,input_dev->keybit);

//再来看看这个映射函数的实现过程吧。

//内核中注释的意思将keymap_data转换到keymap中存储,并使用行+列来索引。

staticinlinevoid

matrix_keypad_build_keymap(conststructmatrix_keymap_data *keymap_data,

unsignedintrow_shift,

unsignedshort*keymap, unsignedlong*keybit)

{

inti;


for(i = 0; i < keymap_data->keymap_size;i++) { //循环处理每一个元素。

unsignedintkey = keymap_data->keymap[i];//存储32位值。

unsignedintrow = KEY_ROW(key); //32位值中拿到行号。

unsignedintcol = KEY_COL(key); //32位值中拿到列号。

unsignedshortcode = KEY_VAL(key); //32位值中拿到键码。


keymap[MATRIX_SCAN_CODE(row,col, row_shift)] = code; //最最关键的这句话!!keymap中指定位置(行号+列号)存储键码!

//这里就是 行号<<8+列号 形成一个16位的数据,这样就可以唯一的标识一个数组的下标索引,将相关的键码保存在此单元中。

__set_bit(code,keybit);

}

__clear_bit(KEY_RESERVED,keybit); //这句真不知道什么意思?

//structinput_dev结构体中找到的定义如下:

*@evbit:bitmap of types of events supported by the device (EV_KEY,

* EV_REL,etc.) 按位操作,表示这个设备支持的事件。

*@keybit:bitmap of keys/buttons this device has :按位操作,表示这个设备支持的按键。

}


好,我们再来看看上面那3句代码,用于向inputcore上报事件:

1code= MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);

2input_event(input_dev,EV_MSC, MSC_SCAN, code);

3input_report_key(input_dev,keypad->keycodes[code],matrix_volatile_state[col]& (1 << row));

1句知道了吧,根据上面的分析就是将行号<<8+列号,组合起来,构成一个16位的数据。

2句这应该是上报类似于键盘扩展码之类的,这个暂时用不到。不过在内核中很多代码都加了这句。

3句比较关键,关键是要正确上报映射的键码。由于之前使用matrix_keypad_build_keymap函数将键码存储到数组指定的位置,

那么下面可以轻松的使用行号<<8+列号来取到键码了。

1表示按下,0表示松开。现在来分析一下,还是比较简单的。

之前看到imx6中的kpp的驱动代码,结合数据手册,感觉imx6的这个kpp简单很鸡肋,没有什么功能。

是提供了I/O的开漏输出和图腾柱输出模式,具体的扫描、消抖还得在代码中手工完成。

因为最近有个项目需要用于自定义的矩阵键盘,同时上层使用Qt来实现,看了下现在最新的qt5支持evdev,可直接从/dev/input/eventx

中读取输入事件,所以只要驱动使用input子系统上报输入事件,那么qt就肯定能收到。

由于是嵌入式设备,界面上就不能使用鼠标进行操作了,就必须使用keyPressEvent/keyReleaseEvent来实现操作了。




版权声明:本文为博主原创文章,未经博主允许不得转载。

Freescale imx6 linux platform 驱动模型分析

Freescale imx6 linux platform 驱动模型分析 一. 概述     platform设备和驱动与linux设备模型密切相关。platform在linux设备模型中,其...
  • wq690968346
  • wq690968346
  • 2016年05月05日 16:38
  • 1040

iMX6开发板—SABER Lite评估板-imx.6评估板学习qnx

- 基于四核ARM Cortex-A9 的飞思卡尔i.MX 6Quad处理器 - 主频高达1.2GHz,1MB的L2 Cache - 整合1080p@60fps 解码、1080p@30pfs编码以及3...
  • xjhhjx
  • xjhhjx
  • 2017年08月12日 08:43
  • 457

imx6 添加matrix keypad

freescale增加matrix keypad 1.添加设备树,imx6 有矩阵键盘功能,支持8*8的键盘 kernel_imx/arch/arm/boot/dts/imx6qdl....
  • zyaiwmy
  • zyaiwmy
  • 2017年01月10日 13:35
  • 1133

键盘按键映射

  • 2013年08月13日 16:28
  • 49KB
  • 下载

嵌入式Linux下矩阵键盘应用

By Toradex 胡珊逢 1). 简介 触摸屏,无论是电阻式还是电容式,在嵌入式领域有着广泛的使用。配合设计优秀的 GUI,能够给用户带来很好的体验。很多时候,触摸屏在使用之前都需要进...
  • toradexsh
  • toradexsh
  • 2017年08月23日 17:46
  • 576

gpio matrix keypad linux driver

Linuxkernel & device driver programming Cross-Referenced Linuxand Device DriverCode ...
  • shell_albert
  • shell_albert
  • 2015年06月24日 10:11
  • 1410

imx6 项目的按键驱动程序

/**  * filename:imx6_key_drv.c  * description: matrix key driver for imx6.  * author:shell.albert...
  • shell_albert
  • shell_albert
  • 2016年01月02日 11:49
  • 1547

IMX6 驱动代码位置

emmc/sdcard 驱动    drivers/mmc/host:sdhci-esdhc-imx.c      /dev/mmcblk*                             ...
  • jack_a8
  • jack_a8
  • 2015年01月31日 12:51
  • 4427

keypad 驱动分析

参考网站http://www.xuephp.com/main/detail.php?cid=39048 对应文件目录: F:\MTK\alps6589_v1.3_s188_patch\me...
  • zlcchina
  • zlcchina
  • 2014年03月27日 16:44
  • 624

[RK3288][Android6.0] 系统按键驱动流程分析

Rockchip的按键驱动位于 kernel/drivers/input/keyboard/rk_keys.c默认支持的key在dts中配置其中 power key作为普通gpio,具有唤醒功能。...
  • kris_fei
  • kris_fei
  • 2017年09月08日 14:30
  • 1245
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:input core输入事件 矩阵键盘 映射 原理分析
举报原因:
原因补充:

(最多只允许输入30个字)