12#line 1 "src/include_private.h"
19#if UDS_SYS == UDS_SYS_UNIX
25#if UDS_SYS == UDS_SYS_WINDOWS
30#if UDS_SYS == UDS_SYS_ARDUINO
34#if UDS_SYS == UDS_SYS_ESP32
38#if UDS_SYS == UDS_SYS_ZEPHYR
39#include <zephyr/kernel.h>
42#if UDS_LOG_LEVEL > UDS_LOG_NONE
47#ifdef UDS_TP_ISOTP_C_SOCKETCAN
50#include <linux/can/raw.h>
60#ifdef UDS_TP_ISOTP_SOCK
63#include <linux/can/isotp.h>
68#include <sys/socket.h>
74#line 1 "src/uds_private.h"
78#define UDS_NEG_RESP_LEN 3U
79#define UDS_0X10_REQ_LEN 2U
80#define UDS_0X10_RESP_LEN 6U
81#define UDS_0X11_REQ_MIN_LEN 2U
82#define UDS_0X11_RESP_BASE_LEN 2U
83#define UDS_0X14_REQ_MIN_LEN 4U
84#define UDS_0X14_RESP_BASE_LEN 1U
85#define UDS_0X19_REQ_MIN_LEN 2U
86#define UDS_0X19_RESP_BASE_LEN 2U
87#define UDS_0X23_REQ_MIN_LEN 4U
88#define UDS_0X23_RESP_BASE_LEN 1U
89#define UDS_0X22_RESP_BASE_LEN 1U
90#define UDS_0X27_REQ_BASE_LEN 2U
91#define UDS_0X27_RESP_BASE_LEN 2U
92#define UDS_0X28_REQ_BASE_LEN 3U
93#define UDS_0X28_RESP_LEN 2U
94#define UDS_0X2C_REQ_MIN_LEN 2U
95#define UDS_0X2C_RESP_BASE_LEN 2U
96#define UDS_0X2E_REQ_BASE_LEN 3U
97#define UDS_0X2E_REQ_MIN_LEN 4U
98#define UDS_0X2E_RESP_LEN 3U
99#define UDS_0X2F_REQ_MIN_LEN 4U
100#define UDS_0X2F_RESP_BASE_LEN 4U
101#define UDS_0X31_REQ_MIN_LEN 4U
102#define UDS_0X31_REQ_BASE_LEN 4U
103#define UDS_0X31_RESP_MIN_LEN 4U
104#define UDS_0X34_REQ_BASE_LEN 3U
105#define UDS_0X34_RESP_BASE_LEN 2U
106#define UDS_0X35_REQ_BASE_LEN 3U
107#define UDS_0X35_RESP_BASE_LEN 2U
108#define UDS_0X36_REQ_BASE_LEN 2U
109#define UDS_0X36_RESP_BASE_LEN 2U
110#define UDS_0X37_REQ_BASE_LEN 1U
111#define UDS_0X37_RESP_BASE_LEN 1U
112#define UDS_0X38_REQ_BASE_LEN 5U
113#define UDS_0X38_RESP_BASE_LEN 2U
114#define UDS_0X3D_REQ_MIN_LEN 5U
115#define UDS_0X3D_RESP_BASE_LEN 2U
116#define UDS_0X3E_REQ_MIN_LEN 2U
117#define UDS_0X3E_REQ_MAX_LEN 2U
118#define UDS_0X3E_RESP_LEN 2U
119#define UDS_0X85_REQ_BASE_LEN 2U
120#define UDS_0X85_RESP_LEN 2U
121#define UDS_0X87_REQ_BASE_LEN 2U
122#define UDS_0X87_RESP_LEN 2U
124#define UDS_SID_DIAGNOSTIC_SESSION_CONTROL 0x10U
125#define UDS_SID_ECU_RESET 0x11U
126#define UDS_SID_CLEAR_DIAGNOSTIC_INFORMATION 0x14U
127#define UDS_SID_READ_DTC_INFORMATION 0x19U
128#define UDS_SID_READ_DATA_BY_IDENTIFIER 0x22U
129#define UDS_SID_READ_MEMORY_BY_ADDRESS 0x23U
130#define UDS_SID_READ_SCALING_DATA_BY_IDENTIFIER 0x24U
131#define UDS_SID_SECURITY_ACCESS 0x27U
132#define UDS_SID_COMMUNICATION_CONTROL 0x28U
133#define UDS_SID_READ_PERIODIC_DATA_BY_IDENTIFIER 0x2AU
134#define UDS_SID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER 0x2CU
135#define UDS_SID_WRITE_DATA_BY_IDENTIFIER 0x2EU
136#define UDS_SID_IO_CONTROL_BY_IDENTIFIER 0x2FU
137#define UDS_SID_ROUTINE_CONTROL 0x31U
138#define UDS_SID_REQUEST_DOWNLOAD 0x34U
139#define UDS_SID_REQUEST_UPLOAD 0x35U
140#define UDS_SID_TRANSFER_DATA 0x36U
141#define UDS_SID_REQUEST_TRANSFER_EXIT 0x37U
142#define UDS_SID_REQUEST_FILE_TRANSFER 0x38U
143#define UDS_SID_WRITE_MEMORY_BY_ADDRESS 0x3DU
144#define UDS_SID_TESTER_PRESENT 0x3EU
145#define UDS_SID_ACCESS_TIMING_PARAMETER 0x83U
146#define UDS_SID_SECURED_DATA_TRANSMISSION 0x84U
147#define UDS_SID_CONTROL_DTC_SETTING 0x85U
148#define UDS_SID_RESPONSE_ON_EVENT 0x86U
149#define UDS_SID_LINK_CONTROL 0x87U
154#line 1 "src/util_static.c"
161static void PackBE(uint8_t *dst, uint64_t val,
size_t n) {
162 for (
size_t i = 0; i < n; i++) {
163 dst[i] = (uint8_t)(val >> (8U * (n - 1U - i)));
173static size_t UnpackBEsize(
const uint8_t *src,
size_t n) {
178 for (
size_t i = 0; i < n; i++) {
179 val = (val << 8U) | src[i];
190static uintptr_t UnpackBEuintptr(
const uint8_t *src,
size_t n) {
195 for (
size_t i = 0; i < n; i++) {
196 val = (val << 8U) | src[i];
207static uint32_t UnpackBEu32(
const uint8_t *src,
size_t n) {
212 for (
size_t i = 0; i < n; i++) {
213 val = (val << 8U) | src[i];
225static uint16_t UnpackBEu16(
const uint8_t *src) {
227 return (uint16_t)((uint16_t)(src[0] << 8U) | (uint16_t)src[1]);
230static uint8_t AsResponseSID(uint8_t request_sid) {
231 UDS_ASSERT(request_sid <= (UINT8_MAX - 0x40U));
232 return request_sid + 0x40U;
235static uint8_t AsRequestSID(uint8_t response_sid) {
237 return response_sid - 0x40U;
251static bool UDSTimeAfter(uint32_t a, uint32_t b) {
252 uint32_t diff = a - b;
253 return (diff - 1U) < 0x7FFFFFFFU;
258static bool UDSSecurityAccessLevelIsReserved(uint8_t subFunction) {
259 if (0U == subFunction) {
262 if (subFunction <= 0x42U) {
265 if (subFunction <= 0x5EU) {
268 if (subFunction <= 0x7EU) {
275static bool UDSErrIsNRC(
UDSErr_t err) {
277 case UDS_PositiveResponse:
278 case UDS_NRC_GeneralReject:
279 case UDS_NRC_ServiceNotSupported:
280 case UDS_NRC_SubFunctionNotSupported:
281 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
282 case UDS_NRC_ResponseTooLong:
283 case UDS_NRC_BusyRepeatRequest:
284 case UDS_NRC_ConditionsNotCorrect:
285 case UDS_NRC_RequestSequenceError:
286 case UDS_NRC_NoResponseFromSubnetComponent:
287 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
288 case UDS_NRC_RequestOutOfRange:
289 case UDS_NRC_SecurityAccessDenied:
290 case UDS_NRC_AuthenticationRequired:
291 case UDS_NRC_InvalidKey:
292 case UDS_NRC_ExceedNumberOfAttempts:
293 case UDS_NRC_RequiredTimeDelayNotExpired:
294 case UDS_NRC_SecureDataTransmissionRequired:
295 case UDS_NRC_SecureDataTransmissionNotAllowed:
296 case UDS_NRC_SecureDataVerificationFailed:
297 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
298 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
299 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
300 case UDS_NRC_CertficateVerificationFailedInvalidType:
301 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
302 case UDS_NRC_CertficateVerificationFailedInvalidContent:
303 case UDS_NRC_CertficateVerificationFailedInvalidScope:
304 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
305 case UDS_NRC_OwnershipVerificationFailed:
306 case UDS_NRC_ChallengeCalculationFailed:
307 case UDS_NRC_SettingAccessRightsFailed:
308 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
309 case UDS_NRC_ConfigurationDataUsageFailed:
310 case UDS_NRC_DeAuthenticationFailed:
311 case UDS_NRC_UploadDownloadNotAccepted:
312 case UDS_NRC_TransferDataSuspended:
313 case UDS_NRC_GeneralProgrammingFailure:
314 case UDS_NRC_WrongBlockSequenceCounter:
315 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
316 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
317 case UDS_NRC_ServiceNotSupportedInActiveSession:
318 case UDS_NRC_RpmTooHigh:
319 case UDS_NRC_RpmTooLow:
320 case UDS_NRC_EngineIsRunning:
321 case UDS_NRC_EngineIsNotRunning:
322 case UDS_NRC_EngineRunTimeTooLow:
323 case UDS_NRC_TemperatureTooHigh:
324 case UDS_NRC_TemperatureTooLow:
325 case UDS_NRC_VehicleSpeedTooHigh:
326 case UDS_NRC_VehicleSpeedTooLow:
327 case UDS_NRC_ThrottlePedalTooHigh:
328 case UDS_NRC_ThrottlePedalTooLow:
329 case UDS_NRC_TransmissionRangeNotInNeutral:
330 case UDS_NRC_TransmissionRangeNotInGear:
331 case UDS_NRC_BrakeSwitchNotClosed:
332 case UDS_NRC_ShifterLeverNotInPark:
333 case UDS_NRC_TorqueConverterClutchLocked:
334 case UDS_NRC_VoltageTooHigh:
335 case UDS_NRC_VoltageTooLow:
336 case UDS_NRC_ResourceTemporarilyNotAvailable:
345#line 1 "src/client.c"
361#define STATE_SENDING 1U
362#define STATE_AWAIT_SEND_COMPLETE 2U
363#define STATE_AWAIT_RESPONSE 3U
367 if (NULL == client) {
368 return UDS_ERR_INVALID_ARG;
370 (void)memset(client, 0,
sizeof(*client));
379 UDS_LOGE(__FILE__,
"p2_star_ms must be >= p2_ms");
386static const char *ClientStateName(uint8_t state) {
393 return "AwaitSendComplete";
395 return "AwaitResponse";
401static void changeState(
UDSClient_t *client, uint8_t state) {
402 if (state != client->
state) {
403 UDS_LOGV(__FILE__,
"client state: %s (%d) -> %s (%d)", ClientStateName(client->
state),
404 client->
state, ClientStateName(state), state);
406 client->
state = state;
422 return UDS_ERR_RESP_TOO_SHORT;
428 return UDS_ERR_SID_MISMATCH;
431 return UDS_ERR_RESP_TOO_SHORT;
434 if (nrc == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
437 if (!UDSErrIsNRC(nrc)) {
438 UDS_LOGW(__FILE__,
"nrc 0x%X not recognized", nrc);
446 return UDS_ERR_SID_MISMATCH;
448 if (client->
send_buf[0] == UDS_SID_ECU_RESET) {
450 return UDS_ERR_RESP_TOO_SHORT;
453 return UDS_ERR_SUBFUNCTION_MISMATCH;
466 if ((uint8_t)UDS_NRC_RequestCorrectlyReceived_ResponsePending == client->
recv_buf[2]) {
468 UDS_LOGI(__FILE__,
"got RCRRP, set p2 timer to %" PRIu32
"", client->
p2_timer);
472 return UDS_NRC_RequestCorrectlyReceived_ResponsePending;
476 uint8_t respSid = client->
recv_buf[0];
477 switch (AsRequestSID(respSid)) {
478 case UDS_SID_DIAGNOSTIC_SESSION_CONTROL: {
479 if (client->
recv_size < UDS_0X10_RESP_LEN) {
480 UDS_LOGI(__FILE__,
"Error: SID %x response too short",
481 UDS_SID_DIAGNOSTIC_SESSION_CONTROL);
483 return UDS_ERR_RESP_TOO_SHORT;
491 uint16_t p2 = UnpackBEu16(&client->
recv_buf[2]);
492 uint32_t p2_star = (uint32_t)UnpackBEu16(&client->
recv_buf[4]) * 10U;
493 UDS_LOGI(__FILE__,
"received new timings: p2: %" PRIu16
", p2*: %" PRIu32, p2, p2_star);
505static void WarnIfRecvWhileSending(
UDSClient_t *client) {
511 UDS_LOGE(__FILE__,
"transport returned error %s", UDSErrToStr(err));
512 }
else if (recvlen == 0U) {
515 UDS_LOGW(__FILE__,
"received %zd unexpected bytes:", recvlen);
516 UDS_LOG_SDU(__FILE__, client->
recv_buf, recvlen, &recvinfo);
524 WarnIfRecvWhileSending(client);
532 .A_Mtype = UDS_A_MTYPE_DIAG,
533 .A_TA_Type = ta_type,
537 UDS_LOGE(__FILE__,
"tport err: %s", UDSErrToStr(err));
550 if (client->
tp->status.is_sending) {
571 }
else if (0U == recvlen) {
573 UDS_LOGI(__FILE__,
"p2 timeout");
574 err = UDS_ERR_TIMEOUT;
578 UDS_LOGD(__FILE__,
"received %zd bytes. Processing...", recvlen);
582 err = ValidateServerResponse(client);
584 err = HandleServerResponse(client);
600 if ((NULL == client) || (NULL == client->
tp) || (NULL == client->
tp->
poll)) {
601 return UDS_ERR_MISUSE;
613 switch (client->
state) {
617 return Handle_SENDING(client);
619 return Handle_AWAIT_SEND_COMPLETE(client);
621 return Handle_AWAIT_RESPONSE(client);
635 UDSErr_t err = PollLowLevel(client);
640 if (NULL == client) {
641 return UDS_ERR_INVALID_ARG;
646 if (client->
tp == NULL) {
647 return UDS_ERR_TPORT;
655 UDSErr_t err = PreRequestCheck(client);
659 if (size >
sizeof(client->
send_buf)) {
660 return UDS_ERR_BUFSIZ;
662 (void)memmove(client->
send_buf, data, size);
664 return SendRequest(client);
668 UDSErr_t err = PreRequestCheck(client);
672 client->
send_buf[0] = UDS_SID_ECU_RESET;
675 return SendRequest(client);
679 UDSErr_t err = PreRequestCheck(client);
683 client->
send_buf[0] = UDS_SID_DIAGNOSTIC_SESSION_CONTROL;
686 return SendRequest(client);
690 UDSErr_t err = PreRequestCheck(client);
694 client->
send_buf[0] = UDS_SID_COMMUNICATION_CONTROL;
698 return SendRequest(client);
702 UDSErr_t err = PreRequestCheck(client);
706 client->
send_buf[0] = UDS_SID_TESTER_PRESENT;
709 return SendRequest(client);
713 const uint16_t numDataIdentifiers) {
714 UDSErr_t err = PreRequestCheck(client);
718 if ((NULL == didList) || (0U == numDataIdentifiers)) {
719 return UDS_ERR_INVALID_ARG;
722 const size_t send_size = 1U + ((size_t)numDataIdentifiers * 2U);
723 if (send_size >
sizeof(client->
send_buf)) {
724 return UDS_ERR_BUFSIZ;
727 client->
send_buf[0] = UDS_SID_READ_DATA_BY_IDENTIFIER;
728 for (uint16_t i = 0U; i < numDataIdentifiers; i++) {
729 uint16_t offset = (uint16_t)(1U + (i * 2U));
730 PackBE(&client->
send_buf[offset], didList[i], 2);
733 return SendRequest(client);
738 UDSErr_t err = PreRequestCheck(client);
742 if ((data == NULL) || (size == 0U)) {
743 return UDS_ERR_INVALID_ARG;
745 const size_t send_size = UDS_0X2E_REQ_BASE_LEN + (size_t)size;
746 if (send_size >
sizeof(client->
send_buf)) {
747 return UDS_ERR_BUFSIZ;
750 client->
send_buf[0] = UDS_SID_WRITE_DATA_BY_IDENTIFIER;
751 PackBE(&client->
send_buf[1], dataIdentifier, 2);
752 (void)memmove(&client->
send_buf[UDS_0X2E_REQ_BASE_LEN], data, size);
754 return SendRequest(client);
769 const uint8_t *data, uint16_t size) {
770 UDSErr_t err = PreRequestCheck(client);
774 client->
send_buf[0] = UDS_SID_ROUTINE_CONTROL;
776 client->
send_buf[2] = routineIdentifier >> 8U;
777 client->
send_buf[3] = routineIdentifier & 0xFFU;
779 if ((0U != size) && (data == NULL)) {
780 return UDS_ERR_INVALID_ARG;
783 const size_t send_size = UDS_0X31_REQ_BASE_LEN + (size_t)size;
784 if (send_size >
sizeof(client->
send_buf)) {
785 return UDS_ERR_BUFSIZ;
788 (void)memmove(&client->
send_buf[UDS_0X31_REQ_BASE_LEN], data, size);
790 return SendRequest(client);
805 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
807 UDSErr_t err = PreRequestCheck(client);
811 uint8_t numMemorySizeBytes = (uint8_t)((addressAndLengthFormatIdentifier & 0xF0U) >> 4U);
812 uint8_t numMemoryAddressBytes = (uint8_t)(addressAndLengthFormatIdentifier & 0x0FU);
813 const size_t send_size = 3U + (size_t)numMemoryAddressBytes + (
size_t)numMemorySizeBytes;
815 if (send_size >
sizeof(client->
send_buf)) {
816 return UDS_ERR_BUFSIZ;
819 client->
send_buf[0] = UDS_SID_REQUEST_DOWNLOAD;
820 client->
send_buf[1] = dataFormatIdentifier;
821 client->
send_buf[2] = addressAndLengthFormatIdentifier;
823 PackBE(&client->
send_buf[3], memoryAddress, numMemoryAddressBytes);
824 PackBE(&client->
send_buf[3U + numMemoryAddressBytes], memorySize, numMemorySizeBytes);
827 return SendRequest(client);
842 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
844 UDSErr_t err = PreRequestCheck(client);
848 uint8_t numMemorySizeBytes = (uint8_t)((addressAndLengthFormatIdentifier & 0xF0U) >> 4U);
849 uint8_t numMemoryAddressBytes = (uint8_t)(addressAndLengthFormatIdentifier & 0x0FU);
850 const size_t send_size = 3U + (size_t)numMemoryAddressBytes + (
size_t)numMemorySizeBytes;
851 if (
sizeof(client->
send_buf) < send_size) {
852 return UDS_ERR_BUFSIZ;
855 client->
send_buf[0] = UDS_SID_REQUEST_UPLOAD;
856 client->
send_buf[1] = dataFormatIdentifier;
857 client->
send_buf[2] = addressAndLengthFormatIdentifier;
859 PackBE(&client->
send_buf[3], memoryAddress, numMemoryAddressBytes);
860 PackBE(&client->
send_buf[3U + numMemoryAddressBytes], memorySize, numMemorySizeBytes);
863 return SendRequest(client);
877 const uint16_t blockLength,
const uint8_t *data, uint16_t size) {
878 UDSErr_t err = PreRequestCheck(client);
884 if (blockLength <= 2U) {
885 return UDS_ERR_INVALID_ARG;
889 if (size > (blockLength - 2U)) {
890 return UDS_ERR_INVALID_ARG;
892 client->
send_buf[0] = UDS_SID_TRANSFER_DATA;
893 client->
send_buf[1] = blockSequenceCounter;
894 (void)memmove(&client->
send_buf[UDS_0X36_REQ_BASE_LEN], data, size);
895 UDS_LOGI(__FILE__,
"size: %d, blocklength: %d", size, blockLength);
896 client->
send_size = UDS_0X36_REQ_BASE_LEN + (size_t)size;
897 return SendRequest(client);
908 UDSErr_t err = PreRequestCheck(client);
912 client->
send_buf[0] = UDS_SID_REQUEST_TRANSFER_EXIT;
914 return SendRequest(client);
918 const size_t filePathLen,
const size_t fileSizeUncompressed,
919 const size_t fileSizeCompressed) {
920 UDSErr_t err = PreRequestCheck(client);
924 if (filePath == NULL) {
925 return UDS_ERR_INVALID_ARG;
929 if (filePathLen > (
size_t)UINT16_MAX) {
930 return UDS_ERR_INVALID_ARG;
954 size_t send_size = SIZE_MAX;
961 if (send_size >
sizeof(client->
send_buf)) {
962 return UDS_ERR_BUFSIZ;
964 client->
send_buf[0] = UDS_SID_REQUEST_FILE_TRANSFER;
966 PackBE(&client->
send_buf[2], filePathLen, 2);
967 (void)memmove(&client->
send_buf[4], filePath, filePathLen);
970 PackBE(&client->
send_buf[6U + filePathLen], fileSizeUncompressed,
979 send_size = 4U + filePathLen + 1U;
980 if (send_size >
sizeof(client->
send_buf)) {
981 return UDS_ERR_BUFSIZ;
983 client->
send_buf[0] = UDS_SID_REQUEST_FILE_TRANSFER;
985 PackBE(&client->
send_buf[2], filePathLen, 2);
986 (void)memmove(&client->
send_buf[4], filePath, filePathLen);
990 send_size = 4U + filePathLen + 1U;
991 if (send_size >
sizeof(client->
send_buf)) {
992 return UDS_ERR_BUFSIZ;
994 client->
send_buf[0] = UDS_SID_REQUEST_FILE_TRANSFER;
996 PackBE(&client->
send_buf[2], filePathLen, 2);
997 (void)memmove(&client->
send_buf[4], filePath, filePathLen);
1009 return SendRequest(client);
1023 const uint8_t *dtcSettingControlOptionRecord, uint16_t len) {
1024 UDSErr_t err = PreRequestCheck(client);
1025 if (UDS_OK != err) {
1030 if ((0x00U == dtcSettingType) || (0x7FU == dtcSettingType) ||
1031 ((0x03U <= dtcSettingType) && (dtcSettingType <= 0x3FU))) {
1032 return UDS_ERR_INVALID_ARG;
1035 if ((len != 0U) && (NULL == dtcSettingControlOptionRecord)) {
1036 return UDS_ERR_INVALID_ARG;
1039 const size_t send_size = 2U + (size_t)len;
1040 if (send_size >
sizeof(client->
send_buf)) {
1041 return UDS_ERR_BUFSIZ;
1044 client->
send_buf[0] = UDS_SID_CONTROL_DTC_SETTING;
1045 client->
send_buf[1] = dtcSettingType;
1046 (void)memmove(&client->
send_buf[2], dtcSettingControlOptionRecord, len);
1049 return SendRequest(client);
1064 UDSErr_t err = PreRequestCheck(client);
1065 if (UDS_OK != err) {
1068 if (UDSSecurityAccessLevelIsReserved(level)) {
1069 return UDS_ERR_INVALID_ARG;
1072 if ((NULL == data) && (0U != size)) {
1073 return UDS_ERR_INVALID_ARG;
1076 const size_t send_size = UDS_0X27_REQ_BASE_LEN + (size_t)size;
1077 if (send_size >
sizeof(client->
send_buf)) {
1078 return UDS_ERR_BUFSIZ;
1081 client->
send_buf[0] = UDS_SID_SECURITY_ACCESS;
1084 (void)memmove(&client->
send_buf[UDS_0X27_REQ_BASE_LEN], data, size);
1088 return SendRequest(client);
1101 if ((NULL == client) || (NULL == resp)) {
1102 return UDS_ERR_INVALID_ARG;
1104 if (AsResponseSID(UDS_SID_SECURITY_ACCESS) != client->
recv_buf[0]) {
1105 return UDS_ERR_SID_MISMATCH;
1107 if (client->
recv_size < UDS_0X27_RESP_BASE_LEN) {
1108 return UDS_ERR_RESP_TOO_SHORT;
1126 if ((NULL == client) || (NULL == resp)) {
1127 return UDS_ERR_INVALID_ARG;
1129 if (AsResponseSID(UDS_SID_ROUTINE_CONTROL) != client->
recv_buf[0]) {
1130 return UDS_ERR_SID_MISMATCH;
1132 if (client->
recv_size < UDS_0X31_RESP_MIN_LEN) {
1133 return UDS_ERR_RESP_TOO_SHORT;
1153 if ((NULL == client) || (NULL == resp)) {
1154 return UDS_ERR_INVALID_ARG;
1156 if (AsResponseSID(UDS_SID_REQUEST_DOWNLOAD) != client->
recv_buf[0]) {
1157 return UDS_ERR_SID_MISMATCH;
1159 if (client->
recv_size < UDS_0X34_RESP_BASE_LEN) {
1160 return UDS_ERR_RESP_TOO_SHORT;
1162 uint8_t mnrobSize = (client->
recv_buf[1] & 0xF0U) >> 4U;
1165 if (client->
recv_size < (2U + mnrobSize)) {
1166 return UDS_ERR_RESP_TOO_SHORT;
1174 if (NULL == client->
fn) {
1175 return UDS_ERR_MISUSE;
1178 UDSErr_t err = PollLowLevel(client);
1180 if ((err == UDS_OK) || (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending)) {
1192 uint16_t offset = UDS_0X22_RESP_BASE_LEN;
1193 if ((client == NULL) || (vars == NULL)) {
1194 return UDS_ERR_INVALID_ARG;
1196 for (uint16_t i = 0U; i < numVars; i++) {
1198 if (offset +
sizeof(uint16_t) > client->
recv_size) {
1199 return UDS_ERR_RESP_TOO_SHORT;
1201 uint16_t did = UnpackBEu16(&client->
recv_buf[offset]);
1202 if (did != vars[i].did) {
1203 return UDS_ERR_DID_MISMATCH;
1205 if ((offset +
sizeof(uint16_t) + vars[i].len) > client->
recv_size) {
1206 return UDS_ERR_RESP_TOO_SHORT;
1208 if (NULL != vars[i].UnpackFn) {
1209 vars[i].
UnpackFn(vars[i].data, &client->
recv_buf[offset +
sizeof(uint16_t)],
1212 return UDS_ERR_INVALID_ARG;
1214 offset +=
sizeof(uint16_t) + vars[i].len;
1221#line 1 "src/server.c"
1232 if ((nrc < UDS_PositiveResponse) || (nrc > UDS_NRC_UNUSED_ISOSAEReserved)) {
1233 UDS_LOGE(__FILE__,
"Invalid negative response code: %d (0x%x)", nrc, nrc);
1234 ret = UDS_NRC_GeneralReject;
1248 if (srv->
fn != NULL) {
1249 err = srv->
fn(srv, evt, data);
1251 UDS_LOGI(__FILE__,
"Unhandled UDSEvent %d, srv.fn not installed!\n", evt);
1252 err = UDS_NRC_GeneralReject;
1254 if (!UDSErrIsNRC(err)) {
1255 UDS_LOGW(__FILE__,
"The returned error code %d (0x%x) is not a negative response code", err,
1262 if (r->
recv_len < UDS_0X10_REQ_LEN) {
1263 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1266 uint8_t sessType = r->
recv_buf[1] & 0x7FU;
1276 if (UDS_PositiveResponse != err) {
1277 return NegativeResponse(r, err);
1292 r->
send_buf[0] = AsResponseSID(UDS_SID_DIAGNOSTIC_SESSION_CONTROL);
1303 return UDS_PositiveResponse;
1307 if (r->
recv_len < UDS_0X11_REQ_MIN_LEN) {
1308 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1311 uint8_t resetType = r->
recv_buf[1] & 0x3FU;
1320 if (UDS_PositiveResponse == err) {
1325 return NegativeResponse(r, err);
1328 r->
send_buf[0] = AsResponseSID(UDS_SID_ECU_RESET);
1333 if (powerDownTime > 255U) {
1334 powerDownTime = 255U;
1336 r->
send_buf[2] = powerDownTime & 0xFFU;
1337 r->
send_len = UDS_0X11_RESP_BASE_LEN + 1U;
1339 r->
send_len = UDS_0X11_RESP_BASE_LEN;
1341 return UDS_PositiveResponse;
1345 if (r->
recv_len < UDS_0X14_REQ_MIN_LEN) {
1346 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1349 r->
send_buf[0] = AsResponseSID(UDS_SID_CLEAR_DIAGNOSTIC_INFORMATION);
1350 r->
send_len = UDS_0X14_RESP_BASE_LEN;
1353 .groupOfDTC = UnpackBEu32(&r->
recv_buf[1], 3),
1354 .hasMemorySelection = (r->
recv_len >= 5U),
1360 if (err != UDS_PositiveResponse) {
1361 return NegativeResponse(r, err);
1364 return UDS_PositiveResponse;
1367static uint8_t safe_copy(
UDSServer_t *srv,
const void *src, uint16_t count) {
1369 return UDS_NRC_GeneralReject;
1372 return UDS_NRC_GeneralReject;
1378 return UDS_PositiveResponse;
1380 return UDS_NRC_ResponseTooLong;
1384 UDSErr_t ret = UDS_PositiveResponse;
1387 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN) {
1388 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1392 r->
send_buf[0] = AsResponseSID(UDS_SID_READ_DTC_INFORMATION);
1394 r->
send_len = UDS_0X19_RESP_BASE_LEN;
1404 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 1U)) {
1405 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1411 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 1U)) {
1412 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1428 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 4U)) {
1429 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1438 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 1U)) {
1439 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1445 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 4U)) {
1446 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1454 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 2U)) {
1455 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1462 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 1U)) {
1463 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1469 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 2U)) {
1470 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1477 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 5U)) {
1478 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1481 args.
subFuncArgs.userDefMemDTCSnapshotRecordByDTCNumArgs.dtc =
1487 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 5U)) {
1488 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1491 args.
subFuncArgs.userDefMemDTCExtDataRecordByDTCNumArgs.dtc =
1497 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 3U)) {
1498 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1506 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 1U)) {
1507 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1513 if (r->
recv_len < (UDS_0X19_REQ_MIN_LEN + 2U)) {
1514 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1521 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1526 if (UDS_PositiveResponse != ret) {
1527 return NegativeResponse(r, ret);
1530 if (r->
send_len < UDS_0X19_RESP_BASE_LEN) {
1531 goto respond_to_0x19_malformed_response;
1538 if (r->
send_len != (UDS_0X19_RESP_BASE_LEN + 4U)) {
1539 goto respond_to_0x19_malformed_response;
1549 if ((r->
send_len < (UDS_0X19_RESP_BASE_LEN + 1U)) ||
1550 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 1U)) &&
1551 (((r->
send_len - UDS_0X19_RESP_BASE_LEN - 1U) % 4U) != 0U))) {
1552 goto respond_to_0x19_malformed_response;
1557 if (((r->
send_len - UDS_0X19_RESP_BASE_LEN) % 4U) != 0U) {
1558 goto respond_to_0x19_malformed_response;
1563 if (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 4U)) {
1564 goto respond_to_0x19_malformed_response;
1569 if (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 1U)) {
1570 goto respond_to_0x19_malformed_response;
1575 if ((r->
send_len < (UDS_0X19_RESP_BASE_LEN + 1U)) ||
1576 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 1U)) &&
1577 (((r->
send_len - UDS_0X19_RESP_BASE_LEN - 1U) % 6U) != 0U))) {
1578 goto respond_to_0x19_malformed_response;
1582 if (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 2U) ||
1583 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 2U)) &&
1584 (((r->
send_len - UDS_0X19_RESP_BASE_LEN + 2U) % 4U) != 0U))) {
1585 goto respond_to_0x19_malformed_response;
1590 if (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 5U)) {
1591 goto respond_to_0x19_malformed_response;
1595 if ((r->
send_len < (UDS_0X19_RESP_BASE_LEN + 1U)) ||
1596 ((r->
send_len != (UDS_0X19_RESP_BASE_LEN + 6U)) &&
1597 (r->
send_len > (UDS_0X19_RESP_BASE_LEN + 1U)) &&
1598 (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 4U))) ||
1599 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 6U)) &&
1600 (((r->
send_len - UDS_0X19_RESP_BASE_LEN + 6U) % 4U) != 0U))) {
1601 goto respond_to_0x19_malformed_response;
1605 if (r->
send_len < (UDS_0X19_RESP_BASE_LEN + 4U) ||
1606 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 4U)) &&
1607 (((r->
send_len - UDS_0X19_RESP_BASE_LEN - 4U) % 5U) != 0U))) {
1608 goto respond_to_0x19_malformed_response;
1612 if ((r->
send_len < (UDS_0X19_RESP_BASE_LEN + 3U)) ||
1613 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 3U)) &&
1614 (((r->
send_len - UDS_0X19_RESP_BASE_LEN - 3U) % 4U) != 0U))) {
1615 goto respond_to_0x19_malformed_response;
1619 if ((r->
send_len < (UDS_0X19_RESP_BASE_LEN + 4U)) ||
1620 ((r->
send_len > (UDS_0X19_RESP_BASE_LEN + 4U)) &&
1621 (((r->
send_len - UDS_0X19_RESP_BASE_LEN + 4U) % 4U) != 0U))) {
1622 goto respond_to_0x19_malformed_response;
1626 UDS_LOGW(__FILE__,
"RDTCI subFunc 0x%02X is not supported.\n", type);
1627 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1630 return UDS_PositiveResponse;
1631respond_to_0x19_malformed_response:
1632 UDS_LOGE(__FILE__,
"RDTCI subFunc 0x%02X is malformed. Length: %zu\n", type, r->
send_len);
1633 return NegativeResponse(r, UDS_NRC_GeneralReject);
1637 if (0U != (r->
recv_len - 1U) %
sizeof(uint16_t)) {
1638 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1641 const uint8_t numDIDs = (uint8_t)(r->
recv_len /
sizeof(uint16_t));
1643 if (0U == numDIDs) {
1644 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1647 r->
send_buf[0] = AsResponseSID(UDS_SID_READ_DATA_BY_IDENTIFIER);
1650 for (uint16_t did = 0; did < numDIDs; did++) {
1651 uint16_t idx = (uint16_t)(1U + (did * 2U));
1652 uint16_t dataId = UnpackBEu16(&r->
recv_buf[idx]);
1655 return NegativeResponse(r, UDS_NRC_ResponseTooLong);
1665 const size_t send_len_before = r->
send_len;
1670 if ((UDS_PositiveResponse == ret) && (send_len_before == r->
send_len)) {
1671 UDS_LOGE(__FILE__,
"RDBI response positive but no data sent\n");
1672 return NegativeResponse(r, UDS_NRC_GeneralReject);
1675 if (UDS_PositiveResponse != ret) {
1676 return NegativeResponse(r, ret);
1679 return UDS_PositiveResponse;
1693static UDSErr_t decodeAddressAndLengthAt(
UDSReq_t *r, uint8_t *
const buf, uintptr_t *memoryAddress,
1694 size_t *memorySize,
size_t offset) {
1702 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1705 const uint8_t memorySizeLength = (buf[0] & 0xF0U) >> 4U;
1706 const uint8_t memoryAddressLength = buf[0] & 0x0FU;
1708 if ((memorySizeLength == 0U) || (memorySizeLength >
sizeof(
size_t))) {
1709 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1712 if ((memoryAddressLength == 0U) || (memoryAddressLength >
sizeof(
size_t))) {
1713 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1716 const size_t offsetBytes = offset * ((size_t)memoryAddressLength + (size_t)memorySizeLength);
1718 if ((1U + offsetBytes + memorySizeLength + memoryAddressLength) > r->
recv_len) {
1719 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1722 *memoryAddress = UnpackBEuintptr(&buf[1U + offsetBytes], memoryAddressLength);
1723 *memorySize = UnpackBEsize(&buf[1U + offsetBytes + memoryAddressLength], memorySizeLength);
1725 return UDS_PositiveResponse;
1737static UDSErr_t decodeAddressAndLength(
UDSReq_t *r, uint8_t *
const buf, uintptr_t *memoryAddress,
1738 size_t *memorySize) {
1739 return decodeAddressAndLengthAt(r, buf, memoryAddress, memorySize, 0);
1743 UDSErr_t ret = UDS_PositiveResponse;
1744 uintptr_t address = 0;
1747 if (r->
recv_len < UDS_0X23_REQ_MIN_LEN) {
1748 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1751 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
1752 if (UDS_PositiveResponse != ret) {
1753 return NegativeResponse(r, ret);
1762 r->
send_buf[0] = AsResponseSID(UDS_SID_READ_MEMORY_BY_ADDRESS);
1763 r->
send_len = UDS_0X23_RESP_BASE_LEN;
1765 if (UDS_PositiveResponse != ret) {
1766 return NegativeResponse(r, ret);
1768 if (r->
send_len != (UDS_0X23_RESP_BASE_LEN + length)) {
1769 UDS_LOGE(__FILE__,
"response positive but not all data sent: expected %zu, sent %zu",
1770 length, r->
send_len - UDS_0X23_RESP_BASE_LEN);
1771 return NegativeResponse(r, UDS_NRC_GeneralReject);
1773 return UDS_PositiveResponse;
1777 if (r->
recv_len < UDS_0X27_REQ_BASE_LEN) {
1778 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1782 return NegativeResponse(r, UDS_NRC_RequiredTimeDelayNotExpired);
1786 return NegativeResponse(r, UDS_NRC_ExceedNumberOfAttempts);
1789 uint8_t subFunction = r->
recv_buf[1];
1790 if (UDSSecurityAccessLevelIsReserved(subFunction)) {
1791 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1794 r->
send_buf[0] = AsResponseSID(UDS_SID_SECURITY_ACCESS);
1796 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1799 if (0U == (subFunction % 2U)) {
1801 uint8_t requestedLevel = subFunction - 1U;
1803 .level = requestedLevel,
1804 .key = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1805 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1810 if (UDS_PositiveResponse != ret) {
1813 return NegativeResponse(r, ret);
1821 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1822 return UDS_PositiveResponse;
1832 const uint8_t already_unlocked[] = {0x00, 0x00};
1833 return safe_copy(srv, already_unlocked,
sizeof(already_unlocked));
1840 .level = subFunction,
1841 .dataRecord = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1842 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1843 .copySeed = safe_copy,
1848 if (UDS_PositiveResponse != ret) {
1849 return NegativeResponse(r, ret);
1852 if (r->
send_len <= UDS_0X27_RESP_BASE_LEN) {
1853 UDS_LOGE(__FILE__,
"0x27: no seed data was copied");
1854 return NegativeResponse(r, UDS_NRC_GeneralReject);
1856 return UDS_PositiveResponse;
1860 uint8_t controlType = r->
recv_buf[1] & 0x7FU;
1861 uint8_t communicationType = r->
recv_buf[2];
1863 if (r->
recv_len < UDS_0X28_REQ_BASE_LEN) {
1864 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1868 .ctrlType = controlType,
1869 .commType = communicationType,
1874 if (r->
recv_len < (UDS_0X28_REQ_BASE_LEN + 2U)) {
1875 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1881 if (UDS_PositiveResponse != err) {
1882 return NegativeResponse(r, err);
1885 r->
send_buf[0] = AsResponseSID(UDS_SID_COMMUNICATION_CONTROL);
1888 return UDS_PositiveResponse;
1892 UDSErr_t ret = UDS_PositiveResponse;
1895 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN) {
1896 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1899 r->
send_buf[0] = AsResponseSID(UDS_SID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER);
1904 r->
send_len = UDS_0X2C_RESP_BASE_LEN + 2U;
1908 .allDataIds =
false,
1909 .dynamicDataId = UnpackBEu16(&r->
recv_buf[2]),
1918 if ((r->
recv_len < (UDS_0X2C_REQ_MIN_LEN + 2U + 4U)) ||
1919 (((r->
recv_len - (UDS_0X2C_REQ_MIN_LEN + 2U)) % 4U) != 0U)) {
1920 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1923 size_t numDIDs = (r->
recv_len - 4U) / 4U;
1925 for (
size_t i = 0; i < numDIDs; i++) {
1932 if (UDS_PositiveResponse != ret) {
1933 return NegativeResponse(r, ret);
1937 return UDS_PositiveResponse;
1946 if (r->
recv_len < (UDS_0X2C_REQ_MIN_LEN + 5U)) {
1947 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1950 size_t bytesPerAddrAndSize = ((r->
recv_buf[4] & 0xF0U) >> 4U) + (r->
recv_buf[4] & 0x0FU);
1952 if (bytesPerAddrAndSize == 0U) {
1954 "DDDI: define By Memory Address request with invalid "
1955 "AddressAndLengthFormatIdentifier: 0x%02X\n",
1957 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1960 if (((r->
recv_len - 5U) % bytesPerAddrAndSize) != 0U) {
1961 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1964 size_t numAddrs = (r->
recv_len - 5U) / bytesPerAddrAndSize;
1966 for (
size_t i = 0; i < numAddrs; i++) {
1967 ret = decodeAddressAndLengthAt(r, &r->
recv_buf[4],
1971 if (UDS_PositiveResponse != ret) {
1972 return NegativeResponse(r, ret);
1977 if (UDS_PositiveResponse != ret) {
1978 return NegativeResponse(r, ret);
1982 return UDS_PositiveResponse;
1987 if (r->
recv_len == UDS_0X2C_REQ_MIN_LEN) {
1989 r->
send_len = UDS_0X2C_RESP_BASE_LEN;
1993 if (UDS_PositiveResponse != ret) {
1994 return NegativeResponse(r, ret);
1997 return UDS_PositiveResponse;
2000 UDS_LOGW(__FILE__,
"Unsupported DDDI subFunc 0x%02X\n", type);
2001 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
2006 uint16_t dataLen = 0;
2007 uint16_t dataId = 0;
2008 UDSErr_t err = UDS_PositiveResponse;
2011 if (r->
recv_len < UDS_0X2E_REQ_MIN_LEN) {
2012 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2015 dataId = UnpackBEu16(&r->
recv_buf[1]);
2016 dataLen = (uint16_t)(r->
recv_len - UDS_0X2E_REQ_BASE_LEN);
2020 .data = &r->
recv_buf[UDS_0X2E_REQ_BASE_LEN],
2025 if (UDS_PositiveResponse != err) {
2026 return NegativeResponse(r, err);
2029 r->
send_buf[0] = AsResponseSID(UDS_SID_WRITE_DATA_BY_IDENTIFIER);
2030 PackBE(&r->
send_buf[1], dataId, 2);
2032 return UDS_PositiveResponse;
2036 if (r->
recv_len < UDS_0X2F_REQ_MIN_LEN) {
2037 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2040 r->
send_buf[0] = AsResponseSID(UDS_SID_IO_CONTROL_BY_IDENTIFIER);
2044 r->
send_len = UDS_0X2F_RESP_BASE_LEN;
2047 .dataId = UnpackBEu16(&r->
recv_buf[1]),
2049 .ctrlStateAndMask = &r->
recv_buf[UDS_0X2F_REQ_MIN_LEN],
2050 .ctrlStateAndMaskLen = r->
recv_len - UDS_0X2F_REQ_MIN_LEN,
2056 if (err != UDS_PositiveResponse) {
2057 return NegativeResponse(r, err);
2060 return UDS_PositiveResponse;
2064 UDSErr_t err = UDS_PositiveResponse;
2065 if (r->
recv_len < UDS_0X31_REQ_MIN_LEN) {
2066 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2069 uint8_t routineControlType = r->
recv_buf[1] & 0x7FU;
2070 uint16_t routineIdentifier = UnpackBEu16(&r->
recv_buf[2]);
2073 .ctrlType = routineControlType,
2074 .id = routineIdentifier,
2075 .optionRecord = &r->
recv_buf[UDS_0X31_REQ_MIN_LEN],
2076 .len = (uint16_t)(r->
recv_len - UDS_0X31_REQ_MIN_LEN),
2077 .copyStatusRecord = safe_copy,
2080 r->
send_buf[0] = AsResponseSID(UDS_SID_ROUTINE_CONTROL);
2081 r->
send_buf[1] = routineControlType;
2082 PackBE(&r->
send_buf[2], routineIdentifier, 2);
2083 r->
send_len = UDS_0X31_RESP_MIN_LEN;
2085 switch (routineControlType) {
2090 if (UDS_PositiveResponse != err) {
2091 return NegativeResponse(r, err);
2095 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
2097 return UDS_PositiveResponse;
2108static void BeginTransfer(
UDSServer_t *srv,
size_t xferTotalBytes,
size_t xferBlockLength) {
2118 UDSErr_t err = UDS_PositiveResponse;
2119 uintptr_t memoryAddress = 0;
2120 size_t memorySize = 0;
2123 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
2126 if (r->
recv_len < UDS_0X34_REQ_BASE_LEN) {
2127 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2130 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
2131 if (UDS_PositiveResponse != err) {
2132 return NegativeResponse(r, err);
2136 .addr = memoryAddress,
2138 .dataFormatIdentifier = r->
recv_buf[1],
2145 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
2146 return NegativeResponse(r, UDS_NRC_GeneralReject);
2149 if (UDS_PositiveResponse != err) {
2150 return NegativeResponse(r, err);
2169 r->
send_buf[0] = AsResponseSID(UDS_SID_REQUEST_DOWNLOAD);
2170 r->
send_buf[1] = lengthFormatIdentifier;
2174 r->
send_len = UDS_0X34_RESP_BASE_LEN + N;
2175 return UDS_PositiveResponse;
2179 UDSErr_t err = UDS_PositiveResponse;
2180 uintptr_t memoryAddress = 0;
2181 size_t memorySize = 0;
2184 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
2187 if (r->
recv_len < UDS_0X35_REQ_BASE_LEN) {
2188 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2191 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
2192 if (UDS_PositiveResponse != err) {
2193 return NegativeResponse(r, err);
2197 .addr = memoryAddress,
2199 .dataFormatIdentifier = r->
recv_buf[1],
2206 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
2207 return NegativeResponse(r, UDS_NRC_GeneralReject);
2210 if (UDS_PositiveResponse != err) {
2211 return NegativeResponse(r, err);
2218 r->
send_buf[0] = AsResponseSID(UDS_SID_REQUEST_UPLOAD);
2219 r->
send_buf[1] = lengthFormatIdentifier;
2223 return UDS_PositiveResponse;
2227 UDSErr_t err = UDS_PositiveResponse;
2228 uint8_t blockSequenceCounter = 0;
2231 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
2234 if (r->
recv_len < UDS_0X36_REQ_BASE_LEN) {
2235 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2239 uint16_t request_data_len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN);
2240 blockSequenceCounter = r->
recv_buf[1];
2244 err = UDS_NRC_RequestSequenceError;
2252 err = UDS_NRC_TransferDataSuspended;
2258 .data = &r->
recv_buf[UDS_0X36_REQ_BASE_LEN],
2259 .len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN),
2260 .maxRespLen = (uint16_t)(srv->
xferBlockLength - UDS_0X36_RESP_BASE_LEN),
2261 .copyResponse = safe_copy,
2264 r->
send_buf[0] = AsResponseSID(UDS_SID_TRANSFER_DATA);
2265 r->
send_buf[1] = blockSequenceCounter;
2266 r->
send_len = UDS_0X36_RESP_BASE_LEN;
2270 if (err == UDS_PositiveResponse) {
2272 return UDS_PositiveResponse;
2274 if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
2275 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
2282 return NegativeResponse(r, err);
2286 UDSErr_t err = UDS_PositiveResponse;
2289 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
2292 r->
send_buf[0] = AsResponseSID(UDS_SID_REQUEST_TRANSFER_EXIT);
2293 r->
send_len = UDS_0X37_RESP_BASE_LEN;
2296 .data = &r->
recv_buf[UDS_0X37_REQ_BASE_LEN],
2297 .len = (uint16_t)(r->
recv_len - UDS_0X37_REQ_BASE_LEN),
2298 .copyResponse = safe_copy,
2303 if (err == UDS_PositiveResponse) {
2305 return UDS_PositiveResponse;
2307 if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
2308 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
2311 return NegativeResponse(r, err);
2317 return UDS_NRC_ConditionsNotCorrect;
2319 if (r->
recv_len < UDS_0X38_REQ_BASE_LEN) {
2320 return UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2323 const uint8_t mode_of_operation = r->
recv_buf[1];
2326 return UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2329 const uint16_t file_path_len = UnpackBEu16(&r->
recv_buf[2]);
2330 uint8_t data_format_identifier = 0;
2331 size_t file_size_uncompressed = 0;
2332 size_t file_size_compressed = 0;
2333 size_t byte_idx = 4U + (size_t)file_path_len;
2336 return UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2344 data_format_identifier = r->
recv_buf[byte_idx];
2356 const uint8_t file_size_parameter_length = r->
recv_buf[byte_idx];
2359 static_assert(
sizeof(file_size_uncompressed) ==
sizeof(file_size_compressed),
2360 "Both should be k-byte numbers per Table 480");
2361 if (file_size_parameter_length >
sizeof(file_size_compressed)) {
2362 return UDS_NRC_RequestOutOfRange;
2366 if ((byte_idx + (2U * (
size_t)file_size_parameter_length)) > r->
recv_len) {
2367 return UDS_NRC_RequestOutOfRange;
2369 for (uint8_t i = 0; i < file_size_parameter_length; i++) {
2370 uint8_t data_byte = r->
recv_buf[byte_idx];
2371 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1U);
2372 file_size_uncompressed |= (size_t)data_byte << (8U * (
size_t)shift_by_bytes);
2375 for (uint8_t i = 0; i < file_size_parameter_length; i++) {
2376 uint8_t data_byte = r->
recv_buf[byte_idx];
2377 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1U);
2378 file_size_compressed |= (size_t)data_byte << (8U * (
size_t)shift_by_bytes);
2384 .modeOfOperation = mode_of_operation,
2385 .filePathLen = file_path_len,
2386 .filePath = (file_path_len == 0U) ? NULL : &r->recv_buf[4],
2387 .dataFormatIdentifier = data_format_identifier,
2388 .fileSizeUnCompressed = file_size_uncompressed,
2389 .fileSizeCompressed = file_size_compressed,
2396 if (UDS_PositiveResponse != err) {
2400 r->
send_buf[0] = AsResponseSID(UDS_SID_REQUEST_FILE_TRANSFER);
2401 r->
send_buf[1] = mode_of_operation;
2409 UDS_LOGW(__FILE__,
"Clamping maxNumberOfBlockLength %hu to %hu",
2427 (
UDS_MOOP_RDDIR == mode_of_operation) ? 0x00U : args.dataFormatIdentifier;
2466 UDSErr_t ret = UDS_PositiveResponse;
2467 uintptr_t address = 0;
2470 if (r->
recv_len < UDS_0X3D_REQ_MIN_LEN) {
2471 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2474 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
2475 if (UDS_PositiveResponse != ret) {
2476 return NegativeResponse(r, ret);
2479 uint8_t memorySizeLength = (r->
recv_buf[1] & 0xF0U) >> 4U;
2480 uint8_t memoryAddressLength = r->
recv_buf[1] & 0x0FU;
2482 uint8_t dataOffset = 2U + memorySizeLength + memoryAddressLength;
2484 if ((dataOffset + length) != r->
recv_len) {
2485 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2495 if (UDS_PositiveResponse != ret) {
2496 return NegativeResponse(r, ret);
2499 r->
send_buf[0] = AsResponseSID(UDS_SID_WRITE_MEMORY_BY_ADDRESS);
2501 (void)memcpy(&r->
send_buf[1], &r->
recv_buf[1], 1U + memorySizeLength + memoryAddressLength);
2502 r->
send_len = UDS_0X3D_RESP_BASE_LEN + (size_t)memorySizeLength + (
size_t)memoryAddressLength;
2503 return UDS_PositiveResponse;
2507 if ((r->
recv_len < UDS_0X3E_REQ_MIN_LEN) || (r->
recv_len > UDS_0X3E_REQ_MAX_LEN)) {
2508 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2510 uint8_t zeroSubFunction = r->
recv_buf[1];
2512 switch (zeroSubFunction) {
2516 r->
send_buf[0] = AsResponseSID(UDS_SID_TESTER_PRESENT);
2519 return UDS_PositiveResponse;
2521 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
2527 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2528 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2531 uint8_t type = r->
recv_buf[1] & 0x7FU;
2535 .data = (r->
recv_len > UDS_0X85_REQ_BASE_LEN) ? &r->
recv_buf[UDS_0X85_REQ_BASE_LEN] : NULL,
2536 .len = (r->recv_len > UDS_0X85_REQ_BASE_LEN) ? (r->recv_len - UDS_0X85_REQ_BASE_LEN) : 0U,
2540 if (UDS_PositiveResponse != ret) {
2541 return NegativeResponse(r, ret);
2544 r->
send_buf[0] = AsResponseSID(UDS_SID_CONTROL_DTC_SETTING);
2547 return UDS_PositiveResponse;
2551 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2552 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2555 uint8_t type = r->
recv_buf[1] & 0x7FU;
2557 if ((type == 0x03U) && ((r->
recv_buf[1] & 0x80U) == 0U) &&
2559 UDS_LOGW(__FILE__,
"0x87 LinkControl: Transitioning mode without suppressing response!");
2562 r->
send_buf[0] = AsResponseSID(UDS_SID_LINK_CONTROL);
2569 .len = (r->
recv_len - UDS_0X87_REQ_BASE_LEN),
2570 .data = &r->
recv_buf[UDS_0X87_REQ_BASE_LEN],
2574 if (err != UDS_PositiveResponse) {
2575 return NegativeResponse(r, err);
2578 return UDS_PositiveResponse;
2589static UDSService getServiceForSID(uint8_t sid) {
2591 case UDS_SID_DIAGNOSTIC_SESSION_CONTROL:
2592 return &Handle_0x10_DiagnosticSessionControl;
2593 case UDS_SID_ECU_RESET:
2594 return &Handle_0x11_ECUReset;
2595 case UDS_SID_CLEAR_DIAGNOSTIC_INFORMATION:
2596 return &Handle_0x14_ClearDiagnosticInformation;
2597 case UDS_SID_READ_DTC_INFORMATION:
2598 return Handle_0x19_ReadDTCInformation;
2599 case UDS_SID_READ_DATA_BY_IDENTIFIER:
2600 return &Handle_0x22_ReadDataByIdentifier;
2601 case UDS_SID_READ_MEMORY_BY_ADDRESS:
2602 return &Handle_0x23_ReadMemoryByAddress;
2603 case UDS_SID_READ_SCALING_DATA_BY_IDENTIFIER:
2605 case UDS_SID_SECURITY_ACCESS:
2606 return &Handle_0x27_SecurityAccess;
2607 case UDS_SID_COMMUNICATION_CONTROL:
2608 return &Handle_0x28_CommunicationControl;
2609 case UDS_SID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2611 case UDS_SID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2612 return &Handle_0x2C_DynamicDefineDataIdentifier;
2613 case UDS_SID_WRITE_DATA_BY_IDENTIFIER:
2614 return &Handle_0x2E_WriteDataByIdentifier;
2615 case UDS_SID_IO_CONTROL_BY_IDENTIFIER:
2616 return &Handle_0x2F_IOControlByIdentifier;
2617 case UDS_SID_ROUTINE_CONTROL:
2618 return &Handle_0x31_RoutineControl;
2619 case UDS_SID_REQUEST_DOWNLOAD:
2620 return &Handle_0x34_RequestDownload;
2621 case UDS_SID_REQUEST_UPLOAD:
2622 return &Handle_0x35_RequestUpload;
2623 case UDS_SID_TRANSFER_DATA:
2624 return &Handle_0x36_TransferData;
2625 case UDS_SID_REQUEST_TRANSFER_EXIT:
2626 return &Handle_0x37_RequestTransferExit;
2627 case UDS_SID_REQUEST_FILE_TRANSFER:
2628 return &Handle_0x38_RequestFileTransfer;
2629 case UDS_SID_WRITE_MEMORY_BY_ADDRESS:
2630 return &Handle_0x3D_WriteMemoryByAddress;
2631 case UDS_SID_TESTER_PRESENT:
2632 return &Handle_0x3E_TesterPresent;
2633 case UDS_SID_ACCESS_TIMING_PARAMETER:
2634 case UDS_SID_SECURED_DATA_TRANSMISSION:
2636 case UDS_SID_CONTROL_DTC_SETTING:
2637 return &Handle_0x85_ControlDTCSetting;
2638 case UDS_SID_RESPONSE_ON_EVENT:
2640 case UDS_SID_LINK_CONTROL:
2641 return &Handle_0x87_LinkControl;
2643 UDS_LOGI(__FILE__,
"no handler for request SID %x", sid);
2656 UDSErr_t response = UDS_PositiveResponse;
2657 bool suppressResponse =
false;
2661 if (NULL == srv->
fn) {
2662 return NegativeResponse(r, UDS_NRC_ServiceNotSupported);
2669 case UDS_SID_DIAGNOSTIC_SESSION_CONTROL:
2670 case UDS_SID_ECU_RESET:
2671 case UDS_SID_SECURITY_ACCESS:
2672 case UDS_SID_COMMUNICATION_CONTROL:
2673 case UDS_SID_ROUTINE_CONTROL:
2674 case UDS_SID_TESTER_PRESENT:
2675 case UDS_SID_CONTROL_DTC_SETTING:
2676 case UDS_SID_LINK_CONTROL: {
2678 response = service(srv, r);
2680 bool suppressPosRspMsgIndicationBit = (r->
recv_buf[1] & 0x80U) != 0U;
2683 if (suppressPosRspMsgIndicationBit && (response == UDS_PositiveResponse) &&
2687 suppressResponse =
true;
2689 suppressResponse =
false;
2696 case UDS_SID_READ_DATA_BY_IDENTIFIER:
2697 case UDS_SID_READ_MEMORY_BY_ADDRESS:
2698 case UDS_SID_WRITE_DATA_BY_IDENTIFIER:
2699 case UDS_SID_REQUEST_DOWNLOAD:
2700 case UDS_SID_REQUEST_UPLOAD:
2701 case UDS_SID_TRANSFER_DATA:
2702 case UDS_SID_REQUEST_FILE_TRANSFER:
2703 case UDS_SID_REQUEST_TRANSFER_EXIT: {
2705 response = service(srv, r);
2710 case UDS_SID_CLEAR_DIAGNOSTIC_INFORMATION:
2711 case UDS_SID_READ_DTC_INFORMATION:
2712 case UDS_SID_READ_SCALING_DATA_BY_IDENTIFIER:
2713 case UDS_SID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2714 case UDS_SID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2715 case UDS_SID_IO_CONTROL_BY_IDENTIFIER:
2716 case UDS_SID_WRITE_MEMORY_BY_ADDRESS:
2717 case UDS_SID_ACCESS_TIMING_PARAMETER:
2718 case UDS_SID_SECURED_DATA_TRANSMISSION:
2719 case UDS_SID_RESPONSE_ON_EVENT:
2721 if (service != NULL) {
2722 response = service(srv, r);
2731 return NegativeResponse(r, UDS_NRC_ServiceNotSupported);
2737 .len = (uint16_t)(r->
recv_len - 1U),
2738 .copyResponse = safe_copy,
2741 r->
send_buf[0] = AsResponseSID(sid);
2745 if (UDS_PositiveResponse != response) {
2746 return NegativeResponse(r, response);
2754 ((UDS_NRC_ServiceNotSupported == response) ||
2755 (UDS_NRC_SubFunctionNotSupported == response) ||
2756 (UDS_NRC_ServiceNotSupportedInActiveSession == response) ||
2757 (UDS_NRC_SubFunctionNotSupportedInActiveSession == response) ||
2758 (UDS_NRC_RequestOutOfRange == response)) &&
2763 suppressResponse =
true;
2766 if (suppressResponse) {
2775 return UDS_ERR_INVALID_ARG;
2806 if (UDS_OK != err) {
2808 UDS_LOGE(__FILE__,
"UDSTpPoll failed with %s", UDSErrToStr(err));
2819 UDSErr_t response = evaluateServiceResponse(srv, r);
2820 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2838 if (UDS_OK != err) {
2840 UDS_LOGE(__FILE__,
"UDSTpSend failed with %s", UDSErrToStr(err));
2847 uint32_t wait_time = srv->
p2_star_ms * 3U / 10U;
2861 if (UDS_OK != err) {
2862 UDS_LOGE(__FILE__,
"UDSTpRecv failed with %s\n", UDSErrToStr(err));
2868 UDSErr_t response = evaluateServiceResponse(srv, r);
2870 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2888 return hdl->
send(hdl, buf, len, info);
2896 return hdl->
recv(hdl, buf, bufsiz, recvlen, info);
2902 return hdl->
poll(hdl);
2915#ifdef UDS_CUSTOM_MILLIS
2919#if UDS_SYS == UDS_SYS_UNIX
2921 gettimeofday(&te, NULL);
2922 long long milliseconds = (te.tv_sec * 1000LL) + (te.tv_usec / 1000);
2923 return (uint32_t)milliseconds;
2924#elif UDS_SYS == UDS_SYS_WINDOWS
2926 timespec_get(&ts, TIME_UTC);
2927 long long milliseconds = ts.tv_sec * 1000LL + ts.tv_nsec / 1000000;
2928 return (uint32_t)milliseconds;
2929#elif UDS_SYS == UDS_SYS_ARDUINO
2931#elif UDS_SYS == UDS_SYS_ESP32
2932 return esp_timer_get_time() / 1000;
2933#elif UDS_SYS == UDS_SYS_ZEPHYR
2934 return k_uptime_get_32();
2936#error "UDSMillis not implemented for this UDS_SYS"
2941const char *UDSErrToStr(
UDSErr_t err) {
2947 case UDS_NRC_GeneralReject:
2948 return "UDS_NRC_GeneralReject";
2949 case UDS_NRC_ServiceNotSupported:
2950 return "UDS_NRC_ServiceNotSupported";
2951 case UDS_NRC_SubFunctionNotSupported:
2952 return "UDS_NRC_SubFunctionNotSupported";
2953 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2954 return "UDS_NRC_IncorrectMessageLengthOrInvalidFormat";
2955 case UDS_NRC_ResponseTooLong:
2956 return "UDS_NRC_ResponseTooLong";
2957 case UDS_NRC_BusyRepeatRequest:
2958 return "UDS_NRC_BusyRepeatRequest";
2959 case UDS_NRC_ConditionsNotCorrect:
2960 return "UDS_NRC_ConditionsNotCorrect";
2961 case UDS_NRC_RequestSequenceError:
2962 return "UDS_NRC_RequestSequenceError";
2963 case UDS_NRC_NoResponseFromSubnetComponent:
2964 return "UDS_NRC_NoResponseFromSubnetComponent";
2965 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2966 return "UDS_NRC_FailurePreventsExecutionOfRequestedAction";
2967 case UDS_NRC_RequestOutOfRange:
2968 return "UDS_NRC_RequestOutOfRange";
2969 case UDS_NRC_SecurityAccessDenied:
2970 return "UDS_NRC_SecurityAccessDenied";
2971 case UDS_NRC_AuthenticationRequired:
2972 return "UDS_NRC_AuthenticationRequired";
2973 case UDS_NRC_InvalidKey:
2974 return "UDS_NRC_InvalidKey";
2975 case UDS_NRC_ExceedNumberOfAttempts:
2976 return "UDS_NRC_ExceedNumberOfAttempts";
2977 case UDS_NRC_RequiredTimeDelayNotExpired:
2978 return "UDS_NRC_RequiredTimeDelayNotExpired";
2979 case UDS_NRC_SecureDataTransmissionRequired:
2980 return "UDS_NRC_SecureDataTransmissionRequired";
2981 case UDS_NRC_SecureDataTransmissionNotAllowed:
2982 return "UDS_NRC_SecureDataTransmissionNotAllowed";
2983 case UDS_NRC_SecureDataVerificationFailed:
2984 return "UDS_NRC_SecureDataVerificationFailed";
2985 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2986 return "UDS_NRC_CertficateVerificationFailedInvalidTimePeriod";
2987 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2988 return "UDS_NRC_CertficateVerificationFailedInvalidSignature";
2989 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2990 return "UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust";
2991 case UDS_NRC_CertficateVerificationFailedInvalidType:
2992 return "UDS_NRC_CertficateVerificationFailedInvalidType";
2993 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2994 return "UDS_NRC_CertficateVerificationFailedInvalidFormat";
2995 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2996 return "UDS_NRC_CertficateVerificationFailedInvalidContent";
2997 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2998 return "UDS_NRC_CertficateVerificationFailedInvalidScope";
2999 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
3000 return "UDS_NRC_CertficateVerificationFailedInvalidCertificate";
3001 case UDS_NRC_OwnershipVerificationFailed:
3002 return "UDS_NRC_OwnershipVerificationFailed";
3003 case UDS_NRC_ChallengeCalculationFailed:
3004 return "UDS_NRC_ChallengeCalculationFailed";
3005 case UDS_NRC_SettingAccessRightsFailed:
3006 return "UDS_NRC_SettingAccessRightsFailed";
3007 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
3008 return "UDS_NRC_SessionKeyCreationOrDerivationFailed";
3009 case UDS_NRC_ConfigurationDataUsageFailed:
3010 return "UDS_NRC_ConfigurationDataUsageFailed";
3011 case UDS_NRC_DeAuthenticationFailed:
3012 return "UDS_NRC_DeAuthenticationFailed";
3013 case UDS_NRC_UploadDownloadNotAccepted:
3014 return "UDS_NRC_UploadDownloadNotAccepted";
3015 case UDS_NRC_TransferDataSuspended:
3016 return "UDS_NRC_TransferDataSuspended";
3017 case UDS_NRC_GeneralProgrammingFailure:
3018 return "UDS_NRC_GeneralProgrammingFailure";
3019 case UDS_NRC_WrongBlockSequenceCounter:
3020 return "UDS_NRC_WrongBlockSequenceCounter";
3021 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
3022 return "UDS_NRC_RequestCorrectlyReceived_ResponsePending";
3023 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
3024 return "UDS_NRC_SubFunctionNotSupportedInActiveSession";
3025 case UDS_NRC_ServiceNotSupportedInActiveSession:
3026 return "UDS_NRC_ServiceNotSupportedInActiveSession";
3027 case UDS_NRC_RpmTooHigh:
3028 return "UDS_NRC_RpmTooHigh";
3029 case UDS_NRC_RpmTooLow:
3030 return "UDS_NRC_RpmTooLow";
3031 case UDS_NRC_EngineIsRunning:
3032 return "UDS_NRC_EngineIsRunning";
3033 case UDS_NRC_EngineIsNotRunning:
3034 return "UDS_NRC_EngineIsNotRunning";
3035 case UDS_NRC_EngineRunTimeTooLow:
3036 return "UDS_NRC_EngineRunTimeTooLow";
3037 case UDS_NRC_TemperatureTooHigh:
3038 return "UDS_NRC_TemperatureTooHigh";
3039 case UDS_NRC_TemperatureTooLow:
3040 return "UDS_NRC_TemperatureTooLow";
3041 case UDS_NRC_VehicleSpeedTooHigh:
3042 return "UDS_NRC_VehicleSpeedTooHigh";
3043 case UDS_NRC_VehicleSpeedTooLow:
3044 return "UDS_NRC_VehicleSpeedTooLow";
3045 case UDS_NRC_ThrottlePedalTooHigh:
3046 return "UDS_NRC_ThrottlePedalTooHigh";
3047 case UDS_NRC_ThrottlePedalTooLow:
3048 return "UDS_NRC_ThrottlePedalTooLow";
3049 case UDS_NRC_TransmissionRangeNotInNeutral:
3050 return "UDS_NRC_TransmissionRangeNotInNeutral";
3051 case UDS_NRC_TransmissionRangeNotInGear:
3052 return "UDS_NRC_TransmissionRangeNotInGear";
3053 case UDS_NRC_BrakeSwitchNotClosed:
3054 return "UDS_NRC_BrakeSwitchNotClosed";
3055 case UDS_NRC_ShifterLeverNotInPark:
3056 return "UDS_NRC_ShifterLeverNotInPark";
3057 case UDS_NRC_TorqueConverterClutchLocked:
3058 return "UDS_NRC_TorqueConverterClutchLocked";
3059 case UDS_NRC_VoltageTooHigh:
3060 return "UDS_NRC_VoltageTooHigh";
3061 case UDS_NRC_VoltageTooLow:
3062 return "UDS_NRC_VoltageTooLow";
3063 case UDS_NRC_ResourceTemporarilyNotAvailable:
3064 return "UDS_NRC_ResourceTemporarilyNotAvailable";
3065 case UDS_ERR_TIMEOUT:
3066 return "UDS_ERR_TIMEOUT";
3067 case UDS_ERR_DID_MISMATCH:
3068 return "UDS_ERR_DID_MISMATCH";
3069 case UDS_ERR_SID_MISMATCH:
3070 return "UDS_ERR_SID_MISMATCH";
3071 case UDS_ERR_SUBFUNCTION_MISMATCH:
3072 return "UDS_ERR_SUBFUNCTION_MISMATCH";
3074 return "UDS_ERR_TPORT";
3075 case UDS_ERR_RESP_TOO_SHORT:
3076 return "UDS_ERR_RESP_TOO_SHORT";
3077 case UDS_ERR_BUFSIZ:
3078 return "UDS_ERR_BUFSIZ";
3079 case UDS_ERR_INVALID_ARG:
3080 return "UDS_ERR_INVALID_ARG";
3082 return "UDS_ERR_BUSY";
3083 case UDS_ERR_MISUSE:
3084 return "UDS_ERR_MISUSE";
3094 return "UDS_EVT_Custom";
3096 return "UDS_EVT_Err";
3098 return "UDS_EVT_DiagSessCtrl";
3100 return "UDS_EVT_EcuReset";
3102 return "UDS_EVT_ReadDataByIdent";
3104 return "UDS_EVT_ReadMemByAddr";
3106 return "UDS_EVT_CommCtrl";
3108 return "UDS_EVT_SecAccessRequestSeed";
3110 return "UDS_EVT_SecAccessValidateKey";
3112 return "UDS_EVT_WriteDataByIdent";
3114 return "UDS_EVT_RoutineCtrl";
3116 return "UDS_EVT_RequestDownload";
3118 return "UDS_EVT_RequestUpload";
3120 return "UDS_EVT_TransferData";
3122 return "UDS_EVT_RequestTransferExit";
3124 return "UDS_EVT_SessionTimeout";
3126 return "UDS_EVT_DoScheduledReset";
3128 return "UDS_EVT_RequestFileTransfer";
3130 return "UDS_EVT_Poll";
3132 return "UDS_EVT_SendComplete";
3134 return "UDS_EVT_ResponseReceived";
3136 return "UDS_EVT_Idle";
3138 return "UDS_EVT_MAX";
3151#if UDS_LOG_LEVEL > UDS_LOG_NONE
3152void UDS_LogWrite(
UDS_LogLevel_t level,
const char *tag,
const char *format, ...) {
3156 va_start(list, format);
3157 (void)vprintf(format, list);
3161void UDS_LogSDUInternal(
UDS_LogLevel_t level,
const char *tag,
const uint8_t *buffer,
size_t buflen,
3164 for (
size_t i = 0; i < buflen; i++) {
3165 UDS_LogWrite(level, tag,
"%02x ", buffer[i]);
3167 UDS_LogWrite(level, tag,
"\n");
3171#ifdef UDS_TP_ISOTP_C
3173#line 1 "src/tp/isotp_c.c"
3184 isotp_poll(&impl->phys_link);
3185 isotp_poll(&impl->func_link);
3186 if (ISOTP_SEND_STATUS_INPROGRESS == impl->phys_link.send_status) {
3187 hdl->status.is_sending = 1;
3189 hdl->status.is_sending = 0;
3192 if (ISOTP_SEND_STATUS_ERROR == impl->phys_link.send_status) {
3193 return UDS_ERR_TPORT;
3201 IsoTpLink *link = NULL;
3204 if (len > UINT32_MAX) {
3209 case UDS_A_TA_TYPE_PHYSICAL:
3210 link = &tp->phys_link;
3212 case UDS_A_TA_TYPE_FUNCTIONAL:
3213 link = &tp->func_link;
3215 UDS_LOGE(__FILE__,
"Cannot send more than 7 bytes via functional addressing");
3216 return UDS_ERR_MISUSE;
3220 UDS_LOGE(__FILE__,
"unknown UDS_A_TA_TYPE");
3221 return UDS_ERR_MISUSE;
3224 int ret = isotp_send(link, buf, (uint32_t)len);
3226 case ISOTP_RET_OK: {
3229 case ISOTP_RET_INPROGRESS:
3230 case ISOTP_RET_OVERFLOW:
3232 return UDS_ERR_TPORT;
3237safe_api_shim_isotp_receive(IsoTpLink *link, uint8_t *payload,
3238 const size_t payload_size,
3239 size_t *out_size,
int *isotp_ret) {
3240 uint32_t u32out_size = 0;
3242 if (payload_size > UINT32_MAX) {
3246 *isotp_ret = isotp_receive(link, payload, (uint32_t)payload_size, &u32out_size);
3248#if UINT32_MAX > SIZE_MAX
3249 if (u32out_size > SIZE_MAX) {
3254 *out_size = u32out_size;
3258static UDSErr_t tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsiz,
size_t *recvlen,
3264 err = safe_api_shim_isotp_receive(&tp->phys_link, buf, bufsiz, recvlen, &ret);
3265 if (UDS_OK != err) {
3268 if (ISOTP_RET_OK == ret) {
3269 UDS_LOGI(__FILE__,
"phys link received %zd bytes", *recvlen);
3271 info->
A_TA = tp->phys_sa;
3272 info->
A_SA = tp->phys_ta;
3273 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3275 }
else if (ISOTP_RET_NO_DATA == ret) {
3276 err = safe_api_shim_isotp_receive(&tp->func_link, buf, bufsiz, recvlen, &ret);
3277 if (UDS_OK != err) {
3280 if (ISOTP_RET_OK == ret) {
3281 UDS_LOGI(__FILE__,
"func link received %zd bytes", *recvlen);
3283 info->
A_TA = tp->func_sa;
3284 info->
A_SA = tp->func_ta;
3285 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3287 }
else if (ISOTP_RET_NO_DATA == ret) {
3290 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
3293 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
3301 return UDS_ERR_INVALID_ARG;
3303 tp->hdl.poll = UDSTpISOTpCPoll;
3304 tp->hdl.send = tp_send;
3305 tp->hdl.recv = tp_recv;
3308 tp->func_sa = sa_func;
3309 tp->func_ta = ta_func;
3311 isotp_init_link(&tp->phys_link, tp->phys_ta, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3312 sizeof(tp->recv_buf));
3313 isotp_init_link(&tp->func_link, tp->func_ta, tp->func_send_buf,
sizeof(tp->func_send_buf),
3314 tp->func_recv_buf,
sizeof(tp->func_recv_buf));
3319 uint32_t source_addr_func) {
3320 return UDSTpISOTpCInit(tp, source_addr, target_addr, source_addr_func,
UDS_TP_NOOP_ADDR);
3324 uint32_t target_addr_func) {
3325 return UDSTpISOTpCInit(tp, source_addr, target_addr,
UDS_TP_NOOP_ADDR, target_addr_func);
3330#ifdef UDS_TP_ISOTP_C_SOCKETCAN
3332#line 1 "src/tp/isotp_c_socketcan.c"
3343static int SetupSocketCAN(
const char *ifname) {
3344 struct sockaddr_can addr = {0};
3345 struct ifreq ifr = {0};
3346 int sockfd = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW);
3353 (void)memset(&ifr, 0,
sizeof(ifr));
3354 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", ifname) >= (
int)
sizeof(ifr.ifr_name)) {
3355 UDS_LOGE(__FILE__,
"Interface name too long");
3356 if (close(sockfd) < 0) {
3361 if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) {
3364 (void)memset(&addr, 0,
sizeof(addr));
3365 addr.can_family = AF_CAN;
3366 addr.can_ifindex = ifr.ifr_ifindex;
3367 if (bind(sockfd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3373uint32_t isotp_user_get_us(
void) {
return UDSMillis() * 1000U; }
3375__attribute__((format(printf, 1, 2))) void isotp_user_debug(const
char *message, ...) {
3377 va_start(args, message);
3378 (void)vprintf(message, args);
3382#ifndef ISO_TP_USER_SEND_CAN_ARG
3383#error "ISO_TP_USER_SEND_CAN_ARG must be defined"
3385int isotp_user_send_can(
const uint32_t arbitration_id,
const uint8_t *data,
const uint8_t size,
3387 (void)fflush(stdout);
3390 (void)memcpy(&sockfd, user_data,
sizeof(sockfd));
3391 struct can_frame frame = {0};
3392 frame.can_id = arbitration_id;
3393 frame.can_dlc = size;
3394 (void)memmove(frame.data, data, size);
3395 ssize_t ret = write(sockfd, &frame,
sizeof(
struct can_frame));
3397 perror(
"Write err");
3398 return ISOTP_RET_ERROR;
3400 return ISOTP_RET_OK;
3403static bool GetNextFrame(
int fd,
struct can_frame *frame) {
3405 ssize_t nbytes = read(fd, frame,
sizeof(
struct can_frame));
3407 if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
3413 }
else if (nbytes == 0) {
3422 struct can_frame frame = {0};
3424 while (GetNextFrame(tp->fd, &frame)) {
3425 if (frame.can_id == tp->hdl2.phys_sa) {
3426 isotp_on_can_message(&tp->hdl2.phys_link, frame.data, frame.can_dlc);
3427 }
else if (frame.can_id == tp->hdl2.func_sa) {
3428 isotp_on_can_message(&tp->hdl2.func_link, frame.data, frame.can_dlc);
3429 if (ISOTP_RECEIVE_STATUS_IDLE != tp->hdl2.func_link.receive_status) {
3431 "func frame received but cannot process because link is not idle");
3435 isotp_on_can_message(&tp->hdl2.func_link, frame.data, frame.can_dlc);
3437 UDS_LOGD(__FILE__,
"received frame 0x%x not matching phys or func addresses",
3446 SocketCANRecv(impl);
3447 return UDSTpISOTpCPoll((
UDSTp_t *)&(impl->hdl2));
3451 uint32_t source_addr, uint32_t target_addr,
3452 uint32_t source_addr_func, uint32_t target_addr_func) {
3455 err = UDSTpISOTpCInit(&tp->hdl2, source_addr, target_addr, source_addr_func, target_addr_func);
3456 if (UDS_OK != err) {
3460 hdl->
poll = isotp_c_socketcan_poll;
3462 tp->fd = SetupSocketCAN(ifname);
3463 tp->hdl2.phys_link.user_send_can_arg = &(tp->fd);
3464 tp->hdl2.func_link.user_send_can_arg = &(tp->fd);
3470 uint32_t source_addr, uint32_t target_addr,
3471 uint32_t source_addr_func) {
3472 return UDSTpISOTpCSocketCANInit(tp, ifname, source_addr, target_addr, source_addr_func,
3477 uint32_t source_addr, uint32_t target_addr,
3478 uint32_t target_addr_func) {
3479 return UDSTpISOTpCSocketCANInit(tp, ifname, source_addr, target_addr,
UDS_TP_NOOP_ADDR,
3485 if (close(tp->fd) < 0) {
3493#ifdef UDS_TP_ISOTP_SOCK
3495#line 1 "src/tp/isotp_sock.c"
3503static bool revents_has(
short revents,
short flag) {
3504 return (
bool)(((
unsigned int)revents & (
unsigned int)flag) != 0U);
3511 const int fds[2] = {impl->phys_fd, impl->func_fd};
3512 struct pollfd pfds[2] = {0};
3513 pfds[0].fd = impl->phys_fd;
3514 pfds[0].events = POLLERR | POLLOUT;
3515 pfds[0].revents = 0;
3517 pfds[1].fd = impl->func_fd;
3518 pfds[1].events = POLLERR | POLLOUT;
3519 pfds[1].revents = 0;
3521 ret = poll(pfds, 2, 1);
3523 UDS_LOGE(__FILE__,
"poll failed: %d", ret);
3524 err = UDS_ERR_TPORT;
3525 }
else if (ret == 0) {
3529 for (
int i = 0; i < 2; i++) {
3530 struct pollfd pfd = pfds[i];
3533 if (revents_has(pfd.revents, POLLERR)) {
3534 int pending_err = 0;
3535 socklen_t len =
sizeof(pending_err);
3536 if (0 == getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &pending_err, &len) &&
3538 if (ECOMM == pending_err) {
3539 UDS_LOGE(__FILE__,
"ECOMM: Communication error on send");
3540 err = UDS_ERR_TPORT;
3542 UDS_LOGE(__FILE__,
"Asynchronous socket error: %s (%d)",
3543 strerror(pending_err), pending_err);
3546 UDS_LOGE(__FILE__,
"POLLERR was set, but no error returned via SO_ERROR?");
3552 if ((fds[i] == impl->phys_fd) && (pfd.revents != 0)) {
3557 if (!revents_has(pfd.revents, POLLOUT)) {
3558 hdl->status.is_sending = 1;
3560 hdl->status.is_sending = 0;
3568static UDSErr_t tp_recv_once(
int fd, uint8_t *buf,
const size_t bufsiz,
size_t *recvlen) {
3570 ssize_t ret = read(fd, buf, bufsiz);
3572 if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
3575 UDS_LOGE(__FILE__,
"read failed: %zd with errno: %d", ret, errno);
3580 *recvlen = (ret < 0) ? 0U : (size_t)ret;
3584static UDSErr_t isotp_sock_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
const size_t bufsiz,
size_t *recvlen,
3590 err = tp_recv_once(impl->phys_fd, buf, bufsiz, recvlen);
3591 if (UDS_OK != err) {
3595 msg->
A_TA = impl->phys_sa;
3596 msg->
A_SA = impl->phys_ta;
3597 msg->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3599 err = tp_recv_once(impl->func_fd, buf, bufsiz, recvlen);
3600 if (UDS_OK != err) {
3604 msg->
A_TA = impl->func_sa;
3605 msg->
A_SA = impl->func_ta;
3606 msg->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3615 UDS_LOGD(__FILE__,
"'%s' received %zd bytes from 0x%03x (%s), ", impl->tag, *recvlen,
3616 msg->
A_TA, (msg->
A_TA_Type == UDS_A_TA_TYPE_PHYSICAL) ?
"phys" :
"func");
3617 UDS_LOG_SDU(__FILE__, impl->recv_buf, *recvlen, msg);
3622static UDSErr_t isotp_sock_tp_send(
UDSTp_t *hdl,
const uint8_t *buf,
const size_t len,
3630 case UDS_A_TA_TYPE_PHYSICAL:
3633 case UDS_A_TA_TYPE_FUNCTIONAL: {
3635 UDS_LOGE(__FILE__,
"UDSTpIsoTpSock: functional request too large");
3636 return UDS_ERR_MISUSE;
3641 UDS_LOGE(__FILE__,
"unknown UDS_A_TA_TYPE");
3642 return UDS_ERR_MISUSE;
3646 ret = write(fd, buf, len);
3652 uint32_t ta = (ta_type == UDS_A_TA_TYPE_PHYSICAL) ? impl->phys_ta : impl->func_ta;
3653 UDS_LOGD(__FILE__,
"'%s' sends %zu bytes to 0x%03x (%s)", impl->tag, len, ta,
3654 (ta_type == UDS_A_TA_TYPE_PHYSICAL) ?
"phys" :
"func");
3655 UDS_LOG_SDU(__FILE__, buf, len, info);
3659static int LinuxSockBind(
const char *if_name, uint32_t rxid, uint32_t txid,
bool functional) {
3660 int fd = socket(AF_CAN, SOCK_DGRAM | SOCK_NONBLOCK, CAN_ISOTP);
3666 struct can_isotp_fc_options fcopts = {
3671 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts,
sizeof(fcopts)) < 0) {
3672 perror(
"setsockopt");
3676 struct can_isotp_options opts;
3677 (void)memset(&opts, 0,
sizeof(opts));
3681 opts.flags |= CAN_ISOTP_LISTEN_MODE;
3684 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts,
sizeof(opts)) < 0) {
3685 perror(
"setsockopt (isotp_options):");
3690 (void)memset(&ifr, 0,
sizeof(ifr));
3691 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", if_name) >= (
int)
sizeof(ifr.ifr_name)) {
3692 UDS_LOGE(__FILE__,
"Interface name too long");
3695 ioctl(fd, SIOCGIFINDEX, &ifr);
3697 struct sockaddr_can addr;
3698 (void)memset(&addr, 0,
sizeof(addr));
3699 addr.can_family = AF_CAN;
3700 addr.can_addr.tp.rx_id = rxid;
3701 addr.can_addr.tp.tx_id = txid;
3702 addr.can_ifindex = ifr.ifr_ifindex;
3704 if (bind(fd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3705 UDS_LOGE(__FILE__,
"Bind: %s %s", strerror(errno), if_name);
3711 if (close(fd) < 0) {
3718 uint32_t target_addr, uint32_t source_addr_func) {
3720 (void)memset(tp, 0,
sizeof(*tp));
3721 tp->hdl.send = isotp_sock_tp_send;
3722 tp->hdl.recv = isotp_sock_tp_recv;
3723 tp->hdl.poll = isotp_sock_tp_poll;
3724 tp->phys_sa = source_addr;
3725 tp->phys_ta = target_addr;
3726 tp->func_sa = source_addr_func;
3728 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3729 if (tp->phys_fd < 0) {
3732 tp->func_fd = LinuxSockBind(ifname, source_addr_func, 0,
true);
3733 if (tp->func_fd < 0) {
3736 const char *tag =
"server";
3737 (void)memmove(tp->tag, tag, strlen(tag));
3738 UDS_LOGI(__FILE__,
"%s initialized phys link rx 0x%03x tx 0x%03x func link rx 0x%03x tx 0x%03x",
3739 strlen(tp->tag) ? tp->tag :
"server", source_addr, target_addr, source_addr_func,
3745 uint32_t target_addr, uint32_t target_addr_func) {
3747 (void)memset(tp, 0,
sizeof(*tp));
3748 tp->hdl.send = isotp_sock_tp_send;
3749 tp->hdl.recv = isotp_sock_tp_recv;
3750 tp->hdl.poll = isotp_sock_tp_poll;
3751 tp->func_ta = target_addr_func;
3752 tp->phys_ta = target_addr;
3753 tp->phys_sa = source_addr;
3755 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3756 tp->func_fd = LinuxSockBind(ifname, 0, target_addr_func,
true);
3757 if ((tp->phys_fd < 0) || (tp->func_fd < 0)) {
3760 const char *tag =
"client";
3761 (void)memmove(tp->tag, tag, strlen(tag));
3763 "%s initialized phys link (fd %d) rx 0x%03x tx 0x%03x func link (fd %d) rx 0x%03x tx "
3765 strlen(tp->tag) ? tp->tag :
"client", tp->phys_fd, source_addr, target_addr,
3766 tp->func_fd, source_addr, target_addr_func);
3772 if (close(tp->phys_fd) < 0) {
3773 perror(
"failed to close phys socket");
3775 if (close(tp->func_fd) < 0) {
3776 perror(
"failed to close func socket");
3783#ifdef UDS_TP_ISOTP_MOCK
3785#line 1 "src/tp/isotp_mock.c"
3798#define MAX_NUM_TP 16U
3800static ISOTPMock_t TPs[MAX_NUM_TP];
3801static const char ZeroTestBlock[
sizeof(ISOTPMock_t)] = {0};
3802static unsigned TPCount = 0;
3803static FILE *LogFile = NULL;
3808 uint32_t scheduled_tx_time;
3809 ISOTPMock_t *sender;
3811static unsigned MsgCount = 0;
3813static void NetworkPoll(
void) {
3815 while (i < MsgCount) {
3816 if (UDSTimeAfter(
UDSMillis(), msgs[i].scheduled_tx_time)) {
3818 for (
unsigned j = 0; j < MAX_NUM_TP; j++) {
3819 ISOTPMock_t *tp = &TPs[j];
3820 if (0 == memcmp(tp, ZeroTestBlock,
sizeof(ISOTPMock_t))) {
3823 if ((tp->sa_phys == msgs[i].info.A_TA) || (tp->sa_func == msgs[i].info.A_TA)) {
3825 if (tp->recv_len > 0U) {
3827 "TPMock: %s recv buffer is already full. Message dropped",
3833 "%s receives %ld bytes from TA=0x%03X (A_TA_Type=%s):", tp->name,
3834 msgs[i].len, msgs[i].info.A_TA,
3835 (msgs[i].info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL) ?
"PHYSICAL"
3837 UDS_LOG_SDU(__FILE__, msgs[i].buf, msgs[i].len, &(msgs[i].info));
3839 (void)memmove(tp->recv_buf, msgs[i].buf, msgs[i].len);
3840 tp->recv_len = msgs[i].len;
3841 tp->recv_info = msgs[i].info;
3846 UDS_LOGW(__FILE__,
"TPMock: no matching receiver for message");
3849 for (
unsigned j = i + 1U; j < MsgCount; j++) {
3850 msgs[j - 1U] = msgs[j];
3859static UDSErr_t mock_tp_send(
struct UDSTp *hdl,
const uint8_t *buf,
size_t len,
3862 ISOTPMock_t *tp = (ISOTPMock_t *)hdl;
3863 if (MsgCount >= NUM_MSGS) {
3864 UDS_LOGW(__FILE__,
"mock_tp_send: too many messages in the queue");
3867 struct Msg *m = &msgs[MsgCount];
3872 m->info.A_AE = (info == NULL) ? 0U : info->A_AE;
3873 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3874 m->info.A_TA = tp->ta_phys;
3875 m->info.A_SA = tp->sa_phys;
3876 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3882 UDS_LOGW(__FILE__,
"mock_tp_send: functional message too long: %zu", len);
3885 m->info.A_TA = tp->ta_func;
3886 m->info.A_SA = tp->sa_func;
3888 UDS_LOGW(__FILE__,
"mock_tp_send: unknown TA type: %d", ta_type);
3891 m->info.A_TA_Type = ta_type;
3892 m->scheduled_tx_time =
UDSMillis() + tp->send_tx_delay_ms;
3893 (void)memmove(m->buf, buf, len);
3895 UDS_LOGD(__FILE__,
"%s sends %ld bytes to TA=0x%03X (A_TA_Type=%s):", tp->name, len,
3897 (m->info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL) ?
"PHYSICAL" :
"FUNCTIONAL");
3898 UDS_LOG_SDU(__FILE__, buf, len, &m->info);
3903static UDSErr_t mock_tp_recv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsiz,
size_t *recvlen,
3906 ISOTPMock_t *tp = (ISOTPMock_t *)hdl;
3907 if (tp->recv_len == 0U) {
3910 if (bufsiz < tp->recv_len) {
3911 UDS_LOGE(__FILE__,
"mock_tp_recv: buffer too small: %ld < %ld", bufsiz, tp->recv_len);
3914 *recvlen = tp->recv_len;
3915 (void)memmove(buf, tp->recv_buf, tp->recv_len);
3917 *info = tp->recv_info;
3923static UDSErr_t mock_tp_poll(
struct UDSTp *hdl) {
3929static void ISOTPMockAttach(ISOTPMock_t *tp,
const ISOTPMockArgs_t *args) {
3934 tp->hdl.send = mock_tp_send;
3935 tp->hdl.recv = mock_tp_recv;
3936 tp->hdl.poll = mock_tp_poll;
3937 tp->sa_func = args->sa_func;
3938 tp->sa_phys = args->sa_phys;
3939 tp->ta_func = args->ta_func;
3940 tp->ta_phys = args->ta_phys;
3942 UDS_LOGV(__FILE__,
"attached %s. TPCount: %d", tp->name, TPCount);
3945static void ISOTPMockDetach(ISOTPMock_t *tp) {
3947 for (
unsigned i = 0; i < MAX_NUM_TP; i++) {
3948 if (&TPs[i] == tp) {
3950 UDS_LOGV(__FILE__,
"TPMock: detached %s. TPCount: %d", tp->name, TPCount);
3957UDSTp_t *ISOTPMockNew(
const char *name,
const ISOTPMockArgs_t *args) {
3958 if (TPCount >= MAX_NUM_TP) {
3959 UDS_LOGI(__FILE__,
"TPCount: %d, too many TPs\n", TPCount);
3964 if (0 == memcmp(&TPs[i], ZeroTestBlock,
sizeof(ISOTPMock_t))) {
3968 }
while (i < MAX_NUM_TP);
3970 ISOTPMock_t *tp = &TPs[i];
3972 (void)memset(tp, 0,
sizeof(ISOTPMock_t));
3974 if (snprintf(tp->name,
sizeof(tp->name),
"%s", name) >= (
int)
sizeof(tp->name)) {
3975 UDS_LOGE(__FILE__,
"Transport name too long, truncated");
3978 (void)snprintf(tp->name,
sizeof(tp->name),
"TPMock%u", TPCount);
3980 ISOTPMockAttach(tp, args);
3986void ISOTPMockLogToFile(
const char *filename) {
3987 if (LogFile != NULL) {
3988 (void)fprintf(stderr,
"Log file is already open\n");
3992 (void)fprintf(stderr,
"Filename is NULL\n");
3996 LogFile = fopen(filename,
"w");
3997 if (NULL == LogFile) {
3998 (void)fprintf(stderr,
"Failed to open log file %s\n", filename);
4003void ISOTPMockLogToStdout(
void) {
4004 if (NULL == LogFile) {
4010void ISOTPMockReset(
void) {
4011 (void)memset(TPs, 0,
sizeof(TPs));
4013 (void)memset(msgs, 0,
sizeof(msgs));
4017void ISOTPMockFree(
UDSTp_t *tp) {
4019 UDS_ASSERT(0 != memcmp(tp, ZeroTestBlock,
sizeof(ISOTPMock_t)));
4020 ISOTPMock_t *tpm = (ISOTPMock_t *)tp;
4021 ISOTPMockDetach(tpm);
4022 (void)memset(tp, 0,
sizeof(ISOTPMock_t));
4029#if defined(UDS_TP_ISOTP_C)
4032#ifndef ISO_TP_USER_SEND_CAN_ARG
4036#ifndef ISO_TP_NO_FORMATTED_ERRORS
4037#error "need this too"
4042#line 1 "src/tp/isotp-c/isotp.c"
4064static const uint8_t isotp_can_fd_frame_sizes[] = {12, 16, 20, 24, 32, 48, 64};
4067static uint8_t isotp_ceil_can_dl(uint8_t length) {
4068 if (length <= ISOTP_CAN_DL_CLASSIC) {
4073 for (uint8_t i = 0; i < (uint8_t)(
sizeof(isotp_can_fd_frame_sizes) /
sizeof(isotp_can_fd_frame_sizes[0])); ++i) {
4074 if (length <= isotp_can_fd_frame_sizes[i]) {
return isotp_can_fd_frame_sizes[i]; }
4077 return isotp_can_fd_frame_sizes[
sizeof(isotp_can_fd_frame_sizes) /
sizeof(isotp_can_fd_frame_sizes[0]) - 1];
4081static uint8_t isotp_is_valid_can_dl(uint8_t length) {
return (uint8_t)(length == isotp_ceil_can_dl(length)); }
4086static uint8_t isotp_tx_dl(
const IsoTpLink* link) {
4087 if (link->tx_dl < ISOTP_CAN_DL_CLASSIC || link->tx_dl > ISO_TP_MAX_CAN_FRAME_SIZE || !isotp_is_valid_can_dl(link->tx_dl)) {
return ISOTP_CAN_DL_CLASSIC; }
4092#ifdef ISO_TP_USER_SEND_CAN_FLAGS
4097static uint8_t isotp_frame_flags(
const IsoTpLink* link) {
4098 uint8_t flags = ISOTP_CAN_FRAME_FLAG_NONE;
4100 if (isotp_tx_dl(link) > ISOTP_CAN_DL_CLASSIC) {
4101 flags |= ISOTP_CAN_FRAME_FLAG_FD;
4103 #ifdef ISO_TP_CAN_FD_USE_BRS
4104 flags |= ISOTP_CAN_FRAME_FLAG_BRS;
4119static uint8_t isotp_pad_frame(IsoTpCanMessage* message, uint8_t used_length) {
4120 uint8_t frame_length = used_length;
4122#ifdef ISO_TP_FRAME_PADDING
4123 if (frame_length < ISOTP_CAN_DL_CLASSIC) { frame_length = ISOTP_CAN_DL_CLASSIC; }
4126 frame_length = isotp_ceil_can_dl(frame_length);
4128 if (frame_length > used_length) { (void)memset(message->as.data_array.ptr + used_length, ISO_TP_FRAME_PADDING_VALUE, frame_length - used_length); }
4130 return frame_length;
4134static uint8_t isotp_us_to_st_min(uint32_t us) {
4138 const uint32_t STMIN_MS_MAX = 127000;
4139 const uint32_t STMIN_US_MIN = 100;
4140 const uint32_t STMIN_US_MAX = 900;
4141 const uint8_t STMIN_US_BASE = 0xF0;
4143 if (us <= STMIN_MS_MAX) {
4144 if (us >= STMIN_US_MIN && us <= STMIN_US_MAX) {
4145 return (uint8_t)(STMIN_US_BASE + (us / 100));
4147 return (uint8_t)(us / 1000u);
4155static uint32_t isotp_st_min_to_us(uint8_t st_min) {
4159 const uint8_t STMIN_MS_MAX = 0x7F;
4160 const uint8_t STMIN_US_MIN_CODE = 0xF1;
4161 const uint8_t STMIN_US_MAX_CODE = 0xF9;
4162 const uint8_t STMIN_US_BASE = 0xF0;
4163 const uint32_t US_PER_MS = 1000;
4164 const uint32_t US_STEP = 100;
4166 if (st_min <= STMIN_MS_MAX) {
4167 return st_min * US_PER_MS;
4168 }
else if (st_min >= STMIN_US_MIN_CODE && st_min <= STMIN_US_MAX_CODE) {
4169 return (st_min - STMIN_US_BASE) * US_STEP;
4174static int isotp_send_flow_control(
const IsoTpLink* link, uint8_t flow_status, uint8_t block_size, uint32_t st_min_us) {
4175 IsoTpCanMessage message;
4176 (void)memset(&message, 0,
sizeof(message));
4181 message.as.flow_control.type = ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME;
4182 message.as.flow_control.FS = flow_status;
4183 message.as.flow_control.BS = block_size;
4184 message.as.flow_control.STmin = isotp_us_to_st_min(st_min_us);
4187 size = isotp_pad_frame(&message, 3);
4189 ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
4190#
if defined(ISO_TP_USER_SEND_CAN_FLAGS)
4191 , isotp_frame_flags(link)
4193#
if defined(ISO_TP_USER_SEND_CAN_ARG)
4194 , link->user_send_can_arg
4201static int isotp_send_single_frame(
const IsoTpLink* link, uint32_t
id) {
4202 IsoTpCanMessage message;
4206 (void)memset(&message, 0,
sizeof(message));
4209 assert(link->send_size <= ISOTP_SF_MAX_PAYLOAD(isotp_tx_dl(link)));
4212 if (link->send_size < ISOTP_CAN_DL_CLASSIC) {
4213 message.as.single_frame.type = ISOTP_PCI_TYPE_SINGLE;
4214 message.as.single_frame.SF_DL = (uint8_t)link->send_size;
4215 (void)memcpy(message.as.single_frame.data, link->send_buffer, link->send_size);
4217 size = isotp_pad_frame(&message, (uint8_t)(link->send_size + 1u));
4220 message.as.single_frame_escape.type = ISOTP_PCI_TYPE_SINGLE;
4221 message.as.single_frame_escape.set_to_zero = 0;
4222 message.as.single_frame_escape.SF_DL = (uint8_t)link->send_size;
4223 (void)memcpy(message.as.single_frame_escape.data, link->send_buffer, link->send_size);
4225 size = isotp_pad_frame(&message, (uint8_t)(link->send_size + 2u));
4230 ret = isotp_user_send_can(
id, message.as.data_array.ptr, size
4231#
if defined(ISO_TP_USER_SEND_CAN_FLAGS)
4232 , isotp_frame_flags(link)
4234#
if defined(ISO_TP_USER_SEND_CAN_ARG)
4235 , link->user_send_can_arg
4241static int isotp_send_first_frame(IsoTpLink* link, uint32_t
id) {
4242 IsoTpCanMessage message;
4244 const uint8_t tx_dl = isotp_tx_dl(link);
4245 uint32_t data_length;
4247 (void)memset(&message, 0,
sizeof(message));
4250 assert(link->send_size > ISOTP_SF_MAX_PAYLOAD(tx_dl));
4253 if (link->send_size <= 4095) {
4255 data_length = (uint32_t)tx_dl - 2u;
4256 message.as.first_frame_short.type = ISOTP_PCI_TYPE_FIRST_FRAME;
4257 message.as.first_frame_short.FF_DL_low = (uint8_t)link->send_size;
4258 message.as.first_frame_short.FF_DL_high = (uint8_t)(0x0F & (link->send_size >> 8));
4259 (void)memcpy(message.as.first_frame_short.data, link->send_buffer, data_length);
4262 data_length = (uint32_t)tx_dl - 6u;
4263 message.as.first_frame_long.set_to_zero_high = 0;
4264 message.as.first_frame_long.set_to_zero_low = 0;
4265 message.as.first_frame_long.type = ISOTP_PCI_TYPE_FIRST_FRAME;
4266 message.as.first_frame_long.FF_DL = LE32TOH(link->send_size);
4267 (void)memcpy(message.as.first_frame_long.data, link->send_buffer, data_length);
4271 ret = isotp_user_send_can(
id, message.as.data_array.ptr, tx_dl
4272#
if defined(ISO_TP_USER_SEND_CAN_FLAGS)
4273 , isotp_frame_flags(link)
4275#
if defined(ISO_TP_USER_SEND_CAN_ARG)
4276 , link->user_send_can_arg
4280 if (ISOTP_RET_OK == ret) { link->send_offset += data_length; }
4287static int isotp_send_consecutive_frame(IsoTpLink* link) {
4288 IsoTpCanMessage message;
4289 uint32_t data_length;
4290 uint32_t max_data_length;
4294 (void)memset(&message, 0,
sizeof(message));
4297 assert(link->send_size > ISOTP_SF_MAX_PAYLOAD(isotp_tx_dl(link)));
4300 message.as.consecutive_frame.type = ISOTP_PCI_TYPE_CONSECUTIVE_FRAME;
4301 message.as.consecutive_frame.SN = link->send_sn;
4302 max_data_length = (uint32_t)isotp_tx_dl(link) - 1u;
4303 data_length = link->send_size - link->send_offset;
4304 if (data_length > max_data_length) { data_length = max_data_length; }
4305 (void)memcpy(message.as.consecutive_frame.data, link->send_buffer + link->send_offset, data_length);
4308 size = isotp_pad_frame(&message, (uint8_t)(data_length + 1u));
4310 ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
4311#
if defined(ISO_TP_USER_SEND_CAN_FLAGS)
4312 , isotp_frame_flags(link)
4314#
if defined(ISO_TP_USER_SEND_CAN_ARG)
4315 , link->user_send_can_arg
4319 if (ISOTP_RET_OK == ret) {
4320 link->send_offset += data_length;
4321 if (++(link->send_sn) > 0x0F) { link->send_sn = 0; }
4327static int isotp_receive_single_frame(IsoTpLink* link,
const IsoTpCanMessage* message, uint8_t len) {
4328 const uint8_t* payload;
4329 uint32_t payload_length;
4330 uint32_t max_payload_length;
4332 if (0 == message->as.single_frame.SF_DL) {
4334 if (len <= ISOTP_CAN_DL_CLASSIC) {
4335 isotp_user_debug(
"Single-frame length too small.");
4336 return ISOTP_RET_LENGTH;
4339 payload = message->as.single_frame_escape.data;
4340 payload_length = message->as.single_frame_escape.SF_DL;
4341 max_payload_length = (uint32_t)len - 2u;
4343 payload = message->as.single_frame.data;
4344 payload_length = message->as.single_frame.SF_DL;
4345 max_payload_length = (uint32_t)len - 1u;
4349 if ((0 == payload_length) || (payload_length > max_payload_length)) {
4350 isotp_user_debug(
"Single-frame length too small.");
4351 return ISOTP_RET_LENGTH;
4354 if (payload_length > link->receive_buf_size) {
4355 isotp_user_debug(
"Single-frame message too large for receiving buffer.");
4356 return ISOTP_RET_OVERFLOW;
4360 (void)memcpy(link->receive_buffer, payload, payload_length);
4361 link->receive_size = payload_length;
4362 link->receive_offset = link->receive_size;
4364#ifdef ISO_TP_ENABLE_STREAMING
4365 link->receive_stream_size = link->receive_size;
4366 link->receive_streaming = 0;
4367 link->receive_stream_carry_size = 0;
4370 return ISOTP_RET_OK;
4373static int isotp_receive_first_frame(IsoTpLink* link, IsoTpCanMessage* message, uint8_t len) {
4374 const uint8_t* first_frame_data;
4375 uint8_t is_long_packet = 0;
4376 uint32_t first_frame_data_length;
4377 uint32_t payload_length;
4382 if (len < ISOTP_CAN_DL_CLASSIC || !isotp_is_valid_can_dl(len)) {
4383 isotp_user_debug(
"First frame should be a full CAN frame of at least 8 bytes in length.");
4384 return ISOTP_RET_LENGTH;
4388 payload_length = message->as.first_frame_short.FF_DL_high;
4389 payload_length = (payload_length << 8) + message->as.first_frame_short.FF_DL_low;
4392 if (payload_length == 0) {
4394 payload_length = LE32TOH(message->as.first_frame_long.FF_DL);
4395 first_frame_data_length = (uint32_t)len - 6u;
4397 first_frame_data_length = (uint32_t)len - 2u;
4401 if (payload_length <= ISOTP_SF_MAX_PAYLOAD(len)) {
4402 isotp_user_debug(
"Should not use multiple frame transmission.");
4403 return ISOTP_RET_LENGTH;
4406#ifndef ISO_TP_ENABLE_STREAMING
4407 if (payload_length > link->receive_buf_size) {
4408 isotp_user_debug(
"Multi-frame response too large for receiving buffer.");
4409 return ISOTP_RET_OVERFLOW;
4412 if (link->receive_buf_size == 0) {
4413 isotp_user_debug(
"Receiving buffer must not be empty.");
4414 return ISOTP_RET_OVERFLOW;
4417 link->receive_streaming = payload_length > link->receive_buf_size;
4418 link->receive_stream_size = 0;
4419 link->receive_stream_carry_size = 0;
4423 if (is_long_packet) {
4424 first_frame_data = message->as.first_frame_long.data;
4426 first_frame_data = message->as.first_frame_short.data;
4429#ifdef ISO_TP_ENABLE_STREAMING
4430 if (first_frame_data_length > link->receive_buf_size) {
4431 (void)memcpy(link->receive_buffer, first_frame_data, link->receive_buf_size);
4432 link->receive_stream_size = link->receive_buf_size;
4433 link->receive_stream_carry_size = (uint8_t)(first_frame_data_length - link->receive_buf_size);
4434 (void)memcpy(link->receive_stream_carry, first_frame_data + link->receive_buf_size, link->receive_stream_carry_size);
4436 (void)memcpy(link->receive_buffer, first_frame_data, first_frame_data_length);
4437 link->receive_stream_size = first_frame_data_length;
4440 (void)memcpy(link->receive_buffer, first_frame_data, first_frame_data_length);
4443 link->receive_offset = first_frame_data_length;
4444 link->receive_size = payload_length;
4445 link->receive_sn = 1;
4448 return ISOTP_RET_OK;
4451static int isotp_receive_consecutive_frame(IsoTpLink* link,
const IsoTpCanMessage* message, uint8_t len) {
4452 uint32_t remaining_bytes;
4453 uint32_t max_data_length;
4456 if (link->receive_sn != message->as.consecutive_frame.SN) {
return ISOTP_RET_WRONG_SN; }
4459 max_data_length = (uint32_t)(link->rx_dl < ISOTP_CAN_DL_CLASSIC ? ISOTP_CAN_DL_CLASSIC : link->rx_dl) - 1u;
4462 remaining_bytes = link->receive_size - link->receive_offset;
4463 if (remaining_bytes > max_data_length) { remaining_bytes = max_data_length; }
4464 if (remaining_bytes > (uint32_t)(len - 1)) {
4465 isotp_user_debug(
"Consecutive frame too short.");
4466 return ISOTP_RET_LENGTH;
4469#ifdef ISO_TP_ENABLE_STREAMING
4470 if (link->receive_streaming) {
4471 uint32_t available = link->receive_buf_size - link->receive_stream_size;
4472 uint32_t copy_size = remaining_bytes < available ? remaining_bytes : available;
4474 (void)memcpy(link->receive_buffer + link->receive_stream_size, message->as.consecutive_frame.data, copy_size);
4475 link->receive_stream_size += copy_size;
4477 link->receive_stream_carry_size = (uint8_t)(remaining_bytes - copy_size);
4478 if (link->receive_stream_carry_size > 0) {
4479 (void)memcpy(link->receive_stream_carry, message->as.consecutive_frame.data + copy_size, link->receive_stream_carry_size);
4485 (void)memcpy(link->receive_buffer + link->receive_offset, message->as.consecutive_frame.data, remaining_bytes);
4488 link->receive_offset += remaining_bytes;
4489 if (++(link->receive_sn) > 0x0F) { link->receive_sn = 0; }
4491 return ISOTP_RET_OK;
4494static int isotp_receive_flow_control_frame(IsoTpLink* link, IsoTpCanMessage* message, uint8_t len) {
4501 isotp_user_debug(
"Flow control frame too short.");
4502 return ISOTP_RET_LENGTH;
4505 return ISOTP_RET_OK;
4512int isotp_send(IsoTpLink* link,
const uint8_t payload[], uint32_t size) {
return isotp_send_with_id(link, link->send_arbitration_id, payload, size); }
4514int isotp_send_with_id(IsoTpLink* link, uint32_t
id,
const uint8_t payload[], uint32_t size) {
4518 isotp_user_debug(
"Link is null!");
4519 return ISOTP_RET_ERROR;
4522 if (size > link->send_buf_size) {
4523 isotp_user_debug(
"Message size too large. Increase ISO_TP_MAX_MESSAGE_SIZE to set a larger buffer\n");
4525#ifndef ISO_TP_NO_FORMATTED_ERRORS
4526 char message[ISOTP_MAX_ERROR_MSG_SIZE] = {0};
4527 int32_t writtenChars = ISOTP_SNPRINTF(&message[0], ISOTP_MAX_ERROR_MSG_SIZE,
"Attempted to send %u bytes; max size is %u!\n", (
unsigned int)size,
4528 (
unsigned int)link->send_buf_size);
4530 assert(writtenChars <= ISOTP_MAX_ERROR_MSG_SIZE);
4533 isotp_user_debug(message);
4535 return ISOTP_RET_OVERFLOW;
4538 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4539 isotp_user_debug(
"Abort previous message, transmission in progress.\n");
4540 return ISOTP_RET_INPROGRESS;
4544 link->send_size = size;
4545 link->send_offset = 0;
4546 (void)memcpy(link->send_buffer, payload, size);
4548 if (link->send_size <= ISOTP_SF_MAX_PAYLOAD(isotp_tx_dl(link))) {
4550 ret = isotp_send_single_frame(link,
id);
4551#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
4552 if (ret == ISOTP_RET_OK && link->tx_done_cb) { link->tx_done_cb(link, link->send_size, link->tx_done_cb_arg); }
4556 ret = isotp_send_first_frame(link,
id);
4559 if (ISOTP_RET_OK == ret) {
4560 link->send_bs_remain = 0;
4561 link->send_st_min_us = 0;
4562 link->send_wtf_count = 0;
4563 link->send_timer_st = isotp_user_get_us();
4564 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4565 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4566 link->send_status = ISOTP_SEND_STATUS_INPROGRESS;
4573void isotp_on_can_message(IsoTpLink* link,
const uint8_t* data, uint8_t len) {
4574 IsoTpCanMessage message;
4577 if (len < 2 || len > ISO_TP_MAX_CAN_FRAME_SIZE) {
return; }
4579 memcpy(message.as.data_array.ptr, data, len);
4580 memset(message.as.data_array.ptr + len, 0,
sizeof(message.as.data_array.ptr) - len);
4582 switch (message.as.common.type) {
4583 case ISOTP_PCI_TYPE_SINGLE: {
4585 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4586 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4588 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4592 ret = isotp_receive_single_frame(link, &message, len);
4594 if (ISOTP_RET_OVERFLOW == ret) {
4596 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4597 }
else if (ISOTP_RET_OK == ret) {
4599 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4603 case ISOTP_PCI_TYPE_FIRST_FRAME: {
4605 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4606 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4608 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4612 ret = isotp_receive_first_frame(link, &message, len);
4615 if (ISOTP_RET_OVERFLOW == ret) {
4617 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4619 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4621 isotp_send_flow_control(link, PCI_FLOW_STATUS_OVERFLOW, 0, 0);
4626 if (ISOTP_RET_OK == ret) {
4628#ifdef ISO_TP_ENABLE_STREAMING
4629 if (link->receive_streaming && link->receive_stream_size >= link->receive_buf_size) {
4630 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4632 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4633 link->receive_bs_count = link->receive_streaming ? 1 : ISO_TP_DEFAULT_BLOCK_SIZE;
4634 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4637 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4638 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4639 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4642 link->receive_timer_cr = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4647 case ISOTP_PCI_TYPE_CONSECUTIVE_FRAME: {
4649 if (ISOTP_RECEIVE_STATUS_INPROGRESS != link->receive_status) {
4650 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4655 ret = isotp_receive_consecutive_frame(link, &message, len);
4658 if (ISOTP_RET_WRONG_SN == ret) {
4659 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_WRONG_SN;
4660 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4665 if (ISOTP_RET_OK == ret) {
4667 link->receive_timer_cr = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4670 if (link->receive_offset >= link->receive_size
4671#ifdef ISO_TP_ENABLE_STREAMING
4672 || (link->receive_streaming && link->receive_stream_size >= link->receive_buf_size)
4675 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4678 if (0 == --link->receive_bs_count) {
4679 link->receive_bs_count =
4680#ifdef ISO_TP_ENABLE_STREAMING
4681 link->receive_streaming ? 1 :
4683 ISO_TP_DEFAULT_BLOCK_SIZE;
4684 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4691 case ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME:
4693 if (ISOTP_SEND_STATUS_INPROGRESS != link->send_status) {
break; }
4696 ret = isotp_receive_flow_control_frame(link, &message, len);
4698 if (ISOTP_RET_OK == ret) {
4700 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4703 if (PCI_FLOW_STATUS_OVERFLOW == message.as.flow_control.FS) {
4704 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4705 link->send_status = ISOTP_SEND_STATUS_ERROR;
4709 else if (PCI_FLOW_STATUS_WAIT == message.as.flow_control.FS) {
4710 link->send_wtf_count += 1;
4712 if (link->send_wtf_count > ISO_TP_MAX_WFT_NUMBER) {
4713 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_WFT_OVRN;
4714 link->send_status = ISOTP_SEND_STATUS_ERROR;
4719 else if (PCI_FLOW_STATUS_CONTINUE == message.as.flow_control.FS) {
4720 if (0 == message.as.flow_control.BS) {
4721 link->send_bs_remain = ISOTP_INVALID_BS;
4723 link->send_bs_remain = message.as.flow_control.BS;
4725 uint32_t message_st_min_us = isotp_st_min_to_us(message.as.flow_control.STmin);
4726 link->send_st_min_us = message_st_min_us > ISO_TP_DEFAULT_ST_MIN_US
4728 : ISO_TP_DEFAULT_ST_MIN_US;
4729 link->send_wtf_count = 0;
4736#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
4738 if (link->receive_status == ISOTP_RECEIVE_STATUS_FULL && link->rx_done_cb != NULL
4739#ifdef ISO_TP_ENABLE_STREAMING
4740 && !link->receive_streaming
4743 link->rx_done_cb(link, link->receive_buffer, link->receive_size, link->rx_done_cb_arg);
4744 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4750int isotp_receive(IsoTpLink* link, uint8_t* payload,
const uint32_t payload_size, uint32_t* out_size) {
4753#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
4755 if (link->rx_done_cb != NULL) {
return ISOTP_RET_ERROR; }
4758#ifdef ISO_TP_ENABLE_STREAMING
4759 if (link->receive_streaming) {
return ISOTP_RET_ERROR; }
4762 if (ISOTP_RECEIVE_STATUS_FULL != link->receive_status) {
return ISOTP_RET_NO_DATA; }
4764 copylen = link->receive_size;
4765 if (copylen > payload_size) { copylen = payload_size; }
4767 memcpy(payload, link->receive_buffer, copylen);
4768 *out_size = copylen;
4770 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4772 return ISOTP_RET_OK;
4775#ifdef ISO_TP_ENABLE_STREAMING
4776int isotp_receive_streaming(IsoTpLink* link, uint8_t* payload,
const uint32_t payload_size, uint32_t* out_size,
bool* is_complete) {
4779 if (link == NULL || payload == NULL || out_size == NULL || is_complete == NULL) {
return ISOTP_RET_ERROR; }
4780 if (ISOTP_RECEIVE_STATUS_FULL != link->receive_status) {
return ISOTP_RET_NO_DATA; }
4782 copylen = link->receive_streaming ? link->receive_stream_size : link->receive_size;
4783 if (payload_size < copylen) {
return ISOTP_RET_NOSPACE; }
4785 (void)memcpy(payload, link->receive_buffer, copylen);
4786 *out_size = copylen;
4787 *is_complete = link->receive_offset >= link->receive_size && link->receive_stream_carry_size == 0;
4789 if (!link->receive_streaming || *is_complete) {
4790 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4791 link->receive_streaming = 0;
4792 return ISOTP_RET_OK;
4795 link->receive_stream_size = link->receive_stream_carry_size;
4796 if (link->receive_stream_size > link->receive_buf_size) {
4797 link->receive_stream_size = link->receive_buf_size;
4799 if (link->receive_stream_size > 0) {
4800 (void)memcpy(link->receive_buffer, link->receive_stream_carry, link->receive_stream_size);
4801 link->receive_stream_carry_size -= (uint8_t)link->receive_stream_size;
4802 if (link->receive_stream_carry_size > 0) {
4803 (void)memmove(link->receive_stream_carry, link->receive_stream_carry + link->receive_stream_size, link->receive_stream_carry_size);
4807 if (link->receive_stream_carry_size > 0 || link->receive_offset >= link->receive_size) {
4808 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4810 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4811 link->receive_bs_count = 1;
4812 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4813 link->receive_timer_cr = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4816 return ISOTP_RET_OK;
4820void isotp_init_link(IsoTpLink* link, uint32_t sendid, uint8_t* sendbuf, uint32_t sendbufsize, uint8_t* recvbuf, uint32_t recvbufsize) {
4821 memset(link, 0,
sizeof(*link));
4822 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4823 link->send_status = ISOTP_SEND_STATUS_IDLE;
4824 link->send_arbitration_id = sendid;
4825 link->send_buffer = sendbuf;
4826 link->send_buf_size = sendbufsize;
4827 link->receive_buffer = recvbuf;
4828 link->receive_buf_size = recvbufsize;
4829 link->tx_dl = ISO_TP_DEFAULT_TX_DL;
4830 link->rx_dl = ISOTP_CAN_DL_CLASSIC;
4832#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
4833 link->tx_done_cb = NULL;
4834 link->tx_done_cb_arg = NULL;
4837#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
4838 link->rx_done_cb = NULL;
4839 link->rx_done_cb_arg = NULL;
4845int isotp_set_tx_dl(IsoTpLink* link, uint8_t tx_dl) {
4847 isotp_user_debug(
"Link is null!");
4848 return ISOTP_RET_ERROR;
4851 if (tx_dl < ISOTP_CAN_DL_CLASSIC || tx_dl > ISO_TP_MAX_CAN_FRAME_SIZE || !isotp_is_valid_can_dl(tx_dl)) {
4852#ifndef ISO_TP_NO_FORMATTED_ERRORS
4853 char message[ISOTP_MAX_ERROR_MSG_SIZE] = {0};
4854 int32_t writtenChars =
4855 ISOTP_SNPRINTF(&message[0], ISOTP_MAX_ERROR_MSG_SIZE,
"Invalid TX_DL of %u bytes; must be a CAN frame length between 8 and %u!\n",
4856 (
unsigned int)tx_dl, (
unsigned int)ISO_TP_MAX_CAN_FRAME_SIZE);
4858 assert(writtenChars <= ISOTP_MAX_ERROR_MSG_SIZE);
4861 isotp_user_debug(message);
4863 isotp_user_debug(
"Invalid TX_DL; must be a valid CAN frame length.\n");
4865 return ISOTP_RET_ERROR;
4868 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4869 isotp_user_debug(
"Cannot change TX_DL while a transmission is in progress.\n");
4870 return ISOTP_RET_INPROGRESS;
4873 link->tx_dl = tx_dl;
4875 return ISOTP_RET_OK;
4878uint8_t isotp_get_tx_dl(
const IsoTpLink* link) {
4880 isotp_user_debug(
"Link is null!");
4884 return isotp_tx_dl(link);
4887void isotp_destroy_link(IsoTpLink* link) {
4888 if (link == NULL) {
return; }
4891#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
4892 link->tx_done_cb = NULL;
4893 link->tx_done_cb_arg = NULL;
4896#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
4897 link->rx_done_cb = NULL;
4898 link->rx_done_cb_arg = NULL;
4902 memset(link, 0,
sizeof(IsoTpLink));
4905void isotp_poll(IsoTpLink* link) {
4909 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4912 (ISOTP_INVALID_BS == link->send_bs_remain || link->send_bs_remain > 0) &&
4914 (0 == link->send_st_min_us || IsoTpTimeAfter(isotp_user_get_us(), link->send_timer_st))) {
4915 ret = isotp_send_consecutive_frame(link);
4916 if (ISOTP_RET_OK == ret) {
4917 if (ISOTP_INVALID_BS != link->send_bs_remain) { link->send_bs_remain -= 1; }
4918 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4919 link->send_timer_st = isotp_user_get_us() + link->send_st_min_us;
4922 if (link->send_offset >= link->send_size) {
4923 link->send_status = ISOTP_SEND_STATUS_IDLE;
4924#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
4925 if (link->tx_done_cb != NULL) { link->tx_done_cb(link, link->send_size, link->tx_done_cb_arg); }
4928 }
else if (ISOTP_RET_NOSPACE == ret) {
4931 link->send_status = ISOTP_SEND_STATUS_ERROR;
4936 if (IsoTpTimeAfter(isotp_user_get_us(), link->send_timer_bs)) {
4937 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_BS;
4938 link->send_status = ISOTP_SEND_STATUS_ERROR;
4943 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4945 if ((link->receive_timer_cr > 0) && IsoTpTimeAfter(isotp_user_get_us(), link->receive_timer_cr)) {
4946 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_CR;
4947 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4954#ifdef ISO_TP_TRANSMIT_COMPLETE_CALLBACK
4955void isotp_set_tx_done_cb(IsoTpLink* link, isotp_tx_done_cb cb,
void* arg) {
4957 link->tx_done_cb = cb;
4958 link->tx_done_cb_arg = arg;
4963#ifdef ISO_TP_RECEIVE_COMPLETE_CALLBACK
4964void isotp_set_rx_done_cb(IsoTpLink* link, isotp_rx_done_cb cb,
void* arg) {
4966 link->rx_done_cb = cb;
4967 link->rx_done_cb_arg = arg;
#define STATE_AWAIT_SEND_COMPLETE
#define STATE_AWAIT_RESPONSE
#define UDS_LEV_DS_DS
Default Session.
#define UDS_LEV_DS_PRGS
Programming Session.
#define UDS_LEV_DS_EXTDS
Extended Diagnostic Session.
#define UDS_LEV_RCTP_RRR
RequestRoutineResults.
#define UDS_LEV_RCTP_STPR
StopRoutine.
#define UDS_LEV_RCTP_STR
StartRoutine.
#define UDS_LEV_RT_ERPSD
Enable Rapid Power Shut Down.
#define UDS_MOOP_ADDFILE
AddFile.
#define UDS_MOOP_DELFILE
DeleteFile.
#define UDS_MOOP_RDDIR
ReadDirectory.
#define UDS_MOOP_RSFILE
ResumeFile.
#define UDS_MOOP_RDFILE
ReadFile.
#define UDS_MOOP_REPLFILE
ReplaceFile.
UDSErr_t(*) UDSService(UDSServer_t *srv, UDSReq_t *r)
signature of internal service handlers
#define UDS_CLIENT_DEFAULT_P2_MS
default P2 timeout
UDSErr_t UDSSendECUReset(UDSClient_t *client, uint8_t type)
Request ECUReset.
UDSErr_t UDSServerTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t source_addr, uint32_t target_addr, uint32_t source_addr_func)
Initialize isotp-c transport for UDSServer_t.
void UDSServerPoll(UDSServer_t *srv)
Call this at <5ms intervals.
UDSErr_t UDSClientTpISOTpCSocketCANInit(UDSTpISOTpCSocketCAN_t *tp, const char *ifname, uint32_t source_addr, uint32_t target_addr, uint32_t target_addr_func)
Initialize isotp-c over SocketCAN transport for UDSClient_t.
UDSErr_t UDSTpRecv(UDSTp_t *hdl, uint8_t *buf, size_t bufsiz, size_t *recvlen, UDSSDU_t *info)
Receive from transport.
@ UDS_EVT_RequestFileTransfer
@ UDS_EVT_ReadDTCInformation
@ UDS_EVT_ClearDiagnosticInfo
@ UDS_EVT_DynamicDefineDataId
@ UDS_EVT_SecAccessRequestSeed
@ UDS_EVT_SecAccessValidateKey
@ UDS_EVT_RequestDownload
@ UDS_EVT_WriteDataByIdent
@ UDS_EVT_RequestTransferExit
@ UDS_EVT_ResponseReceived
@ UDS_EVT_ControlDTCSetting
@ UDS_EVT_DoScheduledReset
@ UDS_EVT_ReadDataByIdent
UDSErr_t UDSSendTesterPresent(UDSClient_t *client)
What's up?
#define UDS_SERVER_DEFAULT_P2_MS
default P2 duration
#define UDS_CLIENT_DEFAULT_P2_STAR_MS
default P2* timeout
UDSErr_t UDSSendRequestTransferExit(UDSClient_t *client)
Call this when finished with TransferData.
UDSErr_t UDSTpPoll(UDSTp_t *hdl)
call this at <5ms intervals
UDSErr_t UDSSendRequestDownload(UDSClient_t *client, uint8_t dataFormatIdentifier, uint8_t addressAndLengthFormatIdentifier, size_t memoryAddress, size_t memorySize)
Request to Download via TransferData.
UDSErr_t UDSUnpackSecurityAccessResponse(const UDSClient_t *client, struct SecurityAccessResponse *resp)
Parse server's response to SecurityAccess.
#define UDS_TP_NOOP_ADDR
flags A_SA / A_TA as unused
UDSErr_t UDSServerTpIsoTpSockInit(UDSTpIsoTpSock_t *tp, const char *ifname, uint32_t source_addr, uint32_t target_addr, uint32_t source_addr_func)
for UDSServer_t
UDSErr_t UDSSendWDBI(UDSClient_t *client, uint16_t dataIdentifier, const uint8_t *data, uint16_t size)
Write Data By Identifier.
UDSErr_t UDSSendCommCtrl(UDSClient_t *client, uint8_t ctrl, uint8_t comm)
Change communication settings.
#define UDS_TP_MTU
ISOTP is the only supported tp type, so UDS inherits its MTU.
UDSErr_t UDSSendRequestUpload(UDSClient_t *client, uint8_t dataFormatIdentifier, uint8_t addressAndLengthFormatIdentifier, size_t memoryAddress, size_t memorySize)
Request to Upload via TransferData.
uint32_t UDSMillis(void)
Get time in milliseconds.
#define UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_BOOT_DELAY_MS
Amount of time to wait after boot before accepting 0x27 requests.
UDSErr_t UDSUnpackRDBIResponse(UDSClient_t *client, UDSRDBIVar_t *vars, uint16_t numVars)
Parse server's response to RDBI.
#define UDS_SERVER_DEFAULT_S3_MS
default S3 duration (ISO14229-2 2013 Table 5: 5000 -0/+200 ms)
UDSErr_t UDSUnpackRoutineControlResponse(const UDSClient_t *client, struct RoutineControlResponse *resp)
Parse server's response to RoutineControl.
UDSErr_t UDSSendSecurityAccess(UDSClient_t *client, uint8_t level, const uint8_t *data, uint16_t size)
Get Security Access.
unsigned int UDS_LogLevel_t
one of valid values for UDS_LOG_LEVEL
#define UDS_SERVER_DEFAULT_P2_STAR_MS
default P2* duration
UDSErr_t UDSClientTpIsoTpSockInit(UDSTpIsoTpSock_t *tp, const char *ifname, uint32_t source_addr, uint32_t target_addr, uint32_t target_addr_func)
for UDSClient_t
UDSErr_t UDSSendTransferData(UDSClient_t *client, uint8_t blockSequenceCounter, uint16_t blockLength, const uint8_t *data, uint16_t size)
Transfer Data to/from a buffer.
uint8_t UDS_A_TA_Type_t
private: oneof Uds_a_ta_type
UDSErr_t UDSSendRequestFileTransfer(UDSClient_t *client, uint8_t mode, const char *filePath, size_t filePathLen, size_t fileSizeUncompressed, size_t fileSizeCompressed)
filesystem-based frontend to TransferData
UDSErr_t UDSSendRoutineCtrl(UDSClient_t *client, uint8_t type, uint16_t routineIdentifier, const uint8_t *data, uint16_t size)
Request to Twiddle Routines.
UDSErr_t UDSClientTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t source_addr, uint32_t target_addr, uint32_t target_addr_func)
Initialize isotp-c transport for UDSClient_t.
UDSErr_t
Error Codes, including NRCs defined by the standard.
void UDSTpISOTpCSocketCANDeinit(UDSTpISOTpCSocketCAN_t *tp)
release socket
#define UDS_ISOTP_MTU
ISO-TP Maximum Transmission Unit (ISO-15764-2-2004 section 5.3.3).
UDSErr_t UDSUnpackRequestDownloadResponse(const UDSClient_t *client, struct RequestDownloadResponse *resp)
Parse server's response to RequestDownload.
UDSErr_t UDSCtrlDTCSetting(UDSClient_t *client, uint8_t dtcSettingType, const uint8_t *dtcSettingControlOptionRecord, uint16_t len)
control DTC setting
UDSErr_t UDSClientInit(UDSClient_t *client)
Call this once.
#define UDS_SERVER_DEFAULT_XFER_DATA_MAX_BLOCKLENGTH
#define UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_AUTH_FAIL_DELAY_MS
Amount of time to wait after an authentication failure before accepting another 0x27 request.
UDSErr_t UDSTpSend(UDSTp_t *hdl, const uint8_t *buf, size_t len, const UDSSDU_t *info)
Send to transport.
UDSErr_t UDSServerTpISOTpCSocketCANInit(UDSTpISOTpCSocketCAN_t *tp, const char *ifname, uint32_t source_addr, uint32_t target_addr, uint32_t source_addr_func)
Initialize isotp-c over SocketCAN transport for UDSServer_t.
UDSErr_t UDSSendDiagSessCtrl(UDSClient_t *client, uint8_t mode)
Change the diagnostic session.
#define UDS_ASSERT(x)
used to enforce runtime invariants within iso14229
UDSErr_t UDSClientPoll(UDSClient_t *client)
Call at <5ms intervals.
UDSErr_t UDSSendBytes(UDSClient_t *client, const uint8_t *data, uint16_t size)
Send user-defined bytes to a UDS server.
UDSErr_t UDSSendRDBI(UDSClient_t *client, const uint16_t *didList, uint16_t numDataIdentifiers)
Read Data By Identifier.
UDSErr_t UDSServerInit(UDSServer_t *srv)
call this once
void UDSTpIsoTpSockDeinit(const UDSTpIsoTpSock_t *tp)
release sockets
#define UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS
Request download response structure.
Routine control response structure.
const uint8_t * routineStatusRecord
size_t routineStatusRecordLength
uint16_t routineIdentifier
uint8_t routineControlType
Security access response structure.
uint8_t securityAccessType
size_t securitySeedLength
const uint8_t * securitySeed
Clear diagnostic information arguments.
uint8_t cfg_file_size_parameter_length
uint8_t cfg_data_format_identifier
unsigned cfg_ignore_srv_sess_timing
int(*) fn(struct UDSClient *client, UDSEvent_t evt, void *ev_data)
unsigned cfg_suppress_pos_resp
uint8_t send_buf[UDS_CLIENT_SEND_BUF_SIZE]
unsigned cfg_send_functional
uint8_t recv_buf[UDS_CLIENT_RECV_BUF_SIZE]
Communication control arguments.
Control DTC setting arguments.
Custom service arguments.
Dynamically define data identifier arguments.
union UDSDDDIArgs_t::@052263275324350175074117356122047100356070003133 subFuncArgs
Diagnostic session control arguments.
uint32_t powerDownTimeMillis
Input/output control by identifier arguments.
Read data by identifier arguments.
Read data by identifier variable structure.
void *(*) UnpackFn(void *dst, const void *src, size_t n)
Read DTC information arguments.
union UDSRDTCIArgs_t::@242172112264143020077310143126066111376236317004 subFuncArgs
Read memory by address arguments.
uint8_t send_buf[UDS_SERVER_SEND_BUF_SIZE]
uint8_t recv_buf[UDS_SERVER_RECV_BUF_SIZE]
Request download arguments.
uint16_t maxNumberOfBlockLength
Request file transfer arguments.
size_t fileSizeUnCompressed
size_t fileSizeCompressed
uint16_t maxNumberOfBlockLength
Request transfer exit arguments.
Request upload arguments.
uint16_t maxNumberOfBlockLength
Routine control arguments.
UDS_A_TA_Type_t A_TA_Type
Security access request seed arguments.
Security access validate key arguments.
uint32_t sec_access_auth_fail_timer
uint16_t p2_ms
Server time constants (milliseconds).
bool notReadyToReceive
UDS-1 2013 defines the following conditions under which the server does not process incoming requests...
uint32_t sec_access_boot_delay_timer
UDSErr_t(*) fn(struct UDSServer *srv, UDSEvent_t event, void *arg)
uint32_t s3_session_timeout_timer
uint8_t ecuResetScheduled
uint8_t xferBlockSequenceCounter
bool xferIsActive
UDS-1-2013: Table 407 - 0x36 TransferData Supported negative response codes requires that the server ...
isotp-c over SocketCAN implementation of UDSTp_t
isotp-c implementation of UDSTp_t
linux ISO-TP socket implementation of UDSTp_t
UDSErr_t(*) poll(struct UDSTp *hdl)
Poll the transport layer.
UDSErr_t(*) recv(struct UDSTp *hdl, uint8_t *buf, size_t bufsiz, size_t *recvlen, UDSSDU_t *info)
Receive data from the transport.
UDSErr_t(*) send(struct UDSTp *hdl, const uint8_t *buf, const size_t len, const UDSSDU_t *info)
Send data to the transport.
Write data by identifier arguments.
Write memory by address arguments.