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