16 内核里gpio-keys设备驱动的设备树描述
来源:互联网 发布:小米关闭软件自动更新 编辑:程序博客网 时间:2024/05/16 14:28
此设备驱动适用于连接到一个具有中断功能的io口的按键驱动.
使用platform_device方法可参考:http://blog.csdn.net/jklinux/article/details/73828786
此设备驱动在内核里配置:
make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Device Drivers ---> Input device support ---> [*] Keyboards ---> <*> GPIO Buttons驱动源码在: drivers/input/keyboard/gpio_keys.c
898 static struct platform_driver gpio_keys_device_driver = {899 .probe = gpio_keys_probe,900 .remove = gpio_keys_remove,901 .driver = {902 .name = "gpio-keys",903 .pm = &gpio_keys_pm_ops,904 .of_match_table = gpio_keys_of_match,905 }906 };722 static const struct of_device_id gpio_keys_of_match[] = {723 { .compatible = "gpio-keys", },724 { },725 };726 MODULE_DEVICE_TABLE(of, gpio_keys_of_match);通过上面两部分内容可以得知,在设备树里设备节点的compatible属性值应为"gpio-keys".
当匹配上时, gpio_keys_probe函数就会被触发调用,获取设备提供的资源.728 static int gpio_keys_probe(struct platform_device *pdev)729 {730 struct device *dev = &pdev->dev;731 const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);732 struct fwnode_handle *child = NULL;733 struct gpio_keys_drvdata *ddata;734 struct input_dev *input;735 size_t size;736 int i, error;737 int wakeup = 0;738 739 if (!pdata) {740 pdata = gpio_keys_get_devtree_pdata(dev); //获取设备树里设备节点提供的资源741 if (IS_ERR(pdata))742 return PTR_ERR(pdata);743 }744 745 size = sizeof(struct gpio_keys_drvdata) +746 pdata->nbuttons * sizeof(struct gpio_button_data);747 ddata = devm_kzalloc(dev, size, GFP_KERNEL);748 if (!ddata) {749 dev_err(dev, "failed to allocate state\n");750 return -ENOMEM;751 }752 753 ddata->keymap = devm_kcalloc(dev,754 pdata->nbuttons, sizeof(ddata->keymap[0]),755 GFP_KERNEL);756 if (!ddata->keymap)757 return -ENOMEM;758 759 input = devm_input_allocate_device(dev);760 if (!input) {761 dev_err(dev, "failed to allocate input device\n");762 return -ENOMEM;763 }764 ... //初始化input_dev对象的成员788 if (pdata->rep)789 __set_bit(EV_REP, input->evbit);790 791 for (i = 0; i < pdata->nbuttons; i++) {792 const struct gpio_keys_button *button = &pdata->buttons[i];793 794 if (!dev_get_platdata(dev)) {795 child = device_get_next_child_node(dev, child); //获取设备节点里的子节点 ...803 804 error = gpio_keys_setup_key(pdev, input, ddata,805 button, i, child); //根据子节点提供的属性值设置input_dev对象所支持的键码 ...813 } ...824 error = input_register_device(input); ...
659 static struct gpio_keys_platform_data *660 gpio_keys_get_devtree_pdata(struct device *dev)661 {662 struct gpio_keys_platform_data *pdata;663 struct gpio_keys_button *button;664 struct fwnode_handle *child;665 int nbuttons;666 667 nbuttons = device_get_child_node_count(dev);668 if (nbuttons == 0)669 return ERR_PTR(-ENODEV);//意味着需要通过设备节点的子节点来提供资源 ...681 682 pdata->rep = device_property_read_bool(dev, "autorepeat");683 //表示设备节点可以有一个autorepeat属性,属性值为bool类型(0/1). 用于表示输入设备是否自动间隔地重复提交按键.684 device_property_read_string(dev, "label", &pdata->name);685 //表示设备节点可以有一个label属性, 属性性为string类型.用于指定输入设备的名字686 device_for_each_child_node(dev, child) { //遍历子节点687 if (is_of_node(child))688 button->irq =689 irq_of_parse_and_map(to_of_node(child), 0);690 691 if (fwnode_property_read_u32(child, "linux,code",692 &button->code)) {693 dev_err(dev, "Button without keycode\n");694 fwnode_handle_put(child);695 return ERR_PTR(-EINVAL); //意味着每个子节点都必须有"linux,code"属性,属性值为u32类型。用于指定此子节点对应的按键的键码.696 }697 698 fwnode_property_read_string(child, "label", &button->desc);699 //每个子节点还可以有一个label属性,属性值为string类型700 if (fwnode_property_read_u32(child, "linux,input-type",701 &button->type))702 button->type = EV_KEY; //每个字节点还可以通过"linux,input-type"属性来指定输入设备所支持的事件类型. 如果不提供则设置为EV_KEY703 704 button->wakeup =705 fwnode_property_read_bool(child, "wakeup-source") ||706 /* legacy name */707 fwnode_property_read_bool(child, "gpio-key,wakeup");708 709 button->can_disable =710 fwnode_property_read_bool(child, "linux,can-disable");711 712 if (fwnode_property_read_u32(child, "debounce-interval",713 &button->debounce_interval))714 button->debounce_interval = 5; //如是中断触发的按键,则"debounce-interval"属性无需设置,如是定时轮询方式的则需要设置此间隔时间.715 716 button++;717 }718 719 return pdata;720 }
当在probe函数里遍历每个子节点时,会调用gpio_keys_setup_key函数来设置并获取io口信息.468 static int gpio_keys_setup_key(struct platform_device *pdev,469 struct input_dev *input,470 struct gpio_keys_drvdata *ddata,471 const struct gpio_keys_button *button,472 int idx,473 struct fwnode_handle *child)474 { ...486 487 if (child) {488 bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,489 child,490 GPIOD_IN,491 desc); // con_id为NULL, 则表示子节点里应用gpios属性来提供io口资源.
如板上有两个按键,一个按键接PA12(作键盘上的UP键), 另一个接PA11(作键盘上的ENTER键).设备树里的设备节点:mykeys { compatible = "gpio-keys"; autorepeat = <1>; label = "mykeys"; btn0 { label = "btn0"; gpios = <&pio 0 12 GPIO_ACTIVE_HIGH>; linux,code = <KEY_UP>; }; btn1 { label = "btn1"; gpios = <&pio 0 11 GPIO_ACTIVE_HIGH>; linux,code = <KEY_ENTER>; }; };
更新使用设备树,重启系统后,可以查看到:^_^ / # cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0100N: Name="mykeys"P: Phys=gpio-keys/input0S: Sysfs=/devices/platform/mykeys/input/input1U: Uniq=H: Handlers=kbd event1 B: PROP=0B: EV=100003B: KEY=8000000000 10000000
另如按键所接的IO口是没有中断功能的,则可以使用gpio_keys_polled.c设备驱动.可参考内核源码里的: Documentation/devicetree/bindings/input/gpio-keys.txt Documentation/devicetree/bindings/input/gpio-keys-polled.txt
阅读全文
0 0
- 16 内核里gpio-keys设备驱动的设备树描述
- 15 内核里leds-gpio设备驱动的设备树方法
- 15 内核里leds-gpio设备驱动的设备树方法
- Linux 内核设备驱动之GPIO驱动之GPIO GPIO描述符到GPIO号
- Linux 内核设备驱动之GPIO驱动之GPIO GPIO描述符到GPIO CHIP
- Linux 内核设备驱动之GPIO驱动之GPIO 控制器设备描述
- Linux 内核设备驱动之GPIO驱动之GPIO 获取GPIO描述符
- Linux 内核设备驱动之GPIO驱动之GPIO 由名字到GPIO描述符
- Linux 内核设备驱动之GPIO驱动之GPIO 控制器描述
- Linux 内核设备驱动之GPIO驱动之GPIO 管脚描述
- Linux 内核设备驱动之GPIO驱动之GPIO API
- 26 设备树里mcp2515的描述
- Linux 内核设备驱动之GPIO驱动之GPIO GPIO字符设备初始化
- 24 设备树里描述spi设备
- 44 linux内核里的platform设备驱动模型
- 67 linux内核里的framebuffer设备驱动模型
- 22 使用内核里的at24-eeprom设备驱动
- 09 linux设备树里的gpio应用
- powerbuilder
- open() "/usr/local/nginx/logs/nginx.pid" failed
- Word2003入门动画教程34:将文档打印成PRN格式
- JAVA集合框架
- 判断一个数是否是2的整数次幂,python实现。
- 16 内核里gpio-keys设备驱动的设备树描述
- ios11非越狱如何安装ipa
- Unity Shader--简单的扇形扫描效果
- 优达(Udacity)-机器学习基础-误差原因
- 11月中下旬张家界自由行
- vs2013 调试到空格
- js工具处理之数字转大写格式
- HDFS的一些理解
- React中函数的封装和数据的state数据存储【摄氏度和华氏度转化】