linux3.4.0 按键驱动程序分析(pandaboard omap4460)

news/2024/11/24 14:13:07/
linux3.4.0 按键驱动程序分析(pandaboard omap4460)

在内核中,按键的驱动程序已经设计好了,要使自己板上的按键工作起来,需要做的是在相应的文件中添加硬件信息,然后对内核进行正确的配置。

以下先使按键工作起来,再对驱动进行分析。
按键属于输入设备,所以在分析按键驱动之前要先学习input子系统的相关知识

1、内核配置:

Device Drivers ->input device support ->[*] keyboards ->[*] GPIO buttons ->

2、添加硬件信息:
修改文件 /arch/arm/mach-omap2/board-omap4panda.c

第一处:
#include <linux/gpio_keys.h>

第二处:
static struct gpio_keys_button pandaboard_exp_gpio_keys[] = {{.code                           = KEY_HOME, //按键码,需要预先定义.gpio                           = 36, //使用的GPIO口.active_low             = 1,.desc                           = "pandaboard_exp_power",.type                           = EV_KEY, //类型.wakeup                         = 1,.debounce_interval      = 10, //去抖},{.code                           = KEY_PROG1,.gpio                           = 32,.active_low             = 1,.desc                           = "pandaboard_exp_menu",.type                           = EV_KEY,.wakeup                         = 1,.debounce_interval      = 10,},{.code                           = KEY_PROG2,.gpio                           = 38,.active_low             = 1,.desc                           = "pandaboard_exp_back",.type                           = EV_KEY,.wakeup                         = 1,.debounce_interval      = 10,},{.code                           = KEY_PROG3,.gpio                           = 33,.active_low             = 1,.desc                           = "pandaboard_exp_volup",.type                           = EV_KEY,.wakeup                         = 1,.debounce_interval      = 10,},{.code                           = KEY_PROG4,.gpio                           = 37,.active_low             = 1,.desc                           = "pandaboard_exp_voldw",.type                           = EV_KEY,.wakeup                         = 1,.debounce_interval      = 10,},
};
static struct gpio_keys_platform_data pandaboard_exp_gpio_keys_data = {.buttons        = pandaboard_exp_gpio_keys,.nbuttons       = ARRAY_SIZE(pandaboard_exp_gpio_keys),
};static struct platform_device pandaboard_exp_gpio_keys_device = {.name   = "gpio-keys",  //平台设备的名称.id     = -1,.dev    = {.platform_data  = &pandaboard_exp_gpio_keys_data,},
};

第三处:
static struct platform_device *panda_devices[] __initdata = {&pandaboard_exp_gpio_keys_device, //加入到系统平台设备数组中&wl1271_device,&btwilink_device,
};

3、测试
cat /dev/input/event1 ,按下或者抬起按键会在终端输出乱码。

测试应用程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>int main(void)
{int key_fd;int key_value,i=0,count;struct input_event ev_key;key_fd = open("/dev/event1", O_RDWR);if (key_fd < 0) {perror("open device keys");exit(1);}while (1) {count = read(key_fd,&ev_key,sizeof(struct input_event));for(i=0; i<(int)count/sizeof(struct input_event); i++){if(EV_KEY==ev_key.type)printf("type:%d, code:%d, value:%d", ev_key.type, ev_key.code, ev_key.value);}}close(key_fd);return 0;
} 

驱动程序分析:
代码位置:/drivers/input/keyboard/gpio_keys.c

//模块加载函数
static int __init gpio_keys_init(void)
{return platform_driver_register(&gpio_keys_device_driver); //注册平台驱动
}

//平台驱动结构体的定义
static struct platform_driver gpio_keys_device_driver = {.probe = gpio_keys_probe, //探测函数,在驱动找到对应的设备时执行.remove = __devexit_p(gpio_keys_remove),.driver = {.name = "gpio-keys", //驱动名称 ,可以在 /sys/ 下找到.owner = THIS_MODULE,.pm = &gpio_keys_pm_ops, //操作函数集.of_match_table = gpio_keys_of_match,}
};

//探测函数
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; //获取平台设备的相关数据struct gpio_keys_drvdata *ddata;struct device *dev = &pdev->dev;struct gpio_keys_platform_data alt_pdata;struct input_dev *input;int i, error;int wakeup = 0;if (!pdata) {error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);if (error)return error;pdata = &alt_pdata;}ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + pdata->nbuttons * sizeof(struct gpio_button_data),GFP_KERNEL);input = input_allocate_device(); //分配一个输入设备结构体if (!ddata || !input) {dev_err(dev, "failed to allocate state\n");error = -ENOMEM;goto fail1;}
//对驱动结构体赋值ddata->input = input;ddata->n_buttons = pdata->nbuttons;ddata->enable = pdata->enable;ddata->disable = pdata->disable;mutex_init(&ddata->disable_lock);platform_set_drvdata(pdev, ddata);input_set_drvdata(input, ddata);
//对输入设备机构体进行赋值,这些值都可以在系统启动后在 /sys/ 下找到对应项input->name = pdata->name ? : pdev->name;input->phys = "gpio-keys/input0";input->dev.parent = &pdev->dev;input->open = gpio_keys_open;input->close = gpio_keys_close;input->id.bustype = BUS_HOST;input->id.vendor = 0x0001;input->id.product = 0x0001;input->id.version = 0x0100;
/* Enable auto repeat feature of Linux input subsystem */if (pdata->rep)__set_bit(EV_REP, input->evbit);
// 依次对每个按键进行设置for (i = 0; i < pdata->nbuttons; i++) {struct gpio_keys_button *button = &pdata->buttons[i];struct gpio_button_data *bdata = &ddata->data[i];unsigned int type = button->type ?: EV_KEY;
		bdata->input = input;bdata->button = button;
//设置按键,相当于初始化,主要工作是申请gpio、设置为输入、设置防抖动时间、中断申请error = gpio_keys_setup_key(pdev, bdata, button);if (error)goto fail2;if (button->wakeup)wakeup = 1;input_set_capability(input, type, button->code); //对输入设备进行类型和码的设置,}error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); //设置属性并创建接口if (error) {dev_err(dev, "Unable to export keys/switches, error: %d\n",error);goto fail2;}error = input_register_device(input); //注册输入设备if (error) {dev_err(dev, "Unable to register input device, error: %d\n",error);goto fail3;}/* get current state of buttons */for (i = 0; i < pdata->nbuttons; i++) //报告事件gpio_keys_report_event(&ddata->data[i]);input_sync(input);device_init_wakeup(&pdev->dev, wakeup);return 0;fail3:sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
fail2:while (--i >= 0) {free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);if (ddata->data[i].timer_debounce)del_timer_sync(&ddata->data[i].timer);cancel_work_sync(&ddata->data[i].work);gpio_free(pdata->buttons[i].gpio);}platform_set_drvdata(pdev, NULL);
fail1:input_free_device(input);kfree(ddata);
/* If we have no platform_data, we allocated buttons dynamically. */if (!pdev->dev.platform_data)kfree(pdata->buttons);return error;
}

中断处理函数:
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{struct gpio_button_data *bdata = dev_id;struct gpio_keys_button *button = bdata->button;BUG_ON(irq != gpio_to_irq(button->gpio));if (bdata->timer_debounce)mod_timer(&bdata->timer,jiffies + msecs_to_jiffies(bdata->timer_debounce));elseschedule_work(&bdata->work);return IRQ_HANDLED;
}

工作流程:
按键触发->gpio_keys_isr->schedule_work(&bdata->work)->gpio_keys_work_func()->gpio_keys_report_event()报告事件
其中work的初始化在gpio_keys_setup_key()函数中:INIT_WORK(&bdata->work, gpio_keys_work_func);




http://www.ppmy.cn/news/527518.html

相关文章

STM32HAL库驱动MPU6050

STM32HAL库驱动MPU6050 STM32CubeMX配置 System Core->RCC->HSE->Crystal/Ceramic Resonator System Core->SYS->Debug->Serial Wire Connectivity->I2C1->I2C->I2C 这里使用PB6/PB7分别作为IIC1的SCL时钟线/SDA数据线&#xff0c;可以分别设置…

异核通信框架(1)——SMP和AMP架构

0.前言 我是菜鸡&#xff0c;很久没有发表文章了。老样子&#xff0c;今天推荐一本书《局外人》。别像主人公似的认为任何事情都没有意义。 目录 1. SMP和 AMP架构 1.1 同构和异构 1.1.1 同构 1.1.2 异构 1.2 SMP和AMP 1.2.1 对称多处理结构(SMP) 1.2.2 非对称多处理…

OPC DA的DCom配置

目录 一、OPC DA的Dcom配置文档 1.1、OPCDA的DCOM配置PDF文档下载 1.2、DCOM在线参考配置&#xff08;英文版&#xff09; 二、配置OPC DA准备内容 2.1、说明 2.2、OPC运行库 三、配置OPC DA操作流程 3.1、创建用户并赋予访问权限 3.2、修改操作系统 Firewall&#xf…

STM32 HAL库编写MPU6050输出六轴原始数据, 移植DMP输出自身姿态角,欧拉角

--------------------------------------------------------- 记录自学过程 ------------------------------------------------------------- 可能有些说明不对的地方&#xff0c;请大家提出来&#xff0c;共同解决 .共同学习 .共同进步. | 程序链接(主函数读取版) | 程序链接…

六轴加速陀螺仪MPU6500/MPU6050使用及DMP库移植,含记步器功能

本篇博客为博主学习使用MPU6500完成后的学习记录&#xff0c;故在这只做主要讲解&#xff0c;如有博友看完后仍不知如何使用&#xff0c;可在下方留言问我&#xff0c;或发邮件问我&#xff08;dayou1024qq.com&#xff09;&#xff0c;因邮件有QQ和微信提示&#xff0c;故我能…

hdl_graph_slam三维激光雷达+GPS+IMU+ODOM

系统ubuntu16.04 源代码位置参考&#xff1a;https://github.com/koide3/hdl_graph_slam 知乎里的算法解析说的很详细&#xff1a;https://zhuanlan.zhihu.com/p/89014435 hdl_graph_slam是由日本风桥科技大学的Kenji Koide在github上开源的六自由度三维激光SLAM算法。主要由…

OMAPL138EZCED4E

OMAPL138EZCED4E 规格 产品属性 制造商:Texas Instruments 产品种类:数字信号处理器和控制器 - DSP, DSC RoHS: 详细信息 产品:DSPs 系列:OMAP-L138 商标名:OMAP 安装风格:SMD/SMT 封装 / 箱体:PBGA-361 核心:ARM926EJ-S, C674x 内核数量:2 Core 比较大时钟频率:456 MHz, 456 M…

ov5640摄像头驱动的开发过程

对于在Linux下OV5640摄像头驱动开发的过程。 硬件连接电路设计 &#xff08;1&#xff09;OMAP4 通过 CSI2 接口连接 OV5640 传感器&#xff08;MIPI 标准&#xff09;&#xff0c;使用三组差分信 号&#xff0c;其中一组差分传送时钟&#xff0c;另两组差分传送数据信号。一…