| /** @file |
| * @brief IPv6 Networking over CAN definitions. |
| * |
| * Definitions for IPv6 Networking over CAN support. |
| */ |
| |
| /* |
| * Copyright (c) 2019 Alexander Wachter |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_NET_CAN_H_ |
| #define ZEPHYR_INCLUDE_NET_CAN_H_ |
| |
| #include <zephyr/types.h> |
| #include <net/net_ip.h> |
| #include <net/net_if.h> |
| #include <drivers/can.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| /** |
| * @brief IPv6 over CAN library |
| * @defgroup net_can Network Core Library |
| * @ingroup networking |
| * @{ |
| */ |
| |
| /** |
| * CAN L2 driver API. Used by 6loCAN. |
| */ |
| |
| /* |
| * Abbreviations |
| * BS Block Size |
| * CAN_DL CAN LL data size |
| * CF Consecutive Frame |
| * CTS Continue to send |
| * DLC Data length code |
| * FC Flow Control |
| * FF First Frame |
| * FS Flow Status |
| */ |
| |
| /** @cond INTERNAL_HIDDEN */ |
| |
| #define NET_CAN_DL 8 |
| #define NET_CAN_MTU 0x0FFF |
| |
| /* 0x3DFF - bit 4 to 10 must not be zero. Also prevent stuffing bit*/ |
| #define NET_CAN_MULTICAST_ADDR 0x3DFF |
| #define NET_CAN_DAD_ADDR 0x3DFE |
| #define NET_CAN_ETH_TRANSLATOR_ADDR 0x3DF0 |
| #define NET_CAN_MAX_ADDR 0x3DEF |
| #define NET_CAN_MIN_ADDR 0x0100 |
| |
| #define CAN_NET_IF_ADDR_MASK 0x3FFF |
| #define CAN_NET_IF_ADDR_BYTE_LEN 2U |
| #define CAN_NET_IF_ADDR_DEST_POS 14U |
| #define CAN_NET_IF_ADDR_DEST_MASK (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS) |
| #define CAN_NET_IF_ADDR_SRC_POS 0U |
| #define CAN_NET_IF_ADDR_SRC_MASK (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_SRC_POS) |
| #define CAN_NET_IF_ADDR_MCAST_POS 28U |
| #define CAN_NET_IF_ADDR_MCAST_MASK (1UL << CAN_NET_IF_ADDR_MCAST_POS) |
| |
| #define CAN_NET_IF_IS_MCAST_BIT (1U << 14) |
| |
| #define CAN_NET_FILTER_NOT_SET -1 |
| |
| /** @endcond */ |
| |
| /* |
| * +-----------+ +-----------+ |
| * | | | | |
| * | IPv6 | | IPv6 | |
| * | 6LoCAN | | 6LoCAN | |
| * | | | | |
| * +----+-+----+ +----+-+----+ |
| * | | | | +---+ |
| * +----+ | | | | / \ +-+ |
| * | | | | | | +--+ / \_/ \ |
| * +++ +---+ +--+----+ +-------+ +--+----+ +--/ \_/ \ |
| * | | \ / | \ / \ / | \ / / | |
| * | | X | X CAN X | X | Internet | |
| * | | / \ | / \ / \ | / \ \ / |
| * +++ +---+ +----+--+ +-------+ +----+--+ +--+ / |
| * | | +-------------------+ |
| * +----+ |
| */ |
| struct net_can_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 single CAN frame */ |
| int (*send)(const struct device *dev, const struct zcan_frame *frame, |
| can_tx_callback_t cb, void *cb_arg, k_timeout_t timeout); |
| /** Attach a filter with it's callback */ |
| int (*attach_filter)(const struct device *dev, can_rx_callback_t cb, |
| void *cb_arg, const struct zcan_filter *filter); |
| /** Detach a filter */ |
| void (*detach_filter)(const struct device *dev, int filter_id); |
| /** Enable or disable the reception of frames for net CAN */ |
| int (*enable)(const struct device *dev, bool enable); |
| }; |
| |
| /* Make sure that the network interface API is properly setup inside |
| * net_can_api struct (it is the first one). |
| */ |
| BUILD_ASSERT(offsetof(struct net_can_api, iface_api) == 0); |
| |
| /** @cond INTERNAL_HIDDEN */ |
| |
| #define CANBUS_L2_CTX_TYPE struct net_canbus_context * |
| |
| /** |
| * Context for canbus net device. |
| */ |
| struct canbus_net_ctx { |
| /** Filter ID for link layer duplicate address detection. */ |
| int dad_filter_id; |
| /** Work item for responding to link layer DAD requests. */ |
| struct k_work dad_work; |
| /** The interface associated with this device */ |
| struct net_if *iface; |
| /** The link layer address chosen for this interface */ |
| uint16_t ll_addr; |
| /** TX queue */ |
| struct k_fifo tx_queue; |
| /** RX error queue */ |
| struct k_fifo rx_err_queue; |
| /** Queue handler thread */ |
| struct k_thread queue_handler; |
| /** Queue handler thread stack */ |
| K_KERNEL_STACK_MEMBER(queue_stack, 512); |
| }; |
| |
| /** |
| * Canbus link layer addresses have a length of 14 bit for source and destination. |
| * Both together are 28 bit to fit a CAN extended identifier with 29 bit length. |
| */ |
| struct net_canbus_lladdr { |
| uint16_t addr : 14; |
| }; |
| |
| /** |
| * STmin is split in two valid ranges: |
| * 0-127: 0ms-127ms |
| * 128-240: Reserved |
| * 241-249: 100us-900us (multiples of 100us) |
| * 250- : Reserved |
| */ |
| struct canbus_fc_opts { |
| /** Block size. Number of CF PDUs before next CF is sent */ |
| uint8_t bs; |
| /**< Minimum separation time. Min time between frames */ |
| uint8_t stmin; |
| }; |
| |
| /** |
| * Context for a transmission of messages that didn't fit in a single frame. |
| * These messages Start with a FF (First Frame) that is in case of unicast |
| * acknowledged by a FC (Frame Control). After that, one or more CF |
| * (Consecutive frames) carry the rest of the message. |
| */ |
| struct canbus_isotp_tx_ctx { |
| /** Pkt containing the data to transmit */ |
| struct net_pkt *pkt; |
| /** Timeout for TX Timeout and separation time */ |
| struct _timeout timeout; |
| /** Frame Control options received from FC frame */ |
| struct canbus_fc_opts opts; |
| /** CAN destination address */ |
| struct net_canbus_lladdr dest_addr; |
| /** Remaining data to transmit in bytes */ |
| uint16_t rem_len; |
| /** Number of bytes in the tx queue */ |
| int8_t tx_backlog; |
| /** State of the transmission */ |
| uint8_t state; |
| /** Actual block number that is transmitted. Counts from BS to 0 */ |
| uint8_t act_block_nr; |
| /** Number of WAIT frames received */ |
| uint8_t wft; |
| /** Sequence number that is added to CF */ |
| uint8_t sn : 4; |
| /** Transmission is multicast */ |
| uint8_t is_mcast : 1; |
| }; |
| |
| /** |
| * Context for reception of messages that are not single frames. |
| * This is the counterpart of the canbus_isotp_tx_ctx. |
| */ |
| struct canbus_isotp_rx_ctx { |
| /** Pkt that is large enough to hold the entire message */ |
| struct net_pkt *pkt; |
| /** Timeout for RX timeout*/ |
| struct _timeout timeout; |
| /** Remaining data to receive. Goes from message length to zero */ |
| uint16_t rem_len; |
| /** State of the reception */ |
| uint8_t state; |
| /** Number of frames received in this block. Counts from BS to 0 */ |
| uint8_t act_block_nr; |
| /** Number of WAIT frames transmitted */ |
| uint8_t wft; |
| /** Expected sequence number in CF */ |
| uint8_t sn : 4; |
| }; |
| |
| /** |
| * Initialization of the canbus L2. |
| * |
| * This function starts the TX workqueue and does some initialization. |
| */ |
| void net_6locan_init(struct net_if *iface); |
| |
| /** |
| * Ethernet frame input function for Ethernet to 6LoCAN translation |
| * |
| * This function checks the destination link layer address for addresses |
| * that has to be forwarded. Frames that need to be forwarded are forwarded here. |
| */ |
| enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface, |
| struct net_pkt *pkt); |
| |
| /** @endcond */ |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */ |