/*****************************************************************************                   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相关推荐

  1. I.MX6 ar1020 SPI device driver hacking

    /************************************************************************************* I.MX6 ar1020 ...

  2. I.MX6 bq27441 driver hacking

    /************************************************************************** I.MX6 bq27441 driver hac ...

  3. I.MX6 Power off register hacking

    /************************************************************************ I.MX6 Power off register h ...

  4. 休眠后gpio状态_1.Linux电源管理-休眠与唤醒

    1.休眠方式 在内核中,休眠方式有很多种,可以通过下面命令查看 常用的休眠方式有freeze,standby, mem, disk freeze:冻结I/O设备,将它们置于低功耗状态,使处理器进入空闲 ...

  5. R40使用GPIO中断实现按键功能【原创】

    采用创建input的方式 可以通过 cat /proc/bus/input/devices 查看生成的input设备对应的event句柄,比如 I: Bus=0019 Vendor=0001 Prod ...

  6. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  7. zynq学习05 Zynq 7000 emio的gpio操作

    http://m.blog.csdn.net/article/details?id=44566855 本文讲述怎样使用emio功能的gpio,涉及到fpga部分,软件涉及到一级引导程序fsbl的创建及 ...

  8. linux内核中的GPIO系统之(2):pin control subsystem

    一.前言 在linux2.6内核上工作的嵌入式软件工程师在pin control上都会遇到这样的状况: (1)启动一个新的项目后,需要根据硬件平台的设定进行pin control相关的编码.例如:在b ...

  9. 设备树与驱动的关系_Linux CommonClock Framework分析之四 gpio clk gate驱动实现

    前面我们已经完成了CCF子系统的分析,也说明了如何实现CCF驱动,本章为该专栏的最后一篇文章, 本章我们将实现一个虚拟的gpio clk gate驱动.本章大概分为如下几个章节: 一. 本次驱动开发涉 ...

最新文章

  1. 为什么Java里面没有 SortedList
  2. 关于 std::set/std::map 的几个为什么
  3. [Swift通天遁地]五、高级扩展-(4)快速生成Invert、Mix、Tint、Shade颜色及调整饱和度阶...
  4. c语言宏定义数组_利用数组处理批量数据 C语言程序编写定义与利用数组技巧全归纳...
  5. 物联网卡如何帮助农民提高收益
  6. Queue与生产者消费者模型
  7. 美学心得(第二百三十六集) 罗国正
  8. 使用docker安装Jenkins教程
  9. Qt自定义实现的日历控件
  10. foxmail邮箱怎么导入邮件_将Foxmail邮件智能导入Outlook
  11. ICP备案线下注销 网站域名备案注销
  12. java 加水印_Java添加水印(图片水印,文字水印)
  13. xp计算机workgroup无法访问,无法访问,小编告诉你怎么解决workgroup无法访问
  14. np.randon模块,numpy.random模块各函数功能详解,分类描述各个函数功能,生成随机数
  15. 社区综合管理系统springboot+vue
  16. instanceof java 报错_java中instanceof怎么理解?java中instanc 爱问知识人
  17. [AGC043-B]Merge Triplets
  18. python爬虫精选11集(selenium进阶总结【selenium的cookies处理、ip代理、useragent替换】)
  19. win10连Android机,win10系统Android手机或iPhone连接的操作方法
  20. 2020_KDD_Dual Channel Hypergraph Collaborative Filtering

热门文章

  1. libaio源码安装_MySQL5.7.17 编译安装及二进制安装详解
  2. graphpad prism显著性差异分析_【市场表现】2020年第三季度企业债利差分析
  3. 帧起始定界符_检测帧起始定界符的方法、装置、设备及计算机存储介质与流程...
  4. python 长时间运行 会停止_如何“停止”和“恢复”长时间运行Python脚本?
  5. html 倒计时字体消失,最简单的一个网页倒计时代码 时间到期后会显示出提醒内容 收藏版...
  6. python如何访问对象的属性_Python:从存储在字典中的对象访问对象属性
  7. jinja Comments
  8. DataFrame 排序
  9. 数据结构之基于Java的顺序列表实现
  10. java createchannel_【原创】java NIO FileChannel 学习笔记 新建一个FileChannel