Linux内核中提供了一个matrix-keypad驱动程序,包括两部分:
- 代码文件:drivers/input/keyboard/matrix_keypad.c
- 头文件定义:include/linux/input/matrix_keypad.h
添加驱动程序
在内核的Config界面中,定位到:
Device Drivers ---> Input device support ---> Keyboards
选中GPIO driven matrix keypad support项,保存并退出,即可启用该驱动程序,并添加CONFIG_KEYBOARD_MATRIX配置宏定义。
配置引脚
matrix-keypad驱动程序要求:
- 矩阵键盘列线(COL)为输出模式。
- 矩阵键盘行线(ROW)为输入模式。
请确保已在设备的平台初始化文件中配置GPIO引脚的输入/输出模式和上下拉状态。matrix-keypad驱动程序不会自动配置引脚的上下拉状态。
填充结构
matrix_keypad.h头文件定义了以下两个需要被填充的结构体。这两个结构体可以在设备平台初始化文件的公共定义区声明。这里以iTop-4418为例,结构体被声明在kernel/arch/arm/plat-s5p4418/topeet/device.c。
/** * matrix_keymap_data结构体 - 矩阵键盘按键映射信息 * @keymap: 指向由KEY(row, col, val)宏定义、代表矩阵键盘按键行-列-键码对应关系的uint32数组 * @keymap_size: 数组的大小 * */ struct matrix_keymap_data { const uint32_t *keymap; unsigned int keymap_size; }; /** * matrix_keypad_platform_data结构体 - 矩阵键盘的平台相关数据 * @keymap_data: 指向matrix_keymap_data结构体的指针 * @row_gpios: 指向代表矩阵键盘的行(Row)的GPIO引脚编号的数组 * @col_gpios: 指向代表矩阵键盘的列(Col)的GPIO引脚编号的数组 * @num_row_gpios: 矩阵键盘设备实际使用的行数 * @num_col_gpios: 矩阵键盘设备实际使用的列数 * @col_scan_delay_us: 以微秒为单位的延时,指示列线扫描的间隔时间 * @debounce_ms: 消抖间隔,单位为毫秒 * @clustered_irq: 指示行线、列线是否共用中断 * @clustered_irq_flags: 共用中断时的配置信息 * @active_low: GPIO极性,设为1指示键按下时,行线为低电平 * @wakeup: 指示设备是否被配置为具有唤醒主机功能 * @no_autorepeat: 指示是否停用按键长按时的自动重复动作,设为1表示停用 */ struct matrix_keypad_platform_data { const struct matrix_keymap_data *keymap_data; const unsigned int *row_gpios; const unsigned int *col_gpios; unsigned int num_row_gpios; unsigned int num_col_gpios; unsigned int col_scan_delay_us; /* key debounce interval in milli-second */ unsigned int debounce_ms; unsigned int clustered_irq; unsigned int clustered_irq_flags; bool active_low; bool wakeup; bool no_autorepeat; };
keymap数组指针
keymap数组指针指向一个由一系列KEY(row, col, val)宏定义组成的uint32数组,该宏的三个参数代表了行、列、键码的对应关系。
/* Key definition */ static u32 arrKeyMapping[] = { //KEY(row, col, keycode) KEY( 3, 3, KEY_1), KEY( 3, 2, KEY_2), KEY( 3, 1, KEY_3), KEY( 3, 0, KEY_4), KEY( 2, 3, KEY_5), KEY( 2, 2, KEY_6), KEY( 2, 1, KEY_7), KEY( 2, 0, KEY_8), KEY( 1, 3, KEY_9), KEY( 1, 2, KEY_0), KEY( 1, 1, KEY_A), KEY( 1, 0, KEY_B), KEY( 0, 3, KEY_C), KEY( 0, 2, KEY_D), KEY( 0, 1, KEY_E), KEY( 0, 0, KEY_F) }; static struct matrix_keymap_data mkdKeyMappingData = { .keymap = arrKeyMapping, .keymap_size = ARRAY_SIZE(arrKeyMapping), };
row_gpios、col_gpios行列GPIO定义指针
row_gpios和row_gpios均指向由unsigned int型数据组成的数组,分别描述了矩阵键盘占用的行、列GPIO端口。行、列GPIO端口定义数组通常会以设备相关的GPIO端口号宏编写。因此,在编写时应当引入设备相关的GPIO头文件。
/* Row & Col definition */ static u32 arrRowGPIOs[] = {PAD_GPIO_E + 3, PAD_GPIO_E + 2, PAD_GPIO_E + 1, PAD_GPIO_E + 0}; //GPIO ports of Row line static u32 arrColGPIOs[] = {PAD_GPIO_D + 31, PAD_GPIO_D + 30, PAD_GPIO_D + 29, PAD_GPIO_D + 28}; //GPIO ports of Col line static struct matrix_keypad_platform_data mkpMatrixKeypadPlatformData = { .keymap_data = &mkdKeyMappingData, .row_gpios = arrRowGPIOs, .col_gpios = arrColGPIOs, .num_row_gpios = ARRAY_SIZE(arrRowGPIOs), .num_col_gpios = ARRAY_SIZE(arrColGPIOs), .col_scan_delay_us = 100, .debounce_ms = 10, .active_low = 1, .no_autorepeat = 0, };
声明平台设备信息
matrix-keypad驱动程序被实现为一个平台总线驱动程序,因此应当声明一个公共的platform_device结构体,并使其name参数为matrix-keypad,且dev->platform_data指向先前声明的matrix_keypad_platform_data结构。该结构体同样可以在设备平台初始化文件的公共定义区声明。
struct platform_device itop4418_matrix_keypad_device = { .name = "matrix-keypad", .id = -1, .dev = { .platform_data = &mkpMatrixKeypadPlatformData, }, };
设备注册
可以在平台初始化函数(这里为kernel/arch/arm/plat-s5p4418/topeet/device.c的nxp_board_devices_register()函数)中,通过platform_device_register()函数注册平台总线设备:
//Modification: register matrix keypad for iTpp-4418 #ifdef CONFIG_KEYBOARD_MATRIX printk("plat: add device matrix-keypad (for itop-4418)\n"); platform_device_register(&itop4418_matrix_keypad_device); #endif //End-of-Modification: register matrix keypad for iTpp-4418
使用设备(Qt/E)
查看引脚占用状况:
mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/gpio
应能观察到类似matrix_kbd_col和matrix_kbd_row的GPIO引脚占用。
检查输入事件对应关系:
cat /proc/bus/input/devices
应能观察到Name="matrix-keypad"的项,并记录其Handlers属性中的Event编号。这里假设为event0。
编辑Qt初始化脚本,导出QWS_KEYBOARD变量,指向/dev/input/event0:
export QWS_KEYBOARD="USB:/dev/input/event0"
参考资料
https://blog.csdn.net/Ace_Shiyuan/article/details/110958057
https://blog.csdn.net/jklinux/article/details/73848927