gpio-keys驱动程序的使用

目录

gpio_keys说明

内核部分

应用部分


gpio_keys说明

key是嵌入式开发中常用到的东西,linux内核中也早已为我们做了一套成熟的机制。

gpio-keys是基于input架构实现的一个通用GPIO按键驱动。该驱动基于platform_driver架构,实现了驱动和设备分离,符合Linux设备驱动模型的思想。


内核部分

linux内核驱动文件:

drivers/input/keyboard/gpio_keys.c 

实现了一个体系结构无关的GPIO按键驱动,使用此按键驱动,只需在相应的设备树定义相关的数据即可。

dts部分修改(方法一):

  key-pwr {
		compatible = "gpio-keys";
		autorepeat;

		pinctrl-names = "default";
		pinctrl-0 = <&pwr_key>;

		power {
			label = "GPIO Key Power";
			linux,code = <KEY_POWER>;
			gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
			debounce-interval = <15>;
			wakeup-source;
		};
	};

	key-home {
		compatible = "gpio-keys";
		autorepeat;

		pinctrl-names = "default";
		pinctrl-0 = <&home_key>;

		home {
			label = "GPIO Home";
			linux,code = <KEY_HOME>;
			gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_LOW>;
			debounce-interval = <15>;
		};
	};

&pinctrl {

    pinctrl-names = "default";

	buttons {
		home_key: home-key {
			rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO  &pcfg_pull_up>;
		};
		pwr_key: pwr-key {
			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
		};
};

方法二:

gpio-keys {
	compatible = "gpio-keys";
	autorepeat;

	pinctrl-names = "default";
	pinctrl-0 = <&s8_keys>;

	power {
		gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>;
		linux,code = <KEY_POWER>;
		label = "GPIO Key Power";
		debounce-interval = <20>;
	};

	home {
		gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>;
		linux,code = <KEY_HOME>;
		label = "GPIO Key Home";
		debounce-interval = <20>;
	};
};


&pinctrl {
	pinctrl-names = "default";
	
	pinctrl-0 = <&pwr_hold &default_gpios>;

	buttons {
		s8_keys: s8-keys {
			rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
					<1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
	};
		
};

相关配置说明可以看内核说明文档:

kernel/Documentation/devicetree/bingings/input/gpio-keys.txt(RK举例)

1. compatible 属性值一定要设置为“gpio-keys”。

2. autorepeat 支持按键自动重复

3. 所有的 KEY 都是 gpio-keys 的子节点,每个子节点可以用如下属性描述自己:

gpios:所连接的 GPIO 信息。

interrupts:KEY 所使用 GPIO 中断信息,不是必须的,可以不写。

label:KEY 名字

linux,code:KEY 要模拟的按键可以直接填数字

wakeup-source:可以被唤醒

debounce-interval:消抖时间,单位毫秒

linux,input-type:事件类型,默认<1> == EV_KEY


应用部分

  • 查看读取event

   方法一:

   /sys/class/input/inputX/name 或者/sys/class/input/eventX/device/name    如果与节点 key-pwr key-home一致

  方法二:

  /sys/class/input/inputX/name 或者/sys/class/input/eventX/device/name  如果与节点 gpio-keys一致

   

  对应设备/dev/input/eventX

  • 查看文件内容

   hexdump /dev/input/eventX

  • 具体应用实现

   可通过epoll监听

 

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gpio-keys 是 Linux 内核中的一个模块,用于将 GPIO 按键映射为键盘上的按键,以便用户可以使用 GPIO 按键来与系统进行交互。在本文中,我将对 gpio-keys 模块的代码进行分析。 首先,我们需要了解的是 gpio-keys 模块的注册和注销过程。在模块初始化期间,我们需要调用 `gpio_keys_probe()` 函数来注册模块,该函数会注册一个 platform 设备,并将其与 gpio_keys_driver 结构体相关联。这个结构体包含了模块的名称、ID、设备树匹配以及一些回调函数。注册完成后,内核就会调用 `gpio_keys_irq()` 函数来设置 GPIO 中断并处理按键事件。 下面是 `gpio_keys_probe()` 函数的代码: ```c static int gpio_keys_probe(struct platform_device *pdev) { struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_button *button; struct input_dev *input; int error, i; ... /* Allocate input device */ input = input_allocate_device(); if (!input) { dev_err(&pdev->dev, "Failed to allocate input device\n"); error = -ENOMEM; goto err_free_desc; } /* Set input device properties */ input->name = pdata->input_name ?: "gpio-keys"; input->dev.parent = &pdev->dev; set_bit(EV_KEY, input->evbit); for (i = 0, button = pdata->buttons; i < pdata->nbuttons; i++, button++) { input_set_capability(input, EV_KEY, button->code); } /* Register input device */ error = input_register_device(input); if (error) { dev_err(&pdev->dev, "Failed to register input device\n"); goto err_free_dev; } /* Allocate and configure gpio_keys_device */ gkd = devm_kzalloc(&pdev->dev, sizeof(*gkd), GFP_KERNEL); if (!gkd) { error = -ENOMEM; goto err_free_dev; } gkd->pdev = pdev; gkd->input = input; gkd->n_buttons = pdata->nbuttons; gkd->buttons = pdata->buttons; /* Request and configure GPIOs */ for (i = 0, button = pdata->buttons; i < pdata->nbuttons; i++, button++) { error = gpio_request(button->gpio, button->desc); if (error) { dev_err(&pdev->dev, "Failed to request gpio %d: %d\n", button->gpio, error); goto err_free_gpio; } error = gpio_direction_input(button->gpio); if (error) { dev_err(&pdev->dev, "Failed to configure gpio %d: %d\n", button->gpio, error); goto err_free_gpio; } } /* Register IRQ handlers */ for (i = 0, button = pdata->buttons; i < pdata->nbuttons; i++, button++) { error = gpio_request(button->gpio, button->desc); if (error) { dev_err(&pdev->dev, "Failed to request gpio %d: %d\n", button->gpio, error); goto err_free_irq; } error = request_irq(gpio_to_irq(button->gpio), gpio_keys_irq, button->irqflags, button->desc, gkd); if (error) { dev_err(&pdev->dev, "Failed to register IRQ for gpio %d: %d\n", button->gpio, error); goto err_free_irq; } } /* Store private data */ platform_set_drvdata(pdev, gkd); return 0; err_free_irq: while (--i >= 0) { button--; free_irq(gpio_to_irq(button->gpio), gkd); } goto err_free_gpio; err_free_gpio: while (--i >= 0) { button--; gpio_free(button->gpio); } err_free_dev: input_free_device(input); err_free_desc: for (i = 0, button = pdata->buttons; i < pdata->nbuttons; i++, button++) { kfree(button->desc); } return error; } ``` 在 `gpio_keys_probe()` 函数中,我们首先为输入设备分配内存,然后设置输入设备的属性,如名称、上级设备、事件类型和按键能力。接下来,我们为每个按键分配 GPIO,并将其配置为输入模式。最后,我们为每个按键注册中断处理程序,并将私有数据存储在 platform 设备的私有数据区域中。 一旦模块已注册并初始化,内核就可以使用 `gpio_keys_irq()` 函数来处理按键事件。该函数会检查哪个按键被按下或释放,并将事件发送到输入子系统。 下面是 `gpio_keys_irq()` 函数的代码: ```c static irqreturn_t gpio_keys_irq(int irq, void *dev_id) { struct gpio_keys_device *gkd = dev_id; struct gpio_keys_button *button; struct input_dev *input = gkd->input; unsigned int state; int i; /* Check each button */ for (i = 0, button = gkd->buttons; i < gkd->n_buttons; i++, button++) { state = gpio_get_value(button->gpio); if (state != button->active_low) continue; /* Send event to input subsystem */ input_report_key(input, button->code, 1); input_sync(input); input_report_key(input, button->code, 0); input_sync(input); } return IRQ_HANDLED; } ``` 在 `gpio_keys_irq()` 函数中,我们遍历每个按键并检查其状态。如果按键被按下,则我们发送 “按下” 事件;如果按键被释放,则我们发送 “释放” 事件。最后,我们将事件同步到输入子系统。 总的来说,gpio-keys 模块是一个非常有用的内核模块,它允许用户通过 GPIO 按键与系统进行交互。通过分析其代码,我们可以更好地了解内核模块是如何工作的,并且可以更好地理解 linux 内核的编程模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值