I.MX6 gpio-keys driver hacking
/***************************************************************************** I.MX6 gpio-keys driver hacking* 说明:* 1. 本文解读gpio-keys驱动是如何注册,最终处理函数在哪里。* 2. 从最后生成的设备节点来看,我们直接可以通过操作该设备节点来来让系统* 进行相关操作,譬如关机、挂起等操作。** 2016-3-17 深圳 南山平山村 曾剑锋***************************************************************************/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, | | #ifdef CONFIG_PM | |.pm = &gpio_keys_pm_ops, | | #endif | |} | | }; | || | 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); | | } | || | module_init(gpio_keys_init); -------------+ | module_exit(gpio_keys_exit); || MODULE_LICENSE("GPL"); | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); | MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); | MODULE_ALIAS("platform:gpio-keys"); || 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 input_dev *input;int i, error;int wakeup = 0;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);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;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); |+---------------------------------------+return error; | } |V static int __devinit gpio_keys_setup_key(struct platform_device *pdev,struct gpio_button_data *bdata,struct gpio_keys_button *button) {const char *desc = button->desc ? button->desc : "gpio_keys";struct device *dev = &pdev->dev;unsigned long irqflags;int irq, error;setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);INIT_WORK(&bdata->work, gpio_keys_work_func); --------------------+|error = gpio_request(button->gpio, desc); |if (error < 0) { |dev_err(dev, "failed to request GPIO %d, error %d\n", |button->gpio, error); |goto fail2; |} ||error = gpio_direction_input(button->gpio); |if (error < 0) { |dev_err(dev, "failed to configure" |" direction for GPIO %d, error %d\n", |button->gpio, error); |goto fail3; |} ||if (button->debounce_interval) { |error = gpio_set_debounce(button->gpio, |button->debounce_interval * 1000); |/* use timer if gpiolib doesn't provide debounce */ |if (error < 0) |bdata->timer_debounce = button->debounce_interval; |} ||irq = gpio_to_irq(button->gpio); |if (irq < 0) { |error = irq; |dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", |button->gpio, error); |goto fail3; |} ||irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; |/* |* If platform has specified that the button can be disabled, |* we don't want it to share the interrupt line. |*/ |if (!button->can_disable) |irqflags |= IRQF_SHARED; |/* |* Resume power key early during syscore instead of at device |* resume time. |* Some platform like Android need to konw the power key is pressed |* then to reume the other devcies |*/ |if (button->wakeup) |irqflags |= IRQF_NO_SUSPEND | IRQF_EARLY_RESUME; ||error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); |if (error < 0) { |dev_err(dev, "Unable to claim irq %d; error %d\n", |irq, error); |goto fail3; |} ||return 0; || fail3: |gpio_free(button->gpio); | fail2: |return error; | } || static void gpio_keys_work_func(struct work_struct *work) <-------------+ {struct gpio_button_data *bdata =container_of(work, struct gpio_button_data, work);gpio_keys_report_event(bdata); -----------+ } || static void gpio_keys_report_event(struct gpio_button_data *bdata) <---------+ {struct gpio_keys_button *button = bdata->button;struct input_dev *input = bdata->input;unsigned int type = button->type ?: EV_KEY;int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;printk("zengjf check gpio-keys positon: %s in line %d.\n", __func__, _LINE__);if (type == EV_ABS) {if (state)input_event(input, type, button->code, button->value);} else {input_event(input, type, button->code, !!state);}input_sync(input); }/*** root@android:/ # cat /proc/bus/input/devices * I: Bus=0019 Vendor=0001 Product=0001 Version=0100* N: Name="gpio-keys"* P: Phys=gpio-keys/input0* S: Sysfs=/devices/platform/gpio-keys/input/input0* U: Uniq=* H: Handlers=event0 * B: PROP=0* B: EV=3* B: KEY=100000 0 0 0* ......*/
转载于:https://www.cnblogs.com/zengjfgit/p/5287784.html
I.MX6 gpio-keys driver hacking相关推荐
- I.MX6 ar1020 SPI device driver hacking
/************************************************************************************* I.MX6 ar1020 ...
- I.MX6 bq27441 driver hacking
/************************************************************************** I.MX6 bq27441 driver hac ...
- I.MX6 Power off register hacking
/************************************************************************ I.MX6 Power off register h ...
- 休眠后gpio状态_1.Linux电源管理-休眠与唤醒
1.休眠方式 在内核中,休眠方式有很多种,可以通过下面命令查看 常用的休眠方式有freeze,standby, mem, disk freeze:冻结I/O设备,将它们置于低功耗状态,使处理器进入空闲 ...
- R40使用GPIO中断实现按键功能【原创】
采用创建input的方式 可以通过 cat /proc/bus/input/devices 查看生成的input设备对应的event句柄,比如 I: Bus=0019 Vendor=0001 Prod ...
- Linux GPIO键盘驱动开发记录_OMAPL138
Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...
- zynq学习05 Zynq 7000 emio的gpio操作
http://m.blog.csdn.net/article/details?id=44566855 本文讲述怎样使用emio功能的gpio,涉及到fpga部分,软件涉及到一级引导程序fsbl的创建及 ...
- linux内核中的GPIO系统之(2):pin control subsystem
一.前言 在linux2.6内核上工作的嵌入式软件工程师在pin control上都会遇到这样的状况: (1)启动一个新的项目后,需要根据硬件平台的设定进行pin control相关的编码.例如:在b ...
- 设备树与驱动的关系_Linux CommonClock Framework分析之四 gpio clk gate驱动实现
前面我们已经完成了CCF子系统的分析,也说明了如何实现CCF驱动,本章为该专栏的最后一篇文章, 本章我们将实现一个虚拟的gpio clk gate驱动.本章大概分为如下几个章节: 一. 本次驱动开发涉 ...
最新文章
- 为什么Java里面没有 SortedList
- 关于 std::set/std::map 的几个为什么
- [Swift通天遁地]五、高级扩展-(4)快速生成Invert、Mix、Tint、Shade颜色及调整饱和度阶...
- c语言宏定义数组_利用数组处理批量数据 C语言程序编写定义与利用数组技巧全归纳...
- 物联网卡如何帮助农民提高收益
- Queue与生产者消费者模型
- 美学心得(第二百三十六集) 罗国正
- 使用docker安装Jenkins教程
- Qt自定义实现的日历控件
- foxmail邮箱怎么导入邮件_将Foxmail邮件智能导入Outlook
- ICP备案线下注销 网站域名备案注销
- java 加水印_Java添加水印(图片水印,文字水印)
- xp计算机workgroup无法访问,无法访问,小编告诉你怎么解决workgroup无法访问
- np.randon模块,numpy.random模块各函数功能详解,分类描述各个函数功能,生成随机数
- 社区综合管理系统springboot+vue
- instanceof java 报错_java中instanceof怎么理解?java中instanc 爱问知识人
- [AGC043-B]Merge Triplets
- python爬虫精选11集(selenium进阶总结【selenium的cookies处理、ip代理、useragent替换】)
- win10连Android机,win10系统Android手机或iPhone连接的操作方法
- 2020_KDD_Dual Channel Hypergraph Collaborative Filtering
热门文章
- libaio源码安装_MySQL5.7.17 编译安装及二进制安装详解
- graphpad prism显著性差异分析_【市场表现】2020年第三季度企业债利差分析
- 帧起始定界符_检测帧起始定界符的方法、装置、设备及计算机存储介质与流程...
- python 长时间运行 会停止_如何“停止”和“恢复”长时间运行Python脚本?
- html 倒计时字体消失,最简单的一个网页倒计时代码 时间到期后会显示出提醒内容 收藏版...
- python如何访问对象的属性_Python:从存储在字典中的对象访问对象属性
- jinja Comments
- DataFrame 排序
- 数据结构之基于Java的顺序列表实现
- java createchannel_【原创】java NIO FileChannel 学习笔记 新建一个FileChannel