1 /** @file
2  * @brief IPv6 Networking over CAN definitions.
3  *
4  * Definitions for IPv6 Networking over CAN support.
5  */
6 
7 /*
8  * Copyright (c) 2019 Alexander Wachter
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_CAN_H_
14 #define ZEPHYR_INCLUDE_NET_CAN_H_
15 
16 #include <zephyr/types.h>
17 #include <net/net_ip.h>
18 #include <net/net_if.h>
19 #include <drivers/can.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 
26 /**
27  * @brief IPv6 over CAN library
28  * @defgroup net_can Network Core Library
29  * @ingroup networking
30  * @{
31  */
32 
33 /**
34  * CAN L2 driver API. Used by 6loCAN.
35  */
36 
37 /*
38  * Abbreviations
39  * BS      Block Size
40  * CAN_DL  CAN LL data size
41  * CF      Consecutive Frame
42  * CTS     Continue to send
43  * DLC     Data length code
44  * FC      Flow Control
45  * FF      First Frame
46  * FS      Flow Status
47  */
48 
49 /** @cond INTERNAL_HIDDEN */
50 
51 #define NET_CAN_DL 8
52 #define NET_CAN_MTU 0x0FFF
53 
54 /* 0x3DFF - bit 4 to 10 must not be zero. Also prevent stuffing bit*/
55 #define NET_CAN_MULTICAST_ADDR      0x3DFF
56 #define NET_CAN_DAD_ADDR            0x3DFE
57 #define NET_CAN_ETH_TRANSLATOR_ADDR 0x3DF0
58 #define NET_CAN_MAX_ADDR            0x3DEF
59 #define NET_CAN_MIN_ADDR            0x0100
60 
61 #define CAN_NET_IF_ADDR_MASK       0x3FFF
62 #define CAN_NET_IF_ADDR_BYTE_LEN   2U
63 #define CAN_NET_IF_ADDR_DEST_POS   14U
64 #define CAN_NET_IF_ADDR_DEST_MASK  (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS)
65 #define CAN_NET_IF_ADDR_SRC_POS    0U
66 #define CAN_NET_IF_ADDR_SRC_MASK   (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_SRC_POS)
67 #define CAN_NET_IF_ADDR_MCAST_POS  28U
68 #define CAN_NET_IF_ADDR_MCAST_MASK (1UL << CAN_NET_IF_ADDR_MCAST_POS)
69 
70 #define CAN_NET_IF_IS_MCAST_BIT    (1U << 14)
71 
72 #define CAN_NET_FILTER_NOT_SET -1
73 
74 /** @endcond */
75 
76 /*
77  *             +-----------+           +-----------+
78  *             |           |           |           |
79  *             |   IPv6    |           |   IPv6    |
80  *             |  6LoCAN   |           |  6LoCAN   |
81  *             |           |           |           |
82  *             +----+-+----+           +----+-+----+
83  *                  | |                     | |                   +---+
84  *  +----+          | |                     | |                  /     \   +-+
85  *  |    |          | |                     | |          +--+   /       \_/   \
86  * +++   +---+   +--+----+   +-------+   +--+----+   +--/    \_/               \
87  * | |        \ /     |   \ /         \ /     |   \ /  /                       |
88  * | |         X      |    X    CAN    X      |    X  |         Internet       |
89  * | |        / \     |   / \         / \     |   / \  \                       /
90  * +++   +---+   +----+--+   +-------+   +----+--+   +--+                     /
91  *  |    |                                               +-------------------+
92  *  +----+
93  */
94 struct net_can_api {
95 	/**
96 	 * The net_if_api must be placed in first position in this
97 	 * struct so that we are compatible with network interface API.
98 	 */
99 	struct net_if_api iface_api;
100 
101 	/** Send a single CAN frame */
102 	int (*send)(const struct device *dev, const struct zcan_frame *frame,
103 		    can_tx_callback_t cb, void *cb_arg, k_timeout_t timeout);
104 	/** Attach a filter with it's callback */
105 	int (*attach_filter)(const struct device *dev, can_rx_callback_t cb,
106 			     void *cb_arg, const struct zcan_filter *filter);
107 	/** Detach a filter */
108 	void (*detach_filter)(const struct device *dev, int filter_id);
109 	/** Enable or disable the reception of frames for net CAN */
110 	int (*enable)(const struct device *dev, bool enable);
111 };
112 
113 /* Make sure that the network interface API is properly setup inside
114  * net_can_api struct (it is the first one).
115  */
116 BUILD_ASSERT(offsetof(struct net_can_api, iface_api) == 0);
117 
118 /** @cond INTERNAL_HIDDEN */
119 
120 #define CANBUS_L2_CTX_TYPE	struct net_canbus_context *
121 
122 /**
123  * Context for canbus net device.
124  */
125 struct canbus_net_ctx {
126 	/** Filter ID for link layer duplicate address detection. */
127 	int dad_filter_id;
128 	/** Work item for responding to link layer DAD requests. */
129 	struct k_work dad_work;
130 	/** The interface associated with this device */
131 	struct net_if *iface;
132 	/** The link layer address chosen for this interface */
133 	uint16_t ll_addr;
134 	/** TX queue */
135 	struct k_fifo tx_queue;
136 	/** RX error queue */
137 	struct k_fifo rx_err_queue;
138 	/** Queue handler thread */
139 	struct k_thread queue_handler;
140 	/** Queue handler thread stack */
141 	K_KERNEL_STACK_MEMBER(queue_stack, 512);
142 };
143 
144 /**
145  * Canbus link layer addresses have a length of 14 bit for source and destination.
146  * Both together are 28 bit to fit a CAN extended identifier with 29 bit length.
147  */
148 struct net_canbus_lladdr {
149 	uint16_t addr : 14;
150 };
151 
152 /**
153  * STmin is split in two valid ranges:
154  *   0-127: 0ms-127ms
155  * 128-240: Reserved
156  * 241-249: 100us-900us (multiples of 100us)
157  * 250-   : Reserved
158  */
159 struct canbus_fc_opts {
160 	/** Block size. Number of CF PDUs before next CF is sent */
161 	uint8_t bs;
162 	/**< Minimum separation time. Min time between frames */
163 	uint8_t stmin;
164 };
165 
166 /**
167  * Context for a transmission of messages that didn't fit in a single frame.
168  * These messages Start with a FF (First Frame) that is in case of unicast
169  * acknowledged by a FC (Frame Control). After that, one or more CF
170  * (Consecutive frames) carry the rest of the message.
171  */
172 struct canbus_isotp_tx_ctx {
173 	/** Pkt containing the data to transmit */
174 	struct net_pkt *pkt;
175 	/** Timeout for TX Timeout and separation time */
176 	struct _timeout timeout;
177 	/** Frame Control options received from FC frame */
178 	struct canbus_fc_opts opts;
179 	/** CAN destination address */
180 	struct net_canbus_lladdr dest_addr;
181 	/** Remaining data to transmit in bytes */
182 	uint16_t rem_len;
183 	/** Number of bytes in the tx queue */
184 	int8_t tx_backlog;
185 	/** State of the transmission */
186 	uint8_t state;
187 	/** Actual block number that is transmitted. Counts from BS to 0 */
188 	uint8_t act_block_nr;
189 	/** Number of WAIT frames received */
190 	uint8_t wft;
191 	/** Sequence number that is added to CF */
192 	uint8_t sn : 4;
193 	/** Transmission is multicast */
194 	uint8_t is_mcast : 1;
195 };
196 
197 /**
198  * Context for reception of messages that are not single frames.
199  * This is the counterpart of the canbus_isotp_tx_ctx.
200  */
201 struct canbus_isotp_rx_ctx {
202 	/** Pkt that is large enough to hold the entire message */
203 	struct net_pkt *pkt;
204 	/** Timeout for RX timeout*/
205 	struct _timeout timeout;
206 	/** Remaining data to receive. Goes from message length to zero */
207 	uint16_t rem_len;
208 	/** State of the reception */
209 	uint8_t state;
210 	/** Number of frames received in this block. Counts from BS to 0 */
211 	uint8_t act_block_nr;
212 	/** Number of WAIT frames transmitted */
213 	uint8_t wft;
214 	/** Expected sequence number in CF */
215 	uint8_t sn : 4;
216 };
217 
218 /**
219  * Initialization of the canbus L2.
220  *
221  * This function starts the TX workqueue and does some initialization.
222  */
223 void net_6locan_init(struct net_if *iface);
224 
225 /**
226  * Ethernet frame input function for Ethernet to 6LoCAN translation
227  *
228  * This function checks the destination link layer address for addresses
229  * that has to be forwarded. Frames that need to be forwarded are forwarded here.
230  */
231 enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface,
232 						struct net_pkt *pkt);
233 
234 /** @endcond */
235 
236 /**
237  * @}
238  */
239 
240 #ifdef __cplusplus
241 }
242 #endif
243 
244 #endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */
245