drivers: can: provide default callback to can_send() if NULL

Provide a default, internal callback to CAN controller drivers
implementation of can_send() if no callback was provided by the caller.

This allows for simplifying the CAN driver implementations of can_send() as
these no longer need special handling for callback/no callback operation.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-09-19 22:49:17 +02:00 committed by Fabio Baltieri
commit d6fc3f6596
2 changed files with 41 additions and 9 deletions

View file

@ -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;

View file

@ -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);
}
/** @} */
/**