LCOV - code coverage report
Current view: top level - zephyr/input - input_kbd_matrix.h Hit Total Coverage
Test: new.info Lines: 24 49 49.0 %
Date: 2024-12-21 15:13:37

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

Generated by: LCOV version 1.14