drivers: can: socketCAN: Move socket code to own file
Move the code for socket instanciation from each driver to a generic driver, that makes an instance of a socketCAN net device for the chosen node. Signed-off-by: Alexander Wachter <alexander@wachter.cloud>
This commit is contained in:
parent
f1e75dea50
commit
e24b087918
8 changed files with 171 additions and 341 deletions
|
@ -16,5 +16,6 @@ zephyr_library_sources_ifdef(CONFIG_CAN_RCAR can_rcar.c)
|
|||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE can_handlers.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CAN_SHELL can_shell.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_CAN can_socketcan.c)
|
||||
|
||||
add_subdirectory(transceiver)
|
||||
|
|
|
@ -18,7 +18,7 @@ module-str = CAN
|
|||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
config CAN_INIT_PRIORITY
|
||||
int "CAN init priority"
|
||||
int "CAN driver init priority"
|
||||
default KERNEL_INIT_PRIORITY_DEVICE
|
||||
help
|
||||
CAN driver device initialization priority.
|
||||
|
@ -66,14 +66,17 @@ config CANFD_MAX_DLC
|
|||
optimize memory consumption.
|
||||
endif # CAN_FD_MODE
|
||||
|
||||
config CAN_INIT_PRIORITY
|
||||
int "CAN driver init priority"
|
||||
default 80
|
||||
config CAN_SOCKETCAN_INIT_PRIORITY
|
||||
int "socketCAN net device init priority"
|
||||
default 81
|
||||
depends on NET_SOCKETS_CAN
|
||||
help
|
||||
CAN device driver initialization priority.
|
||||
socketCAN net device initialization priority.
|
||||
Do not mess with it unless you know what you are doing.
|
||||
Note that the priority needs to be lower than the net stack
|
||||
so that it can start before the networking sub-system.
|
||||
so that it can start before the networking sub-system,
|
||||
and higher than the CAN driver so that it can use the underlaying
|
||||
driver when starting.
|
||||
|
||||
config CAN_RX_TIMESTAMP
|
||||
bool "Receiving timestamps"
|
||||
|
|
|
@ -332,41 +332,3 @@ static int can_loopback_init(const struct device *dev)
|
|||
&can_loopback_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CAN_LOOPBACK_INIT)
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_CAN)
|
||||
#include "socket_can_generic.h"
|
||||
|
||||
#define CAN_LOOPBACK_SOCKET_CAN(inst) \
|
||||
static struct socket_can_context socket_can_context_##inst; \
|
||||
\
|
||||
static int socket_can_init_##inst(const struct device *dev) \
|
||||
{ \
|
||||
const struct device *can_dev = DEVICE_DT_INST_GET(inst); \
|
||||
struct socket_can_context *socket_context = dev->data; \
|
||||
\
|
||||
LOG_DBG("Init socket CAN device %p (%s) for dev %p (%s)", \
|
||||
dev, dev->name, can_dev, can_dev->name); \
|
||||
\
|
||||
socket_context->can_dev = can_dev; \
|
||||
socket_context->msgq = &socket_can_msgq; \
|
||||
\
|
||||
socket_context->rx_tid = \
|
||||
k_thread_create(&socket_context->rx_thread_data, \
|
||||
rx_thread_stack, \
|
||||
K_KERNEL_STACK_SIZEOF(rx_thread_stack), \
|
||||
rx_thread, socket_context, NULL, NULL, \
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
NET_DEVICE_INIT(socket_can_loopback_##inst, SOCKET_CAN_NAME_##inst, \
|
||||
socket_can_init_##inst, NULL, \
|
||||
&socket_can_context_##inst, NULL, \
|
||||
CONFIG_CAN_INIT_PRIORITY, &socket_can_api, \
|
||||
CANBUS_RAW_L2, NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), \
|
||||
CAN_MTU);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CAN_LOOPBACK_SOCKET_CAN)
|
||||
|
||||
#endif /* CONFIG_NET_SOCKETS_CAN */
|
||||
|
|
|
@ -993,39 +993,4 @@ DEVICE_DT_INST_DEFINE(0, &mcp2515_init, NULL,
|
|||
&mcp2515_data_1, &mcp2515_config_1, POST_KERNEL,
|
||||
CONFIG_CAN_INIT_PRIORITY, &can_api_funcs);
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_CAN)
|
||||
|
||||
#include "socket_can_generic.h"
|
||||
|
||||
static struct socket_can_context socket_can_context_1;
|
||||
|
||||
static int socket_can_init(const struct device *dev)
|
||||
{
|
||||
const struct device *can_dev = DEVICE_DT_INST_GET(1);
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
|
||||
LOG_DBG("Init socket CAN device %p (%s) for dev %p (%s)",
|
||||
dev, dev->name, can_dev, can_dev->name);
|
||||
|
||||
socket_context->can_dev = can_dev;
|
||||
socket_context->msgq = &socket_can_msgq;
|
||||
|
||||
socket_context->rx_tid =
|
||||
k_thread_create(&socket_context->rx_thread_data,
|
||||
rx_thread_stack,
|
||||
K_KERNEL_STACK_SIZEOF(rx_thread_stack),
|
||||
rx_thread, socket_context, NULL, NULL,
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NET_DEVICE_INIT(socket_can_mcp2515_1, SOCKET_CAN_NAME_1, socket_can_init,
|
||||
NULL, &socket_can_context_1, NULL,
|
||||
CONFIG_CAN_INIT_PRIORITY,
|
||||
&socket_can_api,
|
||||
CANBUS_RAW_L2, NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), CAN_MTU);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DT_NODE_HAS_STATUS(DT_DRV_INST(0), okay) */
|
||||
|
|
|
@ -869,34 +869,3 @@ static const struct can_driver_api mcux_flexcan_driver_api = {
|
|||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(FLEXCAN_DEVICE_INIT_MCUX)
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_CAN)
|
||||
#include "socket_can_generic.h"
|
||||
#define FLEXCAN_DEVICE_SOCKET_CAN(id) \
|
||||
static struct socket_can_context socket_can_context_##id; \
|
||||
static int socket_can_init_##id(const struct device *dev) \
|
||||
{ \
|
||||
const struct device *can_dev = DEVICE_DT_INST_GET(id); \
|
||||
struct socket_can_context *socket_context = dev->data; \
|
||||
LOG_DBG("Init socket CAN device %p (%s) for dev %p (%s)", \
|
||||
dev, dev->name, can_dev, can_dev->name); \
|
||||
socket_context->can_dev = can_dev; \
|
||||
socket_context->msgq = &socket_can_msgq; \
|
||||
socket_context->rx_tid = \
|
||||
k_thread_create(&socket_context->rx_thread_data, \
|
||||
rx_thread_stack, \
|
||||
K_KERNEL_STACK_SIZEOF(rx_thread_stack), \
|
||||
rx_thread, socket_context, NULL, NULL, \
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
NET_DEVICE_INIT(socket_can_flexcan_##id, SOCKET_CAN_NAME_##id, \
|
||||
socket_can_init_##id, NULL, \
|
||||
&socket_can_context_##id, NULL, \
|
||||
CONFIG_CAN_INIT_PRIORITY, &socket_can_api, \
|
||||
CANBUS_RAW_L2, NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), \
|
||||
CAN_MTU); \
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(FLEXCAN_DEVICE_SOCKET_CAN)
|
||||
#endif
|
||||
|
|
161
drivers/can/can_socketcan.c
Normal file
161
drivers/can/can_socketcan.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Intel Corporation.
|
||||
* Copyright (c) 2022 Alexander Wachter
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/socket_can.h>
|
||||
#include <drivers/can.h>
|
||||
#include <devicetree.h>
|
||||
#include <device.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(can_socketcan, CONFIG_CAN_LOG_LEVEL);
|
||||
|
||||
#define SEND_TIMEOUT K_MSEC(100)
|
||||
|
||||
struct socketcan_context {
|
||||
struct net_if *iface;
|
||||
};
|
||||
|
||||
struct socketcan_config {
|
||||
const struct device *can_dev;
|
||||
};
|
||||
|
||||
static void socketcan_recv(const struct device *dev, struct zcan_frame *frame, void *arg)
|
||||
{
|
||||
struct socketcan_context *ctx = (struct socketcan_context *)arg;
|
||||
struct net_pkt *pkt;
|
||||
int ret;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
LOG_DBG("pkt on interface %p", ctx->iface);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, sizeof(struct zcan_frame),
|
||||
AF_CAN, 0, K_NO_WAIT);
|
||||
if (pkt == NULL) {
|
||||
LOG_ERR("Failed to obtain net_pkt");
|
||||
return;
|
||||
}
|
||||
|
||||
if (net_pkt_write(pkt, frame, sizeof(struct zcan_frame))) {
|
||||
LOG_ERR("Failed to append RX data");
|
||||
net_pkt_unref(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = net_recv_data(ctx->iface, pkt);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("net_recv_data failed [%d]", ret);
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static int socketcan_setsockopt(const struct device *dev, void *obj, int level,
|
||||
int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
const struct socketcan_config *cfg = dev->config;
|
||||
struct socketcan_context *socket_context = dev->data;
|
||||
struct net_context *ctx = obj;
|
||||
int ret;
|
||||
|
||||
if (level != SOL_CAN_RAW && optname != CAN_RAW_FILTER) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(optlen == sizeof(struct zcan_filter));
|
||||
|
||||
ret = can_add_rx_filter(cfg->can_dev, socketcan_recv, socket_context, optval);
|
||||
if (ret == -ENOSPC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_context_set_filter_id(ctx, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void socketcan_close(const struct device *dev, int filter_id)
|
||||
{
|
||||
const struct socketcan_config *cfg = dev->config;
|
||||
|
||||
can_remove_rx_filter(cfg->can_dev, filter_id);
|
||||
}
|
||||
|
||||
static void socketcan_send_tx_callback(const struct device *dev, int error, void *arg)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
if (error != 0) {
|
||||
LOG_DBG("socket CAN TX error [%d]", error);
|
||||
}
|
||||
}
|
||||
|
||||
static int socketcan_send(const struct device *dev, struct net_pkt *pkt)
|
||||
{
|
||||
const struct socketcan_config *cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
if (net_pkt_family(pkt) != AF_CAN) {
|
||||
return -EPFNOSUPPORT;
|
||||
}
|
||||
|
||||
ret = can_send(cfg->can_dev, (struct zcan_frame *)pkt->frags->data,
|
||||
SEND_TIMEOUT, socketcan_send_tx_callback, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
net_pkt_unref(pkt);
|
||||
} else {
|
||||
LOG_DBG("Cannot send socket CAN msg (%d)", ret);
|
||||
}
|
||||
|
||||
/* If something went wrong, then we need to return negative value to
|
||||
* net_if.c:net_if_tx() so that the net_pkt will get released.
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void socketcan_iface_init(struct net_if *iface)
|
||||
{
|
||||
const struct device *dev = net_if_get_device(iface);
|
||||
struct socketcan_context *socket_context = dev->data;
|
||||
|
||||
socket_context->iface = iface;
|
||||
|
||||
LOG_DBG("Init CAN interface %p dev %p", iface, dev);
|
||||
}
|
||||
|
||||
static int socketcan_init(const struct device *dev)
|
||||
{
|
||||
const struct socketcan_config *cfg = dev->config;
|
||||
|
||||
if (!device_is_ready(cfg->can_dev)) {
|
||||
LOG_ERR("CAN device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct canbus_api socketcan_api = {
|
||||
.iface_api.init = socketcan_iface_init,
|
||||
.send = socketcan_send,
|
||||
.close = socketcan_close,
|
||||
.setsockopt = socketcan_setsockopt,
|
||||
};
|
||||
|
||||
static struct socketcan_context socketcan_ctx;
|
||||
|
||||
static const struct socketcan_config socketcan_cfg = {
|
||||
.can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus))
|
||||
};
|
||||
|
||||
NET_DEVICE_INIT(socket_can, "SOCKET_CAN", socketcan_init, NULL, &socketcan_ctx, &socketcan_cfg,
|
||||
CONFIG_CAN_SOCKETCAN_INIT_PRIORITY, &socketcan_api, CANBUS_RAW_L2,
|
||||
NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), CAN_MTU);
|
|
@ -1239,41 +1239,6 @@ static void config_can_1_irq(CAN_TypeDef *can)
|
|||
#endif /* CONFIG_CAN_STATS */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_CAN)
|
||||
|
||||
#include "socket_can_generic.h"
|
||||
|
||||
static struct socket_can_context socket_can_context_1;
|
||||
|
||||
static int socket_can_init_1(const struct device *dev)
|
||||
{
|
||||
const struct device *can_dev = DEVICE_DT_GET(DT_NODELABEL(can1));
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
|
||||
LOG_DBG("Init socket CAN device %p (%s) for dev %p (%s)",
|
||||
dev, dev->name, can_dev, can_dev->name);
|
||||
|
||||
socket_context->can_dev = can_dev;
|
||||
socket_context->msgq = &socket_can_msgq;
|
||||
|
||||
socket_context->rx_tid =
|
||||
k_thread_create(&socket_context->rx_thread_data,
|
||||
rx_thread_stack,
|
||||
K_KERNEL_STACK_SIZEOF(rx_thread_stack),
|
||||
rx_thread, socket_context, NULL, NULL,
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NET_DEVICE_INIT(socket_can_stm32_1, SOCKET_CAN_NAME_1, socket_can_init_1,
|
||||
NULL, &socket_can_context_1, NULL,
|
||||
CONFIG_CAN_INIT_PRIORITY,
|
||||
&socket_can_api,
|
||||
CANBUS_RAW_L2, NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), CAN_MTU);
|
||||
|
||||
#endif /* CONFIG_NET_SOCKETS_CAN */
|
||||
|
||||
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) */
|
||||
|
||||
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(can2), st_stm32_can, okay)
|
||||
|
@ -1335,39 +1300,4 @@ static void config_can_2_irq(CAN_TypeDef *can)
|
|||
#endif /* CONFIG_CAN_STATS */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_CAN)
|
||||
|
||||
#include "socket_can_generic.h"
|
||||
|
||||
static struct socket_can_context socket_can_context_2;
|
||||
|
||||
static int socket_can_init_2(const struct device *dev)
|
||||
{
|
||||
const struct device *can_dev = DEVICE_DT_GET(DT_NODELABEL(can2));
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
|
||||
LOG_DBG("Init socket CAN device %p (%s) for dev %p (%s)",
|
||||
dev, dev->name, can_dev, can_dev->name);
|
||||
|
||||
socket_context->can_dev = can_dev;
|
||||
socket_context->msgq = &socket_can_msgq;
|
||||
|
||||
socket_context->rx_tid =
|
||||
k_thread_create(&socket_context->rx_thread_data,
|
||||
rx_thread_stack,
|
||||
K_KERNEL_STACK_SIZEOF(rx_thread_stack),
|
||||
rx_thread, socket_context, NULL, NULL,
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NET_DEVICE_INIT(socket_can_stm32_2, SOCKET_CAN_NAME_2, socket_can_init_2,
|
||||
NULL, &socket_can_context_2, NULL,
|
||||
CONFIG_CAN_INIT_PRIORITY,
|
||||
&socket_can_api,
|
||||
CANBUS_RAW_L2, NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), CAN_MTU);
|
||||
|
||||
#endif /* CONFIG_NET_SOCKETS_CAN */
|
||||
|
||||
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(can2), okay) */
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
/* CANBUS related functions that are generic in all the drivers. */
|
||||
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/socket_can.h>
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_
|
||||
#define ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_
|
||||
|
||||
#define SOCKET_CAN_NAME_0 "SOCKET_CAN_0"
|
||||
#define SOCKET_CAN_NAME_1 "SOCKET_CAN_1"
|
||||
#define SOCKET_CAN_NAME_2 "SOCKET_CAN_2"
|
||||
#define SEND_TIMEOUT K_MSEC(100)
|
||||
#define RX_THREAD_STACK_SIZE 512
|
||||
#define RX_THREAD_PRIORITY 2
|
||||
#define BUF_ALLOC_TIMEOUT K_MSEC(50)
|
||||
|
||||
/* TODO: make msgq size configurable */
|
||||
CAN_MSGQ_DEFINE(socket_can_msgq, 5);
|
||||
K_KERNEL_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE);
|
||||
|
||||
struct socket_can_context {
|
||||
const struct device *can_dev;
|
||||
struct net_if *iface;
|
||||
struct k_msgq *msgq;
|
||||
|
||||
/* TODO: remove the thread and push data to net directly from rx isr */
|
||||
k_tid_t rx_tid;
|
||||
struct k_thread rx_thread_data;
|
||||
};
|
||||
|
||||
static inline void socket_can_iface_init(struct net_if *iface)
|
||||
{
|
||||
const struct device *dev = net_if_get_device(iface);
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
|
||||
socket_context->iface = iface;
|
||||
|
||||
LOG_DBG("Init CAN interface %p dev %p", iface, dev);
|
||||
}
|
||||
|
||||
static inline void tx_irq_callback(const struct device *dev, int error, void *arg)
|
||||
{
|
||||
char *caller_str = (char *)arg;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (error != 0) {
|
||||
LOG_DBG("TX error from %s! error-code: %d",
|
||||
caller_str, error);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called by net_if.c when packet is about to be sent */
|
||||
static inline int socket_can_send(const struct device *dev,
|
||||
struct net_pkt *pkt)
|
||||
{
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
int ret;
|
||||
|
||||
if (net_pkt_family(pkt) != AF_CAN) {
|
||||
return -EPFNOSUPPORT;
|
||||
}
|
||||
|
||||
ret = can_send(socket_context->can_dev,
|
||||
(struct zcan_frame *)pkt->frags->data,
|
||||
SEND_TIMEOUT, tx_irq_callback, "socket_can_send");
|
||||
if (ret) {
|
||||
LOG_DBG("Cannot send socket CAN msg (%d)", ret);
|
||||
}
|
||||
|
||||
/* If something went wrong, then we need to return negative value to
|
||||
* net_if.c:net_if_tx() so that the net_pkt will get released.
|
||||
*/
|
||||
return -ret;
|
||||
}
|
||||
|
||||
static inline int socket_can_setsockopt(const struct device *dev, void *obj,
|
||||
int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
struct net_context *ctx = obj;
|
||||
int ret;
|
||||
|
||||
if (level != SOL_CAN_RAW && optname != CAN_RAW_FILTER) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(optlen == sizeof(struct zcan_filter));
|
||||
|
||||
ret = can_add_rx_filter_msgq(socket_context->can_dev, socket_context->msgq,
|
||||
optval);
|
||||
if (ret == -ENOSPC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_context_set_filter_id(ctx, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void socket_can_close(const struct device *dev, int filter_id)
|
||||
{
|
||||
struct socket_can_context *socket_context = dev->data;
|
||||
|
||||
can_remove_rx_filter(socket_context->can_dev, filter_id);
|
||||
}
|
||||
|
||||
static struct canbus_api socket_can_api = {
|
||||
.iface_api.init = socket_can_iface_init,
|
||||
.send = socket_can_send,
|
||||
.close = socket_can_close,
|
||||
.setsockopt = socket_can_setsockopt,
|
||||
};
|
||||
|
||||
static inline void rx_thread(void *ctx, void *unused1, void *unused2)
|
||||
{
|
||||
struct socket_can_context *socket_context = ctx;
|
||||
struct net_pkt *pkt;
|
||||
struct zcan_frame frame;
|
||||
int ret;
|
||||
|
||||
ARG_UNUSED(unused1);
|
||||
ARG_UNUSED(unused2);
|
||||
|
||||
while (1) {
|
||||
k_msgq_get((struct k_msgq *)socket_context->msgq, &frame,
|
||||
K_FOREVER);
|
||||
|
||||
pkt = net_pkt_rx_alloc_with_buffer(socket_context->iface,
|
||||
sizeof(frame),
|
||||
AF_CAN, 0,
|
||||
BUF_ALLOC_TIMEOUT);
|
||||
if (!pkt) {
|
||||
LOG_ERR("Failed to obtain RX buffer");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (net_pkt_write(pkt, (void *)&frame, sizeof(frame))) {
|
||||
LOG_ERR("Failed to append RX data");
|
||||
net_pkt_unref(pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = net_recv_data(socket_context->iface, pkt);
|
||||
if (ret < 0) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue