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