Use of gpio-key driver in linux kernel

Keyword

dtsi, gpio, key, input subsystem, event analysis, long-press key detection

gpio_keys description

The key is a commonly used thing in embedded development, and a mature mechanism has been made for us in the Linux kernel.

The drivers / input / keyboard / gpio_keys.c under the linux kernel implements an architecture-independent GPIO key driver. To use this key driver, you only need to define the relevant data in the corresponding device tree. The implementation of the drive is very simple, but it is more suitable for implementing independent key drive.

gpio-keys is a general-purpose GPIO key driver based on the input architecture. The driver is based on the platform_driver architecture, which realizes the separation of driver and device, in line with the idea of ​​Linux device driver model. The key driver in the project is generally written based on gpio-keys, so we need to analyze gpio_keys.

Here I processed at the application layer to support long-press detection (my program is set to long-press 6S printing). I tried to modify the debounce time at the driver layer, and the effect was very poor, so I gave up.

Implementation of dtsi device tree

  • The implementation of the device tree is mostly the same, just fill in the necessary parameters, I have marked below.

gpio_keys {

    compatible = "gpio-keys";

    label = "gpio-keys";



    pinctrl-names = "default";

    pinctrl-0 = <&key_recovery_default>;



    recovery {

     label = "recovery";

     gpios = <&tlmm 23 GPIO_ACTIVE_HIGH>;

     linux,input-type = <1>;

     linux,code = <115>;

    /*这三项根据需求添加*/

    gpio-key,wakeup;

    debounce-interval = <15>;

    linux,can-disable;

    };

 };

1. The node name is "gpio-keys".

2. The compatible attribute value of gpio-keys node must be set to "gpio-keys".

3. All KEYs are child nodes of gpio-keys. Each child node can describe itself with the following attributes:

gpios: GPIO information connected by KEY.

interrupts: GPIO interrupt information used by KEY is not necessary, you can not write.

label: KEY name

linux, code: KEY key to be simulated can To straight Pick up fill number word \ color {red} {You can fill in numbers directly}

gpio-key, wakeup: can be woken up

debounce-interval: debounce time

  • Other fields

1. If the button needs to support double-clicking, add autorepeat

Simple driver analysis

This is a standard platform driver framework. If you want to use the device tree to describe KEY device information, the compatible attribute value of the device node should be set to "gpio-keys". When the device and driver match, the gpio_keys_probe function will be executed


static struct platform_driver gpio_keys_device_driver = {

 .probe = gpio_keys_probe,

 .driver = {

  .name = "gpio-keys",

  .pm = &gpio_keys_pm_ops,

  .of_match_table = gpio_keys_of_match,

 }

};

Device tree analysis, get device node information related to KEY from the device tree


static int gpio_keys_probe(struct platform_device *pdev)

{

if (!pdata) {

  pdata = gpio_keys_get_devtree_pdata(dev);

  if (IS_ERR(pdata))

   return PTR_ERR(pdata);

 }

}

View read event

  • View event

ls -l /dev/input

  • View file content

hexdump /dev/input/event0

Application layer parsing key value


#define RECOVERY_KEY "/dev/input/event2"

#define RECOVERY_KEY_CODE 115

#define RECOVERY_KEY_PRESS 0



void recovery_key_press_timer(int sig)

{

 if(SIGALRM == sig)

 {

  printf("alarm 6s.\n");

 }



 return;

}





static void read_recovery_key_event()

{

 int fd = -1, ret = -1;

 struct input_event ev;



 fd = open(RECOVERY_KEY, O_RDONLY);

 if (fd < 0)

 {

  printf("open RECOVERY_KEY event failed.\n");

  return;

 }



 memset(&ev, 0, sizeof(struct input_event));

 ret = read(fd, &ev, sizeof(struct input_event));

 if (ret != sizeof(struct input_event))

 {

  printf("read RECOVERY_KEY event failed.\n");

  close(fd);

 }



 if( (RECOVERY_KEY_CODE == ev.code) && (RECOVERY_KEY_PRESS == ev.value) )

 {

  printf("recovery-key press.\n");

  alarm(6);

 }

 else

 {

  printf("recovery-key release.\n");

  alarm(0);

 }



 close(fd);

}



int main(int argc, char **argv)

{

    int rc = 0;

 signal(SIGALRM, recovery_key_press_timer);

 while(1)

 {

  read_recovery_key_event();

 }

    return 0;

}

Reference link

LEDE / OpenWRT handles GPIO-based Power key

Published 162 original articles · praised 183 · 120,000 views

Guess you like

Origin blog.csdn.net/qq_31339221/article/details/105233924