diff --git a/drivers/can/can_common.c b/drivers/can/can_common.c index f34b22ab109..4eafb0f1ccd 100644 --- a/drivers/can/can_common.c +++ b/drivers/can/can_common.c @@ -17,6 +17,44 @@ LOG_MODULE_REGISTER(can_common, CONFIG_CAN_LOG_LEVEL); /* CAN sync segment is always one time quantum */ #define CAN_SYNC_SEG 1 +struct can_tx_default_cb_ctx { + struct k_sem done; + int status; +}; + +static void can_tx_default_cb(const struct device *dev, int error, void *user_data) +{ + struct can_tx_default_cb_ctx *ctx = user_data; + + ctx->status = error; + k_sem_give(&ctx->done); +} + +int z_impl_can_send(const struct device *dev, const struct can_frame *frame, + k_timeout_t timeout, can_tx_callback_t callback, + void *user_data) +{ + const struct can_driver_api *api = (const struct can_driver_api *)dev->api; + + if (callback == NULL) { + struct can_tx_default_cb_ctx ctx; + int err; + + k_sem_init(&ctx.done, 0, 1); + + err = api->send(dev, frame, timeout, can_tx_default_cb, &ctx); + if (err != 0) { + return err; + } + + k_sem_take(&ctx.done, K_FOREVER); + + return ctx.status; + } + + return api->send(dev, frame, timeout, callback, user_data); +} + static void can_msgq_put(const struct device *dev, struct can_frame *frame, void *user_data) { struct k_msgq *msgq = (struct k_msgq *)user_data; diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 3f64bb6393c..419b72058d3 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -348,6 +348,9 @@ typedef int (*can_set_mode_t)(const struct device *dev, can_mode_t mode); /** * @brief Callback API upon sending a CAN frame * See @a can_send() for argument description + * + * @note From a driver perspective `callback` will never be `NULL` as a default callback will be + * provided if none is provided by the caller. This allows for simplifying the driver handling. */ typedef int (*can_send_t)(const struct device *dev, const struct can_frame *frame, @@ -1095,15 +1098,6 @@ __syscall int can_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout, can_tx_callback_t callback, void *user_data); -static inline int z_impl_can_send(const struct device *dev, const struct can_frame *frame, - k_timeout_t timeout, can_tx_callback_t callback, - void *user_data) -{ - const struct can_driver_api *api = (const struct can_driver_api *)dev->api; - - return api->send(dev, frame, timeout, callback, user_data); -} - /** @} */ /**