Line data Source code
1 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 1 : #define ISOTP_N_OK 0
56 :
57 : /** Ar/As has timed out */
58 1 : #define ISOTP_N_TIMEOUT_A -1
59 :
60 : /** Reception of next FC has timed out */
61 1 : #define ISOTP_N_TIMEOUT_BS -2
62 :
63 : /** Cr has timed out */
64 1 : #define ISOTP_N_TIMEOUT_CR -3
65 :
66 : /** Unexpected sequence number */
67 1 : #define ISOTP_N_WRONG_SN -4
68 :
69 : /** Invalid flow status received*/
70 1 : #define ISOTP_N_INVALID_FS -5
71 :
72 : /** Unexpected PDU received */
73 1 : #define ISOTP_N_UNEXP_PDU -6
74 :
75 : /** Maximum number of WAIT flowStatus PDUs exceeded */
76 1 : #define ISOTP_N_WFT_OVRN -7
77 :
78 : /** FlowStatus OVFLW PDU was received */
79 1 : #define ISOTP_N_BUFFER_OVERFLW -8
80 :
81 : /** General error */
82 1 : #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 1 : #define ISOTP_NO_FREE_FILTER -10
88 :
89 : /** No net buffer left to allocate */
90 1 : #define ISOTP_NO_NET_BUF_LEFT -11
91 :
92 : /** Not sufficient space in the buffer left for the data */
93 1 : #define ISOTP_NO_BUF_DATA_LEFT -12
94 :
95 : /** No context buffer left to allocate */
96 1 : #define ISOTP_NO_CTX_LEFT -13
97 :
98 : /** Timeout for recv */
99 1 : #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 1 : #define ISOTP_FIXED_ADDR_SA_POS (CONFIG_ISOTP_FIXED_ADDR_SA_POS)
114 :
115 : /** Mask to obtain fixed source address (SA) */
116 1 : #define ISOTP_FIXED_ADDR_SA_MASK (CONFIG_ISOTP_FIXED_ADDR_SA_MASK)
117 :
118 : /** Position of fixed target address (TA) */
119 1 : #define ISOTP_FIXED_ADDR_TA_POS (CONFIG_ISOTP_FIXED_ADDR_TA_POS)
120 :
121 : /** Mask to obtain fixed target address (TA) */
122 1 : #define ISOTP_FIXED_ADDR_TA_MASK (CONFIG_ISOTP_FIXED_ADDR_TA_MASK)
123 :
124 : /** Position of priority in fixed addressing mode */
125 1 : #define ISOTP_FIXED_ADDR_PRIO_POS (CONFIG_ISOTP_FIXED_ADDR_PRIO_POS)
126 :
127 : /** Mask for priority in fixed addressing mode */
128 1 : #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 1 : #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 1 : #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 1 : #define ISOTP_MSG_FIXED_ADDR BIT(1)
152 :
153 : /** Message uses extended (29-bit) CAN ID */
154 1 : #define ISOTP_MSG_IDE BIT(2)
155 :
156 : /** Message uses CAN FD format (FDF) */
157 1 : #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 1 : #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 1 : 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 0 : uint32_t std_id : 11;
178 0 : uint32_t ext_id : 29;
179 1 : };
180 : /** ISO-TP extended address (if used) */
181 1 : 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 1 : uint8_t dl;
193 : /** Flags. @see @ref ISOTP_MSG_FLAGS. */
194 1 : 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 1 : struct isotp_fc_opts {
211 1 : uint8_t bs; /**< Block size. Number of CF PDUs before next CF is sent */
212 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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_ */
|