Coverage Report

Created: 2026-10-17 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/bazel-out/k8-fastbuild-ST-0002fc8e4c46/bin/src/iso14229.h
Line
Count
Source
1
/**
2
 * @file iso14229.h
3
 * SPDX-License-Identifier: MIT
4
 * @brief ISO 14229 (UDS) library
5
 * @copyright Copyright (c) Nick Kirkby
6
 * @see documentation at https://github.com/driftregion/iso14229
7
 */
8
9
#ifndef ISO14229_H
10
#define ISO14229_H
11
12
#ifdef __cplusplus
13
extern "C" {
14
#endif // #ifdef __cplusplus
15
16
17
#ifdef UDS_LINES
18
#line 1 "src/version.h"
19
#endif // #ifdef UDS_LINES
20
#define UDS_LIB_VERSION "0.11.0"
21
22
23
#ifdef UDS_LINES
24
#line 1 "src/include.h"
25
#endif // #ifdef UDS_LINES
26
27
#include <assert.h> // early includes for static_assert
28
29
#if !defined(__cplusplus) && ((!defined(__STDC_VERSION__)) || (__STDC_VERSION__ < 201112L))
30
#ifndef static_assert
31
/* cppcheck-suppress [misra-c2012-19.2,misra-c2012-20.4] Patch static_assert for pre-C11 toolchains
32
 */
33
#define static_assert(expr, msg)
34
#else // #ifndef static_assert
35
#warning "using static_assert of unknown provenance; Please check that the signature is correct"
36
#endif // #ifndef static_assert
37
#endif
38
39
#include <inttypes.h>
40
#include <stdbool.h>
41
#include <stddef.h>
42
#include <stdint.h>
43
#include <stdio.h>
44
#include <string.h>
45
46
47
#ifdef UDS_LINES
48
#line 1 "src/sys.h"
49
#endif // #ifdef UDS_LINES
50
51
/**
52
 * @defgroup uds_sys_ valid values of UDS_SYS
53
 * @brief iso14229 host system selection
54
 * @see UDS_SYS
55
 * @{
56
 */
57
#define UDS_SYS_CUSTOM 0 /**< bare metal or unsupported targets */
58
#define UDS_SYS_UNIX 1
59
#define UDS_SYS_WINDOWS 2
60
#define UDS_SYS_ARDUINO 3
61
#define UDS_SYS_ESP32 4
62
#define UDS_SYS_ZEPHYR 5
63
/** @} */
64
65
#ifndef UDS_SYS   // system auto-detection
66
#ifdef __ZEPHYR__ // native_sim links w/host libc which also defines __unix__
67
#define UDS_SYS UDS_SYS_ZEPHYR
68
#elif defined(__unix__) || defined(__APPLE__)
69
#define UDS_SYS UDS_SYS_UNIX
70
#elif defined(_WIN32)
71
#define UDS_SYS UDS_SYS_WINDOWS
72
#elif defined(ARDUINO)
73
#define UDS_SYS UDS_SYS_ARDUINO
74
#elif defined(ESP_PLATFORM)
75
#define UDS_SYS UDS_SYS_ESP32
76
#else
77
#warning                                                                                           \
78
    "UDS_SYS was not detected, defaulting to UDS_SYS_CUSTOM. Remove this warning by defining UDS_SYS=UDS_SYS_CUSTOM in your build configuration"
79
#define UDS_SYS UDS_SYS_CUSTOM
80
#endif // defined(__ZEPHYR__)
81
#endif // #ifndef(UDS_SYS) // system auto-detection
82
83
84
#ifdef UDS_LINES
85
#line 1 "src/config.h"
86
#endif // #ifdef UDS_LINES
87
88
/**
89
 * @def UDS_SYS
90
 * @brief Selects the host system iso14229 is compiled for.
91
 * @see uds_sys_ for the list of valid values
92
 */
93
94
/**
95
 * @def UDS_CUSTOM_MILLIS
96
 * @brief bring your own UDSMillis implementation
97
 * @details Bring your own UDSMillis implementation. Valid values:
98
 * - `0` (default): iso14229 provides UDSMillis() for the detected @ref UDS_SYS platform
99
 * - `1`: the user must provide their own UDSMillis() implementation
100
 *
101
 * @see UDSMillis
102
 */
103
104
/**
105
 * @def UDS_LOG_LEVEL
106
 * @brief sets the logging level
107
 * @details set UDS_LOG_LEVEL to 0U (UDS_LOG_NONE) to remove logging entirely.
108
 * @see uds_log_level_ for valid values
109
 */
110
#ifndef UDS_LOG_LEVEL
111
#define UDS_LOG_LEVEL 0U
112
#endif
113
114
56.1k
#define UDS_ISOTP_MTU (4095U) ///< ISO-TP Maximum Transmission Unit (ISO-15764-2-2004 section 5.3.3)
115
116
#ifndef UDS_TP_MTU
117
/// ISOTP is the only supported tp type, so UDS inherits its MTU
118
56.1k
#define UDS_TP_MTU UDS_ISOTP_MTU
119
#endif
120
121
/**
122
 * @def UDS_SERVER_SEND_BUF_SIZE
123
 * @brief reduce this at your own risk to save RAM. Fuzz testing is done with the default of @ref
124
 * UDS_TP_MTU.
125
 */
126
#ifndef UDS_SERVER_SEND_BUF_SIZE
127
#define UDS_SERVER_SEND_BUF_SIZE (UDS_TP_MTU)
128
#endif
129
130
/** @copydoc UDS_SERVER_SEND_BUF_SIZE */
131
#ifndef UDS_SERVER_RECV_BUF_SIZE
132
#define UDS_SERVER_RECV_BUF_SIZE (UDS_TP_MTU)
133
#endif
134
135
/** @copydoc UDS_SERVER_SEND_BUF_SIZE */
136
#ifndef UDS_CLIENT_SEND_BUF_SIZE
137
#define UDS_CLIENT_SEND_BUF_SIZE (UDS_TP_MTU)
138
#endif
139
140
/** @copydoc UDS_SERVER_SEND_BUF_SIZE */
141
#ifndef UDS_CLIENT_RECV_BUF_SIZE
142
#define UDS_CLIENT_RECV_BUF_SIZE (UDS_TP_MTU)
143
#endif
144
145
#ifndef UDS_CLIENT_DEFAULT_P2_MS
146
330
#define UDS_CLIENT_DEFAULT_P2_MS (150U) ///< default P2 timeout
147
#endif
148
149
#ifndef UDS_CLIENT_DEFAULT_P2_STAR_MS
150
330
#define UDS_CLIENT_DEFAULT_P2_STAR_MS (1500U) ///< default P2* timeout
151
#endif
152
153
static_assert(UDS_CLIENT_DEFAULT_P2_STAR_MS > UDS_CLIENT_DEFAULT_P2_MS, "");
154
155
#ifndef UDS_SERVER_DEFAULT_P2_MS
156
4.35k
#define UDS_SERVER_DEFAULT_P2_MS (50) ///< default P2 duration
157
#endif
158
159
#ifndef UDS_SERVER_DEFAULT_P2_STAR_MS
160
4.35k
#define UDS_SERVER_DEFAULT_P2_STAR_MS (5000) ///< default P2* duration
161
#endif
162
163
#ifndef UDS_SERVER_DEFAULT_S3_MS
164
#define UDS_SERVER_DEFAULT_S3_MS                                                                   \
165
4.35k
    (5100) ///< default S3 duration (ISO14229-2 2013 Table 5: 5000 -0/+200 ms)
166
#endif
167
168
static_assert((bool)((0 < UDS_SERVER_DEFAULT_P2_MS) &&
169
                     (UDS_SERVER_DEFAULT_P2_MS < UDS_SERVER_DEFAULT_P2_STAR_MS) &&
170
                     (UDS_SERVER_DEFAULT_P2_STAR_MS < UDS_SERVER_DEFAULT_S3_MS)),
171
              "");
172
173
/// Duration between the server sending a positive response to an ECU reset request and the emission
174
/// of a UDS_EVT_DoScheduledReset event. This should be set to a duration adequate for the server
175
/// transport layer to finish responding to the ECU reset request.
176
#ifndef UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS
177
2.44k
#define UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS (60)
178
#endif
179
180
#if (UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS < UDS_SERVER_DEFAULT_P2_MS)
181
#error "The server shall have adequate time to respond before reset"
182
#endif
183
184
/// Amount of time to wait after boot before accepting 0x27 requests.
185
#ifndef UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_BOOT_DELAY_MS
186
4.35k
#define UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_BOOT_DELAY_MS (1000U)
187
#endif
188
189
/// Amount of time to wait after an authentication failure before accepting another 0x27 request.
190
#ifndef UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_AUTH_FAIL_DELAY_MS
191
53
#define UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_AUTH_FAIL_DELAY_MS (1000U)
192
#endif
193
194
#ifndef UDS_SERVER_DEFAULT_XFER_DATA_MAX_BLOCKLENGTH
195
/*! ISO14229-1:2013 Table 396. This parameter is used by the requestDownload positive response
196
message to inform the client how many data bytes (maxNumberOfBlockLength) to include in each
197
TransferData request message from the client. */
198
770
#define UDS_SERVER_DEFAULT_XFER_DATA_MAX_BLOCKLENGTH (UDS_TP_MTU)
199
#endif
200
201
#ifndef UDS_AUTOSELECT_TP // transport auto-selection. Set -DUDS_AUTOSELECT_TP=0 to turn off
202
                          // auto-selection
203
#define UDS_AUTOSELECT_TP 1
204
205
#if ((UDS_SYS == UDS_SYS_CUSTOM) || (UDS_SYS == UDS_SYS_ARDUINO) || (UDS_SYS == UDS_SYS_ESP32) ||  \
206
     (UDS_SYS == UDS_SYS_ZEPHYR))
207
#ifndef UDS_TP_ISOTP_C
208
#define UDS_TP_ISOTP_C
209
#endif // #ifndef UDS_TP_ISOTP_C
210
#elif (UDS_SYS == UDS_SYS_UNIX)
211
#ifndef UDS_TP_ISOTP_SOCK
212
#define UDS_TP_ISOTP_SOCK
213
#endif // #ifndef UDS_TP_ISOTP_SOCK
214
#else
215
// no default tp
216
#endif // ((UDS_SYS == UDS_SYS_CUSTOM) || ... )
217
218
#endif // #ifndef UDS_AUTOSELECT_TP
219
220
221
#ifdef UDS_LINES
222
#line 1 "src/config_internal.h"
223
#endif // #ifdef UDS_LINES
224
// non user-facing config
225
226
#if UDS_SYS == UDS_SYS_CUSTOM
227
#ifndef UDS_CUSTOM_MILLIS
228
#define UDS_CUSTOM_MILLIS
229
#endif // #ifndef UDS_CUSTOM_MILLIS
230
#endif // UDS_SYS == UDS_SYS_CUSTOM
231
232
#if UDS_SYS == UDS_SYS_WINDOWS
233
#ifdef _MSC_VER
234
#define strncasecmp _strnicmp
235
#define strcasecmp _stricmp
236
#endif // ifdef _MSC_VER
237
#endif // if UDS_SYS == UDS_SYS_WINDOWS
238
239
#ifdef UDS_TP_ISOTP_C_SOCKETCAN
240
#ifndef UDS_TP_ISOTP_C
241
#define UDS_TP_ISOTP_C
242
#endif // #ifndef (UDS_TP_ISOTP_C)
243
#endif // #defined(UDS_TP_ISOTP_C_SOCKETCAN)
244
245
#ifdef UDS_TP_ISOTP_C_SOCKETCAN
246
#ifndef UDS_TP_ISOTP_C
247
#error "UDS_TP_ISOTP_C must be defined to use UDS_TP_ISOTP_C_SOCKETCAN"
248
#endif // #ifndef UDS_TP_ISOTP_C
249
#endif // defined(UDS_TP_ISOTP_C_SOCKETCAN)
250
251
#ifdef UDS_TP_ISOTP_C
252
#ifdef ISO_TP_USER_SEND_CAN_ARG
253
#error "this flag is set by iso14229"
254
#endif // #ifdef ISO_TP_USER_SEND_CAN_ARG
255
#define ISO_TP_USER_SEND_CAN_ARG 1
256
257
#ifdef ISO_TP_NO_FORMATTED_ERRORS
258
#error "this flag is set by iso14229"
259
#endif
260
#define ISO_TP_NO_FORMATTED_ERRORS 1
261
#endif // defined(UDS_TP_ISOTP_C)
262
263
264
#ifdef UDS_LINES
265
#line 1 "src/uds.h"
266
#endif // #ifdef UDS_LINES
267
268
/** @file */
269
270
/**
271
 * @enum UDSEvent_t
272
 * @brief UDS events
273
 *
274
 * Events are passed to the server or client callback function along with
275
 * a pointer to the associated argument structure.
276
 */
277
typedef enum UDSEvent {
278
    UDS_EVT_Err, /**< Common event. Argument type: UDSErr_t * */
279
280
    UDS_EVT_DiagSessCtrl,         /**< Server evt 0x10, argtype: UDSDiagSessCtrlArgs_t * */
281
    UDS_EVT_EcuReset,             /**< Server evt 0x11, argtype: UDSECUResetArgs_t * */
282
    UDS_EVT_ClearDiagnosticInfo,  /**< Server evt 0x14, argtype: UDSCDIArgs_t * */
283
    UDS_EVT_ReadDTCInformation,   /**< Server evt 0x19, argtype: UDSRDTCIArgs_t * */
284
    UDS_EVT_ReadDataByIdent,      /**< Server evt 0x22, argtype: UDSRDBIArgs_t * */
285
    UDS_EVT_ReadMemByAddr,        /**< Server evt 0x23, argtype: UDSReadMemByAddrArgs_t * */
286
    UDS_EVT_CommCtrl,             /**< Server evt 0x28, argtype: UDSCommCtrlArgs_t * */
287
    UDS_EVT_SecAccessRequestSeed, /**< Server evt 0x27, argtype: UDSSecAccessRequestSeedArgs_t * */
288
    UDS_EVT_SecAccessValidateKey, /**< Server evt 0x27, argtype: UDSSecAccessValidateKeyArgs_t * */
289
    UDS_EVT_WriteDataByIdent,     /**< Server evt 0x2E, argtype: UDSWDBIArgs_t * */
290
    UDS_EVT_WriteMemByAddr,       /**< Server evt 0x3D, argtype: UDSWriteMemByAddrArgs_t * */
291
    UDS_EVT_DynamicDefineDataId,  /**< Server evt 0x2C, argtype: UDSDDDIArgs_t * */
292
    UDS_EVT_IOControl,            /**< Server evt 0x2F, argtype: UDSIOCtrlArgs_t * */
293
    UDS_EVT_RoutineCtrl,          /**< Server evt 0x31, argtype: UDSRoutineCtrlArgs_t * */
294
    UDS_EVT_RequestDownload,      /**< Server evt 0x34, argtype: UDSRequestDownloadArgs_t * */
295
    UDS_EVT_RequestUpload,        /**< Server evt 0x35, argtype: UDSRequestUploadArgs_t * */
296
    UDS_EVT_TransferData,         /**< Server evt 0x36, argtype: UDSTransferDataArgs_t * */
297
    UDS_EVT_RequestTransferExit,  /**< Server evt 0x37, argtype: UDSRequestTransferExitArgs_t * */
298
    UDS_EVT_SessionTimeout,       /**< Server evt 0x38, argtype: NULL */
299
    UDS_EVT_DoScheduledReset,     /**< Server evt 0x39, argtype: uint8_t * */
300
    UDS_EVT_RequestFileTransfer,  /**< Server evt 0x38, argtype: UDSRequestFileTransferArgs_t * */
301
    UDS_EVT_ControlDTCSetting,    /**< Server evt 0x85, argtype: UDSControlDTCSettingArgs_t * */
302
    UDS_EVT_LinkControl,          /**< Server evt 0x87, argtype: UDSLinkCtrlArgs_t * */
303
    UDS_EVT_Custom,               /**< Server evt other, argtype: UDSCustomArgs_t * */
304
305
    UDS_EVT_Poll,             /**< Client evt: Poll. Argument type: NULL */
306
    UDS_EVT_SendComplete,     /**< Client evt: Send complete. Argument type: NULL */
307
    UDS_EVT_ResponseReceived, /**< Client evt: Response received. Argument type: NULL */
308
    UDS_EVT_Idle,             /**< Client evt: Idle. Argument type: NULL */
309
310
    UDS_EVT_MAX, /**< Unused sentinel value */
311
} UDSEvent_t;
312
313
/**
314
 * @brief Error Codes, including NRCs defined by the standard.
315
 * @see UDSErrToStr
316
 */
317
typedef enum {
318
    UDS_FAIL = -1, // General error
319
    UDS_OK = 0,    // Success
320
321
    // Negative Response Codes (NRCs) as defined in ISO14229-1:2020 Table A.1 - Negative Response
322
    // Code (NRC) definition and values
323
    UDS_PositiveResponse = 0,
324
    // 0x01 to 0x0F are reserved by ISO14229-1:2020
325
    UDS_NRC_GeneralReject = 0x10,
326
    UDS_NRC_ServiceNotSupported = 0x11,
327
    UDS_NRC_SubFunctionNotSupported = 0x12,
328
    UDS_NRC_IncorrectMessageLengthOrInvalidFormat = 0x13,
329
    UDS_NRC_ResponseTooLong = 0x14,
330
    // 0x15 to 0x20 are reserved by ISO14229-1:2020
331
    UDS_NRC_BusyRepeatRequest = 0x21,
332
    UDS_NRC_ConditionsNotCorrect = 0x22,
333
    UDS_NRC_RequestSequenceError = 0x24,
334
    UDS_NRC_NoResponseFromSubnetComponent = 0x25,
335
    UDS_NRC_FailurePreventsExecutionOfRequestedAction = 0x26,
336
    // 0x27 to 0x30 are reserved by ISO14229-1:2020
337
    UDS_NRC_RequestOutOfRange = 0x31,
338
    // 0x32 is reserved by ISO14229-1:2020
339
    UDS_NRC_SecurityAccessDenied = 0x33,
340
    UDS_NRC_AuthenticationRequired = 0x34,
341
    UDS_NRC_InvalidKey = 0x35,
342
    UDS_NRC_ExceedNumberOfAttempts = 0x36,
343
    UDS_NRC_RequiredTimeDelayNotExpired = 0x37,
344
    UDS_NRC_SecureDataTransmissionRequired = 0x38,
345
    UDS_NRC_SecureDataTransmissionNotAllowed = 0x39,
346
    UDS_NRC_SecureDataVerificationFailed = 0x3A,
347
    // 0x3B to 0x4F are reserved by ISO14229-1:2020
348
    UDS_NRC_CertficateVerificationFailedInvalidTimePeriod = 0x50,
349
    UDS_NRC_CertficateVerificationFailedInvalidSignature = 0x51,
350
    UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust = 0x52,
351
    UDS_NRC_CertficateVerificationFailedInvalidType = 0x53,
352
    UDS_NRC_CertficateVerificationFailedInvalidFormat = 0x54,
353
    UDS_NRC_CertficateVerificationFailedInvalidContent = 0x55,
354
    UDS_NRC_CertficateVerificationFailedInvalidScope = 0x56,
355
    UDS_NRC_CertficateVerificationFailedInvalidCertificate = 0x57,
356
    UDS_NRC_OwnershipVerificationFailed = 0x58,
357
    UDS_NRC_ChallengeCalculationFailed = 0x59,
358
    UDS_NRC_SettingAccessRightsFailed = 0x5A,
359
    UDS_NRC_SessionKeyCreationOrDerivationFailed = 0x5B,
360
    UDS_NRC_ConfigurationDataUsageFailed = 0x5C,
361
    UDS_NRC_DeAuthenticationFailed = 0x5D,
362
    // 0x5E to 0x6F are reserved by ISO14229-1:2020
363
    UDS_NRC_UploadDownloadNotAccepted = 0x70,
364
    UDS_NRC_TransferDataSuspended = 0x71,
365
    UDS_NRC_GeneralProgrammingFailure = 0x72,
366
    UDS_NRC_WrongBlockSequenceCounter = 0x73,
367
    // 0x74 to 0x77 are reserved by ISO14229-1:2020
368
    UDS_NRC_RequestCorrectlyReceived_ResponsePending = 0x78,
369
    // 0x79 to 0x7D are reserved by ISO14229-1:2020
370
    UDS_NRC_SubFunctionNotSupportedInActiveSession = 0x7E,
371
    UDS_NRC_ServiceNotSupportedInActiveSession = 0x7F,
372
    // 0x80 is reserved by ISO14229-1:2020
373
    UDS_NRC_RpmTooHigh = 0x81,
374
    UDS_NRC_RpmTooLow = 0x82,
375
    UDS_NRC_EngineIsRunning = 0x83,
376
    UDS_NRC_EngineIsNotRunning = 0x84,
377
    UDS_NRC_EngineRunTimeTooLow = 0x85,
378
    UDS_NRC_TemperatureTooHigh = 0x86,
379
    UDS_NRC_TemperatureTooLow = 0x87,
380
    UDS_NRC_VehicleSpeedTooHigh = 0x88,
381
    UDS_NRC_VehicleSpeedTooLow = 0x89,
382
    UDS_NRC_ThrottlePedalTooHigh = 0x8A,
383
    UDS_NRC_ThrottlePedalTooLow = 0x8B,
384
    UDS_NRC_TransmissionRangeNotInNeutral = 0x8C,
385
    UDS_NRC_TransmissionRangeNotInGear = 0x8D,
386
    // 0x8E is reserved by ISO14229-1:2020
387
    UDS_NRC_BrakeSwitchNotClosed = 0x8F,
388
    UDS_NRC_ShifterLeverNotInPark = 0x90,
389
    UDS_NRC_TorqueConverterClutchLocked = 0x91,
390
    UDS_NRC_VoltageTooHigh = 0x92,
391
    UDS_NRC_VoltageTooLow = 0x93,
392
    UDS_NRC_ResourceTemporarilyNotAvailable = 0x94,
393
394
    /* 0x95 to 0xEF are reservedForSpecificConditionsNotCorrect */
395
    /* 0xF0 to 0xFE are vehicleManufacturerSpecificConditionsNotCorrect */
396
    /* 0xFF is ISOSAEReserved */
397
    UDS_NRC_UNUSED_ISOSAEReserved = 0xFF,
398
399
    // The following values are not defined in ISO14229-1:2020
400
    UDS_ERR_TIMEOUT = 0x100,      // A request has timed out
401
    UDS_ERR_DID_MISMATCH = 0x101, // The response DID does not match the request DID
402
    UDS_ERR_SID_MISMATCH = 0x102, // The response SID does not match the request SID
403
    UDS_ERR_SUBFUNCTION_MISMATCH =
404
        0x103, // The response SubFunction does not match the request SubFunction
405
    UDS_ERR_RESP_TOO_SHORT = 0x104, // The response is too short
406
    UDS_ERR_BUFSIZ = 0x105,         // The buffer is not large enough
407
    UDS_ERR_INVALID_ARG = 0x106,    // The function has been called with invalid arguments
408
    UDS_ERR_BUSY = 0x107,           // The client is busy and cannot process the request
409
    UDS_ERR_MISUSE = 0x108,         // The library is used incorrectly
410
411
    UDS_ERR_TPORT = 0x200, // Transport error
412
} UDSErr_t;
413
414
/**
415
 * @defgroup uds_lev_ds_ Diagnostic Session Levels
416
 * @brief ISO14229-1:2020 Table 25
417
 * @see UDSSendDiagSessCtrl UDS_EVT_DiagSessCtrl
418
 * @{
419
 */
420
38.7M
#define UDS_LEV_DS_DS 1U    ///< Default Session
421
5
#define UDS_LEV_DS_PRGS 2U  ///< Programming Session
422
10
#define UDS_LEV_DS_EXTDS 3U ///< Extended Diagnostic Session
423
#define UDS_LEV_DS_SSDS 4U  ///< Safety System Diagnostic Session
424
/** @} */
425
426
/**
427
 * @defgroup uds_lev_rt_ Reset Types
428
 * @brief ISO14229-1:2020 Table 34
429
 * @see UDSSendECUReset UDS_EVT_ECUReset
430
 * @{
431
 */
432
#define UDS_LEV_RT_HR 1U      ///< Hard Reset
433
#define UDS_LEV_RT_KOFFONR 2U ///< Key Off On Reset
434
#define UDS_LEV_RT_SR 3U      ///< Soft Reset
435
503
#define UDS_LEV_RT_ERPSD 4U   ///< Enable Rapid Power Shut Down
436
#define UDS_LEV_RT_DRPSD 5U   ///< Disable Rapid Power Shut Down
437
/** @} */
438
439
/**
440
 * @defgroup uds_lev_ctrlp_ Communication Control Levels
441
 * @brief ISO14229-1:2020 Table 54
442
 * @see UDSSendCommCtrl UDS_EVT_CommCtrl
443
 * @{
444
 */
445
#define UDS_LEV_CTRLTP_ERXTX 0U  ///< EnableRxAndTx
446
#define UDS_LEV_CTRLTP_ERXDTX 1U ///< EnableRxAndDisableTx
447
#define UDS_LEV_CTRLTP_DRXETX 2U ///< DisableRxAndEnableTx
448
#define UDS_LEV_CTRLTP_DRXTX 3U  ///< DisableRxAndTx
449
/** @} */
450
451
/**
452
 * @defgroup uds_ctp_ Communication Types
453
 * @brief ISO14229-1:2020 Table B.1
454
 * @see UDSSendCommCtrl UDS_EVT_CommCtrl
455
 * @{
456
 */
457
#define UDS_CTP_NCM 1U   ///< NormalCommunicationMessages
458
#define UDS_CTP_NWMCM 2U ///< NetworkManagementCommunicationMessages
459
#define UDS_CTP_NWMCM_NCM                                                                          \
460
    3U ///< NetworkManagementCommunicationMessagesAndNormalCommunicationMessages
461
/** @} */
462
463
/**
464
 * @defgroup uds_lev_rctp_ Routine Control Levels
465
 * @brief ISO14229-1:2020 Table 426
466
 * @see UDSSendRoutineCtrl UDS_EVT_RoutineCtrl
467
 * @{
468
 */
469
212
#define UDS_LEV_RCTP_STR 1U  ///< StartRoutine
470
422
#define UDS_LEV_RCTP_STPR 2U ///< StopRoutine
471
656
#define UDS_LEV_RCTP_RRR 3U  ///< RequestRoutineResults
472
/** @} */
473
474
/**
475
 * @defgroup uds_moop_ Mode of Operation for RequestFileTransfer
476
 * @brief ISO14229-1:2020 Table G.1
477
 * @see UDSSendRequestFileTransfer UDS_EVT_RequestFileTransfer
478
 * @{
479
 */
480
2.07k
#define UDS_MOOP_ADDFILE 1U  ///< AddFile
481
3.79k
#define UDS_MOOP_DELFILE 2U  ///< DeleteFile
482
416
#define UDS_MOOP_REPLFILE 3U ///< ReplaceFile
483
1.54k
#define UDS_MOOP_RDFILE 4U   ///< ReadFile
484
2.83k
#define UDS_MOOP_RDDIR 5U    ///< ReadDirectory
485
1.82k
#define UDS_MOOP_RSFILE 6U   ///< ResumeFile
486
/** @} */
487
488
/**
489
 * @defgroup uds_lev_dtcstp_ Diagnostic Trouble Code Control Level
490
 * @brief ISO14229-1:2020 Table 128
491
 * @see UDSSendControlDTCSetting UDS_EVT_ControlDTCSetting
492
 * @{
493
 */
494
#define UDS_LEV_DTCSTP_ON 1U  ///< Resume updating DTCs
495
#define UDS_LEV_DTCSTP_OFF 2U ///< Stop updating DTCs
496
/** @} */
497
498
/**
499
 * @defgroup uds_lev_lctp_ Link Control Level
500
 * @brief ISO14229-1:2020 Table 171
501
 * @see UDSSendLinkControl UDS_EVT_LinkControl
502
 * @{
503
 */
504
#define UDS_LEV_LCTP_VMTWFP 1U ///< VerifyModeTransitionWithFixedParameter
505
#define UDS_LEV_LCTP_VMTWSP 2U ///< VerifyModeTransitionWithSpecificParameter
506
#define UDS_LEV_LCTP_TM 3U     ///< TransitionMode
507
/** @} */
508
509
510
#ifdef UDS_LINES
511
#line 1 "src/tp.h"
512
#endif // #ifdef UDS_LINES
513
514
515
516
517
#ifdef UDS_TP_ISOTP_C_SOCKETCAN
518
#ifndef UDS_TP_ISOTP_C
519
#define UDS_TP_ISOTP_C
520
#endif
521
#endif
522
523
/** private: transport message type
524
 * @defgroup uds_a_mtype
525
 */
526
43.5k
#define UDS_A_MTYPE_DIAG 0U
527
#define UDS_A_MTYPE_REMOTE_DIAG 1U
528
#define UDS_A_MTYPE_SECURE_DIAG 2U
529
43.5k
#define UDS_A_MTYPE_SECURE_REMOTE_DIAG 3U
530
531
typedef uint8_t UDS_A_Mtype_t; ///< private: oneof @ref uds_a_mtype
532
533
/** private: transport transmission type
534
 * @defgroup uds_a_ta_type
535
 */
536
74.4k
#define UDS_A_TA_TYPE_PHYSICAL 0U   // unicast (1:1)
537
64.2k
#define UDS_A_TA_TYPE_FUNCTIONAL 1U // multicast
538
539
typedef uint8_t UDS_A_TA_Type_t; ///< private: oneof @ref uds_a_ta_type
540
541
/**
542
 * @brief Service data unit (SDU)
543
 * @details Service data unit (SDU): data interface between the application layer and the
544
 * transport layer
545
 */
546
typedef struct {
547
    UDS_A_Mtype_t A_Mtype;     /**< message type (diagnostic, remote diagnostic, secure diagnostic,
548
                                  secure remote diagnostic) */
549
    uint32_t A_SA;             /**< application source address */
550
    uint32_t A_TA;             /**< application target address */
551
    UDS_A_TA_Type_t A_TA_Type; /**< application target address type (physical or functional) */
552
    uint32_t A_AE;             /**< application layer remote address */
553
} UDSSDU_t;
554
555
8.71k
#define UDS_TP_NOOP_ADDR (0xFFFFFFFFU) ///< flags A_SA / A_TA as unused
556
557
/**
558
 * @brief UDS Transport layer
559
 * @note implementers should embed this struct at offset zero in their own transport layer handle
560
 */
561
typedef struct UDSTp {
562
    /**
563
     * @brief Send data to the transport
564
     * @param hdl: pointer to transport handle
565
     * @param buf: a pointer to the data to send
566
     * @param len: length of data to send
567
     * @param info: pointer to SDU info (may be NULL). If NULL, implementation should send with
568
     * physical addressing
569
     * @return UDS_OK if successful
570
     */
571
    UDSErr_t (*send)(struct UDSTp *hdl, const uint8_t *buf, const size_t len, const UDSSDU_t *info);
572
573
    /**
574
     * @brief Receive data from the transport
575
     * @param hdl: transport handle
576
     * @param buf: receive buffer
577
     * @param bufsiz: size of receive buffer
578
     * @param recvlen: number of bytes actually received
579
     * @param info: pointer to SDU info to be updated by transport implementation. May be NULL. If
580
     * non-NULL, the transport implementation must populate it with valid values.
581
     * @return UDS_OK if successful
582
     */
583
    UDSErr_t (*recv)(struct UDSTp *hdl, uint8_t *buf, size_t bufsiz, size_t *recvlen,
584
                     UDSSDU_t *info);
585
586
    /**
587
     * @brief Poll the transport layer.
588
     * @param hdl: pointer to transport handle
589
     * @note
590
     */
591
    UDSErr_t (*poll)(struct UDSTp *hdl);
592
593
    /**
594
     * @brief status flag (read-only)
595
     */
596
    struct {
597
        unsigned is_sending : 1; // set when data transmission starts in send(); cleared when done.
598
    } status;
599
} UDSTp_t;
600
601
UDSErr_t UDSTpSend(UDSTp_t *hdl, const uint8_t *buf, size_t len,
602
                   const UDSSDU_t *info); ///< Send to transport
603
UDSErr_t UDSTpRecv(UDSTp_t *hdl, uint8_t *buf, size_t bufsiz, size_t *recvlen,
604
                   UDSSDU_t *info); ///< Receive from transport
605
UDSErr_t UDSTpPoll(UDSTp_t *hdl);   ///< call this at <5ms intervals
606
607
608
#ifdef UDS_LINES
609
#line 1 "src/util.h"
610
#endif // #ifdef UDS_LINES
611
612
613
614
615
616
617
/**
618
 * @def UDS_ASSERT(x)
619
 * @brief used to enforce runtime invariants within iso14229
620
 */
621
#ifndef UDS_ASSERT
622
293M
#define UDS_ASSERT(x) assert(x)
623
#endif
624
625
/**
626
 * @brief Get time in milliseconds
627
 * @return current time in milliseconds
628
 * @note implementers must ensure the return value is monotonically increasing between
629
 * calls. The value must never go backwards.
630
 * Wrap-around (overflow back to 0) is expected; this is handled by UDSTimeAfter.
631
 */
632
uint32_t UDSMillis(void);
633
634
const char *UDSErrToStr(UDSErr_t err);
635
const char *UDSEventToStr(UDSEvent_t evt);
636
637
638
#ifdef UDS_LINES
639
#line 1 "src/log.h"
640
#endif // #ifdef UDS_LINES
641
642
/**
643
 * @brief logging for bring-up and unit tests.
644
 * Attribution: the initial version of this API was copied from ESP-IDF.
645
 */
646
647
648
649
650
651
/**
652
 * @defgroup uds_log_level_ valid values for UDS_LOG_LEVEL
653
 * @brief configures logging verbosity
654
 * @{
655
 */
656
1.85M
#define UDS_LOG_NONE 0U    /**< No log output */
657
#define UDS_LOG_ERROR 1U   /**< Log errors only */
658
#define UDS_LOG_WARN 2U    /**< Log warnings and errors */
659
#define UDS_LOG_INFO 3U    /**< Log info, warnings, and errors */
660
#define UDS_LOG_DEBUG 4U   /**< Log debug, info, warnings, and errors */
661
#define UDS_LOG_VERBOSE 5U /**< Log verbose, debug, info, warnings, and errors */
662
/** @} */
663
664
typedef unsigned int UDS_LogLevel_t; ///< one of @ref uds_log_level_
665
666
static_assert((bool)((UDS_LOG_LEVEL == UDS_LOG_NONE) || (UDS_LOG_LEVEL == UDS_LOG_ERROR) ||
667
                     (UDS_LOG_LEVEL == UDS_LOG_WARN) || (UDS_LOG_LEVEL == UDS_LOG_INFO) ||
668
                     (UDS_LOG_LEVEL == UDS_LOG_DEBUG) || (UDS_LOG_LEVEL == UDS_LOG_VERBOSE)),
669
              "unknown log level");
670
671
#if UDS_LOG_LEVEL >= UDS_LOG_ERROR && UDS_LOG_LEVEL != UDS_LOG_NONE
672
#define UDS_LOGE(tag, format, ...)                                                                 \
673
    UDS_LogWrite(UDS_LOG_ERROR, tag, UDS_LOG_FORMAT(E, format), UDSMillis(), tag, ##__VA_ARGS__)
674
#else
675
2.44k
#define UDS_LOGE(tag, format, ...) UDS_LogDummy(UDS_LOG_NONE, tag, format, ##__VA_ARGS__)
676
#endif
677
678
#if UDS_LOG_LEVEL >= UDS_LOG_WARN && UDS_LOG_LEVEL != UDS_LOG_NONE
679
#define UDS_LOGW(tag, format, ...)                                                                 \
680
    UDS_LogWrite(UDS_LOG_WARN, tag, UDS_LOG_FORMAT(W, format), UDSMillis(), tag, ##__VA_ARGS__)
681
#else
682
1.79M
#define UDS_LOGW(tag, format, ...) UDS_LogDummy(UDS_LOG_NONE, tag, format, ##__VA_ARGS__)
683
#endif
684
685
#if UDS_LOG_LEVEL >= UDS_LOG_INFO && UDS_LOG_LEVEL != UDS_LOG_NONE
686
#define UDS_LOGI(tag, format, ...)                                                                 \
687
    UDS_LogWrite(UDS_LOG_INFO, tag, UDS_LOG_FORMAT(I, format), UDSMillis(), tag, ##__VA_ARGS__)
688
#else
689
2.49k
#define UDS_LOGI(tag, format, ...) UDS_LogDummy(UDS_LOG_NONE, tag, format, ##__VA_ARGS__)
690
#endif
691
692
#if UDS_LOG_LEVEL >= UDS_LOG_DEBUG && UDS_LOG_LEVEL != UDS_LOG_NONE
693
#define UDS_LOGD(tag, format, ...)                                                                 \
694
    UDS_LogWrite(UDS_LOG_DEBUG, tag, UDS_LOG_FORMAT(D, format), UDSMillis(), tag, ##__VA_ARGS__)
695
#else
696
17.9k
#define UDS_LOGD(tag, format, ...) UDS_LogDummy(UDS_LOG_NONE, tag, format, ##__VA_ARGS__)
697
#endif
698
699
#if UDS_LOG_LEVEL >= UDS_LOG_VERBOSE
700
#define UDS_LOGV(tag, format, ...)                                                                 \
701
    UDS_LogWrite(UDS_LOG_VERBOSE, tag, UDS_LOG_FORMAT(V, format), UDSMillis(), tag, ##__VA_ARGS__)
702
#define UDS_LOG_SDU(tag, buffer, buff_len, info)                                                   \
703
    UDS_LogSDUInternal(UDS_LOG_DEBUG, tag, buffer, buff_len, info)
704
#else
705
17.4k
#define UDS_LOGV(tag, format, ...) UDS_LogDummy(UDS_LOG_NONE, tag, format, ##__VA_ARGS__)
706
#define UDS_LOG_SDU(tag, buffer, buff_len, info)                                                   \
707
17.9k
    UDS_LogSDUDummy(UDS_LOG_NONE, tag, buffer, buff_len, info)
708
#endif
709
710
#if defined(__GNUC__) || defined(__clang__)
711
#define UDS_PRINTF_FORMAT(fmt_index, first_arg)                                                    \
712
    __attribute__((format(printf, fmt_index, first_arg)))
713
#else
714
#define UDS_PRINTF_FORMAT(fmt_index, first_arg)
715
#endif
716
717
#if UDS_LOG_LEVEL > UDS_LOG_NONE
718
/* cppcheck-suppress [misra-c2012-20.10] string logging is not subject to MISRA */
719
#define UDS_LOG_FORMAT(letter, format) #letter " (%" PRIu32 ") %s: " format "\n"
720
void UDS_LogWrite(UDS_LogLevel_t level, const char *tag, const char *format, ...)
721
    UDS_PRINTF_FORMAT(3, 4);
722
void UDS_LogSDUInternal(UDS_LogLevel_t level, const char *tag, const uint8_t *buffer, size_t buflen,
723
                        const UDSSDU_t *info);
724
#endif // UDS_LOG_LEVEL > UDS_LOG_NONE
725
726
1.83M
static inline void UDS_LogDummy(UDS_LogLevel_t level, const char *tag, const char *format, ...) {
727
1.83M
    (void)level;
728
1.83M
    (void)tag;
729
1.83M
    (void)format;
730
1.83M
}
Unexecuted instantiation: fuzz_server.cc:UDS_LogDummy(unsigned int, char const*, char const*, ...)
iso14229.c:UDS_LogDummy
Line
Count
Source
726
1.83M
static inline void UDS_LogDummy(UDS_LogLevel_t level, const char *tag, const char *format, ...) {
727
1.83M
    (void)level;
728
1.83M
    (void)tag;
729
1.83M
    (void)format;
730
1.83M
}
731
static inline void UDS_LogSDUDummy(UDS_LogLevel_t level, const char *tag, const uint8_t *buffer,
732
17.9k
                                   size_t buflen, const UDSSDU_t *info) {
733
17.9k
    (void)level;
734
17.9k
    (void)tag;
735
17.9k
    (void)buffer;
736
17.9k
    (void)buflen;
737
17.9k
    (void)info;
738
17.9k
}
Unexecuted instantiation: fuzz_server.cc:UDS_LogSDUDummy(unsigned int, char const*, unsigned char const*, unsigned long, UDSSDU_t const*)
iso14229.c:UDS_LogSDUDummy
Line
Count
Source
732
17.9k
                                   size_t buflen, const UDSSDU_t *info) {
733
17.9k
    (void)level;
734
17.9k
    (void)tag;
735
17.9k
    (void)buffer;
736
17.9k
    (void)buflen;
737
17.9k
    (void)info;
738
17.9k
}
739
/// \endcond
740
741
742
#ifdef UDS_LINES
743
#line 1 "src/client.h"
744
#endif // #ifdef UDS_LINES
745
746
747
748
749
750
/**
751
 * @brief UDS client structure
752
 */
753
typedef struct UDSClient {
754
    // User-facing configuration options
755
    UDSTp_t *tp; /**< transport layer handle */
756
    int (*fn)(struct UDSClient *client, UDSEvent_t evt, void *ev_data); /**< callback function */
757
    void *fn_data;                      /**< user-specified function data */
758
    unsigned cfg_suppress_pos_resp : 1; /**< suppress positive responses from the server  */
759
    unsigned cfg_send_functional : 1;   /**< send functional (broadcast) requests */
760
    unsigned cfg_ignore_srv_sess_timing
761
        : 1; /**< do not heed the P2 and P2* timings sent by the server  */
762
    uint8_t cfg_data_format_identifier;     /**< 0x38 RequestFileTransfer dataFormatIdentifier */
763
    uint8_t cfg_file_size_parameter_length; /**< 0x38 RequestFileTransfer fileSizeParameterLength */
764
765
    // private members
766
    uint16_t p2_ms;      /**< p2 timeout in milliseconds */
767
    uint32_t p2_star_ms; /**< p2* timeout in milliseconds (for 0x78 response) */
768
    uint32_t p2_timer;   /**< p2 timer value */
769
    uint8_t state;       /**< client request state, @see client_request_states */
770
771
    size_t recv_size;                           /**< size of received data */
772
    size_t send_size;                           /**< size of data to send */
773
    uint8_t recv_buf[UDS_CLIENT_RECV_BUF_SIZE]; /**< receive buffer */
774
    uint8_t send_buf[UDS_CLIENT_SEND_BUF_SIZE]; /**< send buffer */
775
} UDSClient_t;
776
777
/**
778
 * @brief Security access response structure
779
 */
780
struct SecurityAccessResponse {
781
    uint8_t securityAccessType;  /**< security access type (subfunction) */
782
    const uint8_t *securitySeed; /**< pointer to security seed data */
783
    size_t securitySeedLength;   /**< length of security seed */
784
};
785
786
/**
787
 * @brief Request download response structure
788
 */
789
struct RequestDownloadResponse {
790
    uint32_t maxBlockLength; /**< server's maximum block length for TransferData requests */
791
};
792
793
/**
794
 * @brief Routine control response structure
795
 */
796
struct RoutineControlResponse {
797
    uint8_t routineControlType;         /**< routine control type (subfunction) */
798
    uint16_t routineIdentifier;         /**< routine identifier */
799
    const uint8_t *routineStatusRecord; /**< pointer to routine status record */
800
    size_t routineStatusRecordLength;   /**< length of routine status record */
801
};
802
803
/**
804
 * @brief Read data by identifier variable structure
805
 */
806
typedef struct {
807
    uint16_t did;                                            /**< data identifier */
808
    uint16_t len;                                            /**< data length */
809
    void *data;                                              /**< pointer to data buffer */
810
    void *(*UnpackFn)(void *dst, const void *src, size_t n); /**< optional unpack function */
811
} UDSRDBIVar_t;
812
813
UDSErr_t UDSClientInit(UDSClient_t *client); ///< Call this once
814
UDSErr_t UDSClientPoll(UDSClient_t *client); ///< Call at <5ms intervals
815
UDSErr_t UDSSendBytes(UDSClient_t *client, const uint8_t *data,
816
                      uint16_t size); ///< Send user-defined bytes to a UDS server
817
UDSErr_t UDSSendECUReset(UDSClient_t *client, uint8_t type);     ///< Request ECUReset
818
UDSErr_t UDSSendDiagSessCtrl(UDSClient_t *client, uint8_t mode); ///< Change the diagnostic session
819
UDSErr_t UDSSendSecurityAccess(UDSClient_t *client, uint8_t level, const uint8_t *data,
820
                               uint16_t size); ///< Get Security Access
821
UDSErr_t UDSSendCommCtrl(UDSClient_t *client, uint8_t ctrl,
822
                         uint8_t comm); ///< Change communication settings
823
UDSErr_t UDSSendRDBI(UDSClient_t *client, const uint16_t *didList,
824
                     uint16_t numDataIdentifiers); ///< Read Data By Identifier
825
UDSErr_t UDSSendWDBI(UDSClient_t *client, uint16_t dataIdentifier, const uint8_t *data,
826
                     uint16_t size);                ///< Write Data By Identifier
827
UDSErr_t UDSSendTesterPresent(UDSClient_t *client); ///< What's up?
828
UDSErr_t UDSSendRoutineCtrl(UDSClient_t *client, uint8_t type, uint16_t routineIdentifier,
829
                            const uint8_t *data, uint16_t size); ///< Request to Twiddle Routines
830
831
UDSErr_t UDSSendRequestDownload(UDSClient_t *client, uint8_t dataFormatIdentifier,
832
                                uint8_t addressAndLengthFormatIdentifier, size_t memoryAddress,
833
                                size_t memorySize); ///< Request to Download via TransferData
834
835
UDSErr_t UDSSendRequestUpload(UDSClient_t *client, uint8_t dataFormatIdentifier,
836
                              uint8_t addressAndLengthFormatIdentifier, size_t memoryAddress,
837
                              size_t memorySize); ///< Request to Upload via TransferData
838
UDSErr_t UDSSendTransferData(UDSClient_t *client, uint8_t blockSequenceCounter,
839
                             uint16_t blockLength, const uint8_t *data,
840
                             uint16_t size); ///< Transfer Data to/from a buffer
841
UDSErr_t
842
UDSSendRequestTransferExit(UDSClient_t *client); ///< Call this when finished with TransferData
843
844
UDSErr_t UDSSendRequestFileTransfer(
845
    UDSClient_t *client, uint8_t mode, const char *filePath, size_t filePathLen,
846
    size_t fileSizeUncompressed,
847
    size_t fileSizeCompressed); ///< filesystem-based frontend to TransferData
848
UDSErr_t UDSCtrlDTCSetting(UDSClient_t *client, uint8_t dtcSettingType,
849
                           const uint8_t *dtcSettingControlOptionRecord,
850
                           uint16_t len); ///< control DTC setting
851
UDSErr_t UDSUnpackRDBIResponse(UDSClient_t *client, UDSRDBIVar_t *vars,
852
                               uint16_t numVars); ///< Parse server's response to RDBI
853
UDSErr_t UDSUnpackSecurityAccessResponse(
854
    const UDSClient_t *client,
855
    struct SecurityAccessResponse *resp); ///< Parse server's response to SecurityAccess
856
UDSErr_t UDSUnpackRequestDownloadResponse(
857
    const UDSClient_t *client,
858
    struct RequestDownloadResponse *resp); ///< Parse server's response to RequestDownload
859
UDSErr_t UDSUnpackRoutineControlResponse(
860
    const UDSClient_t *client,
861
    struct RoutineControlResponse *resp); ///< Parse server's response to RoutineControl
862
863
864
#ifdef UDS_LINES
865
#line 1 "src/server.h"
866
#endif // #ifdef UDS_LINES
867
868
869
870
871
872
/**
873
 * @brief Server request context
874
 */
875
typedef struct {
876
    uint8_t recv_buf[UDS_SERVER_RECV_BUF_SIZE]; /**< receive buffer */
877
    uint8_t send_buf[UDS_SERVER_SEND_BUF_SIZE]; /**< send buffer */
878
    size_t recv_len;                            /**< received data length */
879
    size_t send_len;                            /**< send data length */
880
    size_t send_buf_size;                       /**< send buffer size */
881
    UDSSDU_t info;                              /**< service data unit information */
882
} UDSReq_t;
883
884
/**
885
 * @brief UDS server structure
886
 */
887
typedef struct UDSServer {
888
    UDSTp_t *tp; /**< transport layer handle */
889
    UDSErr_t (*fn)(struct UDSServer *srv, UDSEvent_t event, void *arg); /**< callback function */
890
    void *fn_data; /**< user-specified function data */
891
892
    /**
893
     * @brief Server time constants (milliseconds)
894
     */
895
    uint16_t p2_ms;      /**< Default P2_server_max timing supported by the server */
896
    uint32_t p2_star_ms; /**< Enhanced (NRC 0x78) P2_server_max supported by the server */
897
    uint16_t s3_ms;      /**< Session timeout */
898
899
    uint8_t ecuResetScheduled;         /**< nonzero indicates that an ECUReset has been scheduled */
900
    uint32_t ecuResetTimer;            /**< for delaying resetting until a response has been sent */
901
    uint32_t p2_timer;                 /**< for rate limiting server responses */
902
    uint32_t s3_session_timeout_timer; /**< indicates that diagnostic session has timed out */
903
    uint32_t sec_access_auth_fail_timer;  /**< brute-force hardening: rate limit security access */
904
    uint32_t sec_access_boot_delay_timer; /**< brute-force hardening: restrict security access until
905
                                             timer expires */
906
907
    /**
908
     * @brief UDS-1-2013: Table 407 - 0x36 TransferData Supported negative
909
     * response codes requires that the server keep track of whether the
910
     * transfer is active
911
     */
912
    bool xferIsActive;                /**< transfer is active */
913
    uint8_t xferBlockSequenceCounter; /**< UDS-1-2013: 14.4.2.3, Table 404: block sequence counter
914
                                         starts at 0x01 */
915
    size_t xferTotalBytes;            /**< total transfer size in bytes requested by the client */
916
    size_t xferByteCounter;           /**< total number of bytes transferred */
917
    size_t xferBlockLength;           /**< block length (convenience for the TransferData API) */
918
919
    uint8_t sessionType;   /**< diagnostic session type (0x10) */
920
    uint8_t securityLevel; /**< SecurityAccess (0x27) level */
921
922
    bool RCRRP;             /**< set to true when user fn returns 0x78 and false otherwise */
923
    bool requestInProgress; /**< set to true when a request has been processed but the response has
924
                               not yet been sent */
925
926
    /**
927
     * @brief UDS-1 2013 defines the following conditions under which the server does not
928
     * process incoming requests:
929
     * - not ready to receive (Table A.1 0x78)
930
     * - not accepting request messages and not sending responses (9.3.1)
931
     *
932
     * when this variable is set to true, incoming ISO-TP data will not be processed.
933
     */
934
    bool notReadyToReceive; /**< incoming ISO-TP data will not be processed */
935
936
    UDSReq_t r; /**< request context */
937
} UDSServer_t;
938
939
/**
940
 * @brief Diagnostic session control arguments
941
 */
942
typedef struct {
943
    const uint8_t type;  /**< oneof @ref uds_lev_ds_ */
944
    uint16_t p2_ms;      /**< optional: p2 timing override */
945
    uint32_t p2_star_ms; /**< optional: p2* timing override */
946
} UDSDiagSessCtrlArgs_t;
947
948
/**
949
 * @brief ECU reset arguments
950
 */
951
typedef struct {
952
    const uint8_t type;           /**< reset type requested by client */
953
    uint32_t powerDownTimeMillis; /**< when this much time has elapsed after a UDS_PositiveResponse,
954
                                     a UDS_EVT_DoScheduledReset will be issued */
955
} UDSECUResetArgs_t;
956
957
/**
958
 * @brief Clear diagnostic information arguments
959
 */
960
typedef struct {
961
    const uint32_t groupOfDTC;     /**< lower 3 bytes describe the groupOfDTC */
962
    const bool hasMemorySelection; /**< `true` when a memory selection byte is present */
963
    const uint8_t memorySelection; /**<  memorySelection byte (optional) */
964
} UDSCDIArgs_t;
965
966
/**
967
 * @brief Read DTC information arguments
968
 */
969
typedef struct {
970
    const uint8_t type; /**< invoked subfunction */
971
    uint8_t (*copy)(UDSServer_t *srv, const void *src,
972
                    uint16_t count); /**< function for copying data */
973
974
    /* cppcheck-suppress [misra-c2012-19.2] */
975
    union {
976
        struct {
977
            uint8_t mask;           /**< DTC status mask */
978
        } numOfDTCByStatusMaskArgs; /**< args for number of DTCs by status mask */
979
        struct {
980
            uint8_t mask;      /**< DTC status mask */
981
        } dtcStatusByMaskArgs; /**< args for DTCs by status mask */
982
        struct {
983
            uint32_t dtc;                /**< DTC Mask Record */
984
            uint8_t snapshotNum;         /**< DTC Snaphot Record Number */
985
        } dtcSnapshotRecordbyDTCNumArgs; /**< args for DTC snapshot record by DTC number */
986
        struct {
987
            uint32_t dtc;                          /**< DTC Mask Record */
988
            uint8_t snapshotNum;                   /**< DTC Snaphot Record Number */
989
            uint8_t memory;                        /**< Memory Selection */
990
        } userDefMemDTCSnapshotRecordByDTCNumArgs; /**< args for user-defined-memory DTC snapshot
991
                                                      record by DTC number */
992
        struct {
993
            uint8_t recordNum;          /**< DTC Data Record Number */
994
        } dtcStoredDataByRecordNumArgs; /**< args for DTC stored data by record number */
995
        struct {
996
            uint8_t recordNum;             /**< DTC Data Record Number */
997
        } dtcExtDataRecordByRecordNumArgs; /**< args for DTC extended data record by record number
998
                                            */
999
        struct {
1000
            uint8_t recordNum;    /**< DTC Data Record Number */
1001
        } dtcExtDataRecordIdArgs; /**< args for supported DTC extended data record ID */
1002
        struct {
1003
            uint32_t dtc;              /**< DTC Mask Record */
1004
            uint8_t extDataRecNum;     /**< DTC Extended Data Record Number */
1005
        } dtcExtDtaRecordByDTCNumArgs; /**< args for DTC extended data record by DTC number */
1006
        struct {
1007
            uint32_t dtc;                         /**< DTC Mask Record */
1008
            uint8_t extDataRecNum;                /**< DTC Extended Data Record Number */
1009
            uint8_t memory;                       /**< Memory Selection */
1010
        } userDefMemDTCExtDataRecordByDTCNumArgs; /**< args for user-defined-memory DTC extended
1011
                                                        data record by DTC number */
1012
        struct {
1013
            uint8_t severityMask;     /**< DTC Severity Mask */
1014
            uint8_t statusMask;       /**< DTC Status Mask */
1015
        } numOfDTCBySeverityMaskArgs; /**< args for number of DTCs by severity mask */
1016
        struct {
1017
            uint8_t functionalGroup; /**< Functional Group Identifier */
1018
            uint8_t severityMask;    /**< DTC Severity Mask */
1019
            uint8_t statusMask;      /**< DTC Status Mask */
1020
        } wwhobdDTCByMaskArgs;       /**< args for WWH-OBD DTCs by mask */
1021
        struct {
1022
            uint32_t dtc;        /**< DTC Mask Record */
1023
        } severityInfoOfDTCArgs; /**< args for severity information of a DTC */
1024
        struct {
1025
            uint8_t mask;                   /**< DTC status mask */
1026
            uint8_t memory;                 /**< Memory Selection */
1027
        } userDefMemoryDTCByStatusMaskArgs; /**< args for user-defined-memory DTCs by status mask */
1028
        struct {
1029
            uint8_t functionalGroup;   /**< Functional Group Identifier */
1030
        } wwhobdDTCWithPermStatusArgs; /**< args for WWH-OBD DTCs with permanent status */
1031
        struct {
1032
            uint8_t functionalGroup;        /**< Functional Group Identifier */
1033
            uint8_t readinessGroup;         /**< DTC Readiness Group Identifier */
1034
        } dtcInfoByDTCReadinessGroupIdArgs; /**< args for DTCs by readiness group */
1035
        /* cppcheck-suppress [misra-c2012-19.2] */
1036
    } subFuncArgs; /**< subfunction-specific arguments, selected by \ref type */
1037
} UDSRDTCIArgs_t;
1038
1039
/**
1040
 * @brief Read data by identifier arguments
1041
 */
1042
typedef struct {
1043
    const uint16_t dataId; /**< RDBI Data Identifier */
1044
    uint8_t (*copy)(UDSServer_t *srv, const void *src,
1045
                    uint16_t count); /**< function for copying data */
1046
} UDSRDBIArgs_t;
1047
1048
/**
1049
 * @brief Read memory by address arguments
1050
 */
1051
typedef struct {
1052
    const uintptr_t memAddr; /**< requested server memory address */
1053
    const size_t memSize;    /**< requested size */
1054
    uint8_t (*copy)(UDSServer_t *srv, const void *src,
1055
                    uint16_t count); /**< function for copying data to response */
1056
} UDSReadMemByAddrArgs_t;
1057
1058
/**
1059
 * @brief Communication control arguments
1060
 */
1061
typedef struct {
1062
    uint8_t ctrlType; /**< ControlType */
1063
    uint8_t commType; /**< CommunicationType */
1064
    uint16_t nodeId;  /**< NodeIdentificationNumber (only used when ctrlType is 0x04 or 0x05) */
1065
} UDSCommCtrlArgs_t;
1066
1067
/**
1068
 * @brief Security access request seed arguments
1069
 */
1070
typedef struct {
1071
    const uint8_t level;             /**< requested security level */
1072
    const uint8_t *const dataRecord; /**< pointer to request data */
1073
    const uint16_t len;              /**< size of request data */
1074
    uint8_t (*copySeed)(UDSServer_t *srv, const void *src,
1075
                        uint16_t len); /**< function for copying data */
1076
} UDSSecAccessRequestSeedArgs_t;
1077
1078
/**
1079
 * @brief Security access validate key arguments
1080
 */
1081
typedef struct {
1082
    const uint8_t level;      /**< security level to be validated */
1083
    const uint8_t *const key; /**< key sent by client */
1084
    const uint16_t len;       /**< length of key */
1085
} UDSSecAccessValidateKeyArgs_t;
1086
1087
/**
1088
 * @brief Write data by identifier arguments
1089
 */
1090
typedef struct {
1091
    const uint16_t dataId;     /**< WDBI Data Identifier */
1092
    const uint8_t *const data; /**< pointer to data */
1093
    const uint16_t len;        /**< length of data */
1094
} UDSWDBIArgs_t;
1095
1096
/**
1097
 * @brief Write memory by address arguments
1098
 */
1099
typedef struct {
1100
    const uintptr_t memAddr;   /**< pointer to memory address */
1101
    const size_t memSize;      /**< size of memory */
1102
    const uint8_t *const data; /**< pointer to data */
1103
} UDSWriteMemByAddrArgs_t;
1104
1105
/**
1106
 * @brief Dynamically define data identifier arguments
1107
 */
1108
typedef struct {
1109
    const uint8_t type;     /**< invoked subfunction */
1110
    bool allDataIds;        /**< is true when request is for all data identifiers (only relevant for
1111
                              subFunc 0x03) */
1112
    uint16_t dynamicDataId; /**< dynamicallyDefinedDataIdentifier */
1113
1114
    /* cppcheck-suppress [misra-c2012-19.2] */
1115
    union {
1116
        struct {
1117
            uint16_t sourceDataId; /**< source DataIdentifier */
1118
            uint8_t position;      /**< position in source data record */
1119
            uint8_t size;          /**< number of bytes to be copied */
1120
        } defineById; /**< args when defining from an existing source data identifier */
1121
        struct {
1122
            uintptr_t memAddr; /**< memory address to read from */
1123
            size_t memSize;    /**< number of bytes to read */
1124
        } defineByMemAddress;  /**< args when defining from a memory address */
1125
        /* cppcheck-suppress [misra-c2012-19.2] */
1126
    } subFuncArgs; /**< subfunction-specific arguments, selected by \ref type */
1127
} UDSDDDIArgs_t;
1128
1129
/**
1130
 * @brief Input/output control by identifier arguments
1131
 */
1132
typedef struct {
1133
    const uint16_t dataId;              /**< Data Identifier */
1134
    const uint8_t ioCtrlParam;          /**< inputOutputControlParameter */
1135
    const void *const ctrlStateAndMask; /**< controlState bytes and controlMask (optional) */
1136
    const size_t ctrlStateAndMaskLen;   /**< number of bytes in `ctrlStateAndMask` */
1137
    uint8_t (*copy)(UDSServer_t *srv, const void *src,
1138
                    uint16_t count); /**< function for copying data */
1139
} UDSIOCtrlArgs_t;
1140
1141
/**
1142
 * @brief Routine control arguments
1143
 */
1144
typedef struct {
1145
    const uint8_t ctrlType;      /**< routineControlType */
1146
    const uint16_t id;           /**< routineIdentifier */
1147
    const uint8_t *optionRecord; /**< optional data */
1148
    const uint16_t len;          /**< length of optional data */
1149
    uint8_t (*copyStatusRecord)(UDSServer_t *srv, const void *src,
1150
                                uint16_t len); /**< function for copying response data */
1151
} UDSRoutineCtrlArgs_t;
1152
1153
/**
1154
 * @brief Request download arguments
1155
 */
1156
typedef struct {
1157
    const uintptr_t addr;               /**< requested address */
1158
    const size_t size;                  /**< requested download size */
1159
    const uint8_t dataFormatIdentifier; /**< optional specifier for format of data */
1160
    uint16_t maxNumberOfBlockLength;    /**< optional response: inform client how many data bytes to
1161
                                           send in each    `TransferData` request */
1162
} UDSRequestDownloadArgs_t;
1163
1164
/**
1165
 * @brief Request upload arguments
1166
 */
1167
typedef struct {
1168
    const uintptr_t addr;               /**< requested address */
1169
    const size_t size;                  /**< requested download size */
1170
    const uint8_t dataFormatIdentifier; /**< optional specifier for format of data */
1171
    uint16_t maxNumberOfBlockLength;    /**< optional response: inform client how many data bytes to
1172
                                           send in each    `TransferData` request */
1173
} UDSRequestUploadArgs_t;
1174
1175
/**
1176
 * @brief Transfer data arguments
1177
 */
1178
typedef struct {
1179
    const uint8_t *const data; /**< transfer data */
1180
    const uint16_t len;        /**< transfer data length */
1181
    const uint16_t maxRespLen; /**< don't send more than this many bytes with copyResponse */
1182
    uint8_t (*copyResponse)(
1183
        UDSServer_t *srv, const void *src,
1184
        uint16_t len); /**< function for copying transfer data response data (optional) */
1185
} UDSTransferDataArgs_t;
1186
1187
/**
1188
 * @brief Request transfer exit arguments
1189
 */
1190
typedef struct {
1191
    const uint8_t *const data; /**< request data */
1192
    const uint16_t len;        /**< request data length */
1193
    uint8_t (*copyResponse)(UDSServer_t *srv, const void *src,
1194
                            uint16_t len); /**< function for copying response data (optional) */
1195
} UDSRequestTransferExitArgs_t;
1196
1197
/**
1198
 * @brief Request file transfer arguments
1199
 */
1200
typedef struct {
1201
    /**
1202
     * request:
1203
     * @see @ref uds_moop_ "modeOfOperation values"
1204
     */
1205
    const uint8_t modeOfOperation;
1206
    const uint16_t filePathLen; /**< request: data length. */
1207
    const uint8_t *filePath;    /**< request: file path or directory name (ReadDirectory). */
1208
    const uint8_t dataFormatIdentifier; /**< request: specifier for format of data (does not apply
1209
                                           to DeleteFile or ReadDir) */
1210
1211
    // if MOOP is AddFile, ReplaceFile, or ResumeFile, these fields are **requests**.
1212
    // if MOOP is ReadFile or ReadDirectory, these fields are **responses** -- the server must set
1213
    // them. if MOOP is DelFile, these fields are unused.
1214
    size_t fileSizeUnCompressed; /**< file size or directory info len (ReadDirectory) */
1215
    size_t fileSizeCompressed;   /**< compressed filesize (ReadFile), otherwise zero. */
1216
1217
    uint16_t maxNumberOfBlockLength; /**< response: Defaults to UDS_TP_MTU. Informs client how many
1218
                                        data bytes to send in each `TransferData` request. (unused
1219
                                        by DelFile). */
1220
    size_t filePosition; /**< response: byte position to resume from after suspended download
1221
                            (ResumeFile), otherwise zero. */
1222
} UDSRequestFileTransferArgs_t;
1223
1224
/**
1225
 * @brief Control DTC setting arguments
1226
 */
1227
typedef struct {
1228
    uint8_t type; /**< invoked subfunction */
1229
    size_t len;   /**< length of data */
1230
    void *data;   /**< DTCSettingControlOptionRecord */
1231
} UDSControlDTCSettingArgs_t;
1232
1233
/**
1234
 * @brief Link control arguments
1235
 */
1236
typedef struct {
1237
    const uint8_t type; /**< invoked subfunction */
1238
    /* purposefully left generic to allow vehicle- and supplier specific data of different sizes */
1239
    const size_t len; /**< length of data */
1240
    const void *data; /**< data used in the subfunction. E.g. on SubFunction 0x01 this is the
1241
                         linkControlModelIdentifier, on SubFunction 0x02 this is the linkRecord */
1242
} UDSLinkCtrlArgs_t;
1243
1244
/**
1245
 * @brief Custom service arguments
1246
 */
1247
typedef struct {
1248
    const uint16_t sid;          /**< serviceIdentifier */
1249
    const uint8_t *optionRecord; /**< optional data */
1250
    const uint16_t len;          /**< length of optional data */
1251
    uint8_t (*copyResponse)(UDSServer_t *srv, const void *src,
1252
                            uint16_t len); /**< function for copying response data (optional) */
1253
} UDSCustomArgs_t;
1254
1255
UDSErr_t UDSServerInit(UDSServer_t *srv); ///< call this once
1256
void UDSServerPoll(UDSServer_t *srv);     ///< Call this at <5ms intervals
1257
1258
#if defined(UDS_TP_ISOTP_C)
1259
/// \cond DOXYGEN_SHOULD_SKIP_THIS
1260
////////////////////////////////////////////////////////////////////////
1261
#ifdef UDS_LINES
1262
#line 1 "src/tp/isotp-c/isotp_config.h"
1263
#endif // #ifdef UDS_LINES
1264
//                  ___ ___  ___ _____ ___      ___                   //
1265
//                 |_ _/ __|/ _ \_   _| _ \___ / __|                  //
1266
//                  | |\__ \ (_) || | |  _/___| (__                   //
1267
//                 |___|___/\___/ |_| |_|      \___|                  //
1268
//                                                                    //
1269
//                      ___ ___  _  _ ___ ___ ___                     //
1270
//                     / __/ _ \| \| | __|_ _/ __|                    //
1271
//                    | (_| (_) | .` | _| | | (_ |                    //
1272
//                     \___\___/|_|\_|_| |___\___|                    //
1273
//                                                                    //
1274
////////////////////////////////////////////////////////////////////////
1275
1276
#ifndef ISOTPC_CONFIG_H
1277
#define ISOTPC_CONFIG_H
1278
1279
/**
1280
 * @file isotp_config.h
1281
 * @brief Compile-time transport configuration and defaults.
1282
 *
1283
 * Prefer the corresponding CMake or Make settings when using a supplied build
1284
 * system. Direct builds must define ABI-affecting options identically while
1285
 * compiling the library and every consumer.
1286
 */
1287
1288
/** @defgroup isotp_config Compile-time configuration
1289
 * @brief Macros controlling frame sizes, timing, optional APIs, and platform integration.
1290
 * @{ */
1291
1292
/** The maximum amount of data bytes a single CAN frame may carry (CAN_DL).
1293
 * Classical CAN is limited to 8 bytes; CAN FD additionally allows frames of
1294
 * 12, 16, 20, 24, 32, 48 and 64 bytes.
1295
 *
1296
 * Set this to one of the CAN FD lengths to enable CAN FD support. This
1297
 * increases the size of the internal frame buffers accordingly, so leave it at
1298
 * 8 on platforms without CAN FD.
1299
 */
1300
#ifndef ISO_TP_MAX_CAN_FRAME_SIZE
1301
    #define ISO_TP_MAX_CAN_FRAME_SIZE 8
1302
#endif
1303
1304
/** The CAN_DL (TX_DL) used by a freshly initialised link.
1305
 * This may be reduced per link at runtime using isotp_set_tx_dl(), e.g. when a
1306
 * peer only supports Classical CAN frame lengths.
1307
 */
1308
#ifndef ISO_TP_DEFAULT_TX_DL
1309
    #define ISO_TP_DEFAULT_TX_DL ISO_TP_MAX_CAN_FRAME_SIZE
1310
#endif
1311
1312
/** Flow Control block size advertised by the receiver.
1313
 * A value of 0 asks the sender not to wait for further block acknowledgements.
1314
 */
1315
#ifndef ISO_TP_DEFAULT_BLOCK_SIZE
1316
    #define ISO_TP_DEFAULT_BLOCK_SIZE 8
1317
#endif
1318
1319
/** Minimum Consecutive Frame separation requested by the receiver, in microseconds.
1320
 */
1321
#ifndef ISO_TP_DEFAULT_ST_MIN_US
1322
    #define ISO_TP_DEFAULT_ST_MIN_US 0
1323
#endif
1324
1325
/** Maximum number of Flow Control Wait frames accepted during transmission.
1326
 */
1327
#ifndef ISO_TP_MAX_WFT_NUMBER
1328
    #define ISO_TP_MAX_WFT_NUMBER 1
1329
#endif
1330
1331
/** Timeout for required Flow Control or Consecutive Frames, in microseconds.
1332
 * Keep this below half the range of the 32-bit microsecond clock so wrapping
1333
 * deadline comparisons remain unambiguous.
1334
 */
1335
#ifndef ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US
1336
    #define ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US 100000
1337
#endif
1338
1339
/** @def ISO_TP_FRAME_PADDING
1340
 * Pad transmitted Classical CAN frames to TX_DL. CAN FD frames larger than
1341
 * eight bytes are always padded to a legal CAN FD data length.
1342
 */
1343
#ifdef DOXYGEN
1344
    #define ISO_TP_FRAME_PADDING
1345
#endif
1346
1347
/** @def ISO_TP_NO_FORMATTED_ERRORS
1348
 * Omit the two formatted error messages, which are the library's only
1349
 * use of snprintf(). Define this on a target whose libc has no snprintf, or
1350
 * where the 128-byte ISOTP_MAX_ERROR_MSG_SIZE stack buffer is unwelcome. The
1351
 * errors are still reported through isotp_user_debug(), without the values.
1352
 *
1353
 * Measured on Cortex-M4, -Os -DNDEBUG: .text 2235 -> 2091 bytes, and the
1354
 * largest stack frame 160 -> 32 bytes. With this and NDEBUG the object needs
1355
 * nothing from libc but memcpy and memset.
1356
 */
1357
#ifdef DOXYGEN
1358
    #define ISO_TP_NO_FORMATTED_ERRORS
1359
#endif
1360
1361
1362
/** Byte written into unused padded frame positions. */
1363
#ifndef ISO_TP_FRAME_PADDING_VALUE
1364
    #define ISO_TP_FRAME_PADDING_VALUE 0xAA
1365
#endif
1366
1367
/** @def ISO_TP_USER_SEND_CAN_ARG
1368
 * Append the link's user_send_can_arg value to isotp_user_send_can(). This
1369
 * changes the shim signature and the public IsoTpLink layout.
1370
 */
1371
#ifdef DOXYGEN
1372
    #define ISO_TP_USER_SEND_CAN_ARG
1373
#endif
1374
1375
/** @def ISO_TP_USER_SEND_CAN_FLAGS
1376
 * Add a frame-flags argument to isotp_user_send_can(), telling the driver whether a frame has to be
1377
 * transmitted as a CAN FD frame. Enable this if the driver cannot derive the
1378
 * frame format from the frame length. When combined with
1379
 * ISO_TP_USER_SEND_CAN_ARG, the flags argument comes first.
1380
 */
1381
#ifdef DOXYGEN
1382
    #define ISO_TP_USER_SEND_CAN_FLAGS
1383
#endif
1384
1385
/** @def ISO_TP_CAN_FD_USE_BRS
1386
 * Add ISOTP_CAN_FRAME_FLAG_BRS to CAN FD transmissions. This has an effect only
1387
 * with ISO_TP_USER_SEND_CAN_FLAGS.
1388
 */
1389
#ifdef DOXYGEN
1390
    #define ISO_TP_CAN_FD_USE_BRS
1391
#endif
1392
1393
/** @def ISO_TP_TRANSMIT_COMPLETE_CALLBACK
1394
 * Add the transmit callback type, registration API, and link state.
1395
 */
1396
#ifdef DOXYGEN
1397
    #define ISO_TP_TRANSMIT_COMPLETE_CALLBACK
1398
#endif
1399
1400
/** @def ISO_TP_RECEIVE_COMPLETE_CALLBACK
1401
 * Add the receive callback type, registration API, and link state.
1402
 */
1403
#ifdef DOXYGEN
1404
    #define ISO_TP_RECEIVE_COMPLETE_CALLBACK
1405
#endif
1406
1407
/** @def ISO_TP_ENABLE_STREAMING
1408
 * Add isotp_receive_streaming() and link state for receiving messages larger
1409
 * than the receive buffer in application-consumable chunks.
1410
 */
1411
#ifdef DOXYGEN
1412
    #define ISO_TP_ENABLE_STREAMING
1413
#endif
1414
1415
/** @} */
1416
1417
#endif // ISOTPC_CONFIG_H
1418
1419
#ifndef ISOTPC_USER_DEFINITIONS_H
1420
#ifdef UDS_LINES
1421
#line 1 "src/tp/isotp-c/isotp_defines.h"
1422
#endif // #ifdef UDS_LINES
1423
#define ISOTPC_USER_DEFINITIONS_H
1424
1425
/**
1426
 * @file isotp_defines.h
1427
 * @brief Public result codes, CAN frame constants, and callback types.
1428
 */
1429
1430
1431
1432
1433
1434
/**************************************************************
1435
 * compiler specific defines
1436
 *************************************************************/
1437
#ifdef __GNUC__
1438
    #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1439
        #define ISOTP_BYTE_ORDER_LITTLE_ENDIAN
1440
    #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1441
    #else
1442
        #error "unsupported byte ordering"
1443
    #endif
1444
#endif
1445
1446
/**************************************************************
1447
 * OS specific defines
1448
 *************************************************************/
1449
#ifdef _MSC_VER
1450
    
1451
    #define ISOTP_BYTE_ORDER_LITTLE_ENDIAN
1452
#endif
1453
1454
#if defined(_MSC_VER) && _MSC_VER < 1900
1455
    #define ISOTP_SNPRINTF _snprintf
1456
#else 
1457
    #define ISOTP_SNPRINTF snprintf
1458
#endif
1459
1460
#define LE32TOH(le) ((uint32_t)(((le) << 24) | (((le) & 0x0000FF00) << 8) | (((le) & 0x00FF0000) >> 8) | ((le) >> 24)))
1461
1462
/**************************************************************
1463
 * CAN frame length (CAN_DL) defines
1464
 *************************************************************/
1465
1466
/** @defgroup isotp_can CAN frame constants
1467
 * @brief Values used to configure CAN and CAN FD transmission.
1468
 * @{ */
1469
1470
/** Number of payload bytes in a full Classical CAN frame. */
1471
#define ISOTP_CAN_DL_CLASSIC 8
1472
1473
#if (ISO_TP_MAX_CAN_FRAME_SIZE != 8) && (ISO_TP_MAX_CAN_FRAME_SIZE != 12) && (ISO_TP_MAX_CAN_FRAME_SIZE != 16) && (ISO_TP_MAX_CAN_FRAME_SIZE != 20) && \
1474
    (ISO_TP_MAX_CAN_FRAME_SIZE != 24) && (ISO_TP_MAX_CAN_FRAME_SIZE != 32) && (ISO_TP_MAX_CAN_FRAME_SIZE != 48) && (ISO_TP_MAX_CAN_FRAME_SIZE != 64)
1475
    #error "ISO_TP_MAX_CAN_FRAME_SIZE must be one of 8, 12, 16, 20, 24, 32, 48, 64"
1476
#endif
1477
1478
#if (ISO_TP_DEFAULT_TX_DL > ISO_TP_MAX_CAN_FRAME_SIZE) || (ISO_TP_DEFAULT_TX_DL < ISOTP_CAN_DL_CLASSIC)
1479
    #error "ISO_TP_DEFAULT_TX_DL must be at least 8 and must not exceed ISO_TP_MAX_CAN_FRAME_SIZE"
1480
#endif
1481
1482
/** Transmit a Classical CAN frame; no optional frame properties are set. */
1483
#define ISOTP_CAN_FRAME_FLAG_NONE 0x00
1484
/** Transmit a CAN FD frame. */
1485
#define ISOTP_CAN_FRAME_FLAG_FD 0x01
1486
/** Enable CAN FD bit-rate switching for the data phase. */
1487
#define ISOTP_CAN_FRAME_FLAG_BRS 0x02
1488
1489
/**
1490
 * Largest ISO-TP payload that fits in one frame for a given CAN_DL.
1491
 *
1492
 * CAN FD data lengths use the two-byte SF_DL escape header; Classical CAN uses
1493
 * a one-byte header.
1494
 */
1495
#define ISOTP_SF_MAX_PAYLOAD(can_dl) ((can_dl) > ISOTP_CAN_DL_CLASSIC ? (uint32_t)((can_dl) - 2u) : (uint32_t)((can_dl) - 1u))
1496
1497
/** @} */
1498
1499
/**************************************************************
1500
 * Result codes
1501
 *************************************************************/
1502
/** @defgroup isotp_results Return values
1503
 * @brief Status values returned by the transport API and platform send shim.
1504
 * @{ */
1505
1506
/** Operation succeeded or a frame was accepted by the CAN driver. */
1507
#define ISOTP_RET_OK 0
1508
/** Invalid argument, incompatible receive mode, or permanent driver failure. */
1509
#define ISOTP_RET_ERROR -1
1510
/** A segmented transmission is already active. */
1511
#define ISOTP_RET_INPROGRESS -2
1512
/** A payload exceeds the configured link buffer. */
1513
#define ISOTP_RET_OVERFLOW -3
1514
/** A Consecutive Frame used an unexpected sequence number. */
1515
#define ISOTP_RET_WRONG_SN -4
1516
/** No completed message or streaming chunk is available. */
1517
#define ISOTP_RET_NO_DATA -5
1518
/** A protocol response was not received before its deadline. */
1519
#define ISOTP_RET_TIMEOUT -6
1520
/** A CAN frame or declared ISO-TP payload length is invalid. */
1521
#define ISOTP_RET_LENGTH -7
1522
/** Temporary CAN-driver backpressure, or a streaming destination that is too small. */
1523
#define ISOTP_RET_NOSPACE -8
1524
1525
/** @} */
1526
1527
/** @cond ISOTP_INTERNAL */
1528
1529
/* return logic true if 'a' is after 'b' */
1530
#define IsoTpTimeAfter(a, b) ((int32_t)((int32_t)(b) - (int32_t)(a)) < 0)
1531
1532
/*  invalid bs */
1533
#define ISOTP_INVALID_BS 0xFFFF
1534
1535
/* Define the maximum amount of characters allowed in an error message. This fixes code which would otherwise break on Microsoft's dumb platform. */
1536
#define ISOTP_MAX_ERROR_MSG_SIZE 128
1537
1538
/** @endcond */
1539
1540
/** @defgroup isotp_status Link status and protocol results
1541
 * @brief Observable state for asynchronous send and receive operations.
1542
 * @{ */
1543
1544
/** Current segmented-transmission state stored in IsoTpLink::send_status. */
1545
typedef enum {
1546
    ISOTP_SEND_STATUS_IDLE,       /**< No segmented transmission is active. */
1547
    ISOTP_SEND_STATUS_INPROGRESS, /**< Consecutive Frames or Flow Control are pending. */
1548
    ISOTP_SEND_STATUS_ERROR,      /**< Transmission stopped; inspect IsoTpLink::send_protocol_result. */
1549
} IsoTpSendStatusTypes;
1550
1551
/** Current reassembly state stored in IsoTpLink::receive_status. */
1552
typedef enum {
1553
    ISOTP_RECEIVE_STATUS_IDLE,       /**< No message is being reassembled. */
1554
    ISOTP_RECEIVE_STATUS_INPROGRESS, /**< Consecutive Frames are expected. */
1555
    ISOTP_RECEIVE_STATUS_FULL,       /**< A complete message or streaming chunk is available. */
1556
} IsoTpReceiveStatusTypes;
1557
1558
/** @} */
1559
1560
/** @cond ISOTP_INTERNAL */
1561
1562
/* can fram defination */
1563
#if defined(ISOTP_BYTE_ORDER_LITTLE_ENDIAN)
1564
typedef struct {
1565
    uint8_t reserve_1 : 4;
1566
    uint8_t type      : 4;
1567
    uint8_t reserve_2[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1568
} IsoTpPciType;
1569
1570
typedef struct {
1571
    uint8_t SF_DL : 4;
1572
    uint8_t type  : 4;
1573
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1574
} IsoTpSingleFrame;
1575
1576
typedef struct {
1577
    uint8_t set_to_zero : 4;
1578
    uint8_t type        : 4;
1579
    uint8_t SF_DL;
1580
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 2];
1581
} IsoTpSingleFrameEscape;
1582
1583
typedef struct {
1584
    uint8_t FF_DL_high : 4;
1585
    uint8_t type       : 4;
1586
    uint8_t FF_DL_low;
1587
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 2];
1588
} IsoTpFirstFrameShort;
1589
1590
#pragma pack(push, 1)
1591
typedef struct {
1592
    uint8_t  set_to_zero_high : 4;
1593
    uint8_t  type             : 4;
1594
    uint8_t  set_to_zero_low;
1595
    uint32_t FF_DL;
1596
    uint8_t  data[ISO_TP_MAX_CAN_FRAME_SIZE - 6];
1597
} IsoTpFirstFrameLong;
1598
#pragma pack(pop)
1599
1600
typedef struct {
1601
    uint8_t SN   : 4;
1602
    uint8_t type : 4;
1603
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1604
} IsoTpConsecutiveFrame;
1605
1606
typedef struct {
1607
    uint8_t FS   : 4;
1608
    uint8_t type : 4;
1609
    uint8_t BS;
1610
    uint8_t STmin;
1611
    uint8_t reserve[ISO_TP_MAX_CAN_FRAME_SIZE - 3];
1612
} IsoTpFlowControl;
1613
1614
#else
1615
1616
typedef struct {
1617
    uint8_t type      : 4;
1618
    uint8_t reserve_1 : 4;
1619
    uint8_t reserve_2[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1620
} IsoTpPciType;
1621
1622
/*
1623
 * single frame
1624
 * +-------------------------+-----+
1625
 * | byte #0                 | ... |
1626
 * +-------------------------+-----+
1627
 * | nibble #0   | nibble #1 | ... |
1628
 * +-------------+-----------+ ... +
1629
 * | PCIType = 0 | SF_DL     | ... |
1630
 * +-------------+-----------+-----+
1631
 */
1632
typedef struct {
1633
    uint8_t type  : 4;
1634
    uint8_t SF_DL : 4;
1635
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1636
} IsoTpSingleFrame;
1637
1638
/*
1639
 * single frame using the SF_DL escape sequence (CAN FD only, CAN_DL > 8)
1640
 * +-------------------------+-----------------------+-----+
1641
 * | byte #0                 | byte #1               | ... |
1642
 * +-------------------------+-----------+-----------+-----+
1643
 * | nibble #0   | nibble #1 | nibble #2 | nibble #3 | ... |
1644
 * +-------------+-----------+-----------+-----------+-----+
1645
 * | PCIType = 0 | unused=0  | SF_DL                 | ... |
1646
 * +-------------+-----------+-----------------------+-----+
1647
 */
1648
typedef struct {
1649
    uint8_t type        : 4;
1650
    uint8_t set_to_zero : 4;
1651
    uint8_t SF_DL;
1652
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 2];
1653
} IsoTpSingleFrameEscape;
1654
1655
/*
1656
 * first frame short
1657
 * +-------------------------+-----------------------+-----+
1658
 * | byte #0                 | byte #1               | ... |
1659
 * +-------------------------+-----------+-----------+-----+
1660
 * | nibble #0   | nibble #1 | nibble #2 | nibble #3 | ... |
1661
 * +-------------+-----------+-----------+-----------+-----+
1662
 * | PCIType = 1 | FF_DL                             | ... |
1663
 * +-------------+-----------+-----------------------+-----+
1664
 */
1665
typedef struct {
1666
    uint8_t type       : 4;
1667
    uint8_t FF_DL_high : 4;
1668
    uint8_t FF_DL_low;
1669
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 2];
1670
} IsoTpFirstFrameShort;
1671
1672
/*
1673
 * first frame long
1674
 * +-------------------------+-----------------------+---------+---------+---------+---------+
1675
 * | byte #0                 | byte #1               | byte #2 | byte #3 | byte #4 | byte #5 |
1676
 * +-------------------------+-----------+-----------+---------+---------+---------+---------+
1677
 * | nibble #0   | nibble #1 | nibble #2 | nibble #3 | ...                                   |
1678
 * +-------------+-----------+-----------+-----------+---------------------------------------+
1679
 * | PCIType = 1 | unused=0  | escape sequence = 0   | FF_DL                                 |
1680
 * +-------------+-----------+-----------------------+---------------------------------------+
1681
 */
1682
#pragma pack(push, 1)
1683
typedef struct {
1684
    uint8_t  type             : 4;
1685
    uint8_t  set_to_zero_high : 4;
1686
    uint8_t  set_to_zero_low;
1687
    uint32_t FF_DL;
1688
    uint8_t  data[ISO_TP_MAX_CAN_FRAME_SIZE - 6];
1689
} IsoTpFirstFrameLong;
1690
#pragma pack(pop)
1691
1692
/*
1693
 * consecutive frame
1694
 * +-------------------------+-----+
1695
 * | byte #0                 | ... |
1696
 * +-------------------------+-----+
1697
 * | nibble #0   | nibble #1 | ... |
1698
 * +-------------+-----------+ ... +
1699
 * | PCIType = 0 | SN        | ... |
1700
 * +-------------+-----------+-----+
1701
 */
1702
typedef struct {
1703
    uint8_t type : 4;
1704
    uint8_t SN   : 4;
1705
    uint8_t data[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
1706
} IsoTpConsecutiveFrame;
1707
1708
/*
1709
 * flow control frame
1710
 * +-------------------------+-----------------------+-----------------------+-----+
1711
 * | byte #0                 | byte #1               | byte #2               | ... |
1712
 * +-------------------------+-----------+-----------+-----------+-----------+-----+
1713
 * | nibble #0   | nibble #1 | nibble #2 | nibble #3 | nibble #4 | nibble #5 | ... |
1714
 * +-------------+-----------+-----------+-----------+-----------+-----------+-----+
1715
 * | PCIType = 1 | FS        | BS                    | STmin                 | ... |
1716
 * +-------------+-----------+-----------------------+-----------------------+-----+
1717
 */
1718
typedef struct {
1719
    uint8_t type : 4;
1720
    uint8_t FS   : 4;
1721
    uint8_t BS;
1722
    uint8_t STmin;
1723
    uint8_t reserve[ISO_TP_MAX_CAN_FRAME_SIZE - 3];
1724
} IsoTpFlowControl;
1725
1726
#endif
1727
1728
typedef struct {
1729
        uint8_t ptr[ISO_TP_MAX_CAN_FRAME_SIZE];
1730
} IsoTpDataArray;
1731
1732
typedef struct {
1733
    union {
1734
        IsoTpPciType           common;
1735
        IsoTpSingleFrame       single_frame;
1736
        IsoTpSingleFrameEscape single_frame_escape;
1737
        IsoTpFirstFrameShort   first_frame_short;
1738
        IsoTpFirstFrameLong    first_frame_long;
1739
        IsoTpConsecutiveFrame  consecutive_frame;
1740
        IsoTpFlowControl       flow_control;
1741
        IsoTpDataArray         data_array;
1742
    } as;
1743
} IsoTpCanMessage;
1744
1745
/** @endcond */
1746
1747
/**************************************************************
1748
 * Callback types
1749
 *************************************************************/
1750
1751
#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
1752
/**
1753
 * @brief Called after a complete payload has been transmitted successfully.
1754
 *
1755
 * @param link Link that completed transmission. Cast to IsoTpLink* when needed.
1756
 * @param tx_size Size of the completed ISO-TP payload in bytes.
1757
 * @param user_arg Value registered with isotp_set_tx_done_cb().
1758
 */
1759
typedef void (*isotp_tx_done_cb)(void* link, uint32_t tx_size, void* user_arg);
1760
#endif
1761
1762
#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
1763
/**
1764
 * @brief Called after a complete payload has been received successfully.
1765
 *
1766
 * @param link Link that received the payload. Cast to IsoTpLink* when needed.
1767
 * @param data Link-owned payload, valid only for the duration of the callback.
1768
 * @param size Payload size in bytes.
1769
 * @param user_arg Value registered with isotp_set_rx_done_cb().
1770
 */
1771
typedef void (*isotp_rx_done_cb)(void* link, const uint8_t* data, uint32_t size, void* user_arg);
1772
#endif
1773
1774
/** @cond ISOTP_INTERNAL */
1775
/* Protocol Control Information (PCI) types. */
1776
typedef enum {
1777
    ISOTP_PCI_TYPE_SINGLE             = 0x0,
1778
    ISOTP_PCI_TYPE_FIRST_FRAME        = 0x1,
1779
    TSOTP_PCI_TYPE_CONSECUTIVE_FRAME  = 0x2,
1780
    ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME = 0x3,
1781
1782
    ISOTP_PCI_TYPE_CONSECUTIVE_FRAME  = 0x2, // Typo fix; but keep broken value for backwards-compat.
1783
} IsoTpProtocolControlInformation;
1784
1785
/* Private: Protocol Control Information (PCI) flow control identifiers.
1786
 */
1787
typedef enum { PCI_FLOW_STATUS_CONTINUE = 0x0, PCI_FLOW_STATUS_WAIT = 0x1, PCI_FLOW_STATUS_OVERFLOW = 0x2 } IsoTpFlowStatus;
1788
1789
/** @endcond */
1790
1791
/** @addtogroup isotp_status
1792
 * @{ */
1793
/** Protocol operation completed without an error. */
1794
#define ISOTP_PROTOCOL_RESULT_OK 0
1795
/** Reserved result for an N_As transmission timeout; not currently produced. */
1796
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_A -1
1797
/** Timeout waiting for a Flow Control frame. */
1798
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_BS -2
1799
/** Timeout waiting for a Consecutive Frame. */
1800
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_CR -3
1801
/** An incoming Consecutive Frame had the wrong sequence number. */
1802
#define ISOTP_PROTOCOL_RESULT_WRONG_SN -4
1803
/** Reserved result for invalid Flow Control status; not currently produced. */
1804
#define ISOTP_PROTOCOL_RESULT_INVALID_FS -5
1805
/** A protocol data unit arrived in an incompatible link state. */
1806
#define ISOTP_PROTOCOL_RESULT_UNEXP_PDU -6
1807
/** The peer sent more Flow Control Wait frames than ISO_TP_MAX_WFT_NUMBER. */
1808
#define ISOTP_PROTOCOL_RESULT_WFT_OVRN -7
1809
/** The sender reported overflow, or an incoming message exceeded the receive buffer. */
1810
#define ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW -8
1811
/** Reserved generic protocol error; not currently produced. */
1812
#define ISOTP_PROTOCOL_RESULT_ERROR -9
1813
1814
/** @} */
1815
1816
#endif // ISOTPC_USER_DEFINITIONS_H
1817
1818
////////////////////////////////////////////////////////////////////////
1819
#ifdef UDS_LINES
1820
#line 1 "src/tp/isotp-c/isotp_user.h"
1821
#endif // #ifdef UDS_LINES
1822
//                  ___ ___  ___ _____ ___      ___                   //
1823
//                 |_ _/ __|/ _ \_   _| _ \___ / __|                  //
1824
//                  | |\__ \ (_) || | |  _/___| (__                   //
1825
//                 |___|___/\___/ |_| |_|      \___|                  //
1826
//                                                                    //
1827
////////////////////////////////////////////////////////////////////////
1828
1829
#ifndef ISOTPC_USER_H
1830
#define ISOTPC_USER_H
1831
1832
1833
1834
#ifdef __cplusplus
1835
extern "C" {
1836
#endif
1837
1838
/**
1839
 * @file isotp_user.h
1840
 * @brief Application-provided platform hooks.
1841
 */
1842
1843
/** @defgroup isotp_platform Platform integration
1844
 * @brief Functions that every application supplies to connect ISO-TP to its driver and clock.
1845
 * @{ */
1846
1847
/**
1848
 * @brief Receive a diagnostic message from the library.
1849
 *
1850
 * The application may implement this as a no-op. Calls can occur from any
1851
 * transport API that detects an error. The library does not require the
1852
 * message to be retained after this function returns.
1853
 *
1854
 * @param[in] message Diagnostic string or printf-style format.
1855
 * @param[in] ... Optional format arguments.
1856
 */
1857
void isotp_user_debug(const char* message, ...);
1858
1859
/**
1860
 * @brief Submit one CAN or CAN FD frame to the application's driver.
1861
 *
1862
 * The implementation must consume or copy @p data before returning. It may be
1863
 * called synchronously from isotp_send(), isotp_on_can_message(),
1864
 * isotp_receive_streaming(), or isotp_poll().
1865
 *
1866
 * @param[in] arbitration_id CAN identifier to transmit.
1867
 * @param[in] data Frame payload, valid only for the duration of this call.
1868
 * @param[in] size Frame payload length. It never exceeds
1869
 *                 ISO_TP_MAX_CAN_FRAME_SIZE. Lengths above 8 require CAN FD.
1870
 * @param[in] flags Present only with ISO_TP_USER_SEND_CAN_FLAGS. A bitwise OR
1871
 *                  of ISOTP_CAN_FRAME_FLAG_FD and ISOTP_CAN_FRAME_FLAG_BRS;
1872
 *                  short frames on a link with TX_DL above 8 still carry the
1873
 *                  FD flag.
1874
 * @param[in] arg Present only with ISO_TP_USER_SEND_CAN_ARG. This is the link's
1875
 *                user_send_can_arg value.
1876
 * @retval ISOTP_RET_OK The driver accepted the frame.
1877
 * @retval ISOTP_RET_NOSPACE The driver is temporarily full and a polled
1878
 *                           Consecutive Frame should be retried.
1879
 * @retval ISOTP_RET_ERROR The frame could not be submitted.
1880
 */
1881
int isotp_user_send_can(const uint32_t arbitration_id, const uint8_t* data, const uint8_t size
1882
#ifdef ISO_TP_USER_SEND_CAN_FLAGS
1883
                        , const uint8_t flags
1884
#endif
1885
#ifdef ISO_TP_USER_SEND_CAN_ARG
1886
                        , void* arg
1887
#endif
1888
);
1889
1890
/**
1891
 * @brief Return the current 32-bit monotonic time in microseconds.
1892
 *
1893
 * The value must advance independently of call frequency. Natural wraparound
1894
 * at UINT32_MAX is supported.
1895
 *
1896
 * @return Current platform tick in microseconds.
1897
 */
1898
uint32_t isotp_user_get_us(void);
1899
1900
/** @} */
1901
1902
#ifdef __cplusplus
1903
}
1904
#endif
1905
1906
#endif // ISOTPC_USER_H
1907
1908
////////////////////////////////////////////////////////////////////////
1909
#ifdef UDS_LINES
1910
#line 1 "src/tp/isotp-c/isotp.h"
1911
#endif // #ifdef UDS_LINES
1912
//                  ___ ___  ___ _____ ___      ___                   //
1913
//                 |_ _/ __|/ _ \_   _| _ \___ / __|                  //
1914
//                  | |\__ \ (_) || | |  _/___| (__                   //
1915
//                 |___|___/\___/ |_| |_|      \___|                  //
1916
//                                                                    //
1917
////////////////////////////////////////////////////////////////////////
1918
1919
#ifndef ISOTPC_H
1920
#define ISOTPC_H
1921
1922
1923
1924
1925
1926
#ifdef __cplusplus
1927
    
1928
1929
extern "C" {
1930
#endif
1931
1932
1933
1934
1935
1936
/**
1937
 * @file isotp.h
1938
 * @brief Public ISO-TP link and transport API.
1939
 */
1940
1941
/**
1942
 * @defgroup isotp_api Transport API
1943
 * @brief Functions for creating, driving, sending through, and receiving from an ISO-TP link.
1944
 * @{
1945
 */
1946
1947
/**
1948
 * @brief State for one independent, full-duplex ISO-TP conversation.
1949
 *
1950
 * Allocate one link for each conversation that can have independent send or
1951
 * receive state. Initialise it with isotp_init_link() before use and keep the
1952
 * object and its buffers alive for the complete lifetime of the link.
1953
 *
1954
 * Calls that access the same link must be serialised. Applications may observe
1955
 * the documented status/result members and set user_send_can_arg when enabled;
1956
 * all other members are implementation state.
1957
 */
1958
typedef struct IsoTpLink {
1959
    /** @cond ISOTP_INTERNAL */
1960
    /* sender parameters */
1961
    uint32_t            send_arbitration_id;
1962
    uint8_t             tx_dl;
1963
1964
    uint8_t*            send_buffer;
1965
    uint32_t            send_buf_size;
1966
    uint32_t            send_size;
1967
    uint32_t            send_offset;
1968
1969
    uint8_t             send_sn;
1970
    uint32_t            send_bs_remain;
1971
    uint32_t            send_st_min_us;
1972
    uint8_t             send_wtf_count;
1973
    uint32_t            send_timer_st;
1974
    uint32_t            send_timer_bs;
1975
    /** @endcond */
1976
    /** Result of the current or most recent segmented transmission. */
1977
    int32_t             send_protocol_result;
1978
    /** Current IsoTpSendStatusTypes value. */
1979
    uint8_t             send_status;
1980
    /** @cond ISOTP_INTERNAL */
1981
1982
    /* receiver parameters */
1983
    uint32_t            receive_arbitration_id;
1984
    uint8_t             rx_dl;
1985
1986
    uint8_t*            receive_buffer;
1987
    uint32_t            receive_buf_size;
1988
    uint32_t            receive_size;
1989
    uint32_t            receive_offset;
1990
1991
    uint8_t             receive_sn;
1992
    uint8_t             receive_bs_count;
1993
    uint32_t            receive_timer_cr;
1994
    /** @endcond */
1995
    /** Result of the current or most recent receive operation. */
1996
    int                 receive_protocol_result;
1997
    /** Current IsoTpReceiveStatusTypes value. Prefer isotp_receive() to consume completed data. */
1998
    uint8_t             receive_status;
1999
    /** @cond ISOTP_INTERNAL */
2000
2001
#ifdef ISO_TP_ENABLE_STREAMING
2002
    uint32_t            receive_stream_size;
2003
    uint8_t             receive_streaming;
2004
    uint8_t             receive_stream_carry_size;
2005
    uint8_t             receive_stream_carry[ISO_TP_MAX_CAN_FRAME_SIZE - 1];
2006
#endif
2007
    /** @endcond */
2008
2009
#if defined(ISO_TP_USER_SEND_CAN_ARG)
2010
    /**
2011
     * Application value passed to isotp_user_send_can() for this link.
2012
     *
2013
     * Set this after isotp_init_link(), which initially clears it to NULL.
2014
     * A CAN controller or driver context pointer is a typical value.
2015
     */
2016
    void*               user_send_can_arg;
2017
#endif
2018
2019
    /** @cond ISOTP_INTERNAL */
2020
#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
2021
    isotp_tx_done_cb    tx_done_cb;
2022
    void*               tx_done_cb_arg;
2023
#endif
2024
2025
#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
2026
    isotp_rx_done_cb    rx_done_cb;
2027
    void*               rx_done_cb_arg;
2028
#endif
2029
    /** @endcond */
2030
} IsoTpLink;
2031
2032
/**
2033
 * @brief Initialise an ISO-TP link and its caller-owned buffers.
2034
 *
2035
 * The complete link object is cleared. Its transmit identifier is set to
2036
 * @p sendid, TX_DL is set to ISO_TP_DEFAULT_TX_DL, and receive and transmit
2037
 * state become idle.
2038
 *
2039
 * @param[out] link Link object to initialise. Must not be NULL.
2040
 * @param[in] sendid CAN arbitration identifier used by isotp_send() and by
2041
 *                   Flow Control responses.
2042
 * @param[in,out] sendbuf Persistent buffer into which outgoing payloads are
2043
 *                        copied. Must not be NULL when @p sendbufsize is nonzero.
2044
 * @param[in] sendbufsize Capacity of @p sendbuf and therefore the maximum
2045
 *                        payload accepted for transmission.
2046
 * @param[in,out] recvbuf Persistent reassembly or streaming buffer. Must not be
2047
 *                        NULL when @p recvbufsize is nonzero.
2048
 * @param[in] recvbufsize Capacity of @p recvbuf. Without streaming, incoming
2049
 *                        messages larger than this are rejected.
2050
 *
2051
 * @pre The link is not being used by another call.
2052
 * @see isotp_set_tx_dl()
2053
 */
2054
void isotp_init_link(IsoTpLink* link, uint32_t sendid, uint8_t* sendbuf, uint32_t sendbufsize, uint8_t* recvbuf, uint32_t recvbufsize);
2055
2056
/**
2057
 * @brief Set the CAN frame data length used to transmit on a link.
2058
 *
2059
 * A Classical CAN link uses 8. CAN FD links may use 12, 16, 20, 24, 32, 48,
2060
 * or 64, subject to the compiled ISO_TP_MAX_CAN_FRAME_SIZE.
2061
 *
2062
 * @param[in,out] link Initialised link, or NULL.
2063
 * @param[in] tx_dl Desired transmit data length.
2064
 * @retval ISOTP_RET_OK The value was applied.
2065
 * @retval ISOTP_RET_ERROR The link is NULL, the value is not a legal CAN data
2066
 *                         length, or it exceeds ISO_TP_MAX_CAN_FRAME_SIZE.
2067
 * @retval ISOTP_RET_INPROGRESS A segmented transmission is active; its TX_DL
2068
 *                              cannot be changed.
2069
 *
2070
 * @note RX_DL is learned independently from each incoming First Frame.
2071
 * @example isotp_example_can_fd.c
2072
 */
2073
int isotp_set_tx_dl(IsoTpLink* link, uint8_t tx_dl);
2074
2075
/**
2076
 * @brief Return the effective transmit data length for a link.
2077
 *
2078
 * @param[in] link Initialised link, or NULL.
2079
 * @return The configured TX_DL, with 8 used as a defensive fallback for a
2080
 *         zero-valued field; returns 0 when @p link is NULL.
2081
 */
2082
uint8_t isotp_get_tx_dl(const IsoTpLink* link);
2083
2084
/**
2085
 * @brief Clear a link's state and callback registrations.
2086
 *
2087
 * No memory is freed because the library owns no allocation. The caller retains
2088
 * ownership of the link and both buffers. Passing NULL has no effect.
2089
 *
2090
 * @param[in,out] link Link to clear, or NULL.
2091
 */
2092
void isotp_destroy_link(IsoTpLink* link);
2093
2094
/**
2095
 * @brief Advance segmented transmission and protocol timeouts.
2096
 *
2097
 * Call this regularly even when completion callbacks are enabled. The required
2098
 * frequency depends on the configured separation time and response timeout.
2099
 * Single-frame transmission and incoming-frame parsing happen synchronously in
2100
 * their respective API calls.
2101
 *
2102
 * @param[in,out] link Initialised link. Must not be NULL.
2103
 * @example isotp_example_polling.c
2104
 */
2105
void isotp_poll(IsoTpLink* link);
2106
2107
/**
2108
 * @brief Process one CAN frame already routed to this link.
2109
 *
2110
 * The application must filter arbitration identifiers before calling this
2111
 * function. Frames shorter than two bytes or longer than
2112
 * ISO_TP_MAX_CAN_FRAME_SIZE are ignored. Valid frames update receive or
2113
 * transmit flow-control state and may synchronously send a Flow Control frame.
2114
 * A registered receive callback may run before this function returns.
2115
 *
2116
 * @param[in,out] link Initialised link. Must not be NULL.
2117
 * @param[in] data Frame payload, valid for at least @p len bytes. Must not be NULL.
2118
 * @param[in] len CAN payload length in bytes.
2119
 */
2120
void isotp_on_can_message(IsoTpLink* link, const uint8_t* data, uint8_t len);
2121
2122
/**
2123
 * @brief Start transmitting a payload with the link's configured CAN identifier.
2124
 *
2125
 * The payload is copied into the link's send buffer. A Single Frame is sent
2126
 * synchronously. For a segmented message, only the First Frame is sent here;
2127
 * isotp_poll() sends the remaining Consecutive Frames after Flow Control.
2128
 *
2129
 * @param[in,out] link Initialised link. Must not be NULL.
2130
 * @param[in] payload Payload to copy. Must be valid for at least @p size bytes.
2131
 * @param[in] size Payload size. It must not exceed the link's send-buffer capacity.
2132
 * @retval ISOTP_RET_OK The Single Frame or First Frame was accepted by the driver.
2133
 * @retval ISOTP_RET_OVERFLOW The payload exceeds the link's send buffer.
2134
 * @retval ISOTP_RET_INPROGRESS Another segmented transmission is active.
2135
 * @return Any other value returned by isotp_user_send_can().
2136
 *
2137
 * @warning ISOTP_RET_OK does not mean a segmented transmission is complete.
2138
 *          Keep polling until the completion callback runs or send_status is
2139
 *          no longer ISOTP_SEND_STATUS_INPROGRESS, then inspect
2140
 *          send_protocol_result.
2141
 */
2142
int isotp_send(IsoTpLink* link, const uint8_t payload[], uint32_t size);
2143
2144
/**
2145
 * @brief Start transmitting with a one-time CAN identifier override.
2146
 *
2147
 * Behaviour and return values are the same as isotp_send(), except @p id is used
2148
 * instead of the identifier stored in the link. This is commonly used for a
2149
 * functional-addressing request. ISO-TP functional requests must fit in a
2150
 * Single Frame; the library does not enforce that addressing rule.
2151
 *
2152
 * @param[in,out] link Initialised link, or NULL.
2153
 * @param[in] id CAN arbitration identifier for this transmission.
2154
 * @param[in] payload Payload to copy. Must be valid for at least @p size bytes.
2155
 * @param[in] size Payload size.
2156
 * @retval ISOTP_RET_ERROR The link is NULL.
2157
 * @retval ISOTP_RET_OK The Single Frame or First Frame was accepted by the driver.
2158
 * @retval ISOTP_RET_OVERFLOW The payload exceeds the link's send buffer.
2159
 * @retval ISOTP_RET_INPROGRESS Another segmented transmission is active.
2160
 * @return Any other value returned by isotp_user_send_can().
2161
 */
2162
int isotp_send_with_id(IsoTpLink* link, uint32_t id, const uint8_t payload[], uint32_t size);
2163
2164
/**
2165
 * @brief Copy and consume one completed, non-streaming message.
2166
 *
2167
 * At most @p payload_size bytes are copied. The completed message is released
2168
 * even when the destination is too small, so any uncopied remainder is lost.
2169
 *
2170
 * @param[in,out] link Initialised link. Must not be NULL.
2171
 * @param[out] payload Destination buffer. Must not be NULL.
2172
 * @param[in] payload_size Capacity of @p payload.
2173
 * @param[out] out_size Number of bytes copied. Must not be NULL.
2174
 * @retval ISOTP_RET_OK A completed message was copied and consumed.
2175
 * @retval ISOTP_RET_NO_DATA No complete message is available.
2176
 * @retval ISOTP_RET_ERROR Streaming reception is active, or a receive callback
2177
 *                         is registered in a build that supports callbacks.
2178
 */
2179
int isotp_receive(IsoTpLink* link, uint8_t* payload, const uint32_t payload_size, uint32_t* out_size);
2180
2181
#ifdef ISO_TP_ENABLE_STREAMING
2182
/**
2183
 * @brief Copy and consume the next available chunk of an incoming message.
2184
 *
2185
 * This function supports both oversized streaming messages and messages that
2186
 * fit in the normal receive buffer. Consuming an intermediate chunk emits a
2187
 * Continue Flow Control frame when more wire data is needed.
2188
 *
2189
 * @param[in,out] link Initialised link, or NULL.
2190
 * @param[out] payload Destination for the complete available chunk, or NULL.
2191
 * @param[in] payload_size Capacity of @p payload.
2192
 * @param[out] out_size Number of bytes copied, or NULL.
2193
 * @param[out] is_complete Set to true when this chunk ends the message, or NULL.
2194
 * @retval ISOTP_RET_OK A chunk was copied.
2195
 * @retval ISOTP_RET_NO_DATA No chunk is currently available.
2196
 * @retval ISOTP_RET_NOSPACE The destination cannot hold the available chunk;
2197
 *                           the chunk remains available.
2198
 * @retval ISOTP_RET_ERROR Any required pointer is NULL.
2199
 * @example isotp_example_streaming.c
2200
 */
2201
int isotp_receive_streaming(IsoTpLink* link, uint8_t* payload, const uint32_t payload_size, uint32_t* out_size, bool* is_complete);
2202
#endif
2203
2204
#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
2205
/**
2206
 * @brief Register or clear the successful-transmission callback.
2207
 *
2208
 * A Single Frame invokes the callback synchronously from isotp_send() or
2209
 * isotp_send_with_id(). A segmented transmission invokes it from isotp_poll()
2210
 * after the final Consecutive Frame is accepted.
2211
 *
2212
 * @param[in,out] link Initialised link. Passing NULL has no effect.
2213
 * @param[in] cb Callback to register, or NULL to disable notification.
2214
 * @param[in] arg Application value passed to @p cb.
2215
 */
2216
void isotp_set_tx_done_cb(IsoTpLink* link, isotp_tx_done_cb cb, void* arg);
2217
#endif
2218
2219
#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
2220
/**
2221
 * @brief Register or clear the completed-receive callback.
2222
 *
2223
 * The callback runs synchronously from isotp_on_can_message(). Its payload
2224
 * pointer refers to the link's receive buffer and is valid only until the
2225
 * callback returns. Registering it disables delivery through isotp_receive().
2226
 * Oversized streaming messages are still delivered through
2227
 * isotp_receive_streaming().
2228
 *
2229
 * @param[in,out] link Initialised link. Passing NULL has no effect.
2230
 * @param[in] cb Callback to register, or NULL to restore polling delivery.
2231
 * @param[in] arg Application value passed to @p cb.
2232
 * @example isotp_example_callbacks.c
2233
 */
2234
void isotp_set_rx_done_cb(IsoTpLink* link, isotp_rx_done_cb cb, void* arg);
2235
#endif
2236
2237
/** @} */
2238
2239
#ifdef __cplusplus
2240
}
2241
#endif
2242
2243
#endif // ISOTPC_H
2244
2245
2246
/// \endcond
2247
#endif // if defined(UDS_TP_ISOTP_C)
2248
2249
#ifdef UDS_LINES
2250
#line 1 "src/tp/isotp_c.h"
2251
#endif // #ifdef UDS_LINES
2252
#ifdef UDS_TP_ISOTP_C
2253
2254
2255
2256
2257
2258
2259
2260
/**
2261
 * @brief isotp-c implementation of \ref UDSTp_t
2262
 */
2263
typedef struct {
2264
    /// \cond DOXYGEN_SHOULD_SKIP_THIS
2265
    UDSTp_t hdl;
2266
    IsoTpLink phys_link;
2267
    IsoTpLink func_link;
2268
    uint8_t send_buf[UDS_ISOTP_MTU];
2269
    uint8_t recv_buf[UDS_ISOTP_MTU];
2270
    uint8_t func_send_buf[8];
2271
    uint8_t func_recv_buf[8];
2272
    uint32_t phys_sa;
2273
    uint32_t phys_ta;
2274
    uint32_t func_sa;
2275
    uint32_t func_ta;
2276
    /// \endcond
2277
} UDSTpISOTpC_t;
2278
2279
static_assert(offsetof(UDSTpISOTpC_t, hdl) == 0U, "hdl must be the first member");
2280
2281
/**
2282
 * @brief Initialize isotp-c transport for \ref UDSServer_t
2283
 * @param tp \ref UDSTpISOTpC_t instance.
2284
 * @param source_addr Server listens for physical transmissions on this address.
2285
 * @param target_addr Server sends responses to this address.
2286
 * @param source_addr_func Server listens for functional transmissions on this address.
2287
 */
2288
UDSErr_t UDSServerTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t source_addr, uint32_t target_addr,
2289
                               uint32_t source_addr_func);
2290
2291
/**
2292
 * @brief Initialize isotp-c transport for \ref UDSClient_t
2293
 * @param tp \ref UDSTpISOTpC_t instance.
2294
 * @param source_addr Client listens for responses at this address.
2295
 * @param target_addr Client sends physical requests to this address.
2296
 * @param target_addr_func Client sends functional transmissions to this address.
2297
 */
2298
UDSErr_t UDSClientTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t source_addr, uint32_t target_addr,
2299
                               uint32_t target_addr_func);
2300
2301
// Internal API
2302
UDSErr_t UDSTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t sa, uint32_t ta, uint32_t sa_func,
2303
                         uint32_t ta_func);
2304
UDSErr_t UDSTpISOTpCPoll(UDSTp_t *tp);
2305
2306
#endif
2307
2308
2309
#ifdef UDS_LINES
2310
#line 1 "src/tp/isotp_c_socketcan.h"
2311
#endif // #ifdef UDS_LINES
2312
2313
#ifdef UDS_TP_ISOTP_C_SOCKETCAN
2314
2315
2316
2317
2318
/**
2319
 * @brief isotp-c over SocketCAN implementation of \ref UDSTp_t
2320
 */
2321
typedef struct {
2322
    /// \cond DOXYGEN_SHOULD_SKIP_THIS
2323
    UDSTpISOTpC_t hdl2;
2324
    int fd;
2325
    char tag[16];
2326
    /// \endcond
2327
} UDSTpISOTpCSocketCAN_t;
2328
2329
static_assert(offsetof(UDSTpISOTpCSocketCAN_t, hdl2) == 0U, "hdl must be the first member");
2330
2331
/**
2332
 * @brief Initialize isotp-c over SocketCAN transport for \ref UDSServer_t
2333
 * @param tp \ref UDSTpISOTpSocketCAN_t instance.
2334
 * @param source_addr Server listens for physical transmissions on this address.
2335
 * @param target_addr Server sends responses to this address.
2336
 * @param source_addr_func Server listens for functional transmissions on this address.
2337
 */
2338
UDSErr_t UDSServerTpISOTpCSocketCANInit(UDSTpISOTpCSocketCAN_t *tp, const char *ifname,
2339
                                        uint32_t source_addr, uint32_t target_addr,
2340
                                        uint32_t source_addr_func);
2341
2342
/**
2343
 * @brief Initialize isotp-c over SocketCAN transport for \ref UDSClient_t
2344
 * @param tp \ref UDSTpISOTpC_t instance.
2345
 * @param source_addr Client listens for responses at this address.
2346
 * @param target_addr Client sends physical requests to this address.
2347
 * @param target_addr_func Client sends functional transmissions to this address.
2348
 */
2349
UDSErr_t UDSClientTpISOTpCSocketCANInit(UDSTpISOTpCSocketCAN_t *tp, const char *ifname,
2350
                                        uint32_t source_addr, uint32_t target_addr,
2351
                                        uint32_t target_addr_func);
2352
2353
void UDSTpISOTpCSocketCANDeinit(UDSTpISOTpCSocketCAN_t *tp); ///< release socket
2354
2355
#endif
2356
2357
#ifdef UDS_TP_ISOTP_SOCK
2358
#ifdef UDS_LINES
2359
#line 1 "src/tp/isotp_sock.h"
2360
#endif // #ifdef UDS_LINES
2361
2362
2363
2364
2365
2366
/**
2367
 * @brief linux ISO-TP socket implementation of \ref UDSTp_t
2368
 */
2369
typedef struct {
2370
    /// \cond DOXYGEN_SHOULD_SKIP_THIS
2371
    UDSTp_t hdl;
2372
    uint8_t recv_buf[UDS_ISOTP_MTU];
2373
    uint8_t send_buf[UDS_ISOTP_MTU];
2374
    size_t recv_len;
2375
    UDSSDU_t recv_info;
2376
    int phys_fd;
2377
    int func_fd;
2378
    uint32_t phys_sa;
2379
    uint32_t phys_ta;
2380
    uint32_t func_sa;
2381
    uint32_t func_ta;
2382
    char tag[16];
2383
    /// \endcond
2384
} UDSTpIsoTpSock_t;
2385
2386
static_assert(offsetof(UDSTpIsoTpSock_t, hdl) == 0U, "hdl must be the first member");
2387
2388
UDSErr_t UDSServerTpIsoTpSockInit(UDSTpIsoTpSock_t *tp, const char *ifname, uint32_t source_addr,
2389
                                  uint32_t target_addr,
2390
                                  uint32_t source_addr_func); ///< for UDSServer_t
2391
UDSErr_t UDSClientTpIsoTpSockInit(UDSTpIsoTpSock_t *tp, const char *ifname, uint32_t source_addr,
2392
                                  uint32_t target_addr,
2393
                                  uint32_t target_addr_func); ///< for UDSClient_t
2394
void UDSTpIsoTpSockDeinit(const UDSTpIsoTpSock_t *tp);        ///< release sockets
2395
2396
#endif
2397
2398
#ifdef UDS_TP_ISOTP_MOCK
2399
#ifdef UDS_LINES
2400
#line 1 "src/tp/isotp_mock.h"
2401
#endif // #ifdef UDS_LINES
2402
2403
2404
2405
/// \cond INTERNAL_INTERFACE
2406
2407
2408
2409
2410
typedef struct ISOTPMock {
2411
    UDSTp_t hdl;
2412
    uint8_t recv_buf[UDS_TP_MTU];
2413
    uint8_t send_buf[UDS_TP_MTU];
2414
    size_t recv_len;
2415
    UDSSDU_t recv_info;
2416
    uint32_t sa_phys;          // source address - physical messages are sent from this address
2417
    uint32_t ta_phys;          // target address - physical messages are sent to this address
2418
    uint32_t sa_func;          // source address - functional messages are sent from this address
2419
    uint32_t ta_func;          // target address - functional messages are sent to this address
2420
    uint32_t send_tx_delay_ms; // simulated delay
2421
    uint32_t send_buf_size;    // simulated size of the send buffer
2422
    char name[32];             // name for logging
2423
} ISOTPMock_t;
2424
2425
static_assert(offsetof(ISOTPMock_t, hdl) == 0U, "ISOTPMock_t must not have any members before hdl");
2426
2427
typedef struct {
2428
    uint32_t sa_phys; // source address - physical messages are sent from this address
2429
    uint32_t ta_phys; // target address - physical messages are sent to this address
2430
    uint32_t sa_func; // source address - functional messages are sent from this address
2431
    uint32_t ta_func; // target address - functional messages are sent to this address
2432
} ISOTPMockArgs_t;
2433
2434
/**
2435
 * @brief Create a mock transport. It is connected by default to a broadcast network of all other
2436
 * mock transports in the same process.
2437
 * @param name optional name of the transport (can be NULL)
2438
 * @return UDSTp_t*
2439
 */
2440
UDSTp_t *ISOTPMockNew(const char *name, const ISOTPMockArgs_t *args);
2441
void ISOTPMockFree(UDSTp_t *tp);
2442
2443
/**
2444
 * @brief write all messages to a file
2445
 * @note uses UDSMillis() to get the current time
2446
 * @param filename log file name (will be overwritten)
2447
 */
2448
void ISOTPMockLogToFile(const char *filename);
2449
void ISOTPMockLogToStdout(void);
2450
2451
/**
2452
 * @brief clear all transports and close the log file
2453
 */
2454
void ISOTPMockReset(void);
2455
2456
/// \endcond INTERNAL_INTERFACE
2457
2458
#endif
2459
2460
2461
#ifdef __cplusplus
2462
}
2463
#endif // #ifdef __cplusplus
2464
#endif // #ifndef ISO14229