android 4.4 按键分析三 -- 键盘添加
来源:互联网 发布:金蝶软件好用吗 编辑:程序博客网 时间:2024/05/21 04:42
5.1 KeyPad
5.1.1 基本介绍
这部分简单介绍Keypad的基本知识。(图片上传不了,后续再补)
对于输入设备,
一般支持的API功能如下,
分配/释放一个输入设备:
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
注册/注销输入设备:
int __must_check input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
报告输入事件:
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);/* 报告指定type、code的输入事件 */
void input_report_key(struct input_dev *dev, unsigned int code, int value);/* 报告键值 */
void input_report_rel(struct input_dev *dev, unsigned int code, int value);/* 报告相对坐标 */
void input_report_abs(struct input_dev *dev, unsigned int code, int value);/* 报告绝对坐标 */
void input_sync(struct input_dev *dev);/* 报告同步事件 */
Input驱动编写步骤
1.分配一个输入设备;
2.注册一个输入设备;
3.驱动支持什么事件;
Set_bit告诉inout子系统它支持哪些事件
Set_bit(EV_KEY,button_dev.evbit)
Struct input_dev中有两个成员,一个是evbit;一个是keybit.分别用来表示设备所支持的事件类型和按键类型。
4.驱动事件报告;
5.释放和注销设备;
5.1.2 编译相关
对于input子系统的编译处理,在\kernel\drivers的makefile里面我们可以看到,它会编译对应的input目录下的makefile,
对应键盘,在\kernel\drivers\input\keyboard目录下,定义了各种键盘实现,部分实例如下,
系统如何选择合适的驱动文件,在本目录下的makefile里面我们可以看到,如果系统配置了对应的键盘,则编译就添加对应文件,进行支持。
对于手机系统来讲,一般是支持GPIO键盘的,如MTK 6572平台的一款设计,硬件原理图设计如下,使用了系统的KROW0-KROW1,KCOL0-KCOL1,模拟出4个按键,提供诸如侧键等物理按键(本来芯片是支持9个按键的,KROW2和KCOL2被JTAG借用了)。
所以我们接着分析CONFIG_KEYBOARD_GPIO是如何开启来支持GPIO键盘的。在\kernel\arch\arm\configs目录下,定义了各种ARM核的相关配置,可以看到GPIO是在这里配置是否支持的。
至此,就知道了一个支持的键盘文件是如何参与编译的,并延伸的了解到,如果要新增加一个新的键盘文件,我们该如何处理。
5.1.3 代码分析
和Linux通用的驱动处理一样,GPIO的驱动编写也有固定的格式,简单介绍如下,
1)编写基本的驱动函数:
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
.pm = &gpio_keys_pm_ops,
.of_match_table = gpio_keys_of_match,
}
};
根据平台编写格式,给每个设备要编写类似上面的驱动节点,并完成节点里的函数实现。
2)向平台注册:
static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver);
}
static void __exit gpio_keys_exit(void)
{
platform_driver_unregister(&gpio_keys_device_driver);
}
late_initcall(gpio_keys_init);
module_exit(gpio_keys_exit);
在驱动编写中,一般在文件最后写上类似下面的代码,完成驱动模块的平台注册。
module_init(gpio_keys_init);
module_exit(gpio_keys_exit);
当模块加载(insmod)或内核引导过程中,gpio_keys_init函数会被调用。首先做的工作是获取能够正确控制硬件设备的硬件资源(例如内存、IO内存、中断和DMA);在系统退出时,gpio_keys_exit会被调用。
对于gpio_keys_probe,它是一个关键的函数,用来检测按键,说明如下,
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
const 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(); //申请一个input设备
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);
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;
//描述input设备节点属性,最后添加eventHup里的节点列表,可以通过log了解到实际相关设置如下,表明这个GPIO键盘设备的节点名字为/dev/input/event4,在节点列表中id为2,并使用的Keylayout和KeyChars设置如下
New device: id=2, fd=121, path='/dev/input/event4', name='mtk-tpd-kpd', classes=0x1, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false, usingSuspendBlockIoctl=true, usingClockIoctl=true
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) {
const struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
error = gpio_keys_setup_key(pdev, input, bdata, button);
if (error)
goto fail2;
if (button->wakeup)
wakeup = 1;
}
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);//设备注册,并和对应的handler处理函数挂钩
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",
error);
goto fail3;
}
/* get current state of buttons that are connected to GPIOs */
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (gpio_is_valid(bdata->button->gpio))
gpio_keys_gpio_report_event(bdata);//这里是中断引起的事件报告,通过gpio_keys_gpio_report_event,传递给input_event,再到input_handle_event,经过check,再通过input_pass_event,获取到对应的handler,用handler->event将事件传递给用户空间。
}
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)
gpio_remove_key(&ddata->data[i]);
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;
}
实际上Keypad驱动的实现依附于Input输入子系统,其完整流程比较复杂,这里只简单分析一下流程,主要是描述键盘按键是如何从驱动传递到界面的。
- android 4.4 按键分析三 -- 键盘添加
- android 4.4 按键分析四--键盘添加
- android 4.4 按键分析三
- android:添加usb键盘+按键布局和映射的修改
- android:添加usb键盘+按键布局和映射的修改
- android:添加usb键盘+按键布局和映射的修改
- android:添加usb键盘+按键布局和映射的修改
- android:添加usb键盘+按键布局和映射的修改
- android 4.4 添加物理按键
- 蓝牙键盘按键添加方法
- android 按键、键盘移植
- android 键盘按键监听
- android 键盘按键监听
- android 4.4 按键分析二
- android 4.4 按键分析一
- android 4.4 按键分析二
- android模拟器按键对应的键盘按键
- Android模拟器按键对应的键盘按键
- 关于前端的优化的一点感受
- tensorflow学习笔记一:安装调试
- Flink源码解读--FlinkKafkaConsumer09
- 一个实现ajax之后既可以刷新又可以让提示信息延长的js实现方法
- control中的invoke、begininvoke
- android 4.4 按键分析三 -- 键盘添加
- 8 C++线程与并发
- Docker 在分布式和大数据框架中的应用
- Innodb Status源码分析
- oracle笔记
- V4.0系列软件如何替换授权文件
- 什么是Promise
- [Leetcode] Contains Duplicate II
- $.each(index,el)方法使用(jQuery)