drivers: net: canbus: move CAN bus network driver to drivers/net

Move the CAN bus network driver from drivers/can to drivers/net as it
implements a network driver, not a CAN controller driver.

Use a separate Kconfig for enabling the CAN bus network driver instead of
piggybacking on the SocketCAN Kconfig. This allows for other
(e.g. out-of-tree) SocketCAN transports.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-05-11 21:53:06 +02:00 committed by Carles Cufí
commit d22a9909a1
10 changed files with 124 additions and 80 deletions

View file

@ -16,6 +16,5 @@ 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)

View file

@ -66,18 +66,6 @@ config CANFD_MAX_DLC
optimize memory consumption.
endif # CAN_FD_MODE
config CAN_SOCKETCAN_INIT_PRIORITY
int "socketCAN net device init priority"
default 81
depends on NET_SOCKETS_CAN
help
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,
and higher than the CAN driver so that it can use the underlaying
driver when starting.
config CAN_RX_TIMESTAMP
bool "Receiving timestamps"
depends on CAN_HAS_RX_TIMESTAMP

View file

@ -3,6 +3,7 @@
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_NET_LOOPBACK loopback.c)
zephyr_library_sources_ifdef(CONFIG_NET_CANBUS canbus.c)
if(CONFIG_NET_NATIVE)
zephyr_library_sources_ifdef(CONFIG_SLIP slip.c)

View file

@ -193,4 +193,32 @@ source "subsys/net/Kconfig.template.log_config.net"
endif
#
# CAN bus network driver options
#
menuconfig NET_CANBUS
bool "Controller Area Network (CAN) bus network driver"
help
Enable the CAN bus network driver. This driver provides a network interface on top of the
CAN controller driver API.
if NET_CANBUS
module = NET_CANBUS
module-dep = LOG
module-str = Log level for CAN bus network driver
module-help = Sets log level CAN bus network driver.
source "subsys/net/Kconfig.template.log_config.net"
config NET_CANBUS_INIT_PRIORITY
int "CAN bus network device init priority"
default 81
help
CAN bus network device initialization priority.
The priority needs to be lower than the network stack and higher than the CAN controller
driver.
endif # NET_CAN
endif # NET_DRIVERS

View file

@ -1,33 +1,35 @@
/*
* Copyright (c) 2019 Intel Corporation.
* Copyright (c) 2022 Vestas Wind Systems A/S
* Copyright (c) 2022 Alexander Wachter
* Copyright (c) 2019 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/canbus.h>
#include <zephyr/net/socket_can.h>
#include <zephyr/drivers/can.h>
#include <zephyr/devicetree.h>
#include <zephyr/device.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(can_socketcan, CONFIG_CAN_LOG_LEVEL);
LOG_MODULE_REGISTER(net_canbus, CONFIG_NET_CANBUS_LOG_LEVEL);
#define SEND_TIMEOUT K_MSEC(100)
struct socketcan_context {
struct net_canbus_context {
struct net_if *iface;
};
struct socketcan_config {
struct net_canbus_config {
const struct device *can_dev;
};
static void socketcan_recv(const struct device *dev, struct zcan_frame *frame, void *arg)
static void net_canbus_recv(const struct device *dev, struct zcan_frame *frame, void *user_data)
{
struct socketcan_context *ctx = (struct socketcan_context *)arg;
struct net_canbus_context *ctx = user_data;
struct net_pkt *pkt;
int ret;
@ -54,11 +56,11 @@ static void socketcan_recv(const struct device *dev, struct zcan_frame *frame, v
}
}
static int socketcan_setsockopt(const struct device *dev, void *obj, int level,
static int net_canbus_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;
const struct net_canbus_config *cfg = dev->config;
struct net_canbus_context *context = dev->data;
struct net_context *ctx = obj;
int ret;
@ -69,7 +71,7 @@ static int socketcan_setsockopt(const struct device *dev, void *obj, int level,
__ASSERT_NO_MSG(optlen == sizeof(struct zcan_filter));
ret = can_add_rx_filter(cfg->can_dev, socketcan_recv, socket_context, optval);
ret = can_add_rx_filter(cfg->can_dev, net_canbus_recv, context, optval);
if (ret == -ENOSPC) {
errno = ENOSPC;
return -1;
@ -80,26 +82,26 @@ static int socketcan_setsockopt(const struct device *dev, void *obj, int level,
return 0;
}
static void socketcan_close(const struct device *dev, int filter_id)
static void net_canbus_close(const struct device *dev, int filter_id)
{
const struct socketcan_config *cfg = dev->config;
const struct net_canbus_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)
static void net_canbus_send_tx_callback(const struct device *dev, int error, void *user_data)
{
ARG_UNUSED(dev);
ARG_UNUSED(arg);
ARG_UNUSED(user_data);
if (error != 0) {
LOG_DBG("socket CAN TX error [%d]", error);
LOG_DBG("CAN bus TX error [%d]", error);
}
}
static int socketcan_send(const struct device *dev, struct net_pkt *pkt)
static int net_canbus_send(const struct device *dev, struct net_pkt *pkt)
{
const struct socketcan_config *cfg = dev->config;
const struct net_canbus_config *cfg = dev->config;
int ret;
if (net_pkt_family(pkt) != AF_CAN) {
@ -107,12 +109,12 @@ static int socketcan_send(const struct device *dev, struct net_pkt *pkt)
}
ret = can_send(cfg->can_dev, (struct zcan_frame *)pkt->frags->data,
SEND_TIMEOUT, socketcan_send_tx_callback, NULL);
SEND_TIMEOUT, net_canbus_send_tx_callback, NULL);
if (ret == 0) {
net_pkt_unref(pkt);
} else {
LOG_DBG("Cannot send socket CAN msg (%d)", ret);
LOG_DBG("Cannot send CAN msg (%d)", ret);
}
/* If something went wrong, then we need to return negative value to
@ -121,19 +123,19 @@ static int socketcan_send(const struct device *dev, struct net_pkt *pkt)
return ret;
}
static void socketcan_iface_init(struct net_if *iface)
static void net_canbus_iface_init(struct net_if *iface)
{
const struct device *dev = net_if_get_device(iface);
struct socketcan_context *socket_context = dev->data;
struct net_canbus_context *context = dev->data;
socket_context->iface = iface;
context->iface = iface;
LOG_DBG("Init CAN interface %p dev %p", iface, dev);
}
static int socketcan_init(const struct device *dev)
static int net_canbus_init(const struct device *dev)
{
const struct socketcan_config *cfg = dev->config;
const struct net_canbus_config *cfg = dev->config;
if (!device_is_ready(cfg->can_dev)) {
LOG_ERR("CAN device not ready");
@ -143,19 +145,19 @@ static int socketcan_init(const struct device *dev)
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 canbus_api net_canbus_api = {
.iface_api.init = net_canbus_iface_init,
.send = net_canbus_send,
.close = net_canbus_close,
.setsockopt = net_canbus_setsockopt,
};
static struct socketcan_context socketcan_ctx;
static struct net_canbus_context net_canbus_ctx;
static const struct socketcan_config socketcan_cfg = {
static const struct net_canbus_config net_canbus_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_DEVICE_INIT(net_canbus, "NET_CANBUS", net_canbus_init, NULL, &net_canbus_ctx, &net_canbus_cfg,
CONFIG_NET_CANBUS_INIT_PRIORITY, &net_canbus_api, CANBUS_RAW_L2,
NET_L2_GET_CTX_TYPE(CANBUS_RAW_L2), CAN_MTU);

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_NET_CAN_H_
#define ZEPHYR_INCLUDE_NET_CAN_H_
#include <zephyr/types.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_if.h>
#include <zephyr/drivers/can.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* CAN L2 network driver API.
*/
struct canbus_api {
/**
* The net_if_api must be placed in first position in this
* struct so that we are compatible with network interface API.
*/
struct net_if_api iface_api;
/** Send a CAN packet by socket */
int (*send)(const struct device *dev, struct net_pkt *pkt);
/** Close the related CAN socket */
void (*close)(const struct device *dev, int filter_id);
/** Set socket CAN option */
int (*setsockopt)(const struct device *dev, void *obj, int level,
int optname,
const void *optval, socklen_t optlen);
/** Get socket CAN option */
int (*getsockopt)(const struct device *dev, void *obj, int level,
int optname,
const void *optval, socklen_t *optlen);
};
/* Make sure that the network interface API is properly setup inside
* CANBUS API struct (it is the first one).
*/
BUILD_ASSERT(offsetof(struct canbus_api, iface_api) == 0);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */

View file

@ -16,7 +16,6 @@
#include <zephyr/types.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_if.h>
#include <zephyr/drivers/can.h>
#ifdef __cplusplus
extern "C" {
@ -52,38 +51,6 @@ struct sockaddr_can {
int can_ifindex;
};
/**
* CAN L2 driver API. Used by socket CAN.
*/
struct canbus_api {
/**
* The net_if_api must be placed in first position in this
* struct so that we are compatible with network interface API.
*/
struct net_if_api iface_api;
/** Send a CAN packet by socket */
int (*send)(const struct device *dev, struct net_pkt *pkt);
/** Close the related CAN socket */
void (*close)(const struct device *dev, int filter_id);
/** Set socket CAN option */
int (*setsockopt)(const struct device *dev, void *obj, int level,
int optname,
const void *optval, socklen_t optlen);
/** Get socket CAN option */
int (*getsockopt)(const struct device *dev, void *obj, int level,
int optname,
const void *optval, socklen_t *optlen);
};
/* Make sure that the network interface API is properly setup inside
* CANBUS API struct (it is the first one).
*/
BUILD_ASSERT(offsetof(struct canbus_api, iface_api) == 0);
/**
* @}
*/

View file

@ -3,6 +3,8 @@ CONFIG_NET_L2_ETHERNET=n
CONFIG_CAN_MAX_FILTER=5
CONFIG_NETWORKING=y
CONFIG_NET_DRIVERS=y
CONFIG_NET_CANBUS=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_CAN=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y

View file

@ -11,7 +11,7 @@ LOG_MODULE_REGISTER(net_l2_canbus, LOG_LEVEL_NONE);
#include <zephyr/net/net_l2.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/socket_can.h>
#include <zephyr/net/canbus.h>
static inline enum net_verdict canbus_recv(struct net_if *iface,
struct net_pkt *pkt)

View file

@ -19,7 +19,9 @@ LOG_MODULE_REGISTER(net_sock_can, CONFIG_NET_SOCKETS_LOG_LEVEL);
#include <zephyr/net/socket.h>
#include <zephyr/syscall_handler.h>
#include <zephyr/sys/fdtable.h>
#include <zephyr/net/canbus.h>
#include <zephyr/net/socket_can.h>
#include <zephyr/drivers/can.h>
#include "sockets_internal.h"