使用Linux的矩阵键盘驱动程序

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_gpioscol_gpios行列GPIO定义指针

row_gpiosrow_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.cnxp_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_colmatrix_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

https://blog.csdn.net/MyArrow/article/details/10582667

https://blog.csdn.net/qq_33205540/article/details/105950700

it
除非特别注明,本页内容采用以下授权方式: Creative Commons Attribution-ShareAlike 3.0 License