linux 按键轮询驱动(gpio_keys_polled.c)

系统自带了gpio_keys_polled.c驱动文件,硬件资源是通过设备树获取,在不修改设备树的情况下,可以直接在驱动文件中对相关的结构体进行赋值。

1、定义当前使用的IO按钮数组

static struct gpio_keys_button buttons[]={
    {
        .gpio = 41,//IO引脚号,根据实际情况修改
        .code = KEY_1,
        .desc = "KEY1",
        .active_low = 1,
    },
    {
        .gpio = 120,
        .code = KEY_2,
        .desc = "KEY2",
        .active_low = 1,
    },
    {
        .gpio = 121,
        .code = KEY_3,
        .desc = "KEY3",
        .active_low = 1,
    },
    {
        .gpio = 5,
        .code = KEY_4,
        .desc = "KEY4",
        .active_low = 1,
    },
    {
        .gpio = 226,
        .code = KEY_5,
        .desc = "KEY5",
        .active_low = 1,
    },
};

2、修改gpio_keys_polled_probe()函数

linux 按键轮询驱动(gpio_keys_polled.c)_第1张图片

具体硬件资源与驱动匹配的函数为 gpio_keys_polled_get_devtree_pdata(),需要注释掉“if(!pdata)这行,否则会出现pdata->poll_interval未赋值的情况。

3、修改gpio_keys_polled_get_devtree_pdata()函数

static struct gpio_keys_platform_data *gpio_keys_polled_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 NULL;
    
    //按键数
	nbuttons = ARRAY_SIZE(buttons);//nbuttons = of_get_child_count(node);
	//if (nbuttons == 0)
	//	return NULL;

	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
			GFP_KERNEL);
	if (!pdata) {
		error = -ENOMEM;
		goto err_out;
	}

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

    //扫描间隔手动赋值,注释掉从设备树获取代码
	//pdata->rep = !!of_get_property(node, "autorepeat", NULL);
	//of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
	pdata->poll_interval = 50;//50ms

	i = 0;
	#if 0 //注释掉从设备树获取相关按键代码
	for_each_child_of_node(node, pp) {
		int gpio;
		enum of_gpio_flags flags;

		if (!of_find_property(pp, "gpios", NULL)) {
			pdata->nbuttons--;
			dev_warn(dev, "Found button without gpios\n");
			continue;
		}

		gpio = of_get_gpio_flags(pp, 0, &flags);
		if (gpio < 0) {
			error = gpio;
			if (error != -EPROBE_DEFER)
				dev_err(dev,
					"Failed to get gpio flags, error: %d\n",
					error);
			goto err_free_pdata;
		}

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

		button->gpio = gpio;
		button->active_low = flags & OF_GPIO_ACTIVE_LOW;

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

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

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

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

		if (of_property_read_u32(pp, "debounce-interval",
					 &button->debounce_interval))
			button->debounce_interval = 5;
	}
	#else //使用我们定义的按键填充相关结构体
	for(i=0; ibuttons[i];	
		button->gpio = buttons[i].gpio;
		button->active_low = buttons[i].active_low;
		button->type = EV_KEY;
		button->code = buttons[i].code;	
	}

	#endif

	if (pdata->nbuttons == 0) {
		error = -EINVAL;
		goto err_free_pdata;
	}

	return pdata;

err_free_pdata:
	kfree(pdata);
err_out:
	return ERR_PTR(error);
}

static struct of_device_id gpio_keys_polled_of_match[] = {
	{ .compatible = "gpio-keys-polled", },
	{ },
};

4、添加platform device 注册相关代码

static struct gpio_keys_platform_data button_data={
	.buttons = buttons,
	.nbuttons = ARRAY_SIZE(buttons),
};

static struct platform_device button_device={
	.name = "gpio-keys-polled",//此名字需与platform driver名字一致
	.id = -1,
	.dev = {
		.platform_data = &button_data,
	},
};
static int keys_dev_init(void)
{
	platform_device_register(&button_device);
	return 0;
}

static void keys_dev_exit(void)
{
	platform_device_unregister(&button_device);
}
module_init(keys_dev_init);
module_exit(keys_dev_exit);

到此修改完毕,编译下载运行。

5、终端输入cat /proc/bus/input/devices

linux 按键轮询驱动(gpio_keys_polled.c)_第2张图片

6、终端输入 hexdump /dev/input/event1  查看运行情况

linux 按键轮询驱动(gpio_keys_polled.c)_第3张图片

你可能感兴趣的:(linux)