drivers/input: Create Single Button Multi Actions

This commit creates a sbutton device that uses a single button to
create a keyboard driver that returns TAB or ENTER depending how
long the user keeps the button pressed.

Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit is contained in:
Alan Carvalho de Assis 2025-07-11 10:37:07 -03:00 committed by Alan C. Assis
parent 3c8859b509
commit 54b2381c42
15 changed files with 849 additions and 0 deletions

View file

@ -6,5 +6,6 @@ Input Devices
:caption: Supported Drivers
keypad.rst
sbutton.rst
See ``include/nuttx/input/*.h`` for registration information.

View file

@ -0,0 +1,41 @@
==================================
Single Button Multi Actions Driver
==================================
**Single Button (aka SButton)** is an kind of keyboard that uses
only a single physical button (Switch) in the board. This kind of
button is used with simple interfaces like those used on 3D Printers
or other devices where all the user needs is to move to the next
option and confirm the selection.
It could be done detecting if the button was pressed for a short
period of time (i.e. less than 500ms) or long pressed. If it is a
short press the driver will return **TAB** and if it is a long
press the driver will return **ENTER**. Using it is possible to
navigate on those kind of menu.
**How does it work?**. The driver uses a simple config data (this
config data is equivalent to the platform data on Linux kernel) to
map the pin from MCU will be used to register and detect the
interrupt from this pin physically connected to the button.
It uses a kind of "polymorphism" in C to allow the driver to get
access to the functions responsible to attach and enable the
interrupt and to get the status of the pin.
See ``include/nuttx/input/sbutton.h``
and ``boards/arm/stm32/common/src/stm32_sbutton.c`` to understand
better how it works. But basically the board file (config data)
creates a struct when the first field (variable) is the config
struct used the but SButton driver (``drivers/input/sbutton.c``).
Every time the user presses or releases the key button an interrupt
is generated. The ISR of this interrupt inside sbutton
(``sbutton_interrupt()``) calls a workqueue to process it (because
we cannot spend time inside the ISR processing data, it could
degradate the performance of the RTOS). All that workqueue
(``sbutton_worker()``) needs to do it measure the elapsed time
(ticks) from the moment the key was pressed until the moment it
was released to decide if it is a "KEY_1" (**TAB**) or a "KEY_2"
(**ENTER**). Then is call the ``keyboard_event()`` from the
keyboard upper to send this key stroke to the user application.

View file

@ -1970,6 +1970,27 @@ the second dongle you will connect to UART3 (PB10 and PB11).
In the main NSH console (in USART2) type: "pts_test &". It will create a
new console in UART3. Just press ENTER and start typing commands on it.
sbutton
-------
This is a configuration to test the Single Button Dual Action feature.
To test it just compile and flash nuttx.bin in the board. Then run the
``kbd`` command inside ``nsh>`` and short press and long press User
Button (B1) on the board.
You will see something like this::
NuttShell (NSH) NuttX-12.10.0
nsh> kbd
kbd_main: nsamples: 0
kbd_main: Opening /dev/kbd0
Sample :
code : 65
type : 0
Sample :
code : 66
type : 0
sporadic
--------

View file

@ -0,0 +1,83 @@
/****************************************************************************
* boards/arm/stm32/common/include/board_sbutton.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __BOARDS_ARM_STM32_COMMON_INCLUDE_BOARD_SBUTTON_H
#define __BOARDS_ARM_STM32_COMMON_INCLUDE_BOARD_SBUTTON_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: stm32_sbutton_initialize
*
* Description:
* This function is called by application-specific, setup logic to
* configure the Single Button Dual Action.
*
* Input Parameters:
* devno - The device number, used to build the device path as /dev/distN
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int board_sbutton_initialize(int devno);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __BOARDS_ARM_STM32_COMMON_INCLUDE_BOARD_SBUTTON_H */

View file

@ -154,4 +154,8 @@ if(CONFIG_STEPPER_DRV8825)
list(APPEND SRCS stm32_drv8825.c)
endif()
if(CONFIG_INPUT_SBUTTON)
list(APPEND SRCS stm32_sbutton.c)
endif()
target_sources(board PRIVATE ${SRCS})

View file

@ -162,6 +162,10 @@ ifeq ($(CONFIG_STEPPER_DRV8825),y)
CSRCS += stm32_drv8825.c
endif
ifeq ($(CONFIG_INPUT_SBUTTON),y)
CSRCS += stm32_sbutton.c
endif
DEPPATH += --dep-path src
VPATH += :src
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src

View file

@ -0,0 +1,182 @@
/****************************************************************************
* boards/arm/stm32/common/src/stm32_sbutton.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <nuttx/input/sbutton.h>
#include "stm32.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct stm32_sbtnconfig_s
{
/* Configuration structure as seen by the HC-SR04 driver */
struct sbutton_config_s config;
/* Additional private definitions only known to this driver */
void *arg; /* Argument to pass to the interrupt handler */
xcpt_t isr; /* ISR Handler */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int sbtn_irq_attach(const struct sbutton_config_s *config,
xcpt_t isr, void *arg);
static void sbtn_irq_enable(const struct sbutton_config_s *config,
bool enable);
static void sbtn_irq_clear(const struct sbutton_config_s *config);
static bool sbtn_pin_status(void);
/****************************************************************************
* Private Data
****************************************************************************/
/* A reference to a structure of this type must be passed to the SButton
* driver. This structure provides information about the configuration
* of the SButton and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
static struct stm32_sbtnconfig_s g_sbtnconfig =
{
.config =
{
.attach = sbtn_irq_attach,
.enable = sbtn_irq_enable,
.clear = sbtn_irq_clear,
.status = sbtn_pin_status,
},
};
/****************************************************************************
* Private Functions
****************************************************************************/
/* Attach the SBUTTON interrupt handler to the GPIO interrupt */
static int sbtn_irq_attach(const struct sbutton_config_s *state, xcpt_t isr,
void *arg)
{
struct stm32_sbtnconfig_s *priv = (struct stm32_sbtnconfig_s *)state;
irqstate_t flags;
sinfo("sbtn_irq_attach\n");
flags = enter_critical_section();
priv->isr = isr;
priv->arg = arg;
stm32_gpiosetevent(BOARD_SBUTTON_GPIO_INT, true, true,
true, isr, arg);
leave_critical_section(flags);
return OK;
}
/* Enable or disable the GPIO interrupt */
static void sbtn_irq_enable(const struct sbutton_config_s *state,
bool enable)
{
struct stm32_sbtnconfig_s *priv = (struct stm32_sbtnconfig_s *)state;
iinfo("%d\n", enable);
stm32_gpiosetevent(BOARD_SBUTTON_GPIO_INT, true, true,
true, enable ? priv->isr : NULL, priv->arg);
}
/* Acknowledge/clear any pending GPIO interrupt */
static void sbtn_irq_clear(const struct sbutton_config_s *state)
{
/* FIXME: Nothing to do ? */
}
/* Read and return the status of button (PRESSED = true; RELEASED = false */
static bool sbtn_pin_status(void)
{
/* STM32F4Discovery button B1 is high level when press
* then just returned the status of the pin directly.
*/
return stm32_gpioread(BOARD_SBUTTON_GPIO_INT);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_sbutton_initialize
*
* Description:
* This function is called by application-specific, setup logic to
* configure the Single Button Dual Action.
*
* Input Parameters:
* devno - The device number, used to build the device path as /dev/kbdN
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int board_sbutton_initialize(int devno)
{
/* Configure the Single Button Dual Action interrupt pin */
stm32_configgpio(BOARD_SBUTTON_GPIO_INT);
/* Register the Single Button with overlay config pointer */
return sbutton_register(&g_sbtnconfig.config, devno);
}

View file

@ -0,0 +1,56 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_FPU is not set
# CONFIG_ASSERTIONS_FILENAME is not set
# CONFIG_NDEBUG is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="stm32f4discovery"
CONFIG_ARCH_BOARD_COMMON=y
CONFIG_ARCH_BOARD_STM32F4_DISCOVERY=y
CONFIG_ARCH_CHIP="stm32"
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32F407VG=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_KEYBOARD=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INPUT=y
CONFIG_INPUT_SBUTTON=y
CONFIG_INTELHEX_BINARY=y
CONFIG_LINE_MAX=64
CONFIG_MM_REGIONS=2
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32_JTAG_SW_ENABLE=y
CONFIG_STM32_PWR=y
CONFIG_STM32_SPI1=y
CONFIG_STM32_USART2=y
CONFIG_SYSTEM_NSH=y
CONFIG_USART2_RXBUFSIZE=128
CONFIG_USART2_SERIAL_CONSOLE=y
CONFIG_USART2_TXBUFSIZE=128
CONFIG_WQUEUE_NOTIFIER=y

View file

@ -465,6 +465,9 @@
#define BOARD_XEN1210_GPIO_INT GPIO_XEN1210_INT
#define BOARD_SBUTTON_GPIO_INT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|\
GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN0)
/* Define what timer to use as XEN1210 CLK (will use channel 1) */
#define BOARD_XEN1210_PWMTIMER 1

View file

@ -98,6 +98,10 @@
#include "stm32_nunchuck.h"
#endif
#ifdef CONFIG_INPUT_SBUTTON
#include "board_sbutton.h"
#endif
#ifdef CONFIG_SENSORS_ZEROCROSS
#include "stm32_zerocross.h"
#endif
@ -452,6 +456,16 @@ int stm32_bringup(void)
}
#endif
#ifdef CONFIG_INPUT_SBUTTON
/* Register the Single Button Dual Action driver */
ret = board_sbutton_initialize(0);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: board_sbtn_initialize() failed: %d\n", ret);
}
#endif
#ifdef CONFIG_SENSORS_APDS9960
/* Register the APDS-9960 gesture sensor */

View file

@ -106,6 +106,10 @@ if(CONFIG_INPUT)
list(APPEND SRCS keyboard_upper.c)
endif()
if(CONFIG_INPUT_SBUTTON)
list(APPEND SRCS sbutton.c)
endif()
if(CONFIG_INPUT_DJOYSTICK)
list(APPEND SRCS djoystick.c)
endif()

View file

@ -622,6 +622,47 @@ config INPUT_BUTTONS_NPOLLWAITERS
endif # INPUT_BUTTONS
config INPUT_SBUTTON
bool "Single Button Multi Actions"
select INPUT_KEYBOARD
default n
---help---
Enable the Single Button Multi Actions upper half driver.
This driver allows using a single button to generate two
events (mapped to short press and long press). Using it
is possible navigate a menu interface when using with a
LCD/OLED display.
if INPUT_SBUTTON
config INPUT_SBUTTON_KEY1
int "ASCII code to generate for short press"
default 9
---help---
Which key will be generated when user do a short press.
Default key is TAB (ASCII 9)
config INPUT_SBUTTON_KEY2
int "ASCII code to generate for long press"
default 13
---help---
Which key will be generated when user do a short press.
Default key is ENTER (ASCII 13)
config INPUT_SBUTTON_BUFSIZE
int "Buffer size to store keys"
default 8
config INPUT_SBUTTON_KEY_THRESH_MS
int "Threshold in milliseconds for short press"
default 500
config INPUT_SBUTTON_KEY_DEBOUNCE_MS
int "Key Debounce value in milliseconds"
default 30
endif # INPUT_SBUTTON
config INPUT_DJOYSTICK
bool "Discrete Joystick"
default n

View file

@ -118,6 +118,10 @@ ifeq ($(CONFIG_INPUT_NUNCHUCK),y)
CSRCS += nunchuck.c
endif
ifeq ($(CONFIG_INPUT_SBUTTON),y)
CSRCS += sbutton.c
endif
ifeq ($(CONFIG_INPUT_SPQ10KBD),y)
CSRCS += spq10kbd.c
endif

278
drivers/input/sbutton.c Normal file
View file

@ -0,0 +1,278 @@
/****************************************************************************
* drivers/input/sbutton.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <poll.h>
#include <fcntl.h>
#include <nuttx/input/sbutton.h>
#include <nuttx/fs/fs.h>
#include <nuttx/clock.h>
#include <nuttx/ascii.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/wqueue.h>
#include <nuttx/semaphore.h>
#include <nuttx/input/keyboard.h>
#include <nuttx/input/kbd_codec.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* This format is used to construct the /dev/kbd[n] device driver path. It
* defined here so that it will be used consistently in all places.
*/
#define DEV_FORMAT "/dev/kbd%d"
#define DEV_NAMELEN 12
#define KEY_PRESS true
#define KEY_RELEASE false
/****************************************************************************
* Private Types
****************************************************************************/
struct sbutton_dev_s
{
FAR const struct sbutton_config_s *config; /* Board configuration data */
mutex_t lock; /* Exclusive access to dev */
clock_t start; /* Clock tick when the key was pressed */
clock_t end; /* Clock tick when the key was released */
bool pressed; /* Keep previous status of button */
struct work_s work; /* Supports the interrupt handling "bottom half" */
/* Keyboard lowerhalf of the registered keyboard */
struct keyboard_lowerhalf_s lower;
};
/****************************************************************************
* Static Function Prototypes
****************************************************************************/
static int sbutton_interrupt(int irq, FAR void *context, FAR void *arg);
static void sbutton_worker(FAR void *arg);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sbutton_worker
****************************************************************************/
static void sbutton_worker(FAR void *arg)
{
FAR struct sbutton_dev_s *priv = (FAR struct sbutton_dev_s *)arg;
uint8_t state;
int ret;
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return;
}
/* Read the status of the button */
state = priv->config->status();
/* If the user just pressed the button, start measuring */
if (state == KEY_PRESS && !priv->pressed)
{
iinfo("Button pressed\n");
priv->pressed = true;
priv->start = clock_systime_ticks();
}
else
{
if (state == KEY_RELEASE && priv->pressed)
{
uint32_t elapsed;
iinfo("Button released\n");
priv->pressed = false;
priv->end = clock_systime_ticks();
elapsed = priv->end - priv->start;
/* Debounce to avoid getting wrong press/release event */
if (elapsed < MSEC2TICK(CONFIG_INPUT_SBUTTON_KEY_DEBOUNCE_MS))
{
iwarn("Button event too short, ignoring it\n");
}
else
{
if (elapsed < MSEC2TICK(CONFIG_INPUT_SBUTTON_KEY_THRESH_MS))
{
iinfo("KEY_1\n");
keyboard_event(&priv->lower, CONFIG_INPUT_SBUTTON_KEY1,
KEYBOARD_PRESS);
}
else
{
iinfo("KEY_2\n");
keyboard_event(&priv->lower, CONFIG_INPUT_SBUTTON_KEY2,
KEYBOARD_PRESS);
}
}
}
}
/* Unlock and return */
nxmutex_unlock(&priv->lock);
}
/****************************************************************************
* Name: sbutton_interrupt
****************************************************************************/
static int sbutton_interrupt(int irq, FAR void *context, FAR void *arg)
{
FAR struct sbutton_dev_s *priv = (FAR struct sbutton_dev_s *)arg;
int ret;
/* Let the event worker know that it has an interrupt event to handle
* It is possible that we will already have work scheduled from a
* previous interrupt event. That is OK we will service all the events
* in the same work job.
*/
if (work_available(&priv->work))
{
ret = work_queue(HPWORK, &priv->work, sbutton_worker, priv, 0);
if (ret != 0)
{
ierr("ERROR: Failed to queue work: %d\n", ret);
}
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sbutton_register
*
* Description:
* Configure the Single Button Multi Key Keyboard to use the provided
* instance. This will register the driver as /dev/kbdN where N is the
* minor device number.
*
* Input Parameters:
* config - Persistent board configuration data
* kbdminor - The keyboard input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int sbutton_register(FAR const struct sbutton_config_s *config,
char kbdminor)
{
FAR struct sbutton_dev_s *priv;
char kbddevname[DEV_NAMELEN];
int ret;
/* Debug Sanity Checks */
DEBUGASSERT(config != NULL);
DEBUGASSERT(config->attach != NULL);
DEBUGASSERT(config->enable != NULL);
DEBUGASSERT(config->clear != NULL);
priv = kmm_zalloc(sizeof(struct sbutton_dev_s));
if (!priv)
{
ierr("ERROR: kmm_zalloc(%d) failed\n", sizeof(struct sbutton_dev_s));
return -ENOMEM;
}
/* Initialize the device driver instance */
priv->config = config; /* Save the board configuration */
priv->pressed = false;
nxmutex_init(&priv->lock); /* Initialize device mutex */
config->clear(config);
config->enable(config, false);
/* Attach the interrupt handler */
ret = config->attach(config, sbutton_interrupt, priv);
if (ret < 0)
{
ierr("ERROR: Failed to attach interrupt\n");
goto errout_with_priv;
}
/* Start servicing events */
priv->config->enable(priv->config, true);
snprintf(kbddevname, sizeof(kbddevname), DEV_FORMAT, kbdminor);
/* Register the device as a keyboard device */
ret = keyboard_register(&priv->lower, kbddevname,
CONFIG_INPUT_SBUTTON_BUFSIZE);
if (ret < 0)
{
ierr("ERROR: keyboard_register() failed: %d\n", ret);
goto errout_with_priv;
}
return OK;
errout_with_priv:
nxmutex_destroy(&priv->lock);
kmm_free(priv);
return ret;
}

View file

@ -0,0 +1,113 @@
/****************************************************************************
* include/nuttx/input/sbutton.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* The single button driver exports a standard character driver interface. By
* convention, the driver is exposed as /dev/kbd[n] and works like a common
* keyboard device, but generates only INPUT_TAB and INPUT_ENTER events.
*/
#ifndef __INCLUDE_NUTTX_INPUT_SBUTTON_H
#define __INCLUDE_NUTTX_INPUT_SBUTTON_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/i2c/i2c_master.h>
#include <stdbool.h>
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/* A reference to a structure of this type must be passed to the
* single button keyboard driver. This structure provides information
* about the configuration and provides some board-specific hooks.
*/
struct sbutton_config_s
{
/* IRQ/GPIO access callbacks. These operations all hidden behind
* callbacks to isolate the Q10 Keyboard driver from differences in GPIO
* interrupt handling by varying boards and MCUs.
*
* attach - Attach the Q10 kbd interrupt handler to the GPIO interrupt
* enable - Enable or disable the GPIO interrupt
* clear - Acknowledge/clear any pending GPIO interrupt
*/
int (*attach)(FAR const struct sbutton_config_s *config, xcpt_t isr,
FAR void *arg);
void (*enable)(FAR const struct sbutton_config_s *config, bool enable);
void (*clear)(FAR const struct sbutton_config_s *config);
bool (*status)(void);
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: spq10kbd_register
*
* Description:
* Configure the single button driver to use the provided instance.
* This will register the driver as /dev/kbdN where N is the
* minor device number.
*
* Input Parameters:
* config - Persistent board configuration data
* kbdminor - The keyboard input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int sbutton_register(FAR const struct sbutton_config_s *config,
char kbdminor);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_INPUT_SBUTTON_H */