11#line 1 "src/util_private.h"
16static inline void StoreBE(uint8_t *dst, uint64_t val,
size_t n) {
17 for (
size_t i = 0; i < n; i++) {
18 dst[i] = (uint8_t)(val >> (8 * (n - 1 - i)));
23static inline uint64_t LoadBE(
const uint8_t *src,
size_t n) {
25 for (
size_t i = 0; i < n; i++) {
26 val = (val << 8) | src[i];
50#define STATE_SENDING 1
51#define STATE_AWAIT_SEND_COMPLETE 2
52#define STATE_AWAIT_RESPONSE 3
57 return UDS_ERR_INVALID_ARG;
59 memset(client, 0,
sizeof(*client));
68 UDS_LOGE(__FILE__,
"p2_star_ms must be >= p2_ms");
75static const char *ClientStateName(uint8_t state) {
82 return "AwaitSendComplete";
84 return "AwaitResponse";
90static void changeState(
UDSClient_t *client, uint8_t state) {
91 if (state != client->
state) {
92 UDS_LOGV(__FILE__,
"client state: %s (%d) -> %s (%d)", ClientStateName(client->
state),
93 client->
state, ClientStateName(state), state);
95 client->
state = state;
122 return UDS_ERR_RESP_TOO_SHORT;
127 return UDS_ERR_RESP_TOO_SHORT;
129 return UDS_ERR_SID_MISMATCH;
130 }
else if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == client->
recv_buf[2]) {
138 return UDS_ERR_SID_MISMATCH;
140 if (client->
send_buf[0] == kSID_ECU_RESET) {
142 return UDS_ERR_RESP_TOO_SHORT;
144 return UDS_ERR_SUBFUNCTION_MISMATCH;
160 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == client->
recv_buf[2]) {
162 UDS_LOGI(__FILE__,
"got RCRRP, set p2 timer to %" PRIu32
"", client->
p2_timer);
166 return UDS_NRC_RequestCorrectlyReceived_ResponsePending;
171 uint8_t respSid = client->
recv_buf[0];
173 case kSID_DIAGNOSTIC_SESSION_CONTROL: {
174 if (client->
recv_size < UDS_0X10_RESP_LEN) {
175 UDS_LOGI(__FILE__,
"Error: SID %x response too short",
176 kSID_DIAGNOSTIC_SESSION_CONTROL);
178 return UDS_ERR_RESP_TOO_SHORT;
187 (uint16_t)(((uint16_t)client->
recv_buf[2] << 8) | (uint16_t)client->
recv_buf[3]);
189 UDS_LOGI(__FILE__,
"received new timings: p2: %" PRIu16
", p2*: %" PRIu32, p2, p2_star);
209 if (NULL == client || NULL == client->
tp || NULL == client->
tp->
poll) {
210 return UDS_ERR_MISUSE;
214 switch (client->
state) {
225 UDS_LOGE(__FILE__,
"transport returned error %" PRId32, len);
226 }
else if (len == 0) {
229 UDS_LOGW(__FILE__,
"received %" PRId32
" unexpected bytes:", len);
230 UDS_LOG_SDU(__FILE__, client->
recv_buf, len, &info);
238 : UDS_A_TA_TYPE_PHYSICAL;
240 .A_Mtype = UDS_A_MTYPE_DIAG,
241 .A_TA_Type = ta_type,
246 UDS_LOGI(__FILE__,
"tport err: %" PRId32, ret);
247 }
else if (0 == ret) {
248 UDS_LOGI(__FILE__,
"send in progress...");
253 err = UDS_ERR_BUFSIZ;
263 if (tp_status & UDS_TP_SEND_IN_PROGRESS) {
283 }
else if (0 == len) {
285 UDS_LOGI(__FILE__,
"p2 timeout");
286 err = UDS_ERR_TIMEOUT;
290 UDS_LOGD(__FILE__,
"received %" PRId32
" bytes. Processing...", len);
294 err = ValidateServerResponse(client);
296 err = HandleServerResponse(client);
323 UDSErr_t err = PollLowLevel(client);
328 if (NULL == client) {
329 return UDS_ERR_INVALID_ARG;
338 if (client->
tp == NULL) {
339 return UDS_ERR_TPORT;
345 UDSErr_t err = PreRequestCheck(client);
349 if (size >
sizeof(client->
send_buf)) {
350 return UDS_ERR_BUFSIZ;
352 memmove(client->
send_buf, data, size);
354 return SendRequest(client);
358 UDSErr_t err = PreRequestCheck(client);
362 client->
send_buf[0] = kSID_ECU_RESET;
365 return SendRequest(client);
369 UDSErr_t err = PreRequestCheck(client);
373 client->
send_buf[0] = kSID_DIAGNOSTIC_SESSION_CONTROL;
376 return SendRequest(client);
380 UDSErr_t err = PreRequestCheck(client);
384 client->
send_buf[0] = kSID_COMMUNICATION_CONTROL;
388 return SendRequest(client);
392 UDSErr_t err = PreRequestCheck(client);
396 client->
send_buf[0] = kSID_TESTER_PRESENT;
399 return SendRequest(client);
403 const uint16_t numDataIdentifiers) {
404 const uint16_t DID_LEN_BYTES = 2;
405 UDSErr_t err = PreRequestCheck(client);
409 if (NULL == didList || 0 == numDataIdentifiers) {
410 return UDS_ERR_INVALID_ARG;
412 client->
send_buf[0] = kSID_READ_DATA_BY_IDENTIFIER;
413 for (
int i = 0; i < numDataIdentifiers; i++) {
414 uint16_t offset = (uint16_t)(1 + DID_LEN_BYTES * i);
415 if ((
size_t)(offset + 2) >
sizeof(client->
send_buf)) {
416 return UDS_ERR_INVALID_ARG;
418 (client->
send_buf + offset)[0] = (didList[i] & 0xFF00) >> 8;
419 (client->
send_buf + offset)[1] = (didList[i] & 0xFF);
421 client->
send_size = 1 + (numDataIdentifiers * DID_LEN_BYTES);
422 return SendRequest(client);
427 UDSErr_t err = PreRequestCheck(client);
431 if (data == NULL || size == 0) {
432 return UDS_ERR_INVALID_ARG;
434 client->
send_buf[0] = kSID_WRITE_DATA_BY_IDENTIFIER;
436 return UDS_ERR_BUFSIZ;
438 client->
send_buf[1] = (dataIdentifier & 0xFF00) >> 8;
439 client->
send_buf[2] = (dataIdentifier & 0xFF);
440 memmove(&client->
send_buf[3], data, size);
442 return SendRequest(client);
457 const uint8_t *data, uint16_t size) {
458 UDSErr_t err = PreRequestCheck(client);
462 client->
send_buf[0] = kSID_ROUTINE_CONTROL;
464 client->
send_buf[2] = routineIdentifier >> 8;
465 client->
send_buf[3] = routineIdentifier & 0xFF;
468 return UDS_ERR_INVALID_ARG;
470 if (size >
sizeof(client->
send_buf) - UDS_0X31_REQ_MIN_LEN) {
471 return UDS_ERR_BUFSIZ;
473 memmove(&client->
send_buf[UDS_0X31_REQ_MIN_LEN], data, size);
476 UDS_LOGI(__FILE__,
"warning: size zero and data non-null");
479 client->
send_size = UDS_0X31_REQ_MIN_LEN + size;
480 return SendRequest(client);
495 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
497 UDSErr_t err = PreRequestCheck(client);
501 uint8_t numMemorySizeBytes = (addressAndLengthFormatIdentifier & 0xF0) >> 4;
502 uint8_t numMemoryAddressBytes = addressAndLengthFormatIdentifier & 0x0F;
504 client->
send_buf[0] = kSID_REQUEST_DOWNLOAD;
505 client->
send_buf[1] = dataFormatIdentifier;
506 client->
send_buf[2] = addressAndLengthFormatIdentifier;
508 uint8_t *ptr = &client->
send_buf[UDS_0X34_REQ_BASE_LEN];
510 for (
int i = numMemoryAddressBytes - 1; i >= 0; i--) {
511 *ptr = (uint8_t)((memoryAddress >> (8 * i)) & 0xFF);
515 for (
int i = numMemorySizeBytes - 1; i >= 0; i--) {
516 *ptr = (uint8_t)((memorySize >> (8 * i)) & 0xFF);
520 client->
send_size = UDS_0X34_REQ_BASE_LEN + numMemoryAddressBytes + numMemorySizeBytes;
521 return SendRequest(client);
536 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
538 UDSErr_t err = PreRequestCheck(client);
542 uint8_t numMemorySizeBytes = (addressAndLengthFormatIdentifier & 0xF0) >> 4;
543 uint8_t numMemoryAddressBytes = addressAndLengthFormatIdentifier & 0x0F;
545 client->
send_buf[0] = kSID_REQUEST_UPLOAD;
546 client->
send_buf[1] = dataFormatIdentifier;
547 client->
send_buf[2] = addressAndLengthFormatIdentifier;
549 uint8_t *ptr = &client->
send_buf[UDS_0X35_REQ_BASE_LEN];
551 for (
int i = numMemoryAddressBytes - 1; i >= 0; i--) {
552 *ptr = (uint8_t)((memoryAddress >> (8 * i)) & 0xFF);
556 for (
int i = numMemorySizeBytes - 1; i >= 0; i--) {
557 *ptr = (uint8_t)((memorySize >> (8 * i)) & 0xFF);
561 client->
send_size = UDS_0X35_REQ_BASE_LEN + numMemoryAddressBytes + numMemorySizeBytes;
562 return SendRequest(client);
576 const uint16_t blockLength,
const uint8_t *data, uint16_t size) {
577 UDSErr_t err = PreRequestCheck(client);
583 if (blockLength <= 2) {
584 return UDS_ERR_INVALID_ARG;
588 if (size > (blockLength - 2)) {
589 return UDS_ERR_INVALID_ARG;
591 client->
send_buf[0] = kSID_TRANSFER_DATA;
592 client->
send_buf[1] = blockSequenceCounter;
593 memmove(&client->
send_buf[UDS_0X36_REQ_BASE_LEN], data, size);
594 UDS_LOGI(__FILE__,
"size: %d, blocklength: %d", size, blockLength);
595 client->
send_size = UDS_0X36_REQ_BASE_LEN + size;
596 return SendRequest(client);
600 const uint16_t blockLength, FILE *fd) {
601 UDSErr_t err = PreRequestCheck(client);
606 if (blockLength <= 2) {
607 return UDS_ERR_INVALID_ARG;
609 client->
send_buf[0] = kSID_TRANSFER_DATA;
610 client->
send_buf[1] = blockSequenceCounter;
612 size_t _size = fread(&client->
send_buf[2], 1, blockLength - 2, fd);
614 uint16_t size = (uint16_t)_size;
615 UDS_LOGI(__FILE__,
"size: %d, blocklength: %d", size, blockLength);
616 client->
send_size = UDS_0X36_REQ_BASE_LEN + size;
617 return SendRequest(client);
628 UDSErr_t err = PreRequestCheck(client);
632 client->
send_buf[0] = kSID_REQUEST_TRANSFER_EXIT;
634 return SendRequest(client);
638 size_t fileSizeUncompressed,
size_t fileSizeCompressed) {
639 UDSErr_t err = PreRequestCheck(client);
643 if (filePath == NULL) {
644 return UDS_ERR_INVALID_ARG;
646 size_t filePathLenSize = strnlen(filePath, UINT16_MAX + 1);
647 if (filePathLenSize == 0) {
648 return UDS_ERR_INVALID_ARG;
650 if (filePathLenSize > UINT16_MAX) {
651 return UDS_ERR_INVALID_ARG;
653 uint16_t n_filePathLen = (uint16_t)filePathLenSize;
671 if (
sizeof(client->
send_buf) < UDS_0X38_REQ_BASE_LEN) {
672 return UDS_ERR_BUFSIZ;
675 size_t bufSizeRequired = SIZE_MAX;
676 client->
send_buf[0] = kSID_REQUEST_FILE_TRANSFER;
678 StoreBE(&client->
send_buf[2], n_filePathLen, 2);
683 if (bufSizeRequired >
sizeof(client->
send_buf)) {
684 return UDS_ERR_BUFSIZ;
686 memmove(&client->
send_buf[4], filePath, n_filePathLen);
689 StoreBE(&client->
send_buf[6 + n_filePathLen], fileSizeUncompressed,
695 bufSizeRequired = 4 + n_filePathLen + 1;
696 if (bufSizeRequired >
sizeof(client->
send_buf)) {
697 return UDS_ERR_BUFSIZ;
699 memmove(&client->
send_buf[4], filePath, n_filePathLen);
703 if (bufSizeRequired >
sizeof(client->
send_buf)) {
704 return UDS_ERR_BUFSIZ;
706 memmove(&client->
send_buf[4], filePath, n_filePathLen);
709 StoreBE(&client->
send_buf[6 + n_filePathLen], fileSizeUncompressed,
715 bufSizeRequired = 4 + n_filePathLen + 1;
716 if (bufSizeRequired >
sizeof(client->
send_buf)) {
717 return UDS_ERR_BUFSIZ;
719 memmove(&client->
send_buf[4], filePath, n_filePathLen);
723 bufSizeRequired = 4 + n_filePathLen;
724 if (bufSizeRequired >
sizeof(client->
send_buf)) {
725 return UDS_ERR_BUFSIZ;
727 memmove(&client->
send_buf[4], filePath, n_filePathLen);
731 if (bufSizeRequired >
sizeof(client->
send_buf)) {
732 return UDS_ERR_BUFSIZ;
734 memmove(&client->
send_buf[4], filePath, n_filePathLen);
737 StoreBE(&client->
send_buf[6 + n_filePathLen], fileSizeUncompressed,
748 client->
send_size = (uint16_t)bufSizeRequired;
749 return SendRequest(client);
764 UDSErr_t err = PreRequestCheck(client);
770 if (0x00 == dtcSettingType || 0x7F == dtcSettingType ||
771 (0x03 <= dtcSettingType && dtcSettingType <= 0x3F)) {
772 return UDS_ERR_INVALID_ARG;
775 client->
send_buf[0] = kSID_CONTROL_DTC_SETTING;
776 client->
send_buf[1] = dtcSettingType;
780 return UDS_ERR_INVALID_ARG;
784 UDS_LOGI(__FILE__,
"warning: size == 0 and data is non-null");
786 if (size >
sizeof(client->
send_buf) - 2) {
787 return UDS_ERR_BUFSIZ;
789 memmove(&client->
send_buf[2], data, size);
792 return SendRequest(client);
806 UDSErr_t err = PreRequestCheck(client);
811 return UDS_ERR_INVALID_ARG;
813 client->
send_buf[0] = kSID_SECURITY_ACCESS;
816 if (size >
sizeof(client->
send_buf) - UDS_0X27_REQ_BASE_LEN) {
817 return UDS_ERR_BUFSIZ;
819 if (size == 0 && NULL != data) {
820 UDS_LOGE(__FILE__,
"size == 0 and data is non-null");
821 return UDS_ERR_INVALID_ARG;
823 if (size > 0 && NULL == data) {
824 UDS_LOGE(__FILE__,
"size > 0 but data is null");
825 return UDS_ERR_INVALID_ARG;
828 memmove(&client->
send_buf[UDS_0X27_REQ_BASE_LEN], data, size);
831 client->
send_size = UDS_0X27_REQ_BASE_LEN + size;
832 return SendRequest(client);
845 if (NULL == client || NULL == resp) {
846 return UDS_ERR_INVALID_ARG;
849 return UDS_ERR_SID_MISMATCH;
851 if (client->
recv_size < UDS_0X27_RESP_BASE_LEN) {
852 return UDS_ERR_RESP_TOO_SHORT;
870 if (NULL == client || NULL == resp) {
871 return UDS_ERR_INVALID_ARG;
874 return UDS_ERR_SID_MISMATCH;
876 if (client->
recv_size < UDS_0X31_RESP_MIN_LEN) {
877 return UDS_ERR_RESP_TOO_SHORT;
881 (uint16_t)((uint16_t)(client->
recv_buf[2] << 8) | (uint16_t)client->
recv_buf[3]);
898 if (NULL == client || NULL == resp) {
899 return UDS_ERR_INVALID_ARG;
902 return UDS_ERR_SID_MISMATCH;
904 if (client->
recv_size < UDS_0X34_RESP_BASE_LEN) {
905 return UDS_ERR_RESP_TOO_SHORT;
907 uint8_t maxNumberOfBlockLengthSize = (client->
recv_buf[1] & 0xF0) >> 4;
910 UDS_LOGI(__FILE__,
"WARNING: sizeof(maxNumberOfBlockLength) > sizeof(size_t)");
914 for (uint8_t byteIdx = 0; byteIdx < maxNumberOfBlockLengthSize; byteIdx++) {
915 uint8_t
byte = client->
recv_buf[UDS_0X34_RESP_BASE_LEN + byteIdx];
916 uint8_t shiftBytes = maxNumberOfBlockLengthSize - 1 - byteIdx;
923 if (NULL == client->
fn) {
924 return UDS_ERR_MISUSE;
927 UDSErr_t err = PollLowLevel(client);
929 if (err == UDS_OK || err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
941 uint16_t offset = UDS_0X22_RESP_BASE_LEN;
942 if (client == NULL || vars == NULL) {
943 return UDS_ERR_INVALID_ARG;
945 for (
int i = 0; i < numVars; i++) {
947 if (offset +
sizeof(uint16_t) > client->
recv_size) {
948 return UDS_ERR_RESP_TOO_SHORT;
950 uint16_t did = (uint16_t)((uint16_t)(client->
recv_buf[offset] << 8) |
951 (uint16_t)client->
recv_buf[offset + 1]);
952 if (did != vars[i].did) {
953 return UDS_ERR_DID_MISMATCH;
955 if (offset +
sizeof(uint16_t) + vars[i].len > client->
recv_size) {
956 return UDS_ERR_RESP_TOO_SHORT;
958 if (vars[i].UnpackFn) {
959 vars[i].
UnpackFn(vars[i].data, client->
recv_buf + offset +
sizeof(uint16_t),
962 return UDS_ERR_INVALID_ARG;
964 offset +=
sizeof(uint16_t) + vars[i].len;
971#line 1 "src/server.c"
976 if (nrc < 0 || nrc > 0xFF) {
977 UDS_LOGW(__FILE__,
"Invalid negative response code: %d (0x%x)", nrc, nrc);
978 nrc = UDS_NRC_GeneralReject;
993 err = srv->
fn(srv, evt, data);
995 UDS_LOGI(__FILE__,
"Unhandled UDSEvent %d, srv.fn not installed!\n", evt);
996 err = UDS_NRC_GeneralReject;
999 UDS_LOGW(__FILE__,
"The returned error code %d (0x%x) is not a negative response code", err,
1006 if (r->
recv_len < UDS_0X10_REQ_LEN) {
1007 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1010 uint8_t sessType = r->
recv_buf[1] & 0x7F;
1020 if (UDS_PositiveResponse != err) {
1021 return NegativeResponse(r, err);
1049 return UDS_PositiveResponse;
1053 if (r->
recv_len < UDS_0X11_REQ_MIN_LEN) {
1054 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1057 uint8_t resetType = r->
recv_buf[1] & 0x3F;
1066 if (UDS_PositiveResponse == err) {
1071 return NegativeResponse(r, err);
1079 if (powerDownTime > 255) {
1080 powerDownTime = 255;
1082 r->
send_buf[2] = powerDownTime & 0xFF;
1083 r->
send_len = UDS_0X11_RESP_BASE_LEN + 1;
1085 r->
send_len = UDS_0X11_RESP_BASE_LEN;
1087 return UDS_PositiveResponse;
1091 if (r->
recv_len < UDS_0X14_REQ_MIN_LEN) {
1092 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1096 r->
send_len = UDS_0X14_RESP_BASE_LEN;
1100 .hasMemorySelection = (r->
recv_len >= 5),
1106 if (err != UDS_PositiveResponse) {
1107 return NegativeResponse(r, err);
1110 return UDS_PositiveResponse;
1113static uint8_t safe_copy(
UDSServer_t *srv,
const void *src, uint16_t count) {
1115 return UDS_NRC_GeneralReject;
1118 return UDS_NRC_GeneralReject;
1124 return UDS_PositiveResponse;
1126 return UDS_NRC_ResponseTooLong;
1130 UDSErr_t ret = UDS_PositiveResponse;
1133 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN) {
1134 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1140 r->
send_len = UDS_0X19_RESP_BASE_LEN;
1150 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1151 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1157 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1158 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1174 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 4) {
1175 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1178 args.
subFuncArgs.dtcSnapshotRecordbyDTCNumArgs.dtc =
1185 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1186 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1192 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 4) {
1193 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1196 args.
subFuncArgs.dtcExtDtaRecordByDTCNumArgs.dtc =
1202 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1203 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1210 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1211 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1218 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1219 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1226 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 5) {
1227 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1230 args.
subFuncArgs.userDefMemDTCSnapshotRecordByDTCNumArgs.dtc =
1236 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 5) {
1237 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1240 args.
subFuncArgs.userDefMemDTCExtDataRecordByDTCNumArgs.dtc =
1246 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 3) {
1247 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1255 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1256 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1262 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1263 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1270 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1275 if (UDS_PositiveResponse != ret) {
1276 return NegativeResponse(r, ret);
1279 if (r->
send_len < UDS_0X19_RESP_BASE_LEN) {
1280 goto respond_to_0x19_malformed_response;
1287 if (r->
send_len != UDS_0X19_RESP_BASE_LEN + 4) {
1288 goto respond_to_0x19_malformed_response;
1298 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1299 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1300 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 1)) % 4 != 0)) {
1301 goto respond_to_0x19_malformed_response;
1306 if ((r->
send_len - UDS_0X19_RESP_BASE_LEN) % 4 != 0) {
1307 goto respond_to_0x19_malformed_response;
1312 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4) {
1313 goto respond_to_0x19_malformed_response;
1318 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1) {
1319 goto respond_to_0x19_malformed_response;
1324 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1325 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1326 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 1)) % 6 != 0)) {
1327 goto respond_to_0x19_malformed_response;
1331 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 2 ||
1332 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 2) &&
1333 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 2)) % 4 != 0)) {
1334 goto respond_to_0x19_malformed_response;
1339 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 5) {
1340 goto respond_to_0x19_malformed_response;
1344 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1345 ((r->
send_len != UDS_0X19_RESP_BASE_LEN + 6) &&
1346 (r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1347 (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4)) ||
1348 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 6) &&
1349 (r->
send_len - UDS_0X19_RESP_BASE_LEN + 6) % 4 != 0)) {
1350 goto respond_to_0x19_malformed_response;
1354 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4 ||
1355 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 4) &&
1356 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 4)) % 5 != 0)) {
1357 goto respond_to_0x19_malformed_response;
1361 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 3 ||
1362 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 3) &&
1363 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 3)) % 4 != 0)) {
1364 goto respond_to_0x19_malformed_response;
1368 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4 ||
1369 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 4) &&
1370 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 4)) % 4 != 0)) {
1371 goto respond_to_0x19_malformed_response;
1375 UDS_LOGW(__FILE__,
"RDTCI subFunc 0x%02X is not supported.\n", type);
1376 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1379 return UDS_PositiveResponse;
1380respond_to_0x19_malformed_response:
1381 UDS_LOGE(__FILE__,
"RDTCI subFunc 0x%02X is malformed. Length: %zu\n", type, r->
send_len);
1382 return NegativeResponse(r, UDS_NRC_GeneralReject);
1387 uint16_t dataId = 0;
1388 UDSErr_t ret = UDS_PositiveResponse;
1392 if (0 != (r->
recv_len - 1) %
sizeof(uint16_t)) {
1393 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1396 numDIDs = (uint8_t)(r->
recv_len /
sizeof(uint16_t));
1399 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1402 for (uint16_t did = 0; did < numDIDs; did++) {
1403 uint16_t idx = (uint16_t)(1 + did * 2);
1404 dataId = (uint16_t)((uint16_t)(r->
recv_buf[idx] << 8) | (uint16_t)r->
recv_buf[idx + 1]);
1407 return NegativeResponse(r, UDS_NRC_ResponseTooLong);
1410 copylocation[0] = dataId >> 8;
1411 copylocation[1] = dataId & 0xFF;
1419 size_t send_len_before = r->
send_len;
1421 if (ret == UDS_PositiveResponse && send_len_before == r->
send_len) {
1422 UDS_LOGE(__FILE__,
"RDBI response positive but no data sent\n");
1423 return NegativeResponse(r, UDS_NRC_GeneralReject);
1426 if (UDS_PositiveResponse != ret) {
1427 return NegativeResponse(r, ret);
1430 return UDS_PositiveResponse;
1445static UDSErr_t decodeAddressAndLengthWithOffset(
UDSReq_t *r, uint8_t *
const buf,
1446 void **memoryAddress,
size_t *memorySize,
1458 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1461 uint8_t memorySizeLength = (buf[0] & 0xF0) >> 4;
1462 uint8_t memoryAddressLength = buf[0] & 0x0F;
1463 size_t offsetBytes = offset * (memoryAddressLength + memorySizeLength);
1465 if (memorySizeLength == 0 || memorySizeLength >
sizeof(
size_t)) {
1466 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1469 if (memoryAddressLength == 0 || memoryAddressLength >
sizeof(
size_t)) {
1470 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1473 if (buf + 1 + offsetBytes + memorySizeLength + memoryAddressLength >
1475 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1478 for (
int byteIdx = 0; byteIdx < memoryAddressLength; byteIdx++) {
1479 long long unsigned int byte = buf[1 + offsetBytes + byteIdx];
1480 uint8_t shiftBytes = (uint8_t)(memoryAddressLength - 1 - byteIdx);
1481 tmp |=
byte << (8 * shiftBytes);
1483 *memoryAddress = (
void *)tmp;
1485 for (
int byteIdx = 0; byteIdx < memorySizeLength; byteIdx++) {
1486 uint8_t
byte = buf[1 + offsetBytes + memoryAddressLength + byteIdx];
1487 uint8_t shiftBytes = (uint8_t)(memorySizeLength - 1 - byteIdx);
1488 *memorySize |= (size_t)
byte << (8 * shiftBytes);
1490 return UDS_PositiveResponse;
1503static UDSErr_t decodeAddressAndLength(
UDSReq_t *r, uint8_t *
const buf,
void **memoryAddress,
1504 size_t *memorySize) {
1505 return decodeAddressAndLengthWithOffset(r, buf, memoryAddress, memorySize, 0);
1509 UDSErr_t ret = UDS_PositiveResponse;
1513 if (r->
recv_len < UDS_0X23_REQ_MIN_LEN) {
1514 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1517 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
1518 if (UDS_PositiveResponse != ret) {
1519 return NegativeResponse(r, ret);
1529 r->
send_len = UDS_0X23_RESP_BASE_LEN;
1531 if (UDS_PositiveResponse != ret) {
1532 return NegativeResponse(r, ret);
1534 if (r->
send_len != UDS_0X23_RESP_BASE_LEN + length) {
1535 UDS_LOGE(__FILE__,
"response positive but not all data sent: expected %zu, sent %zu",
1536 length, r->
send_len - UDS_0X23_RESP_BASE_LEN);
1537 return NegativeResponse(r, UDS_NRC_GeneralReject);
1539 return UDS_PositiveResponse;
1543 uint8_t subFunction = r->
recv_buf[1];
1544 UDSErr_t response = UDS_PositiveResponse;
1547 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1551 return NegativeResponse(r, UDS_NRC_RequiredTimeDelayNotExpired);
1555 return NegativeResponse(r, UDS_NRC_ExceedNumberOfAttempts);
1560 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1563 if (0 == subFunction % 2) {
1564 uint8_t requestedLevel = subFunction - 1;
1566 .level = requestedLevel,
1567 .key = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1568 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1573 if (UDS_PositiveResponse != response) {
1576 return NegativeResponse(r, response);
1584 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1585 return UDS_PositiveResponse;
1600 const uint8_t already_unlocked[] = {0x00, 0x00};
1601 return safe_copy(srv, already_unlocked,
sizeof(already_unlocked));
1604 .level = subFunction,
1605 .dataRecord = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1606 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1607 .copySeed = safe_copy,
1612 if (UDS_PositiveResponse != response) {
1613 return NegativeResponse(r, response);
1616 if (r->
send_len <= UDS_0X27_RESP_BASE_LEN) {
1617 UDS_LOGE(__FILE__,
"0x27: no seed data was copied");
1618 return NegativeResponse(r, UDS_NRC_GeneralReject);
1620 return UDS_PositiveResponse;
1626 uint8_t controlType = r->
recv_buf[1] & 0x7F;
1627 uint8_t communicationType = r->
recv_buf[2];
1629 if (r->
recv_len < UDS_0X28_REQ_BASE_LEN) {
1630 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1634 .ctrlType = controlType,
1635 .commType = communicationType,
1640 if (r->
recv_len < UDS_0X28_REQ_BASE_LEN + 2) {
1641 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1647 if (UDS_PositiveResponse != err) {
1648 return NegativeResponse(r, err);
1654 return UDS_PositiveResponse;
1658 UDSErr_t ret = UDS_PositiveResponse;
1661 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN) {
1662 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1670 r->
send_len = UDS_0X2C_RESP_BASE_LEN + 2;
1674 .allDataIds =
false,
1676 (uint16_t)((uint16_t)r->
recv_buf[2] << 8 | (uint16_t)r->
recv_buf[3]) & 0xFFFF,
1685 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN + 2 + 4 ||
1686 (r->
recv_len - (UDS_0X2C_REQ_MIN_LEN + 2)) % 4 != 0) {
1687 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1690 size_t numDIDs = (r->
recv_len - 4) / 4;
1692 for (
size_t i = 0; i < numDIDs; i++) {
1694 (uint16_t)((uint16_t)r->
recv_buf[4 + i * 4] << 8 |
1695 (uint16_t)r->
recv_buf[5 + i * 4]) &
1702 if (UDS_PositiveResponse != ret) {
1703 return NegativeResponse(r, ret);
1707 return UDS_PositiveResponse;
1716 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN + 5) {
1717 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1720 size_t bytesPerAddrAndSize = ((r->
recv_buf[4] & 0xF0) >> 4) + (r->
recv_buf[4] & 0x0F);
1722 if (bytesPerAddrAndSize == 0) {
1724 "DDDI: define By Memory Address request with invalid "
1725 "AddressAndLengthFormatIdentifier: 0x%02X\n",
1727 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1730 if ((r->
recv_len - 5) % bytesPerAddrAndSize != 0) {
1731 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1734 size_t numAddrs = (r->
recv_len - 5) / bytesPerAddrAndSize;
1736 for (
size_t i = 0; i < numAddrs; i++) {
1737 ret = decodeAddressAndLengthWithOffset(r, &r->
recv_buf[4],
1741 if (UDS_PositiveResponse != ret) {
1742 return NegativeResponse(r, ret);
1747 if (UDS_PositiveResponse != ret) {
1748 return NegativeResponse(r, ret);
1752 return UDS_PositiveResponse;
1757 if (r->
recv_len == UDS_0X2C_REQ_MIN_LEN) {
1759 r->
send_len = UDS_0X2C_RESP_BASE_LEN;
1763 if (UDS_PositiveResponse != ret) {
1764 return NegativeResponse(r, ret);
1767 return UDS_PositiveResponse;
1770 UDS_LOGW(__FILE__,
"Unsupported DDDI subFunc 0x%02X\n", type);
1771 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1776 uint16_t dataLen = 0;
1777 uint16_t dataId = 0;
1778 UDSErr_t err = UDS_PositiveResponse;
1781 if (r->
recv_len < UDS_0X2E_REQ_MIN_LEN) {
1782 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1785 dataId = (uint16_t)((uint16_t)(r->
recv_buf[1] << 8) | (uint16_t)r->
recv_buf[2]);
1786 dataLen = (uint16_t)(r->
recv_len - UDS_0X2E_REQ_BASE_LEN);
1790 .data = &r->
recv_buf[UDS_0X2E_REQ_BASE_LEN],
1795 if (UDS_PositiveResponse != err) {
1796 return NegativeResponse(r, err);
1803 return UDS_PositiveResponse;
1807 if (r->
recv_len < UDS_0X2F_REQ_MIN_LEN) {
1808 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1815 r->
send_len = UDS_0X2F_RESP_BASE_LEN;
1820 .ctrlStateAndMask = &r->
recv_buf[UDS_0X2F_REQ_MIN_LEN],
1821 .ctrlStateAndMaskLen = r->
recv_len - UDS_0X2F_REQ_MIN_LEN,
1827 if (err != UDS_PositiveResponse) {
1828 return NegativeResponse(r, err);
1831 return UDS_PositiveResponse;
1835 UDSErr_t err = UDS_PositiveResponse;
1836 if (r->
recv_len < UDS_0X31_REQ_MIN_LEN) {
1837 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1840 uint8_t routineControlType = r->
recv_buf[1] & 0x7F;
1841 uint16_t routineIdentifier =
1845 .ctrlType = routineControlType,
1846 .id = routineIdentifier,
1847 .optionRecord = &r->
recv_buf[UDS_0X31_REQ_MIN_LEN],
1848 .len = (uint16_t)(r->
recv_len - UDS_0X31_REQ_MIN_LEN),
1849 .copyStatusRecord = safe_copy,
1853 r->
send_buf[1] = routineControlType;
1854 r->
send_buf[2] = routineIdentifier >> 8;
1855 r->
send_buf[3] = routineIdentifier & 0xFF;
1856 r->
send_len = UDS_0X31_RESP_MIN_LEN;
1858 switch (routineControlType) {
1863 if (UDS_PositiveResponse != err) {
1864 return NegativeResponse(r, err);
1868 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1870 return UDS_PositiveResponse;
1881static void BeginTransfer(
UDSServer_t *srv,
size_t xferTotalBytes,
size_t xferBlockLength) {
1891 UDSErr_t err = UDS_PositiveResponse;
1892 void *memoryAddress = 0;
1893 size_t memorySize = 0;
1896 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
1899 if (r->
recv_len < UDS_0X34_REQ_BASE_LEN) {
1900 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1903 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
1904 if (UDS_PositiveResponse != err) {
1905 return NegativeResponse(r, err);
1909 .addr = memoryAddress,
1911 .dataFormatIdentifier = r->
recv_buf[1],
1918 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
1919 return NegativeResponse(r, UDS_NRC_GeneralReject);
1922 if (UDS_PositiveResponse != err) {
1923 return NegativeResponse(r, err);
1943 r->
send_buf[1] = lengthFormatIdentifier;
1947 r->
send_buf[UDS_0X34_RESP_BASE_LEN + idx] = byte;
1950 return UDS_PositiveResponse;
1954 UDSErr_t err = UDS_PositiveResponse;
1955 void *memoryAddress = 0;
1956 size_t memorySize = 0;
1959 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
1962 if (r->
recv_len < UDS_0X35_REQ_BASE_LEN) {
1963 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1966 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
1967 if (UDS_PositiveResponse != err) {
1968 return NegativeResponse(r, err);
1972 .addr = memoryAddress,
1974 .dataFormatIdentifier = r->
recv_buf[1],
1981 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
1982 return NegativeResponse(r, UDS_NRC_GeneralReject);
1985 if (UDS_PositiveResponse != err) {
1986 return NegativeResponse(r, err);
1994 r->
send_buf[1] = lengthFormatIdentifier;
1998 return UDS_PositiveResponse;
2002 UDSErr_t err = UDS_PositiveResponse;
2003 uint8_t blockSequenceCounter = 0;
2006 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
2009 if (r->
recv_len < UDS_0X36_REQ_BASE_LEN) {
2010 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2014 uint16_t request_data_len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN);
2015 blockSequenceCounter = r->
recv_buf[1];
2019 err = UDS_NRC_RequestSequenceError;
2027 err = UDS_NRC_TransferDataSuspended;
2033 .data = &r->
recv_buf[UDS_0X36_REQ_BASE_LEN],
2034 .len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN),
2035 .maxRespLen = (uint16_t)(srv->
xferBlockLength - UDS_0X36_RESP_BASE_LEN),
2036 .copyResponse = safe_copy,
2040 r->
send_buf[1] = blockSequenceCounter;
2041 r->
send_len = UDS_0X36_RESP_BASE_LEN;
2045 if (err == UDS_PositiveResponse) {
2047 return UDS_PositiveResponse;
2048 }
else if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
2049 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
2057 return NegativeResponse(r, err);
2061 UDSErr_t err = UDS_PositiveResponse;
2064 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
2068 r->
send_len = UDS_0X37_RESP_BASE_LEN;
2071 .data = &r->
recv_buf[UDS_0X37_REQ_BASE_LEN],
2072 .len = (uint16_t)(r->
recv_len - UDS_0X37_REQ_BASE_LEN),
2073 .copyResponse = safe_copy,
2078 if (err == UDS_PositiveResponse) {
2080 return UDS_PositiveResponse;
2081 }
else if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
2082 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
2085 return NegativeResponse(r, err);
2090 UDSErr_t err = UDS_PositiveResponse;
2093 err = UDS_NRC_ConditionsNotCorrect;
2096 if (r->
recv_len < UDS_0X38_REQ_BASE_LEN) {
2097 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2101 const uint8_t mode_of_operation = r->
recv_buf[1];
2103 switch (mode_of_operation) {
2112 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2116 const uint16_t file_path_len = (uint16_t)LoadBE(&r->
recv_buf[2], 2);
2117 uint8_t data_format_identifier = 0;
2118 uint8_t file_size_parameter_length = 0;
2119 size_t file_size_uncompressed = 0;
2120 size_t file_size_compressed = 0;
2121 uint16_t byte_idx = 4 + file_path_len;
2124 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2133 data_format_identifier = r->
recv_buf[byte_idx];
2144 file_size_parameter_length = r->
recv_buf[byte_idx];
2147 static_assert(
sizeof(file_size_uncompressed) ==
sizeof(file_size_compressed),
2148 "Both should be k-byte numbers per Table 480");
2149 if (file_size_parameter_length >
sizeof(file_size_compressed)) {
2150 err = UDS_NRC_RequestOutOfRange;
2155 if ((
size_t)byte_idx + 2 * file_size_parameter_length > r->
recv_len) {
2156 err = UDS_NRC_RequestOutOfRange;
2159 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2160 uint8_t data_byte = r->
recv_buf[byte_idx];
2161 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2162 file_size_uncompressed |= (size_t)data_byte << (8 * shift_by_bytes);
2165 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2166 uint8_t data_byte = r->
recv_buf[byte_idx];
2167 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2168 file_size_compressed |= (size_t)data_byte << (8 * shift_by_bytes);
2174 .modeOfOperation = mode_of_operation,
2175 .filePathLen = file_path_len,
2176 .filePath = file_path_len == 0 ? NULL : &r->
recv_buf[4],
2177 .dataFormatIdentifier = data_format_identifier,
2178 .fileSizeUnCompressed = file_size_uncompressed,
2179 .fileSizeCompressed = file_size_compressed,
2186 if (UDS_PositiveResponse != err) {
2191 r->
send_buf[1] = mode_of_operation;
2199 UDS_LOGW(__FILE__,
"Clamping maxNumberOfBlockLength %hu to %hu",
2257 UDSErr_t ret = UDS_PositiveResponse;
2261 if (r->
recv_len < UDS_0X3D_REQ_MIN_LEN) {
2262 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2265 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
2266 if (UDS_PositiveResponse != ret) {
2267 return NegativeResponse(r, ret);
2270 uint8_t memorySizeLength = (r->
recv_buf[1] & 0xF0) >> 4;
2271 uint8_t memoryAddressLength = r->
recv_buf[1] & 0x0F;
2273 uint8_t dataOffset = 2 + memorySizeLength + memoryAddressLength;
2275 if (dataOffset + length != r->
recv_len) {
2276 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2286 if (UDS_PositiveResponse != ret) {
2287 return NegativeResponse(r, ret);
2292 memcpy(&r->
send_buf[1], &r->
recv_buf[1], 1 + memorySizeLength + memoryAddressLength);
2293 r->
send_len = UDS_0X3D_RESP_BASE_LEN + memorySizeLength + memoryAddressLength;
2294 return UDS_PositiveResponse;
2298 if ((r->
recv_len < UDS_0X3E_REQ_MIN_LEN) || (r->
recv_len > UDS_0X3E_REQ_MAX_LEN)) {
2299 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2301 uint8_t zeroSubFunction = r->
recv_buf[1];
2303 switch (zeroSubFunction) {
2310 return UDS_PositiveResponse;
2312 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
2318 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2319 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2322 uint8_t type = r->
recv_buf[1] & 0x7F;
2326 .data = r->
recv_len > UDS_0X85_REQ_BASE_LEN ? &r->
recv_buf[UDS_0X85_REQ_BASE_LEN] : NULL,
2327 .len = r->
recv_len > UDS_0X85_REQ_BASE_LEN ? r->
recv_len - UDS_0X85_REQ_BASE_LEN : 0,
2331 if (UDS_PositiveResponse != ret) {
2332 return NegativeResponse(r, ret);
2338 return UDS_PositiveResponse;
2342 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2343 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2346 uint8_t type = r->
recv_buf[1] & 0x7F;
2348 if (type == 0x03 && (r->
recv_buf[1] & 0x80) == 0 &&
2350 UDS_LOGW(__FILE__,
"0x87 LinkControl: Transitioning mode without suppressing response!");
2360 .len = (r->
recv_len - UDS_0X87_REQ_BASE_LEN),
2361 .data = &r->
recv_buf[UDS_0X87_REQ_BASE_LEN],
2365 if (ret != UDS_PositiveResponse) {
2366 return NegativeResponse(r, ret);
2369 return UDS_PositiveResponse;
2380static UDSService getServiceForSID(uint8_t sid) {
2382 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2383 return &Handle_0x10_DiagnosticSessionControl;
2384 case kSID_ECU_RESET:
2385 return &Handle_0x11_ECUReset;
2386 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2387 return &Handle_0x14_ClearDiagnosticInformation;
2388 case kSID_READ_DTC_INFORMATION:
2389 return Handle_0x19_ReadDTCInformation;
2390 case kSID_READ_DATA_BY_IDENTIFIER:
2391 return &Handle_0x22_ReadDataByIdentifier;
2392 case kSID_READ_MEMORY_BY_ADDRESS:
2393 return &Handle_0x23_ReadMemoryByAddress;
2394 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2396 case kSID_SECURITY_ACCESS:
2397 return &Handle_0x27_SecurityAccess;
2398 case kSID_COMMUNICATION_CONTROL:
2399 return &Handle_0x28_CommunicationControl;
2400 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2402 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2403 return &Handle_0x2C_DynamicDefineDataIdentifier;
2404 case kSID_WRITE_DATA_BY_IDENTIFIER:
2405 return &Handle_0x2E_WriteDataByIdentifier;
2406 case kSID_IO_CONTROL_BY_IDENTIFIER:
2407 return &Handle_0x2F_IOControlByIdentifier;
2408 case kSID_ROUTINE_CONTROL:
2409 return &Handle_0x31_RoutineControl;
2410 case kSID_REQUEST_DOWNLOAD:
2411 return &Handle_0x34_RequestDownload;
2412 case kSID_REQUEST_UPLOAD:
2413 return &Handle_0x35_RequestUpload;
2414 case kSID_TRANSFER_DATA:
2415 return &Handle_0x36_TransferData;
2416 case kSID_REQUEST_TRANSFER_EXIT:
2417 return &Handle_0x37_RequestTransferExit;
2418 case kSID_REQUEST_FILE_TRANSFER:
2419 return &Handle_0x38_RequestFileTransfer;
2420 case kSID_WRITE_MEMORY_BY_ADDRESS:
2421 return &Handle_0x3D_WriteMemoryByAddress;
2422 case kSID_TESTER_PRESENT:
2423 return &Handle_0x3E_TesterPresent;
2424 case kSID_ACCESS_TIMING_PARAMETER:
2426 case kSID_SECURED_DATA_TRANSMISSION:
2428 case kSID_CONTROL_DTC_SETTING:
2429 return &Handle_0x85_ControlDTCSetting;
2430 case kSID_RESPONSE_ON_EVENT:
2432 case kSID_LINK_CONTROL:
2433 return &Handle_0x87_LinkControl;
2435 UDS_LOGI(__FILE__,
"no handler for request SID %x", sid);
2448 UDSErr_t response = UDS_PositiveResponse;
2449 bool suppressResponse =
false;
2453 if (NULL == srv->
fn)
2454 return NegativeResponse(r, UDS_NRC_ServiceNotSupported);
2460 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2461 case kSID_ECU_RESET:
2462 case kSID_SECURITY_ACCESS:
2463 case kSID_COMMUNICATION_CONTROL:
2464 case kSID_ROUTINE_CONTROL:
2465 case kSID_TESTER_PRESENT:
2466 case kSID_CONTROL_DTC_SETTING:
2467 case kSID_LINK_CONTROL: {
2469 response = service(srv, r);
2471 bool suppressPosRspMsgIndicationBit = r->
recv_buf[1] & 0x80;
2474 if (suppressPosRspMsgIndicationBit && (response == UDS_PositiveResponse) &&
2478 suppressResponse =
true;
2480 suppressResponse =
false;
2487 case kSID_READ_DATA_BY_IDENTIFIER:
2488 case kSID_READ_MEMORY_BY_ADDRESS:
2489 case kSID_WRITE_DATA_BY_IDENTIFIER:
2490 case kSID_REQUEST_DOWNLOAD:
2491 case kSID_REQUEST_UPLOAD:
2492 case kSID_TRANSFER_DATA:
2493 case kSID_REQUEST_FILE_TRANSFER:
2494 case kSID_REQUEST_TRANSFER_EXIT: {
2496 response = service(srv, r);
2501 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2502 case kSID_READ_DTC_INFORMATION:
2503 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2504 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2505 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2506 case kSID_IO_CONTROL_BY_IDENTIFIER:
2507 case kSID_WRITE_MEMORY_BY_ADDRESS:
2508 case kSID_ACCESS_TIMING_PARAMETER:
2509 case kSID_SECURED_DATA_TRANSMISSION:
2510 case kSID_RESPONSE_ON_EVENT:
2513 response = service(srv, r);
2518 .len = (uint16_t)(r->
recv_len - 1),
2519 .copyResponse = safe_copy,
2526 if (UDS_PositiveResponse != response)
2527 return NegativeResponse(r, response);
2534 ((UDS_NRC_ServiceNotSupported == response) ||
2535 (UDS_NRC_SubFunctionNotSupported == response) ||
2536 (UDS_NRC_ServiceNotSupportedInActiveSession == response) ||
2537 (UDS_NRC_SubFunctionNotSupportedInActiveSession == response) ||
2538 (UDS_NRC_RequestOutOfRange == response)) &&
2543 suppressResponse =
true;
2546 if (suppressResponse) {
2560 return UDS_ERR_INVALID_ARG;
2597 UDSErr_t response = evaluateServiceResponse(srv, r);
2598 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2621 UDS_LOGE(__FILE__,
"UDSTpSend failed with %" PRId32
"\n", ret);
2627 uint32_t wait_time = srv->
p2_star_ms * 3 / 10;
2641 UDS_LOGE(__FILE__,
"UDSTpRecv failed with %zd\n", r->
recv_len);
2648 UDSErr_t response = evaluateServiceResponse(srv, r);
2650 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2665 return hdl->
send(hdl, (uint8_t *)buf, len, info);
2671 return hdl->
recv(hdl, buf, bufsize, info);
2677 return hdl->
poll(hdl);
2684#if defined(UDS_CUSTOM_MILLIS)
2688#if UDS_SYS == UDS_SYS_UNIX
2690 gettimeofday(&te, NULL);
2691 long long milliseconds = (te.tv_sec * 1000LL) + (te.tv_usec / 1000);
2692 return (uint32_t)milliseconds;
2693#elif UDS_SYS == UDS_SYS_WINDOWS
2695 timespec_get(&ts, TIME_UTC);
2696 long long milliseconds = ts.tv_sec * 1000LL + ts.tv_nsec / 1000000;
2697 return (uint32_t)milliseconds;
2698#elif UDS_SYS == UDS_SYS_ARDUINO
2700#elif UDS_SYS == UDS_SYS_ESP32
2701 return esp_timer_get_time() / 1000;
2703#error "UDSMillis not implemented for this UDS_SYS"
2709 uint8_t securityLevel = subFunction & 0x3F;
2710 if (0u == securityLevel) {
2713 if ((securityLevel >= 0x43u) && (securityLevel <= 0x5Eu)) {
2716 if (securityLevel == 0x7Fu) {
2722const char *UDSErrToStr(
UDSErr_t err) {
2728 case UDS_NRC_GeneralReject:
2729 return "UDS_NRC_GeneralReject";
2730 case UDS_NRC_ServiceNotSupported:
2731 return "UDS_NRC_ServiceNotSupported";
2732 case UDS_NRC_SubFunctionNotSupported:
2733 return "UDS_NRC_SubFunctionNotSupported";
2734 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2735 return "UDS_NRC_IncorrectMessageLengthOrInvalidFormat";
2736 case UDS_NRC_ResponseTooLong:
2737 return "UDS_NRC_ResponseTooLong";
2738 case UDS_NRC_BusyRepeatRequest:
2739 return "UDS_NRC_BusyRepeatRequest";
2740 case UDS_NRC_ConditionsNotCorrect:
2741 return "UDS_NRC_ConditionsNotCorrect";
2742 case UDS_NRC_RequestSequenceError:
2743 return "UDS_NRC_RequestSequenceError";
2744 case UDS_NRC_NoResponseFromSubnetComponent:
2745 return "UDS_NRC_NoResponseFromSubnetComponent";
2746 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2747 return "UDS_NRC_FailurePreventsExecutionOfRequestedAction";
2748 case UDS_NRC_RequestOutOfRange:
2749 return "UDS_NRC_RequestOutOfRange";
2750 case UDS_NRC_SecurityAccessDenied:
2751 return "UDS_NRC_SecurityAccessDenied";
2752 case UDS_NRC_AuthenticationRequired:
2753 return "UDS_NRC_AuthenticationRequired";
2754 case UDS_NRC_InvalidKey:
2755 return "UDS_NRC_InvalidKey";
2756 case UDS_NRC_ExceedNumberOfAttempts:
2757 return "UDS_NRC_ExceedNumberOfAttempts";
2758 case UDS_NRC_RequiredTimeDelayNotExpired:
2759 return "UDS_NRC_RequiredTimeDelayNotExpired";
2760 case UDS_NRC_SecureDataTransmissionRequired:
2761 return "UDS_NRC_SecureDataTransmissionRequired";
2762 case UDS_NRC_SecureDataTransmissionNotAllowed:
2763 return "UDS_NRC_SecureDataTransmissionNotAllowed";
2764 case UDS_NRC_SecureDataVerificationFailed:
2765 return "UDS_NRC_SecureDataVerificationFailed";
2766 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2767 return "UDS_NRC_CertficateVerificationFailedInvalidTimePeriod";
2768 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2769 return "UDS_NRC_CertficateVerificationFailedInvalidSignature";
2770 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2771 return "UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust";
2772 case UDS_NRC_CertficateVerificationFailedInvalidType:
2773 return "UDS_NRC_CertficateVerificationFailedInvalidType";
2774 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2775 return "UDS_NRC_CertficateVerificationFailedInvalidFormat";
2776 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2777 return "UDS_NRC_CertficateVerificationFailedInvalidContent";
2778 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2779 return "UDS_NRC_CertficateVerificationFailedInvalidScope";
2780 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2781 return "UDS_NRC_CertficateVerificationFailedInvalidCertificate";
2782 case UDS_NRC_OwnershipVerificationFailed:
2783 return "UDS_NRC_OwnershipVerificationFailed";
2784 case UDS_NRC_ChallengeCalculationFailed:
2785 return "UDS_NRC_ChallengeCalculationFailed";
2786 case UDS_NRC_SettingAccessRightsFailed:
2787 return "UDS_NRC_SettingAccessRightsFailed";
2788 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2789 return "UDS_NRC_SessionKeyCreationOrDerivationFailed";
2790 case UDS_NRC_ConfigurationDataUsageFailed:
2791 return "UDS_NRC_ConfigurationDataUsageFailed";
2792 case UDS_NRC_DeAuthenticationFailed:
2793 return "UDS_NRC_DeAuthenticationFailed";
2794 case UDS_NRC_UploadDownloadNotAccepted:
2795 return "UDS_NRC_UploadDownloadNotAccepted";
2796 case UDS_NRC_TransferDataSuspended:
2797 return "UDS_NRC_TransferDataSuspended";
2798 case UDS_NRC_GeneralProgrammingFailure:
2799 return "UDS_NRC_GeneralProgrammingFailure";
2800 case UDS_NRC_WrongBlockSequenceCounter:
2801 return "UDS_NRC_WrongBlockSequenceCounter";
2802 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2803 return "UDS_NRC_RequestCorrectlyReceived_ResponsePending";
2804 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2805 return "UDS_NRC_SubFunctionNotSupportedInActiveSession";
2806 case UDS_NRC_ServiceNotSupportedInActiveSession:
2807 return "UDS_NRC_ServiceNotSupportedInActiveSession";
2808 case UDS_NRC_RpmTooHigh:
2809 return "UDS_NRC_RpmTooHigh";
2810 case UDS_NRC_RpmTooLow:
2811 return "UDS_NRC_RpmTooLow";
2812 case UDS_NRC_EngineIsRunning:
2813 return "UDS_NRC_EngineIsRunning";
2814 case UDS_NRC_EngineIsNotRunning:
2815 return "UDS_NRC_EngineIsNotRunning";
2816 case UDS_NRC_EngineRunTimeTooLow:
2817 return "UDS_NRC_EngineRunTimeTooLow";
2818 case UDS_NRC_TemperatureTooHigh:
2819 return "UDS_NRC_TemperatureTooHigh";
2820 case UDS_NRC_TemperatureTooLow:
2821 return "UDS_NRC_TemperatureTooLow";
2822 case UDS_NRC_VehicleSpeedTooHigh:
2823 return "UDS_NRC_VehicleSpeedTooHigh";
2824 case UDS_NRC_VehicleSpeedTooLow:
2825 return "UDS_NRC_VehicleSpeedTooLow";
2826 case UDS_NRC_ThrottlePedalTooHigh:
2827 return "UDS_NRC_ThrottlePedalTooHigh";
2828 case UDS_NRC_ThrottlePedalTooLow:
2829 return "UDS_NRC_ThrottlePedalTooLow";
2830 case UDS_NRC_TransmissionRangeNotInNeutral:
2831 return "UDS_NRC_TransmissionRangeNotInNeutral";
2832 case UDS_NRC_TransmissionRangeNotInGear:
2833 return "UDS_NRC_TransmissionRangeNotInGear";
2834 case UDS_NRC_BrakeSwitchNotClosed:
2835 return "UDS_NRC_BrakeSwitchNotClosed";
2836 case UDS_NRC_ShifterLeverNotInPark:
2837 return "UDS_NRC_ShifterLeverNotInPark";
2838 case UDS_NRC_TorqueConverterClutchLocked:
2839 return "UDS_NRC_TorqueConverterClutchLocked";
2840 case UDS_NRC_VoltageTooHigh:
2841 return "UDS_NRC_VoltageTooHigh";
2842 case UDS_NRC_VoltageTooLow:
2843 return "UDS_NRC_VoltageTooLow";
2844 case UDS_NRC_ResourceTemporarilyNotAvailable:
2845 return "UDS_NRC_ResourceTemporarilyNotAvailable";
2846 case UDS_ERR_TIMEOUT:
2847 return "UDS_ERR_TIMEOUT";
2848 case UDS_ERR_DID_MISMATCH:
2849 return "UDS_ERR_DID_MISMATCH";
2850 case UDS_ERR_SID_MISMATCH:
2851 return "UDS_ERR_SID_MISMATCH";
2852 case UDS_ERR_SUBFUNCTION_MISMATCH:
2853 return "UDS_ERR_SUBFUNCTION_MISMATCH";
2855 return "UDS_ERR_TPORT";
2856 case UDS_ERR_RESP_TOO_SHORT:
2857 return "UDS_ERR_RESP_TOO_SHORT";
2858 case UDS_ERR_BUFSIZ:
2859 return "UDS_ERR_BUFSIZ";
2860 case UDS_ERR_INVALID_ARG:
2861 return "UDS_ERR_INVALID_ARG";
2863 return "UDS_ERR_BUSY";
2864 case UDS_ERR_MISUSE:
2865 return "UDS_ERR_MISUSE";
2875 return "UDS_EVT_Custom";
2877 return "UDS_EVT_Err";
2879 return "UDS_EVT_DiagSessCtrl";
2881 return "UDS_EVT_EcuReset";
2883 return "UDS_EVT_ReadDataByIdent";
2885 return "UDS_EVT_ReadMemByAddr";
2887 return "UDS_EVT_CommCtrl";
2889 return "UDS_EVT_SecAccessRequestSeed";
2891 return "UDS_EVT_SecAccessValidateKey";
2893 return "UDS_EVT_WriteDataByIdent";
2895 return "UDS_EVT_RoutineCtrl";
2897 return "UDS_EVT_RequestDownload";
2899 return "UDS_EVT_RequestUpload";
2901 return "UDS_EVT_TransferData";
2903 return "UDS_EVT_RequestTransferExit";
2905 return "UDS_EVT_SessionTimeout";
2907 return "UDS_EVT_DoScheduledReset";
2909 return "UDS_EVT_RequestFileTransfer";
2911 return "UDS_EVT_Poll";
2913 return "UDS_EVT_SendComplete";
2915 return "UDS_EVT_ResponseReceived";
2917 return "UDS_EVT_Idle";
2919 return "UDS_EVT_MAX";
2927 case UDS_PositiveResponse:
2928 case UDS_NRC_GeneralReject:
2929 case UDS_NRC_ServiceNotSupported:
2930 case UDS_NRC_SubFunctionNotSupported:
2931 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2932 case UDS_NRC_ResponseTooLong:
2933 case UDS_NRC_BusyRepeatRequest:
2934 case UDS_NRC_ConditionsNotCorrect:
2935 case UDS_NRC_RequestSequenceError:
2936 case UDS_NRC_NoResponseFromSubnetComponent:
2937 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2938 case UDS_NRC_RequestOutOfRange:
2939 case UDS_NRC_SecurityAccessDenied:
2940 case UDS_NRC_AuthenticationRequired:
2941 case UDS_NRC_InvalidKey:
2942 case UDS_NRC_ExceedNumberOfAttempts:
2943 case UDS_NRC_RequiredTimeDelayNotExpired:
2944 case UDS_NRC_SecureDataTransmissionRequired:
2945 case UDS_NRC_SecureDataTransmissionNotAllowed:
2946 case UDS_NRC_SecureDataVerificationFailed:
2947 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2948 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2949 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2950 case UDS_NRC_CertficateVerificationFailedInvalidType:
2951 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2952 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2953 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2954 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2955 case UDS_NRC_OwnershipVerificationFailed:
2956 case UDS_NRC_ChallengeCalculationFailed:
2957 case UDS_NRC_SettingAccessRightsFailed:
2958 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2959 case UDS_NRC_ConfigurationDataUsageFailed:
2960 case UDS_NRC_DeAuthenticationFailed:
2961 case UDS_NRC_UploadDownloadNotAccepted:
2962 case UDS_NRC_TransferDataSuspended:
2963 case UDS_NRC_GeneralProgrammingFailure:
2964 case UDS_NRC_WrongBlockSequenceCounter:
2965 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2966 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2967 case UDS_NRC_ServiceNotSupportedInActiveSession:
2968 case UDS_NRC_RpmTooHigh:
2969 case UDS_NRC_RpmTooLow:
2970 case UDS_NRC_EngineIsRunning:
2971 case UDS_NRC_EngineIsNotRunning:
2972 case UDS_NRC_EngineRunTimeTooLow:
2973 case UDS_NRC_TemperatureTooHigh:
2974 case UDS_NRC_TemperatureTooLow:
2975 case UDS_NRC_VehicleSpeedTooHigh:
2976 case UDS_NRC_VehicleSpeedTooLow:
2977 case UDS_NRC_ThrottlePedalTooHigh:
2978 case UDS_NRC_ThrottlePedalTooLow:
2979 case UDS_NRC_TransmissionRangeNotInNeutral:
2980 case UDS_NRC_TransmissionRangeNotInGear:
2981 case UDS_NRC_BrakeSwitchNotClosed:
2982 case UDS_NRC_ShifterLeverNotInPark:
2983 case UDS_NRC_TorqueConverterClutchLocked:
2984 case UDS_NRC_VoltageTooHigh:
2985 case UDS_NRC_VoltageTooLow:
2986 case UDS_NRC_ResourceTemporarilyNotAvailable:
3000#if UDS_LOG_LEVEL > UDS_LOG_NONE
3001void UDS_LogWrite(
UDS_LogLevel_t level,
const char *tag,
const char *format, ...) {
3005 va_start(list, format);
3006 vprintf(format, list);
3010void UDS_LogSDUInternal(
UDS_LogLevel_t level,
const char *tag,
const uint8_t *buffer,
3011 size_t buff_len,
const UDSSDU_t *info) {
3013 for (
unsigned i = 0; i < buff_len; i++) {
3014 UDS_LogWrite(level, tag,
"%02x ", buffer[i]);
3016 UDS_LogWrite(level, tag,
"\n");
3022#line 1 "src/tp/isotp_c.c"
3024#if defined(UDS_TP_ISOTP_C)
3031 isotp_poll(&impl->phys_link);
3032 isotp_poll(&impl->func_link);
3033 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
3034 status |= UDS_TP_SEND_IN_PROGRESS;
3043 IsoTpLink *link = NULL;
3046 case UDS_A_TA_TYPE_PHYSICAL:
3047 link = &tp->phys_link;
3049 case UDS_A_TA_TYPE_FUNCTIONAL:
3050 link = &tp->func_link;
3052 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing\n");
3062 int send_status = isotp_send(link, buf, len);
3063 switch (send_status) {
3067 case ISOTP_RET_INPROGRESS:
3068 case ISOTP_RET_OVERFLOW:
3080 uint16_t out_size = 0;
3083 int ret = isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
3084 if (ret == ISOTP_RET_OK) {
3085 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
3087 info->
A_TA = tp->phys_sa;
3088 info->
A_SA = tp->phys_ta;
3089 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3091 }
else if (ret == ISOTP_RET_NO_DATA) {
3092 ret = isotp_receive(&tp->func_link, buf, bufsize, &out_size);
3093 if (ret == ISOTP_RET_OK) {
3094 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
3096 info->
A_TA = tp->func_sa;
3097 info->
A_SA = tp->func_ta;
3098 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3100 }
else if (ret == ISOTP_RET_NO_DATA) {
3103 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
3106 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
3114 return UDS_ERR_INVALID_ARG;
3116 tp->hdl.poll = tp_poll;
3117 tp->hdl.send = tp_send;
3118 tp->hdl.recv = tp_recv;
3121 tp->func_sa = sa_func;
3122 tp->func_ta = ta_func;
3124 isotp_init_link(&tp->phys_link, tp->phys_ta, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3125 sizeof(tp->recv_buf));
3126 isotp_init_link(&tp->func_link, tp->func_ta, tp->func_send_buf,
sizeof(tp->func_send_buf),
3127 tp->func_recv_buf,
sizeof(tp->func_recv_buf));
3132 uint32_t source_addr_func) {
3133 return UDSTpISOTpCInit(tp, source_addr, target_addr, source_addr_func,
UDS_TP_NOOP_ADDR);
3137 uint32_t target_addr_func) {
3138 return UDSTpISOTpCInit(tp, source_addr, target_addr,
UDS_TP_NOOP_ADDR, target_addr_func);
3145#line 1 "src/tp/isotp_c_socketcan.c"
3147#if defined(UDS_TP_ISOTP_C_SOCKETCAN)
3149#include <linux/can.h>
3150#include <linux/can/raw.h>
3155#include <sys/ioctl.h>
3160static int SetupSocketCAN(
const char *ifname) {
3161 struct sockaddr_can addr = {0};
3162 struct ifreq ifr = {0};
3165 if ((sockfd = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0) {
3170 memset(&ifr, 0,
sizeof(ifr));
3171 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", ifname) >= (
int)
sizeof(ifr.ifr_name)) {
3172 UDS_LOGE(__FILE__,
"Interface name too long");
3177 ioctl(sockfd, SIOCGIFINDEX, &ifr);
3178 memset(&addr, 0,
sizeof(addr));
3179 addr.can_family = AF_CAN;
3180 addr.can_ifindex = ifr.ifr_ifindex;
3181 if (bind(sockfd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3189uint32_t isotp_user_get_us(
void) {
return UDSMillis() * 1000; }
3191__attribute__((format(printf, 1, 2))) void isotp_user_debug(const
char *message, ...) {
3193 va_start(args, message);
3194 vprintf(message, args);
3198#ifndef ISO_TP_USER_SEND_CAN_ARG
3199#error "ISO_TP_USER_SEND_CAN_ARG must be defined"
3201int isotp_user_send_can(
const uint32_t arbitration_id,
const uint8_t *data,
const uint8_t size,
3203 (void)fflush(stdout);
3205 int sockfd = *(
int *)user_data;
3206 struct can_frame frame = {0};
3207 frame.can_id = arbitration_id;
3208 frame.can_dlc = size;
3209 memmove(frame.data, data, size);
3210 if (write(sockfd, &frame,
sizeof(
struct can_frame)) !=
sizeof(
struct can_frame)) {
3211 perror(
"Write err");
3212 return ISOTP_RET_ERROR;
3214 return ISOTP_RET_OK;
3219 struct can_frame frame = {0};
3223 nbytes = read(tp->fd, &frame,
sizeof(
struct can_frame));
3225 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3230 }
else if (nbytes == 0) {
3233 if (frame.can_id == tp->phys_sa) {
3234 isotp_on_can_message(&tp->phys_link, frame.data, frame.can_dlc);
3235 }
else if (frame.can_id == tp->func_sa) {
3236 if (ISOTP_RECEIVE_STATUS_IDLE != tp->phys_link.receive_status) {
3238 "func frame received but cannot process because link is not idle");
3242 isotp_on_can_message(&tp->func_link, frame.data, frame.can_dlc);
3252 SocketCANRecv(impl);
3253 isotp_poll(&impl->phys_link);
3254 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
3255 status |= UDS_TP_SEND_IN_PROGRESS;
3257 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_ERROR) {
3258 status |= UDS_TP_ERR;
3263static UDSTpSize_t isotp_c_socketcan_tp_send(
UDSTp_t *hdl,
const uint8_t *buf,
size_t len,
3268 IsoTpLink *link = NULL;
3270 const uint32_t ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? tp->phys_ta : tp->func_ta;
3272 case UDS_A_TA_TYPE_PHYSICAL:
3273 link = &tp->phys_link;
3275 case UDS_A_TA_TYPE_FUNCTIONAL:
3276 link = &tp->func_link;
3278 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing");
3288 int send_status = isotp_send(link, buf, len);
3289 switch (send_status) {
3293 case ISOTP_RET_INPROGRESS:
3294 case ISOTP_RET_OVERFLOW:
3300 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", tp->tag, len, ta,
3301 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3302 UDS_LOG_SDU(__FILE__, buf, len, info);
3306static UDSTpSize_t isotp_c_socketcan_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
3310 uint16_t out_size = 0;
3313 int ret = isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
3314 if (ret == ISOTP_RET_OK) {
3315 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
3317 info->
A_TA = tp->phys_sa;
3318 info->
A_SA = tp->phys_ta;
3319 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3321 }
else if (ret == ISOTP_RET_NO_DATA) {
3322 ret = isotp_receive(&tp->func_link, buf, bufsize, &out_size);
3323 if (ret == ISOTP_RET_OK) {
3324 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
3326 info->
A_TA = tp->func_sa;
3327 info->
A_SA = tp->func_ta;
3328 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3330 }
else if (ret == ISOTP_RET_NO_DATA) {
3333 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
3336 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
3342 uint32_t source_addr, uint32_t target_addr,
3343 uint32_t source_addr_func, uint32_t target_addr_func) {
3346 tp->hdl.poll = isotp_c_socketcan_tp_poll;
3347 tp->hdl.send = isotp_c_socketcan_tp_send;
3348 tp->hdl.recv = isotp_c_socketcan_tp_recv;
3349 tp->phys_sa = source_addr;
3350 tp->phys_ta = target_addr;
3351 tp->func_sa = source_addr_func;
3352 tp->func_ta = target_addr;
3353 tp->fd = SetupSocketCAN(ifname);
3355 isotp_init_link(&tp->phys_link, target_addr, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3356 sizeof(tp->recv_buf));
3357 isotp_init_link(&tp->func_link, target_addr_func, tp->recv_buf,
sizeof(tp->send_buf),
3358 tp->recv_buf,
sizeof(tp->recv_buf));
3360 tp->phys_link.user_send_can_arg = &(tp->fd);
3361 tp->func_link.user_send_can_arg = &(tp->fd);
3376#line 1 "src/tp/isotp_sock.c"
3378#if defined(UDS_TP_ISOTP_SOCK)
3382#include <linux/can.h>
3383#include <linux/can/isotp.h>
3386#include <sys/ioctl.h>
3387#include <sys/socket.h>
3388#include <sys/socket.h>
3389#include <sys/types.h>
3396 int fds[2] = {impl->phys_fd, impl->func_fd};
3397 struct pollfd pfds[2] = {0};
3398 pfds[0].fd = impl->phys_fd;
3399 pfds[0].events = POLLERR | POLLOUT;
3400 pfds[0].revents = 0;
3402 pfds[1].fd = impl->func_fd;
3403 pfds[1].events = POLLERR | POLLOUT;
3404 pfds[1].revents = 0;
3406 ret = poll(pfds, 2, 1);
3408 UDS_LOGE(__FILE__,
"poll failed: %d", ret);
3409 status |= UDS_TP_ERR;
3410 }
else if (ret == 0) {
3414 for (
int i = 0; i < 2; i++) {
3415 struct pollfd pfd = pfds[i];
3418 if (pfd.revents & POLLERR) {
3419 int pending_err = 0;
3420 socklen_t len =
sizeof(pending_err);
3421 if (!getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &pending_err, &len) && pending_err) {
3422 switch (pending_err) {
3424 UDS_LOGE(__FILE__,
"ECOMM: Communication error on send");
3425 status |= UDS_TP_ERR;
3428 UDS_LOGE(__FILE__,
"Asynchronous socket error: %s (%d)",
3429 strerror(pending_err), pending_err);
3430 status |= UDS_TP_ERR;
3434 UDS_LOGE(__FILE__,
"POLLERR was set, but no error returned via SO_ERROR?");
3440 if (fds[i] == impl->phys_fd && pfd.revents != 0) {
3445 if (!(pfd.revents & POLLOUT)) {
3446 status |= UDS_TP_SEND_IN_PROGRESS;
3454static UDSTpSize_t tp_recv_once(
int fd, uint8_t *buf,
size_t size) {
3457 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3460 UDS_LOGI(__FILE__,
"read failed: %" PRId32
" with errno: %d\n", ret, errno);
3461 if (EILSEQ == errno) {
3462 UDS_LOGI(__FILE__,
"Perhaps I received multiple responses?");
3476 ret = tp_recv_once(impl->phys_fd, buf, bufsize);
3478 msg->
A_TA = impl->phys_sa;
3479 msg->
A_SA = impl->phys_ta;
3480 msg->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3482 ret = tp_recv_once(impl->func_fd, buf, bufsize);
3484 msg->
A_TA = impl->func_sa;
3485 msg->
A_SA = impl->func_ta;
3486 msg->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3495 UDS_LOGD(__FILE__,
"'%s' received %" PRId32
" bytes from 0x%03x (%s), ", impl->tag, ret,
3496 msg->
A_TA, msg->
A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3497 UDS_LOG_SDU(__FILE__, impl->recv_buf, ret, msg);
3511 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3513 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3515 UDS_LOGI(__FILE__,
"UDSTpIsoTpSock: functional request too large");
3523 ret = write(fd, buf, len);
3528 int ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? impl->phys_ta : impl->func_ta;
3529 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", impl->tag, len, ta,
3530 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3531 UDS_LOG_SDU(__FILE__, buf, len, info);
3536static int LinuxSockBind(
const char *if_name, uint32_t rxid, uint32_t txid,
bool functional) {
3538 if ((fd = socket(AF_CAN, SOCK_DGRAM | SOCK_NONBLOCK, CAN_ISOTP)) < 0) {
3543 struct can_isotp_fc_options fcopts = {
3548 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts,
sizeof(fcopts)) < 0) {
3549 perror(
"setsockopt");
3553 struct can_isotp_options opts;
3554 memset(&opts, 0,
sizeof(opts));
3558 opts.flags |= CAN_ISOTP_LISTEN_MODE;
3561 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts,
sizeof(opts)) < 0) {
3562 perror(
"setsockopt (isotp_options):");
3567 memset(&ifr, 0,
sizeof(ifr));
3568 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", if_name) >= (
int)
sizeof(ifr.ifr_name)) {
3569 UDS_LOGE(__FILE__,
"Interface name too long");
3573 ioctl(fd, SIOCGIFINDEX, &ifr);
3575 struct sockaddr_can addr;
3576 memset(&addr, 0,
sizeof(addr));
3577 addr.can_family = AF_CAN;
3578 addr.can_addr.tp.rx_id = rxid;
3579 addr.can_addr.tp.tx_id = txid;
3580 addr.can_ifindex = ifr.ifr_ifindex;
3582 if (bind(fd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3583 UDS_LOGI(__FILE__,
"Bind: %s %s", strerror(errno), if_name);
3590 uint32_t target_addr, uint32_t source_addr_func) {
3592 memset(tp, 0,
sizeof(*tp));
3593 tp->hdl.send = isotp_sock_tp_send;
3594 tp->hdl.recv = isotp_sock_tp_recv;
3595 tp->hdl.poll = isotp_sock_tp_poll;
3596 tp->phys_sa = source_addr;
3597 tp->phys_ta = target_addr;
3598 tp->func_sa = source_addr_func;
3600 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3601 if (tp->phys_fd < 0) {
3604 tp->func_fd = LinuxSockBind(ifname, source_addr_func, 0,
true);
3605 if (tp->func_fd < 0) {
3608 const char *tag =
"server";
3609 memmove(tp->tag, tag, strlen(tag));
3610 UDS_LOGI(__FILE__,
"%s initialized phys link rx 0x%03x tx 0x%03x func link rx 0x%03x tx 0x%03x",
3611 strlen(tp->tag) ? tp->tag :
"server", source_addr, target_addr, source_addr_func,
3617 uint32_t target_addr, uint32_t target_addr_func) {
3619 memset(tp, 0,
sizeof(*tp));
3620 tp->hdl.send = isotp_sock_tp_send;
3621 tp->hdl.recv = isotp_sock_tp_recv;
3622 tp->hdl.poll = isotp_sock_tp_poll;
3623 tp->func_ta = target_addr_func;
3624 tp->phys_ta = target_addr;
3625 tp->phys_sa = source_addr;
3627 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3628 tp->func_fd = LinuxSockBind(ifname, 0, target_addr_func,
true);
3629 if (tp->phys_fd < 0 || tp->func_fd < 0) {
3632 const char *tag =
"client";
3633 memmove(tp->tag, tag, strlen(tag));
3635 "%s initialized phys link (fd %d) rx 0x%03x tx 0x%03x func link (fd %d) rx 0x%03x tx "
3637 strlen(tp->tag) ? tp->tag :
"client", tp->phys_fd, source_addr, target_addr,
3638 tp->func_fd, source_addr, target_addr_func);
3644 if (close(tp->phys_fd) < 0) {
3645 perror(
"failed to close socket");
3647 if (close(tp->func_fd) < 0) {
3648 perror(
"failed to close socket");
3657#line 1 "src/tp/isotp_mock.c"
3659#if defined(UDS_TP_ISOTP_MOCK)
3669#define MAX_NUM_TP 16
3671static ISOTPMock_t *TPs[MAX_NUM_TP];
3672static unsigned TPCount = 0;
3673static FILE *LogFile = NULL;
3678 uint32_t scheduled_tx_time;
3679 ISOTPMock_t *sender;
3681static unsigned MsgCount = 0;
3683static void NetworkPoll(
void) {
3684 for (
unsigned i = 0; i < MsgCount; i++) {
3685 if (UDSTimeAfter(
UDSMillis(), msgs[i].scheduled_tx_time)) {
3687 for (
unsigned j = 0; j < TPCount; j++) {
3688 ISOTPMock_t *tp = TPs[j];
3689 if (tp->sa_phys == msgs[i].info.A_TA || tp->sa_func == msgs[i].info.A_TA) {
3691 if (tp->recv_len > 0) {
3693 "TPMock: %s recv buffer is already full. Message dropped",
3699 "%s receives %ld bytes from TA=0x%03X (A_TA_Type=%s):", tp->name,
3700 msgs[i].len, msgs[i].info.A_TA,
3701 msgs[i].info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL"
3703 UDS_LOG_SDU(__FILE__, msgs[i].buf, msgs[i].len, &(msgs[i].info));
3705 memmove(tp->recv_buf, msgs[i].buf, msgs[i].len);
3706 tp->recv_len = msgs[i].len;
3707 tp->recv_info = msgs[i].info;
3712 UDS_LOGW(__FILE__,
"TPMock: no matching receiver for message");
3715 for (
unsigned j = i + 1; j < MsgCount; j++) {
3716 msgs[j - 1] = msgs[j];
3724static UDSTpSize_t mock_tp_send(
struct UDSTp *hdl,
const uint8_t *buf,
size_t len,
3727 ISOTPMock_t *tp = (ISOTPMock_t *)hdl;
3728 if (MsgCount >= NUM_MSGS) {
3729 UDS_LOGW(__FILE__,
"mock_tp_send: too many messages in the queue");
3732 struct Msg *m = &msgs[MsgCount++];
3736 m->info.A_AE = info == NULL ? 0 : info->
A_AE;
3737 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3738 m->info.A_TA = tp->ta_phys;
3739 m->info.A_SA = tp->sa_phys;
3740 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3746 UDS_LOGW(__FILE__,
"mock_tp_send: functional message too long: %ld", len);
3749 m->info.A_TA = tp->ta_func;
3750 m->info.A_SA = tp->sa_func;
3752 UDS_LOGW(__FILE__,
"mock_tp_send: unknown TA type: %d", ta_type);
3755 m->info.A_TA_Type = ta_type;
3756 m->scheduled_tx_time =
UDSMillis() + tp->send_tx_delay_ms;
3757 memmove(m->buf, buf, len);
3759 UDS_LOGD(__FILE__,
"%s sends %ld bytes to TA=0x%03X (A_TA_Type=%s):", tp->name, len,
3760 m->info.A_TA, m->info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL" :
"FUNCTIONAL");
3761 UDS_LOG_SDU(__FILE__, buf, len, &m->info);
3766static UDSTpSize_t mock_tp_recv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
3768 ISOTPMock_t *tp = (ISOTPMock_t *)hdl;
3769 if (tp->recv_len == 0) {
3772 if (bufsize < tp->recv_len) {
3773 UDS_LOGW(__FILE__,
"mock_tp_recv: buffer too small: %ld < %ld", bufsize, tp->recv_len);
3777 memmove(buf, tp->recv_buf, tp->recv_len);
3779 *info = tp->recv_info;
3792static_assert(offsetof(ISOTPMock_t, hdl) == 0,
"ISOTPMock_t must not have any members before hdl");
3794static void ISOTPMockAttach(ISOTPMock_t *tp, ISOTPMockArgs_t *args) {
3798 TPs[TPCount++] = tp;
3799 tp->hdl.send = mock_tp_send;
3800 tp->hdl.recv = mock_tp_recv;
3801 tp->hdl.poll = mock_tp_poll;
3802 tp->sa_func = args->sa_func;
3803 tp->sa_phys = args->sa_phys;
3804 tp->ta_func = args->ta_func;
3805 tp->ta_phys = args->ta_phys;
3807 UDS_LOGV(__FILE__,
"attached %s. TPCount: %d", tp->name, TPCount);
3810static void ISOTPMockDetach(ISOTPMock_t *tp) {
3812 for (
unsigned i = 0; i < TPCount; i++) {
3814 for (
unsigned j = i + 1; j < TPCount; j++) {
3815 TPs[j - 1] = TPs[j];
3818 UDS_LOGV(__FILE__,
"TPMock: detached %s. TPCount: %d", tp->name, TPCount);
3825UDSTp_t *ISOTPMockNew(
const char *name, ISOTPMockArgs_t *args) {
3826 if (TPCount >= MAX_NUM_TP) {
3827 UDS_LOGI(__FILE__,
"TPCount: %d, too many TPs\n", TPCount);
3830 ISOTPMock_t *tp = malloc(
sizeof(ISOTPMock_t));
3831 memset(tp, 0,
sizeof(ISOTPMock_t));
3833 if (snprintf(tp->name,
sizeof(tp->name),
"%s", name) >= (
int)
sizeof(tp->name)) {
3834 UDS_LOGE(__FILE__,
"Transport name too long, truncated");
3837 (void)snprintf(tp->name,
sizeof(tp->name),
"TPMock%u", TPCount);
3839 ISOTPMockAttach(tp, args);
3845void ISOTPMockLogToFile(
const char *filename) {
3847 (void)fprintf(stderr,
"Log file is already open\n");
3851 (void)fprintf(stderr,
"Filename is NULL\n");
3855 LogFile = fopen(filename,
"w");
3857 (void)fprintf(stderr,
"Failed to open log file %s\n", filename);
3862void ISOTPMockLogToStdout(
void) {
3869void ISOTPMockReset(
void) {
3870 memset(TPs, 0,
sizeof(TPs));
3872 memset(msgs, 0,
sizeof(msgs));
3876void ISOTPMockFree(
UDSTp_t *tp) {
3877 ISOTPMock_t *tpm = (ISOTPMock_t *)tp;
3878 ISOTPMockDetach(tpm);
3886#if defined(UDS_TP_ISOTP_C)
3889#ifndef ISO_TP_USER_SEND_CAN_ARG
3900static uint8_t isotp_us_to_st_min(uint32_t us) {
3902 if (us >= 100 && us <= 900) {
3903 return (uint8_t)(0xF0 + (us / 100));
3905 return (uint8_t)(us / 1000u);
3913static uint32_t isotp_st_min_to_us(uint8_t st_min) {
3914 if (st_min <= 0x7F) {
3915 return st_min * 1000;
3916 }
else if (st_min >= 0xF1 && st_min <= 0xF9) {
3917 return (st_min - 0xF0) * 100;
3922static int isotp_send_flow_control(
const IsoTpLink* link, uint8_t flow_status, uint8_t block_size, uint32_t st_min_us) {
3924 IsoTpCanMessage message;
3929 message.as.flow_control.type = ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME;
3930 message.as.flow_control.FS = flow_status;
3931 message.as.flow_control.BS = block_size;
3932 message.as.flow_control.STmin = isotp_us_to_st_min(st_min_us);
3935#ifdef ISO_TP_FRAME_PADDING
3936 (void) memset(message.as.flow_control.reserve, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.flow_control.reserve));
3937 size =
sizeof(message);
3942 ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
3943 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3944 ,link->user_send_can_arg
3951static int isotp_send_single_frame(
const IsoTpLink* link, uint32_t
id) {
3953 IsoTpCanMessage message;
3959 assert(link->send_size <= 7);
3962 message.as.single_frame.type = ISOTP_PCI_TYPE_SINGLE;
3963 message.as.single_frame.SF_DL = (uint8_t) link->send_size;
3964 (void) memcpy(message.as.single_frame.data, link->send_buffer, link->send_size);
3967#ifdef ISO_TP_FRAME_PADDING
3968 (void) memset(message.as.single_frame.data + link->send_size, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.single_frame.data) - link->send_size);
3969 size =
sizeof(message);
3971 size = link->send_size + 1;
3974 ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
3975 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3976 ,link->user_send_can_arg
3983static int isotp_send_first_frame(IsoTpLink* link, uint32_t
id) {
3985 IsoTpCanMessage message;
3989 assert(link->send_size > 7);
3992 message.as.first_frame.type = ISOTP_PCI_TYPE_FIRST_FRAME;
3993 message.as.first_frame.FF_DL_low = (uint8_t) link->send_size;
3994 message.as.first_frame.FF_DL_high = (uint8_t) (0x0F & (link->send_size >> 8));
3995 (void) memcpy(message.as.first_frame.data, link->send_buffer,
sizeof(message.as.first_frame.data));
3998 ret = isotp_user_send_can(
id, message.as.data_array.ptr,
sizeof(message)
3999 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
4000 ,link->user_send_can_arg
4004 if (ISOTP_RET_OK == ret) {
4005 link->send_offset +=
sizeof(message.as.first_frame.data);
4012static int isotp_send_consecutive_frame(IsoTpLink* link) {
4014 IsoTpCanMessage message;
4015 uint16_t data_length;
4020 assert(link->send_size > 7);
4023 message.as.consecutive_frame.type = TSOTP_PCI_TYPE_CONSECUTIVE_FRAME;
4024 message.as.consecutive_frame.SN = link->send_sn;
4025 data_length = link->send_size - link->send_offset;
4026 if (data_length >
sizeof(message.as.consecutive_frame.data)) {
4027 data_length =
sizeof(message.as.consecutive_frame.data);
4029 (void) memcpy(message.as.consecutive_frame.data, link->send_buffer + link->send_offset, data_length);
4032#ifdef ISO_TP_FRAME_PADDING
4033 (void) memset(message.as.consecutive_frame.data + data_length, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.consecutive_frame.data) - data_length);
4034 size =
sizeof(message);
4036 size = data_length + 1;
4039 ret = isotp_user_send_can(link->send_arbitration_id,
4040 message.as.data_array.ptr, size
4041#
if defined (ISO_TP_USER_SEND_CAN_ARG)
4042 ,link->user_send_can_arg
4046 if (ISOTP_RET_OK == ret) {
4047 link->send_offset += data_length;
4048 if (++(link->send_sn) > 0x0F) {
4056static int isotp_receive_single_frame(IsoTpLink* link,
const IsoTpCanMessage* message, uint8_t len) {
4058 if ((0 == message->as.single_frame.SF_DL) || (message->as.single_frame.SF_DL > (len - 1))) {
4059 isotp_user_debug(
"Single-frame length too small.");
4060 return ISOTP_RET_LENGTH;
4064 (void) memcpy(link->receive_buffer, message->as.single_frame.data, message->as.single_frame.SF_DL);
4065 link->receive_size = message->as.single_frame.SF_DL;
4067 return ISOTP_RET_OK;
4070static int isotp_receive_first_frame(IsoTpLink *link, IsoTpCanMessage *message, uint8_t len) {
4071 uint16_t payload_length;
4074 isotp_user_debug(
"First frame should be 8 bytes in length.");
4075 return ISOTP_RET_LENGTH;
4079 payload_length = message->as.first_frame.FF_DL_high;
4080 payload_length = (uint16_t)(payload_length << 8) + message->as.first_frame.FF_DL_low;
4083 if (payload_length <= 7) {
4084 isotp_user_debug(
"Should not use multiple frame transmission.");
4085 return ISOTP_RET_LENGTH;
4088 if (payload_length > link->receive_buf_size) {
4089 isotp_user_debug(
"Multi-frame response too large for receiving buffer.");
4090 return ISOTP_RET_OVERFLOW;
4094 (void) memcpy(link->receive_buffer, message->as.first_frame.data,
sizeof(message->as.first_frame.data));
4095 link->receive_size = payload_length;
4096 link->receive_offset =
sizeof(message->as.first_frame.data);
4097 link->receive_sn = 1;
4099 return ISOTP_RET_OK;
4102static int isotp_receive_consecutive_frame(IsoTpLink *link, IsoTpCanMessage *message, uint8_t len) {
4103 uint16_t remaining_bytes;
4106 if (link->receive_sn != message->as.consecutive_frame.SN) {
4107 return ISOTP_RET_WRONG_SN;
4111 remaining_bytes = link->receive_size - link->receive_offset;
4112 if (remaining_bytes >
sizeof(message->as.consecutive_frame.data)) {
4113 remaining_bytes =
sizeof(message->as.consecutive_frame.data);
4115 if (remaining_bytes > len - 1) {
4116 isotp_user_debug(
"Consecutive frame too short.");
4117 return ISOTP_RET_LENGTH;
4121 (void) memcpy(link->receive_buffer + link->receive_offset, message->as.consecutive_frame.data, remaining_bytes);
4123 link->receive_offset += remaining_bytes;
4124 if (++(link->receive_sn) > 0x0F) {
4125 link->receive_sn = 0;
4128 return ISOTP_RET_OK;
4131static int isotp_receive_flow_control_frame(IsoTpLink *link, IsoTpCanMessage *message, uint8_t len) {
4138 isotp_user_debug(
"Flow control frame too short.");
4139 return ISOTP_RET_LENGTH;
4142 return ISOTP_RET_OK;
4149int isotp_send(IsoTpLink *link,
const uint8_t payload[], uint16_t size) {
4150 return isotp_send_with_id(link, link->send_arbitration_id, payload, size);
4153int isotp_send_with_id(IsoTpLink *link, uint32_t
id,
const uint8_t payload[], uint16_t size) {
4157 isotp_user_debug(
"Link is null!");
4158 return ISOTP_RET_ERROR;
4161 if (size > link->send_buf_size) {
4162 isotp_user_debug(
"Message size too large. Increase ISO_TP_MAX_MESSAGE_SIZE to set a larger buffer\n");
4163 const int32_t messageSize = 128;
4164 char message[messageSize];
4165 int32_t writtenChars = sprintf(&message[0],
"Attempted to send %d bytes; max size is %d!\n", size, link->send_buf_size);
4167 assert(writtenChars <= messageSize);
4168 (void) writtenChars;
4170 isotp_user_debug(
"%s", message);
4171 return ISOTP_RET_OVERFLOW;
4174 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4175 isotp_user_debug(
"Abort previous message, transmission in progress.\n");
4176 return ISOTP_RET_INPROGRESS;
4180 link->send_size = size;
4181 link->send_offset = 0;
4182 (void) memcpy(link->send_buffer, payload, size);
4184 if (link->send_size < 8) {
4186 ret = isotp_send_single_frame(link,
id);
4189 ret = isotp_send_first_frame(link,
id);
4192 if (ISOTP_RET_OK == ret) {
4193 link->send_bs_remain = 0;
4194 link->send_st_min_us = 0;
4195 link->send_wtf_count = 0;
4196 link->send_timer_st = isotp_user_get_us();
4197 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4198 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4199 link->send_status = ISOTP_SEND_STATUS_INPROGRESS;
4206void isotp_on_can_message(IsoTpLink* link,
const uint8_t* data, uint8_t len) {
4207 IsoTpCanMessage message;
4210 if (len < 2 || len > 8) {
4214 memcpy(message.as.data_array.ptr, data, len);
4215 memset(message.as.data_array.ptr + len, 0,
sizeof(message.as.data_array.ptr) - len);
4217 switch (message.as.common.type) {
4218 case ISOTP_PCI_TYPE_SINGLE: {
4220 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4221 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4223 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4227 ret = isotp_receive_single_frame(link, &message, len);
4229 if (ISOTP_RET_OK == ret) {
4231 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4235 case ISOTP_PCI_TYPE_FIRST_FRAME: {
4237 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4238 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4240 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4244 ret = isotp_receive_first_frame(link, &message, len);
4247 if (ISOTP_RET_OVERFLOW == ret) {
4249 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4251 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4253 isotp_send_flow_control(link, PCI_FLOW_STATUS_OVERFLOW, 0, 0);
4258 if (ISOTP_RET_OK == ret) {
4260 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4262 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4263 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4265 link->receive_timer_cr = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4270 case TSOTP_PCI_TYPE_CONSECUTIVE_FRAME: {
4272 if (ISOTP_RECEIVE_STATUS_INPROGRESS != link->receive_status) {
4273 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4278 ret = isotp_receive_consecutive_frame(link, &message, len);
4281 if (ISOTP_RET_WRONG_SN == ret) {
4282 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_WRONG_SN;
4283 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4288 if (ISOTP_RET_OK == ret) {
4290 link->receive_timer_cr = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4293 if (link->receive_offset >= link->receive_size) {
4294 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4297 if (0 == --link->receive_bs_count) {
4298 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4299 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4306 case ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME:
4308 if (ISOTP_SEND_STATUS_INPROGRESS != link->send_status) {
4313 ret = isotp_receive_flow_control_frame(link, &message, len);
4315 if (ISOTP_RET_OK == ret) {
4317 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4320 if (PCI_FLOW_STATUS_OVERFLOW == message.as.flow_control.FS) {
4321 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4322 link->send_status = ISOTP_SEND_STATUS_ERROR;
4326 else if (PCI_FLOW_STATUS_WAIT == message.as.flow_control.FS) {
4327 link->send_wtf_count += 1;
4329 if (link->send_wtf_count > ISO_TP_MAX_WFT_NUMBER) {
4330 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_WFT_OVRN;
4331 link->send_status = ISOTP_SEND_STATUS_ERROR;
4336 else if (PCI_FLOW_STATUS_CONTINUE == message.as.flow_control.FS) {
4337 if (0 == message.as.flow_control.BS) {
4338 link->send_bs_remain = ISOTP_INVALID_BS;
4340 link->send_bs_remain = message.as.flow_control.BS;
4342 uint32_t message_st_min_us = isotp_st_min_to_us(message.as.flow_control.STmin);
4343 link->send_st_min_us = message_st_min_us > ISO_TP_DEFAULT_ST_MIN_US ? message_st_min_us : ISO_TP_DEFAULT_ST_MIN_US;
4344 link->send_wtf_count = 0;
4355int isotp_receive(IsoTpLink *link, uint8_t *payload,
const uint16_t payload_size, uint16_t *out_size) {
4358 if (ISOTP_RECEIVE_STATUS_FULL != link->receive_status) {
4359 return ISOTP_RET_NO_DATA;
4362 copylen = link->receive_size;
4363 if (copylen > payload_size) {
4364 copylen = payload_size;
4367 memcpy(payload, link->receive_buffer, copylen);
4368 *out_size = copylen;
4370 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4372 return ISOTP_RET_OK;
4375void isotp_init_link(IsoTpLink *link, uint32_t sendid, uint8_t *sendbuf, uint16_t sendbufsize, uint8_t *recvbuf, uint16_t recvbufsize) {
4376 memset(link, 0,
sizeof(*link));
4377 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4378 link->send_status = ISOTP_SEND_STATUS_IDLE;
4379 link->send_arbitration_id = sendid;
4380 link->send_buffer = sendbuf;
4381 link->send_buf_size = sendbufsize;
4382 link->receive_buffer = recvbuf;
4383 link->receive_buf_size = recvbufsize;
4388void isotp_poll(IsoTpLink *link) {
4392 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4396 (ISOTP_INVALID_BS == link->send_bs_remain || link->send_bs_remain > 0) &&
4398 (0 == link->send_st_min_us || IsoTpTimeAfter(isotp_user_get_us(), link->send_timer_st))) {
4400 ret = isotp_send_consecutive_frame(link);
4401 if (ISOTP_RET_OK == ret) {
4402 if (ISOTP_INVALID_BS != link->send_bs_remain) {
4403 link->send_bs_remain -= 1;
4405 link->send_timer_bs = isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4406 link->send_timer_st = isotp_user_get_us() + link->send_st_min_us;
4409 if (link->send_offset >= link->send_size) {
4410 link->send_status = ISOTP_SEND_STATUS_IDLE;
4412 }
else if (ISOTP_RET_NOSPACE == ret) {
4415 link->send_status = ISOTP_SEND_STATUS_ERROR;
4420 if (IsoTpTimeAfter(isotp_user_get_us(), link->send_timer_bs)) {
4421 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_BS;
4422 link->send_status = ISOTP_SEND_STATUS_ERROR;
4427 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4430 if (IsoTpTimeAfter(isotp_user_get_us(), link->receive_timer_cr)) {
4431 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_CR;
4432 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
#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
bool UDSErrIsNRC(UDSErr_t err)
returns true if err is defined in ISO14229-1:2020 as an NRC
bool UDSSecurityAccessLevelIsReserved(uint8_t securityLevel)
returns true if a security level is reserved per ISO14229-1:2020 Table 42
ISO14229-1 (UDS) library.
#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.
@ 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
UDSErr_t UDSSendRequestFileTransfer(UDSClient_t *client, uint8_t mode, const char *filePath, size_t fileSizeUncompressed, size_t fileSizeCompressed)
filesystem-based frontend to TransferData
#define UDS_CLIENT_DEFAULT_P2_STAR_MS
default P2* timeout
UDSErr_t UDSSendRequestTransferExit(UDSClient_t *client)
Call this when finished with TransferData.
UDSTpStatus_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.
void UDSTpIsoTpSockDeinit(UDSTpIsoTpSock_t *tp)
release sockets
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 UDSSendTransferData(UDSClient_t *client, uint8_t blockSequenceCounter, const uint16_t blockLength, const uint8_t *data, uint16_t size)
Transfer Data to/from a buffer.
int UDS_LogLevel_t
one of valid values for UDS_LOG_LEVEL
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
#define UDS_SUPPRESS_POS_RESP
set the suppress positive response bit
UDSErr_t UDSSendWDBI(UDSClient_t *client, uint16_t dataIdentifier, const uint8_t *data, uint16_t size)
Write Data By Identifier.
UDSTpSize_t UDSTpRecv(UDSTp_t *hdl, uint8_t *buf, size_t bufsize, UDSSDU_t *info)
Receive from transport.
uint32_t UDSTpStatus_t
private: bitfield of UDSTpStatusFlags
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 UDSSendSecurityAccess(UDSClient_t *client, uint8_t level, uint8_t *data, uint16_t size)
Get Security Access.
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.
UDSErr_t UDSCtrlDTCSetting(UDSClient_t *client, uint8_t dtcSettingType, uint8_t *dtcSettingControlOptionRecord, uint16_t len)
control DTC setting
#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.
#define UDS_FUNCTIONAL
send the request as a functional request
#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 UDSClientTpISOTpCInit(UDSTpISOTpC_t *tp, uint32_t target_addr, uint32_t source_addr, uint32_t target_addr_func)
Initialize isotp-c transport for UDSClient_t.
UDSErr_t UDSSendRoutineCtrl(UDSClient_t *client, uint8_t type, uint16_t routineIdentifier, const uint8_t *data, uint16_t size)
Request to Twiddle Routines.
uint8_t UDSTpAddr_t
private: oneof UDS_A_TA_Type_t
UDSErr_t
Error Codes, including NRCs defined by the standard.
void UDSTpISOTpCSocketCANDeinit(UDSTpISOTpCSocketCAN_t *tp)
release socket
#define UDS_REQUEST_SID_OF(response_sid)
Convert response SID to request SID.
UDSErr_t UDSSendTransferDataStream(UDSClient_t *client, uint8_t blockSequenceCounter, const uint16_t blockLength, FILE *fd)
Transfer Data to/from a file.
#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.
int32_t UDSTpSize_t
Signed size type used by the transport layer interface (byte count, or negative on error).
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.
#define UDS_IGNORE_SRV_TIMINGS
ignore the server-provided p2 and p2_star
#define UDS_RESPONSE_SID_OF(request_sid)
Convert request SID to response SID.
UDSErr_t UDSTpISOTpCSocketCANInit(UDSTpISOTpCSocketCAN_t *tp, const char *ifname, uint32_t source_addr, uint32_t target_addr, uint32_t source_addr_func, uint32_t target_addr_func)
Initialize the transport.
UDSErr_t UDSSendDiagSessCtrl(UDSClient_t *client, uint8_t mode)
Change the diagnostic session.
#define UDS_ASSERT(x)
define this during library development. It is a no-op by default for library users....
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.
UDSTpSize_t UDSTpSend(UDSTp_t *hdl, const uint8_t *buf, UDSTpSize_t len, const UDSSDU_t *info)
Send to transport.
UDSErr_t UDSServerInit(UDSServer_t *srv)
call this once
#define UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS
UDSErr_t UDSSendRDBI(UDSClient_t *client, const uint16_t *didList, const uint16_t numDataIdentifiers)
Read Data By Identifier.
Request download response structure.
size_t maxNumberOfBlockLength
Routine control response structure.
const uint8_t * routineStatusRecord
uint16_t routineIdentifier
uint8_t routineControlType
uint16_t routineStatusRecordLength
Security access response structure.
uint8_t securityAccessType
uint16_t securitySeedLength
const uint8_t * securitySeed
Clear diagnostic information arguments.
uint8_t cfg_file_size_parameter_length
uint8_t cfg_data_format_identifier
int(*) fn(struct UDSClient *client, UDSEvent_t evt, void *ev_data)
uint8_t send_buf[UDS_CLIENT_SEND_BUF_SIZE]
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::@166357164257276222002146302270155120176057041273 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::@362145371326305243133264240062265164011177277257 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
const uint8_t dataFormatIdentifier
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
UDSTpStatus_t(*) poll(struct UDSTp *hdl)
Poll the transport layer.
UDSTpSize_t(*) recv(struct UDSTp *hdl, uint8_t *buf, size_t bufsize, UDSSDU_t *info)
Receive data from the transport.
UDSTpSize_t(*) send(struct UDSTp *hdl, const uint8_t *buf, size_t len, const UDSSDU_t *info)
Send data to the transport.
Write data by identifier arguments.
Write memory by address arguments.