1 /*
2  * Copyright (c) 2019 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public API for ISO-TP (ISO 15765-2:2016)
10  *
11  * ISO-TP is a transport protocol for CAN (Controller Area Network)
12  */
13 
14 #ifndef ZEPHYR_INCLUDE_CANBUS_ISOTP_H_
15 #define ZEPHYR_INCLUDE_CANBUS_ISOTP_H_
16 
17 /**
18  * @brief CAN ISO-TP Protocol
19  * @defgroup can_isotp CAN ISO-TP Protocol
20  * @ingroup connectivity
21  * @{
22  */
23 
24 #include <zephyr/drivers/can.h>
25 #include <zephyr/types.h>
26 #include <zephyr/net/buf.h>
27 
28 /*
29  * Abbreviations
30  * BS      Block Size
31  * CAN_DL  CAN LL data size
32  * CF      Consecutive Frame
33  * CTS     Continue to send
34  * DLC     Data length code
35  * FC      Flow Control
36  * FF      First Frame
37  * SF      Single Frame
38  * FS      Flow Status
39  * AE      Address Extension
40  * SN      Sequence Number
41  * ST      Separation time
42  * SA      Source Address
43  * TA      Target Address
44  * RX_DL   CAN RX LL data size
45  * TX_DL   CAN TX LL data size
46  * PCI     Process Control Information
47  */
48 
49 /*
50  * N_Result according to ISO 15765-2:2016
51  * ISOTP_ prefix is used to be zephyr conform
52  */
53 
54 /** Completed successfully */
55 #define ISOTP_N_OK              0
56 
57 /** Ar/As has timed out */
58 #define ISOTP_N_TIMEOUT_A      -1
59 
60 /** Reception of next FC has timed out */
61 #define ISOTP_N_TIMEOUT_BS     -2
62 
63 /** Cr has timed out */
64 #define ISOTP_N_TIMEOUT_CR     -3
65 
66 /** Unexpected sequence number */
67 #define ISOTP_N_WRONG_SN       -4
68 
69 /** Invalid flow status received*/
70 #define ISOTP_N_INVALID_FS     -5
71 
72 /** Unexpected PDU received */
73 #define ISOTP_N_UNEXP_PDU      -6
74 
75 /** Maximum number of WAIT flowStatus PDUs exceeded */
76 #define ISOTP_N_WFT_OVRN       -7
77 
78 /** FlowStatus OVFLW PDU was received */
79 #define ISOTP_N_BUFFER_OVERFLW -8
80 
81 /** General error */
82 #define ISOTP_N_ERROR          -9
83 
84 /** Implementation specific errors */
85 
86 /** Can't bind or send because the CAN device has no filter left*/
87 #define ISOTP_NO_FREE_FILTER    -10
88 
89 /** No net buffer left to allocate */
90 #define ISOTP_NO_NET_BUF_LEFT   -11
91 
92 /** Not sufficient space in the buffer left for the data */
93 #define ISOTP_NO_BUF_DATA_LEFT  -12
94 
95 /** No context buffer left to allocate */
96 #define ISOTP_NO_CTX_LEFT       -13
97 
98 /** Timeout for recv */
99 #define ISOTP_RECV_TIMEOUT      -14
100 
101 /*
102  * CAN ID filtering for ISO-TP fixed addressing according to SAE J1939
103  *
104  * Format of 29-bit CAN identifier:
105  * ------------------------------------------------------
106  * | 28 .. 26 | 25  | 24 | 23 .. 16 | 15 .. 8  | 7 .. 0 |
107  * ------------------------------------------------------
108  * | Priority | EDP | DP | N_TAtype |   N_TA   |  N_SA  |
109  * ------------------------------------------------------
110  */
111 
112 /** Position of fixed source address (SA) */
113 #define ISOTP_FIXED_ADDR_SA_POS         (CONFIG_ISOTP_FIXED_ADDR_SA_POS)
114 
115 /** Mask to obtain fixed source address (SA) */
116 #define ISOTP_FIXED_ADDR_SA_MASK        (CONFIG_ISOTP_FIXED_ADDR_SA_MASK)
117 
118 /** Position of fixed target address (TA) */
119 #define ISOTP_FIXED_ADDR_TA_POS         (CONFIG_ISOTP_FIXED_ADDR_TA_POS)
120 
121 /** Mask to obtain fixed target address (TA) */
122 #define ISOTP_FIXED_ADDR_TA_MASK        (CONFIG_ISOTP_FIXED_ADDR_TA_MASK)
123 
124 /** Position of priority in fixed addressing mode */
125 #define ISOTP_FIXED_ADDR_PRIO_POS       (CONFIG_ISOTP_FIXED_ADDR_PRIO_POS)
126 
127 /** Mask for priority in fixed addressing mode */
128 #define ISOTP_FIXED_ADDR_PRIO_MASK      (CONFIG_ISOTP_FIXED_ADDR_PRIO_MASK)
129 
130 /** CAN filter RX mask to match any priority and source address (SA) */
131 #define ISOTP_FIXED_ADDR_RX_MASK        (CONFIG_ISOTP_FIXED_ADDR_RX_MASK)
132 
133 #ifdef __cplusplus
134 extern "C" {
135 #endif
136 
137 /**
138  * @name ISO-TP message ID flags
139  * @anchor ISOTP_MSG_FLAGS
140  *
141  * @{
142  */
143 
144 /** Message uses ISO-TP extended addressing (first payload byte of CAN frame) */
145 #define ISOTP_MSG_EXT_ADDR BIT(0)
146 
147 /**
148  * Message uses ISO-TP fixed addressing (according to SAE J1939). Only valid in combination with
149  * ``ISOTP_MSG_IDE``.
150  */
151 #define ISOTP_MSG_FIXED_ADDR BIT(1)
152 
153 /** Message uses extended (29-bit) CAN ID */
154 #define ISOTP_MSG_IDE BIT(2)
155 
156 /** Message uses CAN FD format (FDF) */
157 #define ISOTP_MSG_FDF BIT(3)
158 
159 /** Message uses CAN FD Baud Rate Switch (BRS). Only valid in combination with ``ISOTP_MSG_FDF``. */
160 #define ISOTP_MSG_BRS BIT(4)
161 
162 /** @} */
163 
164 /**
165  * @brief ISO-TP message id struct
166  *
167  * Used to pass addresses to the bind and send functions.
168  */
169 struct isotp_msg_id {
170 	/**
171 	 * CAN identifier
172 	 *
173 	 * If ISO-TP fixed addressing is used, isotp_bind ignores SA and
174 	 * priority sections and modifies TA section in flow control frames.
175 	 */
176 	union {
177 		uint32_t std_id  : 11;
178 		uint32_t ext_id  : 29;
179 	};
180 	/** ISO-TP extended address (if used) */
181 	uint8_t ext_addr;
182 	/**
183 	 * ISO-TP frame data length (TX_DL for TX address or RX_DL for RX address).
184 	 *
185 	 * Valid values are 8 for classical CAN or 8, 12, 16, 20, 24, 32, 48 and 64 for CAN FD.
186 	 *
187 	 * 0 will be interpreted as 8 or 64 (if ISOTP_MSG_FDF is set).
188 	 *
189 	 * The value for incoming transmissions (RX_DL) is determined automatically based on the
190 	 * received first frame and does not need to be set during initialization.
191 	 */
192 	uint8_t dl;
193 	/** Flags. @see @ref ISOTP_MSG_FLAGS. */
194 	uint8_t flags;
195 };
196 
197 /*
198  * STmin is split in two valid ranges:
199  *   0-127: 0ms-127ms
200  * 128-240: Reserved
201  * 241-249: 100us-900us (multiples of 100us)
202  * 250-   : Reserved
203  */
204 
205 /**
206  * @brief ISO-TP frame control options struct
207  *
208  * Used to pass the options to the bind and send functions.
209  */
210 struct isotp_fc_opts {
211 	uint8_t bs;    /**< Block size. Number of CF PDUs before next CF is sent */
212 	uint8_t stmin; /**< Minimum separation time. Min time between frames */
213 };
214 
215 /**
216  * @brief Transmission callback
217  *
218  * This callback is called when a transmission is completed.
219  *
220  * @param error_nr ISOTP_N_OK on success, ISOTP_N_* on error
221  * @param arg      Callback argument passed to the send function
222  */
223 typedef void (*isotp_tx_callback_t)(int error_nr, void *arg);
224 
225 struct isotp_send_ctx;
226 struct isotp_recv_ctx;
227 
228 /**
229  * @brief Bind an address to a receiving context.
230  *
231  * This function binds an RX and TX address combination to an RX context.
232  * When data arrives from the specified address, it is buffered and can be read
233  * by calling isotp_recv.
234  * When calling this routine, a filter is applied in the CAN device, and the
235  * context is initialized. The context must be valid until calling unbind.
236  *
237  * @param rctx    Context to store the internal states.
238  * @param can_dev The CAN device to be used for sending and receiving.
239  * @param rx_addr Identifier for incoming data.
240  * @param tx_addr Identifier for FC frames.
241  * @param opts    Flow control options.
242  * @param timeout Timeout for FF SF buffer allocation.
243  *
244  * @retval ISOTP_N_OK on success
245  * @retval ISOTP_NO_FREE_FILTER if CAN device has no filters left.
246  */
247 int isotp_bind(struct isotp_recv_ctx *rctx, const struct device *can_dev,
248 	       const struct isotp_msg_id *rx_addr,
249 	       const struct isotp_msg_id *tx_addr,
250 	       const struct isotp_fc_opts *opts,
251 	       k_timeout_t timeout);
252 
253 /**
254  * @brief Unbind a context from the interface
255  *
256  * This function removes the binding from isotp_bind.
257  * The filter is detached from the CAN device, and if a transmission is ongoing,
258  * buffers are freed.
259  * The context can be discarded safely after calling this function.
260  *
261  * @param rctx    Context that should be unbound.
262  */
263 void isotp_unbind(struct isotp_recv_ctx *rctx);
264 
265 /**
266  * @brief Read out received data from fifo.
267  *
268  * This function reads the data from the receive FIFO of the context.
269  * It blocks if the FIFO is empty.
270  * If an error occurs, the function returns a negative number and leaves the
271  * data buffer unchanged.
272  *
273  * @param rctx    Context that is already bound.
274  * @param data    Pointer to a buffer where the data is copied to.
275  * @param len     Size of the buffer.
276  * @param timeout Timeout for incoming data.
277  *
278  * @retval Number of bytes copied on success
279  * @retval ISOTP_RECV_TIMEOUT when "timeout" timed out
280  * @retval ISOTP_N_* on error
281  */
282 int isotp_recv(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len, k_timeout_t timeout);
283 
284 /**
285  * @brief Get the net buffer on data reception
286  *
287  * This function reads incoming data into net-buffers.
288  * It blocks until the entire packet is received, BS is reached, or an error
289  * occurred. If BS was zero, the data is in a single net_buf. Otherwise,
290  * the data is fragmented in chunks of BS size.
291  * The net-buffers are referenced and must be freed with net_buf_unref after the
292  * data is processed.
293  *
294  * @param rctx    Context that is already bound.
295  * @param buffer  Pointer where the net_buf pointer is written to.
296  * @param timeout Timeout for incoming data.
297  *
298  * @retval Remaining data length for this transfer if BS > 0, 0 for BS = 0
299  * @retval ISOTP_RECV_TIMEOUT when "timeout" timed out
300  * @retval ISOTP_N_* on error
301  */
302 int isotp_recv_net(struct isotp_recv_ctx *rctx, struct net_buf **buffer, k_timeout_t timeout);
303 
304 /**
305  * @brief Send data
306  *
307  * This function is used to send data to a peer that listens to the tx_addr.
308  * An internal work-queue is used to transfer the segmented data.
309  * Data and context must be valid until the transmission has finished.
310  * If a complete_cb is given, this function is non-blocking, and the callback
311  * is called on completion with the return value as a parameter.
312  *
313  * @param sctx        Context to store the internal states.
314  * @param can_dev     The CAN device to be used for sending and receiving.
315  * @param data        Data to be sent.
316  * @param len         Length of the data to be sent.
317  * @param rx_addr     Identifier for FC frames.
318  * @param tx_addr     Identifier for outgoing frames the receiver listens on.
319  * @param complete_cb Function called on completion or NULL.
320  * @param cb_arg      Argument passed to the complete callback.
321  *
322  * @retval ISOTP_N_OK on success
323  * @retval ISOTP_N_* on error
324  */
325 int isotp_send(struct isotp_send_ctx *sctx, const struct device *can_dev,
326 	       const uint8_t *data, size_t len,
327 	       const struct isotp_msg_id *tx_addr,
328 	       const struct isotp_msg_id *rx_addr,
329 	       isotp_tx_callback_t complete_cb, void *cb_arg);
330 
331 #ifdef CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS
332 /**
333  * @brief Send data with buffered context
334  *
335  * This function is similar to isotp_send, but the context is automatically
336  * allocated from an internal pool.
337  *
338  * @param can_dev     The CAN device to be used for sending and receiving.
339  * @param data        Data to be sent.
340  * @param len         Length of the data to be sent.
341  * @param rx_addr     Identifier for FC frames.
342  * @param tx_addr     Identifier for outgoing frames the receiver listens on.
343  * @param complete_cb Function called on completion or NULL.
344  * @param cb_arg      Argument passed to the complete callback.
345  * @param timeout     Timeout for buffer allocation.
346  *
347  * @retval ISOTP_N_OK on success
348  * @retval ISOTP_N_* on error
349  */
350 int isotp_send_ctx_buf(const struct device *can_dev,
351 		       const uint8_t *data, size_t len,
352 		       const struct isotp_msg_id *tx_addr,
353 		       const struct isotp_msg_id *rx_addr,
354 		       isotp_tx_callback_t complete_cb, void *cb_arg,
355 		       k_timeout_t timeout);
356 
357 /**
358  * @brief Send data with buffered context
359  *
360  * This function is similar to isotp_send_ctx_buf, but the data is carried in
361  * a net_buf. net_buf_unref is called on the net_buf when sending is completed.
362  *
363  * @param can_dev     The CAN device to be used for sending and receiving.
364  * @param data        Data to be sent.
365  * @param len         Length of the data to be sent.
366  * @param rx_addr     Identifier for FC frames.
367  * @param tx_addr     Identifier for outgoing frames the receiver listens on.
368  * @param complete_cb Function called on completion or NULL.
369  * @param cb_arg      Argument passed to the complete callback.
370  * @param timeout     Timeout for buffer allocation.
371  *
372  * @retval ISOTP_N_OK on success
373  * @retval ISOTP_* on error
374  */
375 int isotp_send_net_ctx_buf(const struct device *can_dev,
376 			   struct net_buf *data,
377 			   const struct isotp_msg_id *tx_addr,
378 			   const struct isotp_msg_id *rx_addr,
379 			   isotp_tx_callback_t complete_cb, void *cb_arg,
380 			   k_timeout_t timeout);
381 
382 #endif /*CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS*/
383 
384 #if defined(CONFIG_ISOTP_USE_TX_BUF) && \
385 	defined(CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS)
386 /**
387  * @brief Send data with buffered context
388  *
389  * This function is similar to isotp_send, but the context is automatically
390  * allocated from an internal pool and the data to be send is buffered in an
391  * internal net_buff.
392  *
393  * @param can_dev     The CAN device to be used for sending and receiving.
394  * @param data        Data to be sent.
395  * @param len         Length of the data to be sent.
396  * @param rx_addr     Identifier for FC frames.
397  * @param tx_addr     Identifier for outgoing frames the receiver listens on.
398  * @param complete_cb Function called on completion or NULL.
399  * @param cb_arg      Argument passed to the complete callback.
400  * @param timeout     Timeout for buffer allocation.
401  *
402  * @retval ISOTP_N_OK on success
403  * @retval ISOTP_* on error
404  */
405 int isotp_send_buf(const struct device *can_dev,
406 		   const uint8_t *data, size_t len,
407 		   const struct isotp_msg_id *tx_addr,
408 		   const struct isotp_msg_id *rx_addr,
409 		   isotp_tx_callback_t complete_cb, void *cb_arg,
410 		   k_timeout_t timeout);
411 #endif
412 
413 /** @cond INTERNAL_HIDDEN */
414 
415 struct isotp_callback {
416 	isotp_tx_callback_t cb;
417 	void *arg;
418 };
419 
420 struct isotp_send_ctx {
421 	int filter_id;
422 	uint32_t error_nr;
423 	const struct device *can_dev;
424 	union {
425 		struct net_buf *buf;
426 		struct {
427 			const uint8_t *data;
428 			size_t len;
429 		};
430 	};
431 	struct k_work work;
432 	struct k_timer timer;
433 	union {
434 		struct isotp_callback fin_cb;
435 		struct k_sem fin_sem;
436 	};
437 	struct isotp_fc_opts opts;
438 	uint8_t state;
439 	uint8_t tx_backlog;
440 	struct k_sem tx_sem;
441 	struct isotp_msg_id rx_addr;
442 	struct isotp_msg_id tx_addr;
443 	uint8_t wft;
444 	uint8_t bs;
445 	uint8_t sn : 4;
446 	uint8_t is_net_buf  : 1;
447 	uint8_t is_ctx_slab : 1;
448 	uint8_t has_callback: 1;
449 };
450 
451 struct isotp_recv_ctx {
452 	int filter_id;
453 	const struct device *can_dev;
454 	struct net_buf *buf;
455 	struct net_buf *act_frag;
456 	/* buffer currently processed in isotp_recv */
457 	struct net_buf *recv_buf;
458 	sys_snode_t alloc_node;
459 	uint32_t length;
460 	int error_nr;
461 	struct k_work work;
462 	struct k_timer timer;
463 	struct k_fifo fifo;
464 	struct isotp_msg_id rx_addr;
465 	struct isotp_msg_id tx_addr;
466 	struct isotp_fc_opts opts;
467 	uint8_t state;
468 	uint8_t bs;
469 	uint8_t wft;
470 	uint8_t sn_expected : 4;
471 };
472 
473 /** @endcond */
474 
475 /**
476  * @}
477  */
478 
479 #ifdef __cplusplus
480 }
481 #endif
482 
483 #endif /* ZEPHYR_INCLUDE_CANBUS_ISOTP_H_ */
484