LCOV - code coverage report
Current view: top level - zephyr/input - input_kbd_matrix.h Coverage Total Hit
Test: new.info Lines: 51.0 % 49 25
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            1 : /*
       2              :  * Copyright 2023 Google LLC
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : /**
       8              :  * @file
       9              :  * @ingroup input_kbd_matrix
      10              :  * @brief Main header file for keyboard matrix input devices.
      11              :  */
      12              : 
      13              : #ifndef ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_
      14              : #define ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_
      15              : 
      16              : /**
      17              :  * @defgroup input_kbd_matrix Keyboard Matrix
      18              :  * @ingroup input_interface
      19              :  * @{
      20              :  */
      21              : 
      22              : #include <zephyr/device.h>
      23              : #include <zephyr/kernel.h>
      24              : #include <zephyr/pm/device.h>
      25              : #include <zephyr/sys/atomic.h>
      26              : #include <zephyr/sys/util.h>
      27              : #include <zephyr/sys_clock.h>
      28              : #include <zephyr/toolchain.h>
      29              : 
      30              : /** Special drive_column argument for not driving any column */
      31            1 : #define INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE -1
      32              : 
      33              : /** Special drive_column argument for driving all the columns */
      34            1 : #define INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL  -2
      35              : 
      36              : /** Number of tracked scan cycles */
      37            1 : #define INPUT_KBD_MATRIX_SCAN_OCURRENCES 30U
      38              : 
      39              : /** Row entry data type */
      40              : #if CONFIG_INPUT_KBD_MATRIX_16_BIT_ROW
      41              : typedef uint16_t kbd_row_t;
      42              : #define PRIkbdrow "04" PRIx16
      43              : #else
      44            1 : typedef uint8_t kbd_row_t;
      45            0 : #define PRIkbdrow "02" PRIx8
      46              : #endif
      47              : 
      48              : #if defined(CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC) || defined(__DOXYGEN__)
      49            0 : #define INPUT_KBD_ACTUAL_KEY_MASK_CONST
      50              : /**
      51              :  * @brief Enables or disables a specific row, column combination in the actual
      52              :  * key mask.
      53              :  *
      54              :  * This allows enabling or disabling specific row, column combination in the
      55              :  * actual key mask in runtime. It can be useful if some of the keys are not
      56              :  * present in some configuration, and the specific configuration is determined
      57              :  * in runtime. Requires @kconfig{CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC} to
      58              :  * be enabled.
      59              :  *
      60              :  * @param dev Pointer to the keyboard matrix device.
      61              :  * @param row The matrix row to enable or disable.
      62              :  * @param col The matrix column to enable or disable.
      63              :  * @param enabled Whether the specified row, col has to be enabled or disabled.
      64              :  *
      65              :  * @retval 0 If the change is successful.
      66              :  * @retval -errno Negative errno if row or col are out of range for the device.
      67              :  */
      68            1 : int input_kbd_matrix_actual_key_mask_set(const struct device *dev,
      69              :                                           uint8_t row, uint8_t col, bool enabled);
      70              : #else
      71              : #define INPUT_KBD_ACTUAL_KEY_MASK_CONST const
      72              : #endif
      73              : 
      74              : /** Maximum number of rows */
      75            1 : #define INPUT_KBD_MATRIX_ROW_BITS NUM_BITS(kbd_row_t)
      76              : 
      77              : /**
      78              :  * @brief Keyboard matrix internal APIs.
      79              :  */
      80            1 : struct input_kbd_matrix_api {
      81              :         /**
      82              :          * @brief Request to drive a specific column.
      83              :          *
      84              :          * Request to drive a specific matrix column, or none, or all.
      85              :          *
      86              :          * @param dev Pointer to the keyboard matrix device.
      87              :          * @param col The column to drive, or
      88              :          *      @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE or
      89              :          *      @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL.
      90              :          */
      91            1 :         void (*drive_column)(const struct device *dev, int col);
      92              :         /**
      93              :          * @brief Read the matrix row.
      94              :          *
      95              :          * @param dev Pointer to the keyboard matrix device.
      96              :          */
      97            1 :         kbd_row_t (*read_row)(const struct device *dev);
      98              :         /**
      99              :          * @brief Request to put the matrix in detection mode.
     100              :          *
     101              :          * Request to put the driver in detection mode, this is called after a
     102              :          * request to drive all the column and typically involves reenabling
     103              :          * interrupts row pin changes.
     104              :          *
     105              :          * @param dev Pointer to the keyboard matrix device.
     106              :          * @param enable Whether detection mode has to be enabled or disabled.
     107              :          */
     108            1 :         void (*set_detect_mode)(const struct device *dev, bool enabled);
     109              : };
     110              : 
     111              : /**
     112              :  * @brief Common keyboard matrix config.
     113              :  *
     114              :  * This structure **must** be placed first in the driver's config structure.
     115              :  */
     116            1 : struct input_kbd_matrix_common_config {
     117            0 :         const struct input_kbd_matrix_api *api;
     118            0 :         uint8_t row_size;
     119            0 :         uint8_t col_size;
     120            0 :         uint32_t poll_period_us;
     121            0 :         uint32_t stable_poll_period_us;
     122            0 :         uint32_t poll_timeout_ms;
     123            0 :         uint32_t debounce_down_us;
     124            0 :         uint32_t debounce_up_us;
     125            0 :         uint32_t settle_time_us;
     126            0 :         bool ghostkey_check;
     127            0 :         INPUT_KBD_ACTUAL_KEY_MASK_CONST kbd_row_t *actual_key_mask;
     128              : 
     129              :         /* extra data pointers */
     130            0 :         kbd_row_t *matrix_stable_state;
     131            0 :         kbd_row_t *matrix_unstable_state;
     132            0 :         kbd_row_t *matrix_previous_state;
     133            0 :         kbd_row_t *matrix_new_state;
     134            0 :         uint8_t *scan_cycle_idx;
     135              : };
     136              : 
     137            0 : #define INPUT_KBD_MATRIX_DATA_NAME(node_id, name) \
     138              :         _CONCAT(__input_kbd_matrix_, \
     139              :                 _CONCAT(name, DEVICE_DT_NAME_GET(node_id)))
     140              : 
     141              : /**
     142              :  * @brief Defines the common keyboard matrix support data from devicetree,
     143              :  * specify row and col count.
     144              :  */
     145            1 : #define INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL(node_id, _row_size, _col_size) \
     146              :         BUILD_ASSERT(IN_RANGE(_row_size, 1, INPUT_KBD_MATRIX_ROW_BITS), "invalid row-size"); \
     147              :         BUILD_ASSERT(IN_RANGE(_col_size, 1, UINT8_MAX), "invalid col-size"); \
     148              :         IF_ENABLED(DT_NODE_HAS_PROP(node_id, actual_key_mask), ( \
     149              :         BUILD_ASSERT(DT_PROP_LEN(node_id, actual_key_mask) == _col_size, \
     150              :                      "actual-key-mask size does not match the number of columns"); \
     151              :         static INPUT_KBD_ACTUAL_KEY_MASK_CONST kbd_row_t \
     152              :                 INPUT_KBD_MATRIX_DATA_NAME(node_id, actual_key_mask)[_col_size] = \
     153              :                         DT_PROP(node_id, actual_key_mask); \
     154              :         )) \
     155              :         static kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, stable_state)[_col_size]; \
     156              :         static kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, unstable_state)[_col_size]; \
     157              :         static kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, previous_state)[_col_size]; \
     158              :         static kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, new_state)[_col_size]; \
     159              :         static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, scan_cycle_idx)[_row_size * _col_size];
     160              : 
     161              : /**
     162              :  * @brief Defines the common keyboard matrix support data from devicetree.
     163              :  */
     164            1 : #define INPUT_KBD_MATRIX_DT_DEFINE(node_id) \
     165              :         INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL( \
     166              :                 node_id, DT_PROP(node_id, row_size), DT_PROP(node_id, col_size))
     167              : 
     168              : /**
     169              :  * @brief Defines the common keyboard matrix support data from devicetree
     170              :  * instance, specify row and col count.
     171              :  *
     172              :  * @param inst Instance.
     173              :  * @param row_size The matrix row count.
     174              :  * @param col_size The matrix column count.
     175              :  */
     176            1 : #define INPUT_KBD_MATRIX_DT_INST_DEFINE_ROW_COL(inst, row_size, col_size) \
     177              :         INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL(DT_DRV_INST(inst), row_size, col_size)
     178              : 
     179              : /**
     180              :  * @brief Defines the common keyboard matrix support data from devicetree instance.
     181              :  *
     182              :  * @param inst Instance.
     183              :  */
     184            1 : #define INPUT_KBD_MATRIX_DT_INST_DEFINE(inst) \
     185              :         INPUT_KBD_MATRIX_DT_DEFINE(DT_DRV_INST(inst))
     186              : 
     187              : /**
     188              :  * @brief Initialize common keyboard matrix config from devicetree, specify row and col count.
     189              :  *
     190              :  * @param node_id The devicetree node identifier.
     191              :  * @param _api Pointer to a @ref input_kbd_matrix_api structure.
     192              :  * @param _row_size The matrix row count.
     193              :  * @param _col_size The matrix column count.
     194              :  */
     195            1 : #define INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL(node_id, _api, _row_size, _col_size) \
     196              :         { \
     197              :                 .api = _api, \
     198              :                 .row_size = _row_size, \
     199              :                 .col_size = _col_size, \
     200              :                 .poll_period_us = DT_PROP(node_id, poll_period_ms) * USEC_PER_MSEC, \
     201              :                 .stable_poll_period_us = DT_PROP_OR(node_id, stable_poll_period_ms, \
     202              :                                                     DT_PROP(node_id, poll_period_ms)) * \
     203              :                                                         USEC_PER_MSEC, \
     204              :                 .poll_timeout_ms = DT_PROP(node_id, poll_timeout_ms), \
     205              :                 .debounce_down_us = DT_PROP(node_id, debounce_down_ms) * USEC_PER_MSEC, \
     206              :                 .debounce_up_us = DT_PROP(node_id, debounce_up_ms) * USEC_PER_MSEC, \
     207              :                 .settle_time_us = DT_PROP(node_id, settle_time_us), \
     208              :                 .ghostkey_check = !DT_PROP(node_id, no_ghostkey_check), \
     209              :                 IF_ENABLED(DT_NODE_HAS_PROP(node_id, actual_key_mask), ( \
     210              :                 .actual_key_mask = INPUT_KBD_MATRIX_DATA_NAME(node_id, actual_key_mask), \
     211              :                 )) \
     212              :                 \
     213              :                 .matrix_stable_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, stable_state), \
     214              :                 .matrix_unstable_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, unstable_state), \
     215              :                 .matrix_previous_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, previous_state), \
     216              :                 .matrix_new_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, new_state), \
     217              :                 .scan_cycle_idx = INPUT_KBD_MATRIX_DATA_NAME(node_id, scan_cycle_idx), \
     218              :         }
     219              : 
     220              : /**
     221              :  * @brief Initialize common keyboard matrix config from devicetree.
     222              :  *
     223              :  * @param node_id The devicetree node identifier.
     224              :  * @param api Pointer to a @ref input_kbd_matrix_api structure.
     225              :  */
     226            1 : #define INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT(node_id, api) \
     227              :         INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL( \
     228              :                 node_id, api, DT_PROP(node_id, row_size), DT_PROP(node_id, col_size))
     229              : 
     230              : /**
     231              :  * @brief Initialize common keyboard matrix config from devicetree instance,
     232              :  * specify row and col count.
     233              :  *
     234              :  * @param inst Instance.
     235              :  * @param api Pointer to a @ref input_kbd_matrix_api structure.
     236              :  * @param row_size The matrix row count.
     237              :  * @param col_size The matrix column count.
     238              :  */
     239            1 : #define INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT_ROW_COL(inst, api, row_size, col_size) \
     240              :         INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL(DT_DRV_INST(inst), api, row_size, col_size)
     241              : 
     242              : /**
     243              :  * @brief Initialize common keyboard matrix config from devicetree instance.
     244              :  *
     245              :  * @param inst Instance.
     246              :  * @param api Pointer to a @ref input_kbd_matrix_api structure.
     247              :  */
     248            1 : #define INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT(inst, api) \
     249              :         INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT(DT_DRV_INST(inst), api)
     250              : 
     251              : /**
     252              :  * @brief Common keyboard matrix data.
     253              :  *
     254              :  * This structure **must** be placed first in the driver's data structure.
     255              :  */
     256            1 : struct input_kbd_matrix_common_data {
     257              :         /* Track previous cycles, used for debouncing. */
     258            0 :         uint32_t scan_clk_cycle[INPUT_KBD_MATRIX_SCAN_OCURRENCES];
     259            0 :         uint8_t scan_cycles_idx;
     260              : 
     261            0 :         struct k_sem poll_lock;
     262              : #ifdef CONFIG_PM_DEVICE
     263              :         atomic_t suspended;
     264              : #endif
     265              : 
     266            0 :         struct k_thread thread;
     267              : 
     268            0 :         K_KERNEL_STACK_MEMBER(thread_stack,
     269              :                               CONFIG_INPUT_KBD_MATRIX_THREAD_STACK_SIZE);
     270              : };
     271              : 
     272              : /**
     273              :  * @brief Validate the offset of the common data structures.
     274              :  *
     275              :  * @param config Name of the config structure.
     276              :  * @param data Name of the data structure.
     277              :  */
     278            1 : #define INPUT_KBD_STRUCT_CHECK(config, data) \
     279              :         BUILD_ASSERT(offsetof(config, common) == 0, \
     280              :                      "struct input_kbd_matrix_common_config must be placed first"); \
     281              :         BUILD_ASSERT(offsetof(data, common) == 0, \
     282              :                      "struct input_kbd_matrix_common_data must be placed first")
     283              : 
     284              : /**
     285              :  * @brief Start scanning the keyboard matrix
     286              :  *
     287              :  * Starts the keyboard matrix scanning cycle, this should be called in reaction
     288              :  * of a press event, after the device has been put in detect mode.
     289              :  *
     290              :  * @param dev Keyboard matrix device instance.
     291              :  */
     292            1 : void input_kbd_matrix_poll_start(const struct device *dev);
     293              : 
     294              : #if defined(CONFIG_INPUT_KBD_DRIVE_COLUMN_HOOK) || defined(__DOXYGEN__)
     295              : /**
     296              :  * @brief Drive column hook
     297              :  *
     298              :  * This can be implemented by the application to handle column selection
     299              :  * quirks. Called after the driver specific drive_column function. Requires
     300              :  * @kconfig{CONFIG_INPUT_KBD_DRIVE_COLUMN_HOOK} to be enabled.
     301              :  *
     302              :  * @param dev Keyboard matrix device instance.
     303              :  * @param col The column to drive, or
     304              :  *      @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE or
     305              :  *      @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL.
     306              :  */
     307            1 : void input_kbd_matrix_drive_column_hook(const struct device *dev, int col);
     308              : #endif
     309              : 
     310              : /**
     311              :  * @brief Common function to initialize a keyboard matrix device at init time.
     312              :  *
     313              :  * This function must be called at the end of the device init function.
     314              :  *
     315              :  * @param dev Keyboard matrix device instance.
     316              :  *
     317              :  * @retval 0 If initialized successfully.
     318              :  * @retval -errno Negative errno in case of failure.
     319              :  */
     320            1 : int input_kbd_matrix_common_init(const struct device *dev);
     321              : 
     322              : #ifdef CONFIG_PM_DEVICE
     323              : /**
     324              :  * @brief Common power management action handler.
     325              :  *
     326              :  * This handles PM actions for a keyboard matrix device, meant to be used as
     327              :  * argument of @ref PM_DEVICE_DT_INST_DEFINE.
     328              :  *
     329              :  * @param dev Keyboard matrix device instance.
     330              :  * @param action The power management action to handle.
     331              :  */
     332              : int input_kbd_matrix_pm_action(const struct device *dev,
     333              :                                enum pm_device_action action);
     334              : #endif
     335              : 
     336              : /** @} */
     337              : 
     338              : #endif /* ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_ */
        

Generated by: LCOV version 2.0-1