linux gpio_keys.c 分析

网上有好多的关于linux driver gpio_keys.c的分析,这里就不多赘述了。

在这里主要写一下自己遇到的思路问题,看了一遍代码深知自己基础太薄弱了。

感觉学了这么长时间的代码,基础都不会了。。。。。。反思中

下面就遇到的问题分析:

gpio_keys_probe 函数刚入口就会调用解析设备树的函数:

gpio_keys_get_devtree_pdata.

static struct gpio_keys_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{
	struct device_node *node, *pp;
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button *button;
	int error;
	int nbuttons;
	int i;

	node = dev->of_node;
	if (!node)
		return ERR_PTR(-ENODEV);

	nbuttons = of_get_child_count(node);
	if (nbuttons == 0)
		return ERR_PTR(-ENODEV);

	pdata = devm_kzalloc(dev,
			     sizeof(*pdata) + nbuttons * sizeof(*button),
			     GFP_KERNEL);
	if (!pdata)
		return ERR_PTR(-ENOMEM);

	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
	pdata->nbuttons = nbuttons;

	pdata->rep = !!of_get_property(node, "autorepeat", NULL);

	i = 0;
	for_each_child_of_node(node, pp) {
		enum of_gpio_flags flags;

		button = &pdata->buttons[i++];

		button->gpio = of_get_gpio_flags(pp, 0, &flags);
		if (button->gpio < 0) {
			error = button->gpio;
			if (error != -ENOENT) {
				if (error != -EPROBE_DEFER)
					dev_err(dev,
						"Failed to get gpio flags, error: %d\n",
						error);
				return ERR_PTR(error);
			}
		} else {
			button->active_low = flags & OF_GPIO_ACTIVE_LOW;
		}

		button->irq = irq_of_parse_and_map(pp, 0);

		if (!gpio_is_valid(button->gpio) && !button->irq) {
			dev_err(dev, "Found button without gpios or irqs\n");
			return ERR_PTR(-EINVAL);
		}

		if (of_property_read_u32(pp, "linux,code", &button->code)) {
			dev_err(dev, "Button without keycode: 0x%x\n",
				button->gpio);
			return ERR_PTR(-EINVAL);
		}

		button->desc = of_get_property(pp, "label", NULL);

        /* 判断当前设备节点是否设置input子系统类型, 如果设置,跳过赋值button type为 key类型*/
		if (of_property_read_u32(pp, "linux,input-type", &button->type))
			button->type = EV_KEY;

        /* 判断当前设备节点是否设置(gpio-key,wakeup),
         在指定gpio-key,wakeup查找是否有指定gpio-key,wakeup的value,
         如果存在这gpio-key,wakeup,则返回这个gpio-key,wakeup中的value
         gpio-key,wakeup:布尔值,按钮可唤醒系统                      
         由于取了 !! 操作,即 button->wakeup 只有bool值类型,
         button->can_disable 同样如此
        */
		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);

		button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);

		if (of_property_read_u32(pp, "debounce-interval",
					 &button->debounce_interval))
			button->debounce_interval = 5;
	}

	if (pdata->nbuttons == 0)
		return ERR_PTR(-EINVAL);

	return pdata;
}

if (of_property_read_u32(pp, "linux,input-type", &button->type))

of_property_read_u32,这个函数当匹配到:

linux,input-type时候函数返回0,其他返回错误值,关键我们dts里面就没有配置,所以of_property_read_u32 这个返回值是负值。但是if 条件的语句是判断真假的条件,只有if (0) 不进入循环,其他的比如 :if (-23) 也是会进去的。所以这个判断就是没有设置input 子系统的type类型,则直接赋值为 KEY。

button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);

of_get_property,这个函数使用:

当时理解成获取到gpio-key,wakeup 这个不应该先返回0,然后两次去非,不就还是0吗???

这个理解是错误的,因为这个函数的返回类型和上面是不一样的,他返回的类型是相当于返回

gpio-key,wakeup这个属性的值,就是他的value,但是我们dts并没有配置value额,这个怎么理解?

通过打印,发现: 只要这个属性值配置上,后面的value有没有值, 然后取!,都是为0的,

这个意思就很明显了。

Linux code 当中 如果想要设置某个dts的bool变量值,只需要加上这个属性值,不管设不设置value值,直接在of_get_property 取两次!,就可以配置相应的值了。

关于这个函数的理解有错误,望指正。

    gpio-keys {
		compatible = "gpio-keys";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_gpio_key>;

		user {
			label = "User Button";
			gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
			gpio-key,wakeup;
			linux,code = <KEY_1>;
		};
    };
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值