LCOV - code coverage report
Current view: top level - zephyr/canbus - isotp.h Coverage Total Hit
Test: new.info Lines: 95.5 % 44 42
Test Date: 2025-09-05 16:43:28

            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_ */
        

Generated by: LCOV version 2.0-1