drivers: can: fix multiple issues
* Registration of interrupt context callbacks from user mode is forbidden. - Remove can_attach_isr() as a system call - Enforce that can_send() has a NULL callback parameter * k_msgq are kernel objects that do not live in user memory. Fix the checks for it in can_attach_msgq(). * CAN API documentation was with the API struct typedefs and not the actual APIs. Moved. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
319d8c7e2a
commit
26085d9570
2 changed files with 85 additions and 104 deletions
|
@ -23,6 +23,8 @@ Z_SYSCALL_HANDLER(can_send, dev, msg, timeout, callback_isr) {
|
|||
sizeof(struct zcan_frame)));
|
||||
Z_OOPS(Z_SYSCALL_MEMORY_READ(((struct zcan_frame *)msg)->data,
|
||||
sizeof((struct zcan_frame *)msg)->data));
|
||||
Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback_isr == 0,
|
||||
"callbacks may not be set from user mode"));
|
||||
|
||||
return _impl_can_send((struct device *)dev,
|
||||
(const struct zcan_frame *)msg,
|
||||
|
@ -35,29 +37,13 @@ Z_SYSCALL_HANDLER(can_attach_msgq, dev, msgq, filter) {
|
|||
|
||||
Z_OOPS(Z_SYSCALL_MEMORY_READ((struct zcan_filter *)filter,
|
||||
sizeof(struct zcan_filter)));
|
||||
Z_OOPS(Z_SYSCALL_MEMORY_WRITE((struct k_msgq *)msgq,
|
||||
sizeof(struct k_msgq)));
|
||||
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(((struct k_msgq *)msgq)->buffer_start,
|
||||
((struct k_msgq *)msgq)->buffer_end -
|
||||
((struct k_msgq *)msgq)->buffer_start));
|
||||
Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
|
||||
|
||||
return _impl_can_attach_msgq((struct device *)dev,
|
||||
(struct k_msgq *)msgq,
|
||||
(const struct zcan_filter *) filter);
|
||||
}
|
||||
|
||||
Z_SYSCALL_HANDLER(can_attach_isr, dev, isr, filter) {
|
||||
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, attach_isr));
|
||||
|
||||
Z_OOPS(Z_SYSCALL_MEMORY_READ((struct zcan_filter *)filter,
|
||||
sizeof(struct zcan_filter)));
|
||||
|
||||
return _impl_can_attach_isr((struct device *)dev,
|
||||
(can_rx_callback_t)isr,
|
||||
(const struct zcan_filter *) filter);
|
||||
}
|
||||
|
||||
Z_SYSCALL_HANDLER(can_detach, dev, filter_id) {
|
||||
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, detach));
|
||||
|
|
169
include/can.h
169
include/can.h
|
@ -216,19 +216,29 @@ typedef void (*can_tx_callback_t)(u32_t error_flags);
|
|||
*/
|
||||
typedef void (*can_rx_callback_t)(struct zcan_frame *msg);
|
||||
|
||||
/**
|
||||
* @brief Configure operation of a host controller.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param mode Operation mode
|
||||
* @param bitrate bus-speed in Baud/s
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error, failed to configure device.
|
||||
*/
|
||||
typedef int (*can_configure_t)(struct device *dev, enum can_mode mode,
|
||||
u32_t bitrate);
|
||||
|
||||
typedef int (*can_send_t)(struct device *dev, const struct zcan_frame *msg,
|
||||
s32_t timeout, can_tx_callback_t callback_isr);
|
||||
|
||||
|
||||
typedef int (*can_attach_msgq_t)(struct device *dev, struct k_msgq *msg_q,
|
||||
const struct zcan_filter *filter);
|
||||
|
||||
typedef int (*can_attach_isr_t)(struct device *dev, can_rx_callback_t isr,
|
||||
const struct zcan_filter *filter);
|
||||
|
||||
typedef void (*can_detach_t)(struct device *dev, int filter_id);
|
||||
|
||||
struct can_driver_api {
|
||||
can_configure_t configure;
|
||||
can_send_t send;
|
||||
can_attach_isr_t attach_isr;
|
||||
can_attach_msgq_t attach_msgq;
|
||||
can_detach_t detach;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Perform data transfer to CAN bus.
|
||||
*
|
||||
|
@ -239,80 +249,13 @@ typedef int (*can_configure_t)(struct device *dev, enum can_mode mode,
|
|||
* @param msg Message to transfer.
|
||||
* @param timeout Waiting for empty tx mailbox timeout in ms or K_FOREVER.
|
||||
* @param callback_isr Is called when message was sent or a transmission error
|
||||
* occurred. If null, this function is blocking until
|
||||
* message is sent.
|
||||
* occurred. If NULL, this function is blocking until
|
||||
* message is sent. This must be NULL if called from user
|
||||
* mode.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval CAN_TX_* on failure.
|
||||
*/
|
||||
typedef int (*can_send_t)(struct device *dev, const struct zcan_frame *msg,
|
||||
s32_t timeout, can_tx_callback_t callback_isr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attach a message queue to a single or group of identifiers.
|
||||
*
|
||||
* This routine attaches a message queue to identifiers specified by
|
||||
* a filter. Whenever the filter matches, the message is pushed to the queue
|
||||
* If a message passes more than one filter the priority of the match
|
||||
* is hardware dependent.
|
||||
* A message queue can be attached to more than one filter.
|
||||
* The message queue must me initialized before.
|
||||
* *
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param msgq Pointer to the already initialized message queue.
|
||||
* @param filter Pointer to a zcan_filter structure defining the id
|
||||
* filtering.
|
||||
*
|
||||
* @retval filter id on success.
|
||||
* @retval CAN_NO_FREE_FILTER if there is no filter left.
|
||||
*/
|
||||
typedef int (*can_attach_msgq_t)(struct device *dev, struct k_msgq *msg_q,
|
||||
const struct zcan_filter *filter);
|
||||
|
||||
/**
|
||||
* @brief Attach an isr callback function to a single or group of identifiers.
|
||||
*
|
||||
* This routine attaches an isr callback to identifiers specified by
|
||||
* a filter. Whenever the filter matches, the callback function is called
|
||||
* with isr context.
|
||||
* If a message passes more than one filter the priority of the match
|
||||
* is hardware dependent.
|
||||
* A callback function can be attached to more than one filter.
|
||||
* *
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param isr Callback function pointer.
|
||||
* @param filter Pointer to a zcan_filter structure defining the id
|
||||
* filtering.
|
||||
*
|
||||
* @retval filter id on success.
|
||||
* @retval CAN_NO_FREE_FILTER if there is no filter left.
|
||||
*/
|
||||
typedef int (*can_attach_isr_t)(struct device *dev, can_rx_callback_t isr,
|
||||
const struct zcan_filter *filter);
|
||||
|
||||
/**
|
||||
* @brief Detach an isr or message queue from the identifier filtering.
|
||||
*
|
||||
* This routine detaches an isr callback or message queue from the identifier
|
||||
* filtering.
|
||||
* *
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param filter_id filter id returned by can_attach_isr or can_attach_msgq.
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
typedef void (*can_detach_t)(struct device *dev, int filter_id);
|
||||
|
||||
struct can_driver_api {
|
||||
can_configure_t configure;
|
||||
can_send_t send;
|
||||
can_attach_isr_t attach_isr;
|
||||
can_attach_msgq_t attach_msgq;
|
||||
can_detach_t detach;
|
||||
};
|
||||
|
||||
|
||||
__syscall int can_send(struct device *dev, const struct zcan_frame *msg,
|
||||
s32_t timeout, can_tx_callback_t callback_isr);
|
||||
|
||||
|
@ -369,7 +312,25 @@ static inline int can_write(struct device *dev, const u8_t *data, u8_t length,
|
|||
return can_send(dev, &msg, timeout, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attach a message queue to a single or group of identifiers.
|
||||
*
|
||||
* This routine attaches a message queue to identifiers specified by
|
||||
* a filter. Whenever the filter matches, the message is pushed to the queue
|
||||
* If a message passes more than one filter the priority of the match
|
||||
* is hardware dependent.
|
||||
* A message queue can be attached to more than one filter.
|
||||
* The message queue must me initialized before, and the caller must have
|
||||
* appropriate permissions on it.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param msg_q Pointer to the already initialized message queue.
|
||||
* @param filter Pointer to a zcan_filter structure defining the id
|
||||
* filtering.
|
||||
*
|
||||
* @retval filter id on success.
|
||||
* @retval CAN_NO_FREE_FILTER if there is no filter left.
|
||||
*/
|
||||
__syscall int can_attach_msgq(struct device *dev, struct k_msgq *msg_q,
|
||||
const struct zcan_filter *filter);
|
||||
|
||||
|
@ -382,10 +343,25 @@ static inline int _impl_can_attach_msgq(struct device *dev,
|
|||
return api->attach_msgq(dev, msg_q, filter);
|
||||
}
|
||||
|
||||
|
||||
__syscall int can_attach_isr(struct device *dev, can_rx_callback_t isr,
|
||||
const struct zcan_filter *filter);
|
||||
static inline int _impl_can_attach_isr(struct device *dev,
|
||||
/**
|
||||
* @brief Attach an isr callback function to a single or group of identifiers.
|
||||
*
|
||||
* This routine attaches an isr callback to identifiers specified by
|
||||
* a filter. Whenever the filter matches, the callback function is called
|
||||
* with isr context.
|
||||
* If a message passes more than one filter the priority of the match
|
||||
* is hardware dependent.
|
||||
* A callback function can be attached to more than one filter.
|
||||
* *
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param isr Callback function pointer.
|
||||
* @param filter Pointer to a zcan_filter structure defining the id
|
||||
* filtering.
|
||||
*
|
||||
* @retval filter id on success.
|
||||
* @retval CAN_NO_FREE_FILTER if there is no filter left.
|
||||
*/
|
||||
static inline int can_attach_isr(struct device *dev,
|
||||
can_rx_callback_t isr,
|
||||
const struct zcan_filter *filter)
|
||||
{
|
||||
|
@ -394,7 +370,17 @@ static inline int _impl_can_attach_isr(struct device *dev,
|
|||
return api->attach_isr(dev, isr, filter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Detach an isr or message queue from the identifier filtering.
|
||||
*
|
||||
* This routine detaches an isr callback or message queue from the identifier
|
||||
* filtering.
|
||||
* *
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param filter_id filter id returned by can_attach_isr or can_attach_msgq.
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
__syscall void can_detach(struct device *dev, int filter_id);
|
||||
|
||||
static inline void _impl_can_detach(struct device *dev, int filter_id)
|
||||
|
@ -404,7 +390,16 @@ static inline void _impl_can_detach(struct device *dev, int filter_id)
|
|||
return api->detach(dev, filter_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure operation of a host controller.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param mode Operation mode
|
||||
* @param bitrate bus-speed in Baud/s
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error, failed to configure device.
|
||||
*/
|
||||
__syscall int can_configure(struct device *dev, enum can_mode mode,
|
||||
u32_t bitrate);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue