@ -31,7 +31,8 @@ struct kscan_gpio_item_config {
# define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx)
# define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx)
# define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx)
# define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx)
static int kscan_gpio_config_interrupts ( struct device * * devices ,
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING ,
( static int kscan_gpio_config_interrupts ( struct device * * devices ,
const struct kscan_gpio_item_config * configs , size_t len ,
const struct kscan_gpio_item_config * configs , size_t len ,
gpio_flags_t flags ) {
gpio_flags_t flags ) {
for ( int i = 0 ; i < len ; i + + ) {
for ( int i = 0 ; i < len ; i + + ) {
@ -47,7 +48,8 @@ static int kscan_gpio_config_interrupts(struct device **devices,
}
}
return 0 ;
return 0 ;
}
} ) , ( ) )
# define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios)
# define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios)
# define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios)
# define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios)
# define INST_OUTPUT_LEN(n) \
# define INST_OUTPUT_LEN(n) \
@ -69,6 +71,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} ; \
} ; \
struct kscan_gpio_data_ # # n { \
struct kscan_gpio_data_ # # n { \
kscan_callback_t callback ; \
kscan_callback_t callback ; \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , ( ) , ( struct k_timer poll_timer ; ) ) \
struct COND_CODE_0 ( DT_INST_PROP ( n , debounce_period ) , ( k_work ) , ( k_delayed_work ) ) work ; \
struct COND_CODE_0 ( DT_INST_PROP ( n , debounce_period ) , ( k_work ) , ( k_delayed_work ) ) work ; \
bool matrix_state [ INST_MATRIX_ROWS ( n ) ] [ INST_MATRIX_COLS ( n ) ] ; \
bool matrix_state [ INST_MATRIX_ROWS ( n ) ] [ INST_MATRIX_COLS ( n ) ] ; \
struct device * rows [ INST_MATRIX_ROWS ( n ) ] ; \
struct device * rows [ INST_MATRIX_ROWS ( n ) ] ; \
@ -96,16 +99,17 @@ static int kscan_gpio_config_interrupts(struct device **devices,
return ( \
return ( \
COND_CODE_0 ( DT_ENUM_IDX ( DT_DRV_INST ( n ) , diode_direction ) , ( cfg - > rows ) , ( cfg - > cols ) ) ) ; \
COND_CODE_0 ( DT_ENUM_IDX ( DT_DRV_INST ( n ) , diode_direction ) , ( cfg - > rows ) , ( cfg - > cols ) ) ) ; \
} \
} \
static int kscan_gpio_enable_interrupts_ # # n ( struct device * dev ) { \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , \
return kscan_gpio_config_interrupts ( kscan_gpio_input_devices_ # # n ( dev ) , \
( static int kscan_gpio_enable_interrupts_ # # n ( struct device * dev ) { \
return kscan_gpio_config_interrupts ( kscan_gpio_input_devices_ # # n ( dev ) , \
kscan_gpio_input_configs_ # # n ( dev ) , INST_INPUT_LEN ( n ) , \
kscan_gpio_input_configs_ # # n ( dev ) , INST_INPUT_LEN ( n ) , \
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH ) ; \
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH ) ; \
} \
} \
static int kscan_gpio_disable_interrupts_ # # n ( struct device * dev ) { \
static int kscan_gpio_disable_interrupts_ # # n ( struct device * dev ) { \
return kscan_gpio_config_interrupts ( kscan_gpio_input_devices_ # # n ( dev ) , \
return kscan_gpio_config_interrupts ( kscan_gpio_input_devices_ # # n ( dev ) , \
kscan_gpio_input_configs_ # # n ( dev ) , INST_INPUT_LEN ( n ) , \
kscan_gpio_input_configs_ # # n ( dev ) , INST_INPUT_LEN ( n ) , \
GPIO_INT_DISABLE ) ; \
GPIO_INT_DISABLE ) ; \
} \
} ) , ( ) ) \
static void kscan_gpio_set_output_state_ # # n ( struct device * dev , int value ) { \
static void kscan_gpio_set_output_state_ # # n ( struct device * dev , int value ) { \
for ( int i = 0 ; i < INST_OUTPUT_LEN ( n ) ; i + + ) { \
for ( int i = 0 ; i < INST_OUTPUT_LEN ( n ) ; i + + ) { \
struct device * in_dev = kscan_gpio_output_devices_ # # n ( dev ) [ i ] ; \
struct device * in_dev = kscan_gpio_output_devices_ # # n ( dev ) [ i ] ; \
@ -128,7 +132,8 @@ static int kscan_gpio_config_interrupts(struct device **devices,
/* Disable our interrupts temporarily while we scan, to avoid */ \
/* Disable our interrupts temporarily while we scan, to avoid */ \
/* re-entry while we iterate columns and set them active one by one */ \
/* re-entry while we iterate columns and set them active one by one */ \
/* to get pressed state for each matrix cell. */ \
/* to get pressed state for each matrix cell. */ \
kscan_gpio_disable_interrupts_ # # n ( dev ) ; \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , \
( kscan_gpio_disable_interrupts_ # # n ( dev ) ; ) , ( ) ) \
kscan_gpio_set_output_state_ # # n ( dev , 0 ) ; \
kscan_gpio_set_output_state_ # # n ( dev , 0 ) ; \
for ( int o = 0 ; o < INST_OUTPUT_LEN ( n ) ; o + + ) { \
for ( int o = 0 ; o < INST_OUTPUT_LEN ( n ) ; o + + ) { \
struct device * out_dev = kscan_gpio_output_devices_ # # n ( dev ) [ o ] ; \
struct device * out_dev = kscan_gpio_output_devices_ # # n ( dev ) [ o ] ; \
@ -143,10 +148,11 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \
} \
gpio_pin_set ( out_dev , out_cfg - > pin , 0 ) ; \
gpio_pin_set ( out_dev , out_cfg - > pin , 0 ) ; \
} \
} \
/* Set all our outputs as active again, then re-enable interrupts, */ \
/* Set all our outputs as active again. */ \
/* so we can trigger interrupts again for future press/release */ \
kscan_gpio_set_output_state_ # # n ( dev , 1 ) ; \
kscan_gpio_set_output_state_ # # n ( dev , 1 ) ; \
kscan_gpio_enable_interrupts_ # # n ( dev ) ; \
/*Re-enable interrupts so that they can be triggered again for future press/release*/ \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , \
( kscan_gpio_enable_interrupts_ # # n ( dev ) ; ) , ( ) ) \
for ( int r = 0 ; r < INST_MATRIX_ROWS ( n ) ; r + + ) { \
for ( int r = 0 ; r < INST_MATRIX_ROWS ( n ) ; r + + ) { \
for ( int c = 0 ; c < INST_MATRIX_COLS ( n ) ; c + + ) { \
for ( int c = 0 ; c < INST_MATRIX_COLS ( n ) ; c + + ) { \
bool pressed = read_state [ r ] [ c ] ; \
bool pressed = read_state [ r ] [ c ] ; \
@ -193,12 +199,29 @@ static int kscan_gpio_config_interrupts(struct device **devices,
return 0 ; \
return 0 ; \
} ; \
} ; \
static int kscan_gpio_enable_ # # n ( struct device * dev ) { \
static int kscan_gpio_enable_ # # n ( struct device * dev ) { \
int err = kscan_gpio_enable_interrupts_ # # n ( dev ) ; \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , \
if ( err ) { \
( int err = kscan_gpio_enable_interrupts_ # # n ( dev ) ; \
return err ; \
if ( err ) { \
} \
return err ; \
return kscan_gpio_read_ # # n ( dev ) ; \
} \
return kscan_gpio_read_ # # n ( dev ) ; ) , \
( struct kscan_gpio_data_ # # n * data = dev - > driver_data ; \
k_timer_start ( & data - > poll_timer , K_MSEC ( 10 ) , K_MSEC ( 10 ) ) ; \
return 0 ; ) ) \
} ; \
static int kscan_gpio_disable_ # # n ( struct device * dev ) { \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , \
( return kscan_gpio_disable_interrupts_ # # n ( dev ) ; ) , \
( struct kscan_gpio_data_ # # n * data = dev - > driver_data ; \
k_timer_stop ( & data - > poll_timer ) ; \
return 0 ; ) ) \
} ; \
} ; \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , ( ) , \
( static void kscan_gpio_timer_handler ( struct k_timer * timer ) { \
struct kscan_gpio_data_ # # n * data = \
CONTAINER_OF ( timer , struct kscan_gpio_data_ # # n , poll_timer ) ; \
k_work_submit ( & data - > work . work ) ; \
} ) ) \
static int kscan_gpio_init_ # # n ( struct device * dev ) { \
static int kscan_gpio_init_ # # n ( struct device * dev ) { \
struct kscan_gpio_data_ # # n * data = dev - > driver_data ; \
struct kscan_gpio_data_ # # n * data = dev - > driver_data ; \
int err ; \
int err ; \
@ -214,6 +237,8 @@ static int kscan_gpio_config_interrupts(struct device **devices,
if ( err ) { \
if ( err ) { \
LOG_ERR ( " Unable to configure pin %d on %s for input " , in_cfg - > pin , in_cfg - > label ) ; \
LOG_ERR ( " Unable to configure pin %d on %s for input " , in_cfg - > pin , in_cfg - > label ) ; \
return err ; \
return err ; \
} else { \
LOG_DBG ( " Configured pin %d on %s for input " , in_cfg - > pin , in_cfg - > label ) ; \
} \
} \
irq_callbacks_ # # n [ i ] . work = & data - > work ; \
irq_callbacks_ # # n [ i ] . work = & data - > work ; \
gpio_init_callback ( & irq_callbacks_ # # n [ i ] . callback , \
gpio_init_callback ( & irq_callbacks_ # # n [ i ] . callback , \
@ -241,6 +266,8 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \
} \
} \
} \
data - > dev = dev ; \
data - > dev = dev ; \
COND_CODE_0 ( ZMK_KSCAN_MATRIX_POLLING , ( ) , \
( k_timer_init ( & data - > poll_timer , kscan_gpio_timer_handler , NULL ) ; ) ) \
( COND_CODE_0 ( DT_INST_PROP ( n , debounce_period ) , ( k_work_init ) , ( k_delayed_work_init ) ) ) ( \
( COND_CODE_0 ( DT_INST_PROP ( n , debounce_period ) , ( k_work_init ) , ( k_delayed_work_init ) ) ) ( \
& data - > work , kscan_gpio_work_handler_ # # n ) ; \
& data - > work , kscan_gpio_work_handler_ # # n ) ; \
return 0 ; \
return 0 ; \
@ -248,7 +275,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
static const struct kscan_driver_api gpio_driver_api_ # # n = { \
static const struct kscan_driver_api gpio_driver_api_ # # n = { \
. config = kscan_gpio_configure_ # # n , \
. config = kscan_gpio_configure_ # # n , \
. enable_callback = kscan_gpio_enable_ # # n , \
. enable_callback = kscan_gpio_enable_ # # n , \
. disable_callback = kscan_gpio_disable_interrupts_ # # n , \
. disable_callback = kscan_gpio_disable_ # # n , \
} ; \
} ; \
static const struct kscan_gpio_config_ # # n kscan_gpio_config_ # # n = { \
static const struct kscan_gpio_config_ # # n kscan_gpio_config_ # # n = { \
. rows = { UTIL_LISTIFY ( INST_MATRIX_ROWS ( n ) , _KSCAN_GPIO_ROW_CFG_INIT , n ) } , \
. rows = { UTIL_LISTIFY ( INST_MATRIX_ROWS ( n ) , _KSCAN_GPIO_ROW_CFG_INIT , n ) } , \