From d5672c9ee32c48ba7f49cf5698d98dd42a69e5ec Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Fri, 17 Mar 2023 11:21:26 +0100 Subject: [PATCH] drivers: can: check timing parameters Check the requested CAN timing parameters against the min/max values supported by the driver and return an error if they are out of range. Signed-off-by: Henrik Brix Andersen --- drivers/can/can_common.c | 55 ++++++++++++++++++++++++++++++++++++ include/zephyr/drivers/can.h | 34 +++++----------------- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/drivers/can/can_common.c b/drivers/can/can_common.c index 526762fd4f6..8271c99acd0 100644 --- a/drivers/can/can_common.c +++ b/drivers/can/can_common.c @@ -250,6 +250,41 @@ static uint16_t sample_point_for_bitrate(uint32_t bitrate) return sample_pnt; } +static int check_timing_in_range(const struct can_timing *timing, + const struct can_timing *min, + const struct can_timing *max) +{ + if (timing->sjw != CAN_SJW_NO_CHANGE && + !IN_RANGE(timing->sjw, min->sjw, max->sjw)) { + return -ENOTSUP; + } + + if (!IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) || + !IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) || + !IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) || + !IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) { + return -ENOTSUP; + } + + return 0; +} + +int z_impl_can_set_timing(const struct device *dev, + const struct can_timing *timing) +{ + const struct can_driver_api *api = (const struct can_driver_api *)dev->api; + const struct can_timing *min = can_get_timing_min(dev); + const struct can_timing *max = can_get_timing_max(dev); + int err; + + err = check_timing_in_range(timing, min, max); + if (err != 0) { + return err; + } + + return api->set_timing(dev, timing); +} + int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate) { struct can_timing timing; @@ -285,6 +320,26 @@ int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate) } #ifdef CONFIG_CAN_FD_MODE +int z_impl_can_set_timing_data(const struct device *dev, + const struct can_timing *timing_data) +{ + const struct can_driver_api *api = (const struct can_driver_api *)dev->api; + const struct can_timing *min = can_get_timing_data_min(dev); + const struct can_timing *max = can_get_timing_data_max(dev); + int err; + + if (api->set_timing_data == NULL) { + return -ENOSYS; + } + + err = check_timing_in_range(timing_data, min, max); + if (err != 0) { + return err; + } + + return api->set_timing_data(dev, timing_data); +} + int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) { struct can_timing timing_data; diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 600b0fda3eb..89b6d3c4710 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -234,6 +234,11 @@ struct can_bus_err_cnt { uint8_t rx_err_cnt; }; +/** Synchronization Jump Width (SJW) value to indicate that the SJW should not + * be changed by the timing calculation. + */ +#define CAN_SJW_NO_CHANGE 0 + /** * @brief CAN bus timing structure * @@ -868,25 +873,12 @@ __syscall int can_calc_timing_data(const struct device *dev, struct can_timing * * @retval 0 If successful. * @retval -EBUSY if the CAN controller is not in stopped state. * @retval -EIO General input/output error, failed to configure device. + * @retval -ENOTSUP if the timing parameters are not supported by the driver. * @retval -ENOSYS if CAN-FD support is not implemented by the driver. */ __syscall int can_set_timing_data(const struct device *dev, const struct can_timing *timing_data); -#ifdef CONFIG_CAN_FD_MODE -static inline int z_impl_can_set_timing_data(const struct device *dev, - const struct can_timing *timing_data) -{ - const struct can_driver_api *api = (const struct can_driver_api *)dev->api; - - if (api->set_timing_data == NULL) { - return -ENOSYS; - } - - return api->set_timing_data(dev, timing_data); -} -#endif /* CONFIG_CAN_FD_MODE */ - /** * @brief Set the bitrate for the data phase of the CAN-FD controller * @@ -936,11 +928,6 @@ __syscall int can_set_bitrate_data(const struct device *dev, uint32_t bitrate_da int can_calc_prescaler(const struct device *dev, struct can_timing *timing, uint32_t bitrate); -/** Synchronization Jump Width (SJW) value to indicate that the SJW should not - * be changed by the timing calculation. - */ -#define CAN_SJW_NO_CHANGE 0 - /** * @brief Configure the bus timing of a CAN controller. * @@ -953,19 +940,12 @@ int can_calc_prescaler(const struct device *dev, struct can_timing *timing, * * @retval 0 If successful. * @retval -EBUSY if the CAN controller is not in stopped state. + * @retval -ENOTSUP if the timing parameters are not supported by the driver. * @retval -EIO General input/output error, failed to configure device. */ __syscall int can_set_timing(const struct device *dev, const struct can_timing *timing); -static inline int z_impl_can_set_timing(const struct device *dev, - const struct can_timing *timing) -{ - const struct can_driver_api *api = (const struct can_driver_api *)dev->api; - - return api->set_timing(dev, timing); -} - /** * @brief Get the supported modes of the CAN controller *