diff --git a/drivers/can/can_loopback.c b/drivers/can/can_loopback.c index fb06a8f1a88..67e7ecd7ff0 100644 --- a/drivers/can/can_loopback.c +++ b/drivers/can/can_loopback.c @@ -236,10 +236,12 @@ int can_loopback_recover(const struct device *dev, k_timeout_t timeout) #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ static void can_loopback_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { ARG_UNUSED(dev); ARG_UNUSED(cb); + ARG_UNUSED(user_data); } int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate) diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index fdf935dcc9f..c4b2d1065fe 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -461,11 +461,12 @@ static void can_mcan_state_change_handler(const struct can_mcan_config *cfg, enum can_state state; struct can_bus_err_cnt err_cnt; const can_state_change_callback_t cb = data->state_change_cb; + void *cb_data = data->state_change_cb_data; state = can_mcan_get_state(cfg, &err_cnt); if (cb != NULL) { - cb(state, err_cnt); + cb(state, err_cnt, cb_data); } } diff --git a/drivers/can/can_mcan.h b/drivers/can/can_mcan.h index 068b167f843..eb6952ed835 100644 --- a/drivers/can/can_mcan.h +++ b/drivers/can/can_mcan.h @@ -173,6 +173,7 @@ struct can_mcan_data { void *cb_arg_std[NUM_STD_FILTER_DATA]; void *cb_arg_ext[NUM_EXT_FILTER_DATA]; can_state_change_callback_t state_change_cb; + void *state_change_cb_data; uint32_t std_filt_rtr; uint32_t std_filt_rtr_mask; uint8_t ext_filt_rtr; diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index 083445d62fc..5304186c4f8 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -563,11 +563,13 @@ static void mcp2515_remove_rx_filter(const struct device *dev, int filter_id) } static void mcp2515_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { struct mcp2515_data *dev_data = DEV_DATA(dev); dev_data->state_change_cb = cb; + dev_data->state_change_cb_data = user_data; } static void mcp2515_rx_filter(const struct device *dev, @@ -673,6 +675,7 @@ static void mcp2515_handle_errors(const struct device *dev) { struct mcp2515_data *dev_data = DEV_DATA(dev); can_state_change_callback_t state_change_cb = dev_data->state_change_cb; + void *state_change_cb_data = dev_data->state_change_cb_data; enum can_state state; struct can_bus_err_cnt err_cnt; @@ -680,7 +683,7 @@ static void mcp2515_handle_errors(const struct device *dev) if (state_change_cb && dev_data->old_state != state) { dev_data->old_state = state; - state_change_cb(state, err_cnt); + state_change_cb(state, err_cnt, state_change_cb_data); } } diff --git a/drivers/can/can_mcp2515.h b/drivers/can/can_mcp2515.h index 92b4e96152c..84f21e5a7c8 100644 --- a/drivers/can/can_mcp2515.h +++ b/drivers/can/can_mcp2515.h @@ -43,6 +43,7 @@ struct mcp2515_data { void *cb_arg[CONFIG_CAN_MAX_FILTER]; struct zcan_filter filter[CONFIG_CAN_MAX_FILTER]; can_state_change_callback_t state_change_cb; + void *state_change_cb_data; /* general data */ struct k_mutex mutex; diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 942c108a931..c6b76846ec4 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -117,6 +117,7 @@ struct mcux_flexcan_data { struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX]; enum can_state state; can_state_change_callback_t state_change_cb; + void *state_change_cb_data; struct can_timing timing; }; @@ -423,11 +424,13 @@ static int mcux_flexcan_add_rx_filter(const struct device *dev, } static void mcux_flexcan_set_state_change_callback(const struct device *dev, - can_state_change_callback_t callback) + can_state_change_callback_t callback, + void *user_data) { struct mcux_flexcan_data *data = dev->data; data->state_change_cb = callback; + data->state_change_cb_data = user_data; } static enum can_state mcux_flexcan_get_state(const struct device *dev, @@ -518,6 +521,7 @@ static inline void mcux_flexcan_transfer_error_status(const struct device *dev, const struct mcux_flexcan_config *config = dev->config; struct mcux_flexcan_data *data = dev->data; const can_state_change_callback_t cb = data->state_change_cb; + void *cb_data = data->state_change_cb_data; can_tx_callback_t function; int status = 0; @@ -551,7 +555,7 @@ static inline void mcux_flexcan_transfer_error_status(const struct device *dev, data->state = state; if (cb) { - cb(state, err_cnt); + cb(state, err_cnt, cb_data); } } diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index 60ee7f73dde..12962348fca 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -81,11 +81,13 @@ static enum can_state mcux_mcan_get_state(const struct device *dev, } static void mcux_mcan_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { struct mcux_mcan_data *data = dev->data; data->mcan.state_change_cb = cb; + data->mcan.state_change_cb_data = user_data; } static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate) diff --git a/drivers/can/can_rcar.c b/drivers/can/can_rcar.c index 2150ad8b6bf..a6174e90d20 100644 --- a/drivers/can/can_rcar.c +++ b/drivers/can/can_rcar.c @@ -199,6 +199,7 @@ struct can_rcar_data { void *rx_callback_arg[CONFIG_CAN_RCAR_MAX_FILTER]; struct zcan_filter filter[CONFIG_CAN_RCAR_MAX_FILTER]; can_state_change_callback_t state_change_cb; + void *state_change_cb_data; enum can_state state; }; @@ -251,6 +252,7 @@ static void can_rcar_state_change(const struct device *dev, uint32_t newstate) const struct can_rcar_cfg *config = DEV_CAN_CFG(dev); struct can_rcar_data *data = DEV_CAN_DATA(dev); const can_state_change_callback_t cb = data->state_change_cb; + void *state_change_cb_data = data->state_change_cb_data; struct can_bus_err_cnt err_cnt; if (data->state == newstate) { @@ -265,7 +267,7 @@ static void can_rcar_state_change(const struct device *dev, uint32_t newstate) return; } can_rcar_get_error_count(config, &err_cnt); - cb(newstate, err_cnt); + cb(newstate, err_cnt, state_change_cb_data); } static void can_rcar_error(const struct device *dev) @@ -657,11 +659,13 @@ unlock: } static void can_rcar_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { struct can_rcar_data *data = DEV_CAN_DATA(dev); data->state_change_cb = cb; + data->state_change_cb_data = user_data; } static enum can_state can_rcar_get_state(const struct device *dev, @@ -862,6 +866,7 @@ static int can_rcar_init(const struct device *dev) memset(data->rx_callback, 0, sizeof(data->rx_callback)); data->state = CAN_ERROR_ACTIVE; data->state_change_cb = NULL; + data->state_change_cb_data = NULL; /* reset the registers */ ret = clock_control_off(config->clock_dev, diff --git a/drivers/can/can_stm32.c b/drivers/can/can_stm32.c index 572b4addc70..6a19b78c8c1 100644 --- a/drivers/can/can_stm32.c +++ b/drivers/can/can_stm32.c @@ -123,6 +123,7 @@ static inline void can_stm32_bus_state_change_isr(CAN_TypeDef *can, struct can_bus_err_cnt err_cnt; enum can_state state; const can_state_change_callback_t cb = data->state_change_cb; + void *state_change_cb_data = data->state_change_cb_data; if (!(can->ESR & CAN_ESR_EPVF) && !(can->ESR & CAN_ESR_BOFF)) { return; @@ -140,7 +141,7 @@ static inline void can_stm32_bus_state_change_isr(CAN_TypeDef *can, } if (cb != NULL) { - cb(state, err_cnt); + cb(state, err_cnt, state_change_cb_data); } } @@ -441,6 +442,7 @@ static int can_stm32_init(const struct device *dev) data->mb1.tx_callback = NULL; data->mb2.tx_callback = NULL; data->state_change_cb = NULL; + data->state_change_cb_data = NULL; data->filter_usage = (1ULL << CAN_MAX_NUMBER_OF_FILTERS) - 1ULL; (void)memset(data->rx_cb, 0, sizeof(data->rx_cb)); @@ -525,13 +527,15 @@ static int can_stm32_init(const struct device *dev) } static void can_stm32_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { struct can_stm32_data *data = DEV_DATA(dev); const struct can_stm32_config *cfg = DEV_CFG(dev); CAN_TypeDef *can = cfg->can; data->state_change_cb = cb; + data->state_change_cb_data = user_data; if (cb == NULL) { can->IER &= ~CAN_IER_EPVIE; diff --git a/drivers/can/can_stm32.h b/drivers/can/can_stm32.h index 1d8b0d3e67b..5e83dedab87 100644 --- a/drivers/can/can_stm32.h +++ b/drivers/can/can_stm32.h @@ -65,6 +65,7 @@ struct can_stm32_data { can_rx_callback_t rx_cb[CONFIG_CAN_MAX_FILTER]; void *cb_arg[CONFIG_CAN_MAX_FILTER]; can_state_change_callback_t state_change_cb; + void *state_change_cb_data; }; struct can_stm32_config { diff --git a/drivers/can/can_stm32fd.c b/drivers/can/can_stm32fd.c index 99fcdaf2533..6f2130e87dd 100644 --- a/drivers/can/can_stm32fd.c +++ b/drivers/can/can_stm32fd.c @@ -56,11 +56,13 @@ void can_stm32fd_clock_enable(void) } void can_stm32fd_set_state_change_callback(const struct device *dev, - can_state_change_callback_t cb) + can_state_change_callback_t cb, + void *user_data) { struct can_stm32fd_data *data = DEV_DATA(dev); data->mcan_data.state_change_cb = cb; + data->mcan_data.state_change_cb_data = user_data; } static int can_stm32fd_init(const struct device *dev) diff --git a/include/drivers/can.h b/include/drivers/can.h index 49a15db74a4..91738feed40 100644 --- a/include/drivers/can.h +++ b/include/drivers/can.h @@ -268,7 +268,7 @@ typedef void (*can_tx_callback_t)(int error, void *user_data); * @brief Defines the application callback handler function signature for receiving. * * @param frame Received frame. - * @param user_data User data provided when the filter was attached. + * @param user_data User data provided when the filter was added. */ typedef void (*can_rx_callback_t)(struct zcan_frame *frame, void *user_data); @@ -276,10 +276,13 @@ typedef void (*can_rx_callback_t)(struct zcan_frame *frame, void *user_data); * @typedef can_state_change_callback_t * @brief Defines the state change callback handler function signature * - * @param state State of the CAN controller. - * @param err_cnt CAN controller error counter values. + * @param state State of the CAN controller. + * @param err_cnt CAN controller error counter values. + * @param user_data User data provided the callback was set. */ -typedef void (*can_state_change_callback_t)(enum can_state state, struct can_bus_err_cnt err_cnt); +typedef void (*can_state_change_callback_t)(enum can_state state, + struct can_bus_err_cnt err_cnt, + void *user_data); /** * @cond INTERNAL_HIDDEN @@ -351,7 +354,8 @@ typedef enum can_state (*can_get_state_t)(const struct device *dev, * See @a can_set_state_change_callback() for argument description */ typedef void(*can_set_state_change_callback_t)(const struct device *dev, - can_state_change_callback_t callback); + can_state_change_callback_t callback, + void *user_data); /** * @typedef can_get_core_clock_t @@ -861,15 +865,17 @@ static inline int z_impl_can_recover(const struct device *dev, k_timeout_t timeo * Only one callback can be registered per controller. Calling this function * again overrides any previously registered callback. * - * @param dev Pointer to the device structure for the driver instance. - * @param callback Callback function. + * @param dev Pointer to the device structure for the driver instance. + * @param callback Callback function. + * @param user_data User data to pass to callback function. */ static inline void can_set_state_change_callback(const struct device *dev, - can_state_change_callback_t callback) + can_state_change_callback_t callback, + void *user_data) { const struct can_driver_api *api = (const struct can_driver_api *)dev->api; - return api->set_state_change_callback(dev, callback); + return api->set_state_change_callback(dev, callback, user_data); } /** @} */ @@ -1214,7 +1220,7 @@ __deprecated static inline void can_detach(const struct device *dev, int filter_ __deprecated static inline void can_register_state_change_isr(const struct device *dev, can_state_change_callback_t isr) { - can_set_state_change_callback(dev, isr); + can_set_state_change_callback(dev, isr, NULL); } /** @endcond */ diff --git a/samples/drivers/can/src/main.c b/samples/drivers/can/src/main.c index 361c5e82c07..276f0f97088 100644 --- a/samples/drivers/can/src/main.c +++ b/samples/drivers/can/src/main.c @@ -165,11 +165,13 @@ void state_change_work_handler(struct k_work *work) #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ } -void state_change_callback(enum can_state state, struct can_bus_err_cnt err_cnt) +void state_change_callback(enum can_state state, struct can_bus_err_cnt err_cnt, void *user_data) { + struct k_work *work = (struct k_work *)user_data; + current_state = state; current_err_cnt = err_cnt; - k_work_submit(&state_change_work); + k_work_submit(work); } void main(void) @@ -257,7 +259,7 @@ void main(void) printk("ERROR spawning poll_state_thread\n"); } - can_set_state_change_callback(can_dev, state_change_callback); + can_set_state_change_callback(can_dev, state_change_callback, &state_change_work); printk("Finished init.\n");