Trying to implement longpress function for keypad, but don't know what to set in the device tree for input-device

I'm running V2.60 NCD on a custom n5340 processor and I can't decipher what is the proper device tree based on the examples.

I have a 10 button keypad and want to detect short and long presses on all the keys. 

i tried the test suite code here: v2.6.0\zephyr\tests\subsys\input\input_longpress  which runs (simulating keypresses) and I get the test_cb() to execute.  I can read the keypad via 

gpio_pin_get_dt() manually, so I know that is all connected ok.

 Here is the zephyr testsuite code and their devicetree

tatic const struct device *const fake_dev = DEVICE_DT_GET(
		DT_NODELABEL(fake_input_device));
static const struct device *const longpress_dev = DEVICE_DT_GET(
		DT_NODELABEL(longpress));

DEVICE_DT_DEFINE(DT_INST(0, vnd_input_device), NULL, NULL, NULL, NULL,
		 PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);

static int event_count;
static struct input_event last_events[2];

static void test_cb(struct input_event *evt)
{
	TC_PRINT("%s: %d %x %d\n", __func__, event_count, evt->code, evt->value);

	event_count++;
	memcpy(&last_events[1], &last_events[0], sizeof(struct input_event));
	memcpy(&last_events[0], evt, sizeof(struct input_event));
}
INPUT_CALLBACK_DEFINE(longpress_dev, test_cb);

Their Device tree

#include <zephyr/dt-bindings/input/input-event-codes.h>

/ {
	fake_input_device: fake-device {
		compatible = "vnd,input-device";
	};

	longpress: longpress {
		input = <&fake_input_device>;
		compatible = "zephyr,input-longpress";
		input-codes = <INPUT_KEY_0>, <INPUT_KEY_1>;
		short-codes = <INPUT_KEY_A>, <INPUT_KEY_B>;
		long-codes = <INPUT_KEY_X>, <INPUT_KEY_Y>;
		long-delay-ms = <100>;
        };
};

I used that same code changing from the "fake" names to mine, but  but I get this error during build:

C:/ncs/v2.6.0/zephyr/include/zephyr/toolchain/gcc.h:87:36: error: static assertion failed: "zephyr-code must be specified to use the input-gpio-keys driver".

here's my devicetree file.  I don't know what to use for the kp_input_device compatible value (probably causing the error?).  The test code uses "vnd,input-device" which is a dummy device for test suite.

 my device tree

	buttons: buttons {
		 compatible = "gpio-keys";
		 btntopleft: button_0 {
			gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "BTN_TOP_LEFT";
			zephyr,code = <INPUT_KEY_0>;
		 };		 
		btntopmid: button_1 {
			gpios = <&gpio1 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;			
			label = "BTN_TOP_MIDDLE";
			zephyr,code = <INPUT_KEY_1>;
		};		 
		btntopright: button_2 {
			gpios = <&gpio1 7 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;				
			label = "BTN_TOP_RIGHT";
			zephyr,code = <INPUT_KEY_2>;
		};
		btnleft: button_3 {
			gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;			
			label = "BTN_LEFT";
			zephyr,code = <INPUT_KEY_3>;
		};	
		btndpadleft: button_4 {
			gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "BTN_DPAD_LEFT";
			zephyr,code = <INPUT_KEY_4>;
		};			 
		btndpadtop: button_5 {
			gpios = <&gpio0 25 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "BTN_DPAD_TOP";
			zephyr,code = <INPUT_KEY_5>;
		 };
		btndpadright: button_6 {
		   	gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
		   	label = "BTN_DPAD_RIGHT";	
			   zephyr,code = <INPUT_KEY_6>;	
		}; 		 
		 btndpadbot: button_7 {
			gpios = <&gpio0 28 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "BTN_DPAD_BOTTOM";
			zephyr,code = <INPUT_KEY_7>;
		 };
		 btnright: button_8 {
			gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "BTN_RIGHT";
			zephyr,code = <INPUT_KEY_8>;
		};
		 btnbot: button_9 {
//			gpios = <&gpio0 29 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;		// trigger for testing 
			label = "BTN_BOTTOM";
			zephyr,code = <INPUT_KEY_9>;
		};
	};
	
	kp_input_device: kp-device {
		compatible = "vnd,input-device";
	};

	longpress: longpress {
		input = <&kp_input_device>;
		compatible = "zephyr,input-longpress";
        input-codes = <INPUT_KEY_0>,<INPUT_KEY_1>,<INPUT_KEY_2>,<INPUT_KEY_3>,<INPUT_KEY_4>,<INPUT_KEY_5>,<INPUT_KEY_6>,<INPUT_KEY_7>,<INPUT_KEY_8>, <INPUT_KEY_9>;
        short-codes = <INPUT_KEY_A>,<INPUT_KEY_B>,<INPUT_KEY_C>,<INPUT_KEY_D>,<INPUT_KEY_E>,<INPUT_KEY_F>,<INPUT_KEY_G>,<INPUT_KEY_H>,<INPUT_KEY_I>, <INPUT_KEY_J>;  
		long-codes  = <INPUT_KEY_K>,<INPUT_KEY_L>,<INPUT_KEY_M>,<INPUT_KEY_N>,<INPUT_KEY_O>,<INPUT_KEY_P>,<INPUT_KEY_Q>,<INPUT_KEY_R>,<INPUT_KEY_S>, <INPUT_KEY_T>;
        long-delay-ms = <1000>;
 		};

my longpress code

#include <zephyr/device.h>
#include <zephyr/input/input.h>
#include <zephyr/kernel.h>
//#include <zephyr/ztest.h>

LOG_MODULE_REGISTER(longpress, LOG_LEVEL_INF);

static const struct device *const kp_dev = DEVICE_DT_GET(
		DT_NODELABEL(kp_input_device));
static const struct device *const longpress_dev = DEVICE_DT_GET(
		DT_NODELABEL(longpress));

DEVICE_DT_DEFINE(DT_INST(0, vnd_input_device), NULL, NULL, NULL, NULL,
		 PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);

static int event_count;
static struct input_event last_events[2];

static void longpress_cb(struct input_event *evt)
{
	printk("%s: %d %x %d\n", __func__, event_count, evt->code, evt->value);

	event_count++;
	memcpy(&last_events[1], &last_events[0], sizeof(struct input_event));
	memcpy(&last_events[0], evt, sizeof(struct input_event));
}

INPUT_CALLBACK_DEFINE(longpress_dev, longpress_cb);

there is a good example code here: \v2.6.0\zephyr\subsys\input that has all the processing inside, but this has the same problem as above.

thanks

Parents Reply Children
  • thanks Siguard.  That is working, but I was trying to use the longpress feature in the devicetree (using CONFIG_INPUT=y).  I thought that would be an easier way.  The other question using the longpress feature, if it would work to detect two buttons pressed together.  I'll stay with your solution unless I hear otherwise.

  •   You should pass a different phandle (buttons) to the longpress device to be as an input reference (input = <&buttons>). So your device tree will look like this:

    	buttons: buttons {
    		 compatible = "gpio-keys";
    		 btntopleft: button_0 {
    			gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "BTN_TOP_LEFT";
    			zephyr,code = <INPUT_KEY_0>;
    		 };		 
    		btntopmid: button_1 {
    			gpios = <&gpio1 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;			
    			label = "BTN_TOP_MIDDLE";
    			zephyr,code = <INPUT_KEY_1>;
    		};		 
    		btntopright: button_2 {
    			gpios = <&gpio1 7 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;				
    			label = "BTN_TOP_RIGHT";
    			zephyr,code = <INPUT_KEY_2>;
    		};
    		btnleft: button_3 {
    			gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;			
    			label = "BTN_LEFT";
    			zephyr,code = <INPUT_KEY_3>;
    		};	
    		btndpadleft: button_4 {
    			gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "BTN_DPAD_LEFT";
    			zephyr,code = <INPUT_KEY_4>;
    		};			 
    		btndpadtop: button_5 {
    			gpios = <&gpio0 25 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "BTN_DPAD_TOP";
    			zephyr,code = <INPUT_KEY_5>;
    		 };
    		btndpadright: button_6 {
    		   	gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    		   	label = "BTN_DPAD_RIGHT";	
    			   zephyr,code = <INPUT_KEY_6>;	
    		}; 		 
    		 btndpadbot: button_7 {
    			gpios = <&gpio0 28 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "BTN_DPAD_BOTTOM";
    			zephyr,code = <INPUT_KEY_7>;
    		 };
    		 btnright: button_8 {
    			gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "BTN_RIGHT";
    			zephyr,code = <INPUT_KEY_8>;
    		};
    		 btnbot: button_9 {
    //			gpios = <&gpio0 29 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;		// trigger for testing 
    			label = "BTN_BOTTOM";
    			zephyr,code = <INPUT_KEY_9>;
    		};
    	};
    	
        // No need for kp_input_device
    
    	longpress: longpress {
    		input = <&buttons>;
    		compatible = "zephyr,input-longpress";
            input-codes = <INPUT_KEY_0>,<INPUT_KEY_1>,<INPUT_KEY_2>,<INPUT_KEY_3>,<INPUT_KEY_4>,<INPUT_KEY_5>,<INPUT_KEY_6>,<INPUT_KEY_7>,<INPUT_KEY_8>, <INPUT_KEY_9>;
            short-codes = <INPUT_KEY_A>,<INPUT_KEY_B>,<INPUT_KEY_C>,<INPUT_KEY_D>,<INPUT_KEY_E>,<INPUT_KEY_F>,<INPUT_KEY_G>,<INPUT_KEY_H>,<INPUT_KEY_I>, <INPUT_KEY_J>;  
    		long-codes  = <INPUT_KEY_K>,<INPUT_KEY_L>,<INPUT_KEY_M>,<INPUT_KEY_N>,<INPUT_KEY_O>,<INPUT_KEY_P>,<INPUT_KEY_Q>,<INPUT_KEY_R>,<INPUT_KEY_S>, <INPUT_KEY_T>;
            long-delay-ms = <1000>;
        };

    In your source code you don't need lines

    static const struct device *const kp_dev = DEVICE_DT_GET(
        DT_NODELABEL(kp_input_device));

    and 

    DEVICE_DT_DEFINE(DT_INST(0, vnd_input_device), NULL, NULL, NULL, NULL,
    		 PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);

    since your keypad device is actually buttons and they've already been instantiated by Zephyr.


    Thanks!

Related