16#define STATE_SENDING 1
17#define STATE_AWAIT_SEND_COMPLETE 2
18#define STATE_AWAIT_RESPONSE 3
22 return UDS_ERR_INVALID_ARG;
24 memset(client, 0,
sizeof(*client));
25 client->
state = STATE_IDLE;
27 client->
p2_ms = UDS_CLIENT_DEFAULT_P2_MS;
28 client->
p2_star_ms = UDS_CLIENT_DEFAULT_P2_STAR_MS;
31 UDS_LOGE(__FILE__,
"p2_star_ms must be >= p2_ms");
38static const char *ClientStateName(uint8_t state) {
44 case STATE_AWAIT_SEND_COMPLETE:
45 return "AwaitSendComplete";
46 case STATE_AWAIT_RESPONSE:
47 return "AwaitResponse";
53static void changeState(
UDSClient_t *client, uint8_t state) {
54 if (state != client->
state) {
55 UDS_LOGI(__FILE__,
"client state: %s (%d) -> %s (%d)", ClientStateName(client->
state),
56 client->
state, ClientStateName(state), state);
58 client->
state = state;
66 case STATE_AWAIT_SEND_COMPLETE:
68 case STATE_AWAIT_RESPONSE:
82static UDSErr_t ValidateServerResponse(
const UDSClient_t *client) {
85 return UDS_ERR_RESP_TOO_SHORT;
90 return UDS_ERR_RESP_TOO_SHORT;
92 return UDS_ERR_SID_MISMATCH;
93 }
else if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == client->
recv_buf[2]) {
101 return UDS_ERR_SID_MISMATCH;
103 if (client->
send_buf[0] == kSID_ECU_RESET) {
105 return UDS_ERR_RESP_TOO_SHORT;
107 return UDS_ERR_SUBFUNCTION_MISMATCH;
121static UDSErr_t HandleServerResponse(
UDSClient_t *client) {
123 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == client->
recv_buf[2]) {
125 UDS_LOGI(__FILE__,
"got RCRRP, set p2 timer to %" PRIu32
"", client->
p2_timer);
128 changeState(client, STATE_AWAIT_RESPONSE);
129 return UDS_NRC_RequestCorrectlyReceived_ResponsePending;
134 uint8_t respSid = client->
recv_buf[0];
135 switch (UDS_REQUEST_SID_OF(respSid)) {
136 case kSID_DIAGNOSTIC_SESSION_CONTROL: {
137 if (client->
recv_size < UDS_0X10_RESP_LEN) {
138 UDS_LOGI(__FILE__,
"Error: SID %x response too short",
139 kSID_DIAGNOSTIC_SESSION_CONTROL);
140 changeState(client, STATE_IDLE);
141 return UDS_ERR_RESP_TOO_SHORT;
145 changeState(client, STATE_IDLE);
150 (uint16_t)(((uint16_t)client->
recv_buf[2] << 8) | (uint16_t)client->
recv_buf[3]);
152 UDS_LOGI(__FILE__,
"received new timings: p2: %" PRIu16
", p2*: %" PRIu32, p2, p2_star);
169 UDSErr_t err = UDS_OK;
172 if (NULL == client || NULL == client->
tp || NULL == client->
tp->
poll) {
173 return UDS_ERR_MISUSE;
176 UDSTpStatus_t tp_status = UDSTpPoll(client->
tp);
177 switch (client->
state) {
182 case STATE_SENDING: {
185 ssize_t len = UDSTpRecv(client->
tp, client->
recv_buf,
sizeof(client->
recv_buf), &info);
187 UDS_LOGE(__FILE__,
"transport returned error %zd", len);
188 }
else if (len == 0) {
191 UDS_LOGW(__FILE__,
"received %zd unexpected bytes:", len);
192 UDS_LOG_SDU(__FILE__, client->
recv_buf, len, &info);
199 UDSTpAddr_t ta_type = client->
_options_copy & UDS_FUNCTIONAL ? UDS_A_TA_TYPE_FUNCTIONAL
200 : UDS_A_TA_TYPE_PHYSICAL;
203 .A_TA_Type = ta_type,
208 UDS_LOGI(__FILE__,
"tport err: %zd", ret);
209 }
else if (0 == ret) {
210 UDS_LOGI(__FILE__,
"send in progress...");
213 changeState(client, STATE_AWAIT_SEND_COMPLETE);
215 err = UDS_ERR_BUFSIZ;
219 case STATE_AWAIT_SEND_COMPLETE: {
223 changeState(client, STATE_IDLE);
225 if (tp_status & UDS_TP_SEND_IN_PROGRESS) {
230 changeState(client, STATE_IDLE);
232 changeState(client, STATE_AWAIT_RESPONSE);
238 case STATE_AWAIT_RESPONSE: {
241 ssize_t len = UDSTpRecv(client->
tp, client->
recv_buf,
sizeof(client->
recv_buf), &info);
244 changeState(client, STATE_IDLE);
245 }
else if (0 == len) {
247 UDS_LOGI(__FILE__,
"p2 timeout");
248 err = UDS_ERR_TIMEOUT;
249 changeState(client, STATE_IDLE);
252 UDS_LOGI(__FILE__,
"received %zd bytes. Processing...", len);
253 UDS_ASSERT(len <= (ssize_t)UINT16_MAX);
256 err = ValidateServerResponse(client);
258 err = HandleServerResponse(client);
263 changeState(client, STATE_IDLE);
284 changeState(client, STATE_SENDING);
285 UDSErr_t err = PollLowLevel(client);
289static UDSErr_t PreRequestCheck(
UDSClient_t *client) {
290 if (NULL == client) {
291 return UDS_ERR_INVALID_ARG;
293 if (STATE_IDLE != client->
state) {
300 if (client->
tp == NULL) {
301 return UDS_ERR_TPORT;
306UDSErr_t UDSSendBytes(
UDSClient_t *client,
const uint8_t *data, uint16_t size) {
307 UDSErr_t err = PreRequestCheck(client);
311 if (size >
sizeof(client->
send_buf)) {
312 return UDS_ERR_BUFSIZ;
314 memmove(client->
send_buf, data, size);
316 return SendRequest(client);
319UDSErr_t UDSSendECUReset(
UDSClient_t *client, uint8_t type) {
320 UDSErr_t err = PreRequestCheck(client);
324 client->
send_buf[0] = kSID_ECU_RESET;
327 return SendRequest(client);
330UDSErr_t UDSSendDiagSessCtrl(
UDSClient_t *client, uint8_t mode) {
331 UDSErr_t err = PreRequestCheck(client);
335 client->
send_buf[0] = kSID_DIAGNOSTIC_SESSION_CONTROL;
338 return SendRequest(client);
341UDSErr_t UDSSendCommCtrl(
UDSClient_t *client, uint8_t ctrl, uint8_t comm) {
342 UDSErr_t err = PreRequestCheck(client);
346 client->
send_buf[0] = kSID_COMMUNICATION_CONTROL;
350 return SendRequest(client);
353UDSErr_t UDSSendTesterPresent(
UDSClient_t *client) {
354 UDSErr_t err = PreRequestCheck(client);
358 client->
send_buf[0] = kSID_TESTER_PRESENT;
361 return SendRequest(client);
364UDSErr_t UDSSendRDBI(
UDSClient_t *client,
const uint16_t *didList,
365 const uint16_t numDataIdentifiers) {
366 const uint16_t DID_LEN_BYTES = 2;
367 UDSErr_t err = PreRequestCheck(client);
371 if (NULL == didList || 0 == numDataIdentifiers) {
372 return UDS_ERR_INVALID_ARG;
374 client->
send_buf[0] = kSID_READ_DATA_BY_IDENTIFIER;
375 for (
int i = 0; i < numDataIdentifiers; i++) {
376 uint16_t offset = (uint16_t)(1 + DID_LEN_BYTES * i);
377 if ((
size_t)(offset + 2) >
sizeof(client->
send_buf)) {
378 return UDS_ERR_INVALID_ARG;
380 (client->
send_buf + offset)[0] = (didList[i] & 0xFF00) >> 8;
381 (client->
send_buf + offset)[1] = (didList[i] & 0xFF);
383 client->
send_size = 1 + (numDataIdentifiers * DID_LEN_BYTES);
384 return SendRequest(client);
387UDSErr_t UDSSendWDBI(
UDSClient_t *client, uint16_t dataIdentifier,
const uint8_t *data,
389 UDSErr_t err = PreRequestCheck(client);
393 if (data == NULL || size == 0) {
394 return UDS_ERR_INVALID_ARG;
396 client->
send_buf[0] = kSID_WRITE_DATA_BY_IDENTIFIER;
398 return UDS_ERR_BUFSIZ;
400 client->
send_buf[1] = (dataIdentifier & 0xFF00) >> 8;
401 client->
send_buf[2] = (dataIdentifier & 0xFF);
402 memmove(&client->
send_buf[3], data, size);
404 return SendRequest(client);
418UDSErr_t UDSSendRoutineCtrl(
UDSClient_t *client, uint8_t type, uint16_t routineIdentifier,
419 const uint8_t *data, uint16_t size) {
420 UDSErr_t err = PreRequestCheck(client);
424 client->
send_buf[0] = kSID_ROUTINE_CONTROL;
426 client->
send_buf[2] = routineIdentifier >> 8;
427 client->
send_buf[3] = routineIdentifier & 0xFF;
430 return UDS_ERR_INVALID_ARG;
432 if (size >
sizeof(client->
send_buf) - UDS_0X31_REQ_MIN_LEN) {
433 return UDS_ERR_BUFSIZ;
435 memmove(&client->
send_buf[UDS_0X31_REQ_MIN_LEN], data, size);
438 UDS_LOGI(__FILE__,
"warning: size zero and data non-null");
441 client->
send_size = UDS_0X31_REQ_MIN_LEN + size;
442 return SendRequest(client);
456UDSErr_t UDSSendRequestDownload(
UDSClient_t *client, uint8_t dataFormatIdentifier,
457 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
459 UDSErr_t err = PreRequestCheck(client);
463 uint8_t numMemorySizeBytes = (addressAndLengthFormatIdentifier & 0xF0) >> 4;
464 uint8_t numMemoryAddressBytes = addressAndLengthFormatIdentifier & 0x0F;
466 client->
send_buf[0] = kSID_REQUEST_DOWNLOAD;
467 client->
send_buf[1] = dataFormatIdentifier;
468 client->
send_buf[2] = addressAndLengthFormatIdentifier;
470 uint8_t *ptr = &client->
send_buf[UDS_0X34_REQ_BASE_LEN];
472 for (
int i = numMemoryAddressBytes - 1; i >= 0; i--) {
473 *ptr = (uint8_t)((memoryAddress >> (8 * i)) & 0xFF);
477 for (
int i = numMemorySizeBytes - 1; i >= 0; i--) {
478 *ptr = (uint8_t)((memorySize >> (8 * i)) & 0xFF);
482 client->
send_size = UDS_0X34_REQ_BASE_LEN + numMemoryAddressBytes + numMemorySizeBytes;
483 return SendRequest(client);
497UDSErr_t UDSSendRequestUpload(
UDSClient_t *client, uint8_t dataFormatIdentifier,
498 uint8_t addressAndLengthFormatIdentifier,
size_t memoryAddress,
500 UDSErr_t err = PreRequestCheck(client);
504 uint8_t numMemorySizeBytes = (addressAndLengthFormatIdentifier & 0xF0) >> 4;
505 uint8_t numMemoryAddressBytes = addressAndLengthFormatIdentifier & 0x0F;
507 client->
send_buf[0] = kSID_REQUEST_UPLOAD;
508 client->
send_buf[1] = dataFormatIdentifier;
509 client->
send_buf[2] = addressAndLengthFormatIdentifier;
511 uint8_t *ptr = &client->
send_buf[UDS_0X35_REQ_BASE_LEN];
513 for (
int i = numMemoryAddressBytes - 1; i >= 0; i--) {
514 *ptr = (uint8_t)((memoryAddress >> (8 * i)) & 0xFF);
518 for (
int i = numMemorySizeBytes - 1; i >= 0; i--) {
519 *ptr = (uint8_t)((memorySize >> (8 * i)) & 0xFF);
523 client->
send_size = UDS_0X35_REQ_BASE_LEN + numMemoryAddressBytes + numMemorySizeBytes;
524 return SendRequest(client);
537UDSErr_t UDSSendTransferData(
UDSClient_t *client, uint8_t blockSequenceCounter,
538 const uint16_t blockLength,
const uint8_t *data, uint16_t size) {
539 UDSErr_t err = PreRequestCheck(client);
545 if (blockLength <= 2) {
546 return UDS_ERR_INVALID_ARG;
550 if (size > (blockLength - 2)) {
551 return UDS_ERR_INVALID_ARG;
553 client->
send_buf[0] = kSID_TRANSFER_DATA;
554 client->
send_buf[1] = blockSequenceCounter;
555 memmove(&client->
send_buf[UDS_0X36_REQ_BASE_LEN], data, size);
556 UDS_LOGI(__FILE__,
"size: %d, blocklength: %d", size, blockLength);
557 client->
send_size = UDS_0X36_REQ_BASE_LEN + size;
558 return SendRequest(client);
561UDSErr_t UDSSendTransferDataStream(
UDSClient_t *client, uint8_t blockSequenceCounter,
562 const uint16_t blockLength, FILE *fd) {
563 UDSErr_t err = PreRequestCheck(client);
568 if (blockLength <= 2) {
569 return UDS_ERR_INVALID_ARG;
571 client->
send_buf[0] = kSID_TRANSFER_DATA;
572 client->
send_buf[1] = blockSequenceCounter;
574 size_t _size = fread(&client->
send_buf[2], 1, blockLength - 2, fd);
575 UDS_ASSERT(_size < UINT16_MAX);
576 uint16_t size = (uint16_t)_size;
577 UDS_LOGI(__FILE__,
"size: %d, blocklength: %d", size, blockLength);
578 client->
send_size = UDS_0X36_REQ_BASE_LEN + size;
579 return SendRequest(client);
589UDSErr_t UDSSendRequestTransferExit(
UDSClient_t *client) {
590 UDSErr_t err = PreRequestCheck(client);
594 client->
send_buf[0] = kSID_REQUEST_TRANSFER_EXIT;
596 return SendRequest(client);
599UDSErr_t UDSSendRequestFileTransfer(
UDSClient_t *client, uint8_t mode,
const char *filePath,
600 uint8_t dataFormatIdentifier, uint8_t fileSizeParameterLength,
601 size_t fileSizeUncompressed,
size_t fileSizeCompressed) {
602 UDSErr_t err = PreRequestCheck(client);
606 if (filePath == NULL) {
607 return UDS_ERR_INVALID_ARG;
609 size_t filePathLenSize = strnlen(filePath, UINT16_MAX + 1);
610 if (filePathLenSize == 0) {
611 return UDS_ERR_INVALID_ARG;
613 if (filePathLenSize > UINT16_MAX) {
614 return UDS_ERR_INVALID_ARG;
616 uint16_t filePathLen = (uint16_t)filePathLenSize;
618 uint8_t fileSizeBytes = 0;
620 fileSizeBytes = fileSizeParameterLength;
622 size_t bufSize = 5 + filePathLen + fileSizeBytes + fileSizeBytes;
623 if ((mode ==
UDS_MOOP_ADDFILE) || (mode == UDS_MOOP_REPLFILE) || (mode == UDS_MOOP_RDFILE)) {
626 if (
sizeof(client->
send_buf) < bufSize)
627 return UDS_ERR_BUFSIZ;
629 client->
send_buf[0] = kSID_REQUEST_FILE_TRANSFER;
631 client->
send_buf[2] = (filePathLen >> 8) & 0xFF;
632 client->
send_buf[3] = filePathLen & 0xFF;
633 if (filePathLen >
sizeof(client->
send_buf) - 4)
634 return UDS_ERR_BUFSIZ;
635 memcpy(&client->
send_buf[4], filePath, filePathLen);
636 if ((mode ==
UDS_MOOP_ADDFILE) || (mode == UDS_MOOP_REPLFILE) || (mode == UDS_MOOP_RDFILE)) {
637 client->
send_buf[4 + filePathLen] = dataFormatIdentifier;
640 client->
send_buf[5 + filePathLen] = fileSizeParameterLength;
641 uint8_t *ptr = &client->
send_buf[6 + filePathLen];
642 for (
int i = fileSizeParameterLength - 1; i >= 0; i--) {
643 *ptr = (uint8_t)((fileSizeUncompressed >> (8 * i)) & 0xFF);
647 for (
int i = fileSizeParameterLength - 1; i >= 0; i--) {
648 *ptr = (uint8_t)((fileSizeCompressed >> (8 * i)) & 0xFF);
654 return SendRequest(client);
667UDSErr_t UDSCtrlDTCSetting(
UDSClient_t *client, uint8_t dtcSettingType, uint8_t *data,
669 UDSErr_t err = PreRequestCheck(client);
675 if (0x00 == dtcSettingType || 0x7F == dtcSettingType ||
676 (0x03 <= dtcSettingType && dtcSettingType <= 0x3F)) {
677 return UDS_ERR_INVALID_ARG;
680 client->
send_buf[0] = kSID_CONTROL_DTC_SETTING;
681 client->
send_buf[1] = dtcSettingType;
685 return UDS_ERR_INVALID_ARG;
689 UDS_LOGI(__FILE__,
"warning: size == 0 and data is non-null");
691 if (size >
sizeof(client->
send_buf) - 2) {
692 return UDS_ERR_BUFSIZ;
694 memmove(&client->
send_buf[2], data, size);
697 return SendRequest(client);
710UDSErr_t UDSSendSecurityAccess(
UDSClient_t *client, uint8_t level, uint8_t *data, uint16_t size) {
711 UDSErr_t err = PreRequestCheck(client);
716 return UDS_ERR_INVALID_ARG;
718 client->
send_buf[0] = kSID_SECURITY_ACCESS;
721 if (size >
sizeof(client->
send_buf) - UDS_0X27_REQ_BASE_LEN) {
722 return UDS_ERR_BUFSIZ;
724 if (size == 0 && NULL != data) {
725 UDS_LOGE(__FILE__,
"size == 0 and data is non-null");
726 return UDS_ERR_INVALID_ARG;
728 if (size > 0 && NULL == data) {
729 UDS_LOGE(__FILE__,
"size > 0 but data is null");
730 return UDS_ERR_INVALID_ARG;
733 memmove(&client->
send_buf[UDS_0X27_REQ_BASE_LEN], data, size);
736 client->
send_size = UDS_0X27_REQ_BASE_LEN + size;
737 return SendRequest(client);
748UDSErr_t UDSUnpackSecurityAccessResponse(
const UDSClient_t *client,
750 if (NULL == client || NULL == resp) {
751 return UDS_ERR_INVALID_ARG;
753 if (UDS_RESPONSE_SID_OF(kSID_SECURITY_ACCESS) != client->
recv_buf[0]) {
754 return UDS_ERR_SID_MISMATCH;
756 if (client->
recv_size < UDS_0X27_RESP_BASE_LEN) {
757 return UDS_ERR_RESP_TOO_SHORT;
773UDSErr_t UDSUnpackRoutineControlResponse(
const UDSClient_t *client,
775 if (NULL == client || NULL == resp) {
776 return UDS_ERR_INVALID_ARG;
778 if (UDS_RESPONSE_SID_OF(kSID_ROUTINE_CONTROL) != client->
recv_buf[0]) {
779 return UDS_ERR_SID_MISMATCH;
781 if (client->
recv_size < UDS_0X31_RESP_MIN_LEN) {
782 return UDS_ERR_RESP_TOO_SHORT;
786 (uint16_t)((uint16_t)(client->
recv_buf[2] << 8) | (uint16_t)client->
recv_buf[3]);
801UDSErr_t UDSUnpackRequestDownloadResponse(
const UDSClient_t *client,
803 if (NULL == client || NULL == resp) {
804 return UDS_ERR_INVALID_ARG;
806 if (UDS_RESPONSE_SID_OF(kSID_REQUEST_DOWNLOAD) != client->
recv_buf[0]) {
807 return UDS_ERR_SID_MISMATCH;
809 if (client->
recv_size < UDS_0X34_RESP_BASE_LEN) {
810 return UDS_ERR_RESP_TOO_SHORT;
812 uint8_t maxNumberOfBlockLengthSize = (client->
recv_buf[1] & 0xF0) >> 4;
815 UDS_LOGI(__FILE__,
"WARNING: sizeof(maxNumberOfBlockLength) > sizeof(size_t)");
819 for (uint8_t byteIdx = 0; byteIdx < maxNumberOfBlockLengthSize; byteIdx++) {
820 uint8_t
byte = client->
recv_buf[UDS_0X34_RESP_BASE_LEN + byteIdx];
821 uint8_t shiftBytes = maxNumberOfBlockLengthSize - 1 - byteIdx;
828 if (NULL == client->
fn) {
829 return UDS_ERR_MISUSE;
832 UDSErr_t err = PollLowLevel(client);
834 if (err == UDS_OK || err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
838 changeState(client, STATE_IDLE);
846 uint16_t offset = UDS_0X22_RESP_BASE_LEN;
847 if (client == NULL || vars == NULL) {
848 return UDS_ERR_INVALID_ARG;
850 for (
int i = 0; i < numVars; i++) {
852 if (offset +
sizeof(uint16_t) > client->
recv_size) {
853 return UDS_ERR_RESP_TOO_SHORT;
855 uint16_t did = (uint16_t)((uint16_t)(client->
recv_buf[offset] << 8) |
856 (uint16_t)client->
recv_buf[offset + 1]);
857 if (did != vars[i].did) {
858 return UDS_ERR_DID_MISMATCH;
860 if (offset +
sizeof(uint16_t) + vars[i].
len > client->
recv_size) {
861 return UDS_ERR_RESP_TOO_SHORT;
863 if (vars[i].UnpackFn) {
864 vars[i].
UnpackFn(vars[i].data, client->
recv_buf + offset +
sizeof(uint16_t),
867 return UDS_ERR_INVALID_ARG;
869 offset +=
sizeof(uint16_t) + vars[i].len;
876#line 1 "src/server.c"
880static inline UDSErr_t NegativeResponse(
UDSReq_t *r, UDSErr_t nrc) {
881 if (nrc < 0 || nrc > 0xFF) {
882 UDS_LOGW(__FILE__,
"Invalid negative response code: %d (0x%x)", nrc, nrc);
883 nrc = UDS_NRC_GeneralReject;
896 UDSErr_t err = UDS_OK;
898 err = srv->
fn(srv, evt, data);
900 UDS_LOGI(__FILE__,
"Unhandled UDSEvent %d, srv.fn not installed!\n", evt);
901 err = UDS_NRC_GeneralReject;
903 if (!UDSErrIsNRC(err)) {
904 UDS_LOGW(__FILE__,
"The returned error code %d (0x%x) is not a negative response code", err,
911 if (r->
recv_len < UDS_0X10_REQ_LEN) {
912 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
915 uint8_t sessType = r->
recv_buf[1] & 0x7F;
919 .p2_ms = UDS_CLIENT_DEFAULT_P2_MS,
920 .p2_star_ms = UDS_CLIENT_DEFAULT_P2_STAR_MS,
925 if (UDS_PositiveResponse != err) {
926 return NegativeResponse(r, err);
934 case UDS_LEV_DS_PRGS:
935 case UDS_LEV_DS_EXTDS:
941 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_DIAGNOSTIC_SESSION_CONTROL);
954 return UDS_PositiveResponse;
958 uint8_t resetType = r->
recv_buf[1] & 0x3F;
960 if (r->
recv_len < UDS_0X11_REQ_MIN_LEN) {
961 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
966 .powerDownTimeMillis = UDS_SERVER_DEFAULT_POWER_DOWN_TIME_MS,
971 if (UDS_PositiveResponse == err) {
976 return NegativeResponse(r, err);
979 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_ECU_RESET);
982 if (UDS_LEV_RT_ERPSD == resetType) {
984 if (powerDownTime > 255) {
987 r->
send_buf[2] = powerDownTime & 0xFF;
988 r->
send_len = UDS_0X11_RESP_BASE_LEN + 1;
990 r->
send_len = UDS_0X11_RESP_BASE_LEN;
992 return UDS_PositiveResponse;
996 if (r->
recv_len < UDS_0X14_REQ_MIN_LEN) {
997 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1000 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_CLEAR_DIAGNOSTIC_INFORMATION);
1001 r->
send_len = UDS_0X14_RESP_BASE_LEN;
1005 .hasMemorySelection = (r->
recv_len >= 5),
1011 if (err != UDS_PositiveResponse) {
1012 return NegativeResponse(r, err);
1015 return UDS_PositiveResponse;
1018static uint8_t safe_copy(
UDSServer_t *srv,
const void *src, uint16_t count) {
1020 return UDS_NRC_GeneralReject;
1023 return UDS_NRC_GeneralReject;
1029 return UDS_PositiveResponse;
1031 return UDS_NRC_ResponseTooLong;
1035 UDSErr_t ret = UDS_PositiveResponse;
1038 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN) {
1039 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1043 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_READ_DTC_INFORMATION);
1045 r->
send_len = UDS_0X19_RESP_BASE_LEN;
1055 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1056 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1062 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1063 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1079 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 4) {
1080 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1083 args.
subFuncArgs.dtcSnapshotRecordbyDTCNumArgs.dtc =
1090 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1091 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1097 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 4) {
1098 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1101 args.
subFuncArgs.dtcExtDtaRecordByDTCNumArgs.dtc =
1107 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1108 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1115 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1116 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1123 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1124 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1131 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 5) {
1132 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1135 args.
subFuncArgs.userDefMemDTCSnapshotRecordByDTCNumArgs.dtc =
1141 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 5) {
1142 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1145 args.
subFuncArgs.userDefMemDTCExtDataRecordByDTCNumArgs.dtc =
1151 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 3) {
1152 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1160 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 1) {
1161 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1167 if (r->
recv_len < UDS_0X19_REQ_MIN_LEN + 2) {
1168 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1175 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1180 if (UDS_PositiveResponse != ret) {
1181 return NegativeResponse(r, ret);
1184 if (r->
send_len < UDS_0X19_RESP_BASE_LEN) {
1185 goto respond_to_0x19_malformed_response;
1192 if (r->
send_len != UDS_0X19_RESP_BASE_LEN + 4) {
1193 goto respond_to_0x19_malformed_response;
1203 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1204 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1205 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 1)) % 4 != 0)) {
1206 goto respond_to_0x19_malformed_response;
1211 if ((r->
send_len - UDS_0X19_RESP_BASE_LEN) % 4 != 0) {
1212 goto respond_to_0x19_malformed_response;
1217 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4) {
1218 goto respond_to_0x19_malformed_response;
1223 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1) {
1224 goto respond_to_0x19_malformed_response;
1229 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1230 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1231 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 1)) % 6 != 0)) {
1232 goto respond_to_0x19_malformed_response;
1236 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 2 ||
1237 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 2) &&
1238 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 2)) % 4 != 0)) {
1239 goto respond_to_0x19_malformed_response;
1244 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 5) {
1245 goto respond_to_0x19_malformed_response;
1249 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 1 ||
1250 ((r->
send_len != UDS_0X19_RESP_BASE_LEN + 6) &&
1251 (r->
send_len > UDS_0X19_RESP_BASE_LEN + 1) &&
1252 (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4)) ||
1253 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 6) &&
1254 (r->
send_len - UDS_0X19_RESP_BASE_LEN + 6) % 4 != 0)) {
1255 goto respond_to_0x19_malformed_response;
1259 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4 ||
1260 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 4) &&
1261 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 4)) % 5 != 0)) {
1262 goto respond_to_0x19_malformed_response;
1266 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 3 ||
1267 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 3) &&
1268 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 3)) % 4 != 0)) {
1269 goto respond_to_0x19_malformed_response;
1273 if (r->
send_len < UDS_0X19_RESP_BASE_LEN + 4 ||
1274 ((r->
send_len > UDS_0X19_RESP_BASE_LEN + 4) &&
1275 (r->
send_len - (UDS_0X19_RESP_BASE_LEN + 4)) % 4 != 0)) {
1276 goto respond_to_0x19_malformed_response;
1280 UDS_LOGW(__FILE__,
"RDTCI subFunc 0x%02X is not supported.\n", type);
1281 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1284 return UDS_PositiveResponse;
1285respond_to_0x19_malformed_response:
1286 UDS_LOGE(__FILE__,
"RDTCI subFunc 0x%02X is malformed. Length: %zu\n", type, r->
send_len);
1287 return NegativeResponse(r, UDS_NRC_GeneralReject);
1292 uint16_t dataId = 0;
1293 UDSErr_t ret = UDS_PositiveResponse;
1294 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_READ_DATA_BY_IDENTIFIER);
1297 if (0 != (r->
recv_len - 1) %
sizeof(uint16_t)) {
1298 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1301 numDIDs = (uint8_t)(r->
recv_len /
sizeof(uint16_t));
1304 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1307 for (uint16_t did = 0; did < numDIDs; did++) {
1308 uint16_t idx = (uint16_t)(1 + did * 2);
1309 dataId = (uint16_t)((uint16_t)(r->
recv_buf[idx] << 8) | (uint16_t)r->
recv_buf[idx + 1]);
1312 return NegativeResponse(r, UDS_NRC_ResponseTooLong);
1315 copylocation[0] = dataId >> 8;
1316 copylocation[1] = dataId & 0xFF;
1324 size_t send_len_before = r->
send_len;
1326 if (ret == UDS_PositiveResponse && send_len_before == r->
send_len) {
1327 UDS_LOGE(__FILE__,
"RDBI response positive but no data sent\n");
1328 return NegativeResponse(r, UDS_NRC_GeneralReject);
1331 if (UDS_PositiveResponse != ret) {
1332 return NegativeResponse(r, ret);
1335 return UDS_PositiveResponse;
1350static UDSErr_t decodeAddressAndLengthWithOffset(
UDSReq_t *r, uint8_t *
const buf,
1351 void **memoryAddress,
size_t *memorySize,
1354 UDS_ASSERT(memoryAddress);
1355 UDS_ASSERT(memorySize);
1360 UDS_ASSERT(buf >= r->
recv_buf && buf <= r->recv_buf +
sizeof(r->
recv_buf));
1363 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1366 uint8_t memorySizeLength = (buf[0] & 0xF0) >> 4;
1367 uint8_t memoryAddressLength = buf[0] & 0x0F;
1368 size_t offsetBytes = offset * (memoryAddressLength + memorySizeLength);
1370 if (memorySizeLength == 0 || memorySizeLength >
sizeof(
size_t)) {
1371 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1374 if (memoryAddressLength == 0 || memoryAddressLength >
sizeof(
size_t)) {
1375 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1378 if (buf + 1 + offsetBytes + memorySizeLength + memoryAddressLength >
1380 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1383 for (
int byteIdx = 0; byteIdx < memoryAddressLength; byteIdx++) {
1384 long long unsigned int byte = buf[1 + offsetBytes + byteIdx];
1385 uint8_t shiftBytes = (uint8_t)(memoryAddressLength - 1 - byteIdx);
1386 tmp |=
byte << (8 * shiftBytes);
1388 *memoryAddress = (
void *)tmp;
1390 for (
int byteIdx = 0; byteIdx < memorySizeLength; byteIdx++) {
1391 uint8_t
byte = buf[1 + offsetBytes + memoryAddressLength + byteIdx];
1392 uint8_t shiftBytes = (uint8_t)(memorySizeLength - 1 - byteIdx);
1393 *memorySize |= (size_t)
byte << (8 * shiftBytes);
1395 return UDS_PositiveResponse;
1408static UDSErr_t decodeAddressAndLength(
UDSReq_t *r, uint8_t *
const buf,
void **memoryAddress,
1409 size_t *memorySize) {
1410 return decodeAddressAndLengthWithOffset(r, buf, memoryAddress, memorySize, 0);
1414 UDSErr_t ret = UDS_PositiveResponse;
1418 if (r->
recv_len < UDS_0X23_REQ_MIN_LEN) {
1419 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1422 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
1423 if (UDS_PositiveResponse != ret) {
1424 return NegativeResponse(r, ret);
1433 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_READ_MEMORY_BY_ADDRESS);
1434 r->
send_len = UDS_0X23_RESP_BASE_LEN;
1436 if (UDS_PositiveResponse != ret) {
1437 return NegativeResponse(r, ret);
1439 if (r->
send_len != UDS_0X23_RESP_BASE_LEN + length) {
1440 UDS_LOGE(__FILE__,
"response positive but not all data sent: expected %zu, sent %zu",
1441 length, r->
send_len - UDS_0X23_RESP_BASE_LEN);
1442 return NegativeResponse(r, UDS_NRC_GeneralReject);
1444 return UDS_PositiveResponse;
1448 uint8_t subFunction = r->
recv_buf[1];
1449 UDSErr_t response = UDS_PositiveResponse;
1452 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1456 return NegativeResponse(r, UDS_NRC_RequiredTimeDelayNotExpired);
1460 return NegativeResponse(r, UDS_NRC_ExceedNumberOfAttempts);
1463 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_SECURITY_ACCESS);
1465 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1468 if (0 == subFunction % 2) {
1469 uint8_t requestedLevel = subFunction - 1;
1471 .level = requestedLevel,
1472 .key = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1473 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1478 if (UDS_PositiveResponse != response) {
1480 UDSMillis() + UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_AUTH_FAIL_DELAY_MS;
1481 return NegativeResponse(r, response);
1489 r->
send_len = UDS_0X27_RESP_BASE_LEN;
1490 return UDS_PositiveResponse;
1505 const uint8_t already_unlocked[] = {0x00, 0x00};
1506 return safe_copy(srv, already_unlocked,
sizeof(already_unlocked));
1509 .level = subFunction,
1510 .dataRecord = &r->
recv_buf[UDS_0X27_REQ_BASE_LEN],
1511 .len = (uint16_t)(r->
recv_len - UDS_0X27_REQ_BASE_LEN),
1512 .copySeed = safe_copy,
1517 if (UDS_PositiveResponse != response) {
1518 return NegativeResponse(r, response);
1521 if (r->
send_len <= UDS_0X27_RESP_BASE_LEN) {
1522 UDS_LOGE(__FILE__,
"0x27: no seed data was copied");
1523 return NegativeResponse(r, UDS_NRC_GeneralReject);
1525 return UDS_PositiveResponse;
1531 uint8_t controlType = r->
recv_buf[1] & 0x7F;
1532 uint8_t communicationType = r->
recv_buf[2];
1534 if (r->
recv_len < UDS_0X28_REQ_BASE_LEN) {
1535 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1539 .ctrlType = controlType,
1540 .commType = communicationType,
1544 if (args.ctrlType == 0x04 || args.ctrlType == 0x05) {
1545 if (r->
recv_len < UDS_0X28_REQ_BASE_LEN + 2) {
1546 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1552 if (UDS_PositiveResponse != err) {
1553 return NegativeResponse(r, err);
1556 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_COMMUNICATION_CONTROL);
1559 return UDS_PositiveResponse;
1563 UDSErr_t ret = UDS_PositiveResponse;
1566 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN) {
1567 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1570 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER);
1575 r->
send_len = UDS_0X2C_RESP_BASE_LEN + 2;
1579 .allDataIds =
false,
1581 (uint16_t)((uint16_t)r->
recv_buf[2] << 8 | (uint16_t)r->
recv_buf[3]) & 0xFFFF,
1590 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN + 2 + 4 ||
1591 (r->
recv_len - (UDS_0X2C_REQ_MIN_LEN + 2)) % 4 != 0) {
1592 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1595 size_t numDIDs = (r->
recv_len - 4) / 4;
1597 for (
size_t i = 0; i < numDIDs; i++) {
1599 (uint16_t)((uint16_t)r->
recv_buf[4 + i * 4] << 8 |
1600 (uint16_t)r->
recv_buf[5 + i * 4]) &
1607 if (UDS_PositiveResponse != ret) {
1608 return NegativeResponse(r, ret);
1612 return UDS_PositiveResponse;
1621 if (r->
recv_len < UDS_0X2C_REQ_MIN_LEN + 5) {
1622 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1625 size_t bytesPerAddrAndSize = ((r->
recv_buf[4] & 0xF0) >> 4) + (r->
recv_buf[4] & 0x0F);
1627 if (bytesPerAddrAndSize == 0) {
1629 "DDDI: define By Memory Address request with invalid "
1630 "AddressAndLengthFormatIdentifier: 0x%02X\n",
1632 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1635 if ((r->
recv_len - 5) % bytesPerAddrAndSize != 0) {
1636 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1639 size_t numAddrs = (r->
recv_len - 5) / bytesPerAddrAndSize;
1641 for (
size_t i = 0; i < numAddrs; i++) {
1642 ret = decodeAddressAndLengthWithOffset(r, &r->
recv_buf[4],
1646 if (UDS_PositiveResponse != ret) {
1647 return NegativeResponse(r, ret);
1652 if (UDS_PositiveResponse != ret) {
1653 return NegativeResponse(r, ret);
1657 return UDS_PositiveResponse;
1662 if (r->
recv_len == UDS_0X2C_REQ_MIN_LEN) {
1664 r->
send_len = UDS_0X2C_RESP_BASE_LEN;
1668 if (UDS_PositiveResponse != ret) {
1669 return NegativeResponse(r, ret);
1672 return UDS_PositiveResponse;
1675 UDS_LOGW(__FILE__,
"Unsupported DDDI subFunc 0x%02X\n", type);
1676 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
1681 uint16_t dataLen = 0;
1682 uint16_t dataId = 0;
1683 UDSErr_t err = UDS_PositiveResponse;
1686 if (r->
recv_len < UDS_0X2E_REQ_MIN_LEN) {
1687 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1690 dataId = (uint16_t)((uint16_t)(r->
recv_buf[1] << 8) | (uint16_t)r->
recv_buf[2]);
1691 dataLen = (uint16_t)(r->
recv_len - UDS_0X2E_REQ_BASE_LEN);
1695 .data = &r->
recv_buf[UDS_0X2E_REQ_BASE_LEN],
1700 if (UDS_PositiveResponse != err) {
1701 return NegativeResponse(r, err);
1704 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_WRITE_DATA_BY_IDENTIFIER);
1708 return UDS_PositiveResponse;
1712 if (r->
recv_len < UDS_0X2F_REQ_MIN_LEN) {
1713 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1716 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_IO_CONTROL_BY_IDENTIFIER);
1720 r->
send_len = UDS_0X2F_RESP_BASE_LEN;
1725 .ctrlStateAndMask = &r->
recv_buf[UDS_0X2F_REQ_MIN_LEN],
1726 .ctrlStateAndMaskLen = r->
recv_len - UDS_0X2F_REQ_MIN_LEN,
1732 if (err != UDS_PositiveResponse) {
1733 return NegativeResponse(r, err);
1736 return UDS_PositiveResponse;
1740 UDSErr_t err = UDS_PositiveResponse;
1741 if (r->
recv_len < UDS_0X31_REQ_MIN_LEN) {
1742 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1745 uint8_t routineControlType = r->
recv_buf[1] & 0x7F;
1746 uint16_t routineIdentifier =
1750 .ctrlType = routineControlType,
1751 .id = routineIdentifier,
1752 .optionRecord = &r->
recv_buf[UDS_0X31_REQ_MIN_LEN],
1753 .len = (uint16_t)(r->
recv_len - UDS_0X31_REQ_MIN_LEN),
1754 .copyStatusRecord = safe_copy,
1757 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_ROUTINE_CONTROL);
1758 r->
send_buf[1] = routineControlType;
1759 r->
send_buf[2] = routineIdentifier >> 8;
1760 r->
send_buf[3] = routineIdentifier & 0xFF;
1761 r->
send_len = UDS_0X31_RESP_MIN_LEN;
1763 switch (routineControlType) {
1765 case UDS_LEV_RCTP_STPR:
1766 case UDS_LEV_RCTP_RRR:
1768 if (UDS_PositiveResponse != err) {
1769 return NegativeResponse(r, err);
1773 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
1775 return UDS_PositiveResponse;
1787 UDSErr_t err = UDS_PositiveResponse;
1788 void *memoryAddress = 0;
1789 size_t memorySize = 0;
1792 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
1795 if (r->
recv_len < UDS_0X34_REQ_BASE_LEN) {
1796 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1799 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
1800 if (UDS_PositiveResponse != err) {
1801 return NegativeResponse(r, err);
1805 .addr = memoryAddress,
1807 .dataFormatIdentifier = r->
recv_buf[1],
1814 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
1815 return NegativeResponse(r, UDS_NRC_GeneralReject);
1818 if (UDS_PositiveResponse != err) {
1819 return NegativeResponse(r, err);
1841 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_REQUEST_DOWNLOAD);
1842 r->
send_buf[1] = lengthFormatIdentifier;
1846 r->
send_buf[UDS_0X34_RESP_BASE_LEN + idx] = byte;
1849 return UDS_PositiveResponse;
1853 UDSErr_t err = UDS_PositiveResponse;
1854 void *memoryAddress = 0;
1855 size_t memorySize = 0;
1858 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
1861 if (r->
recv_len < UDS_0X35_REQ_BASE_LEN) {
1862 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
1865 err = decodeAddressAndLength(r, &r->
recv_buf[2], &memoryAddress, &memorySize);
1866 if (UDS_PositiveResponse != err) {
1867 return NegativeResponse(r, err);
1871 .addr = memoryAddress,
1873 .dataFormatIdentifier = r->
recv_buf[1],
1880 UDS_LOGE(__FILE__,
"maxNumberOfBlockLength too short");
1881 return NegativeResponse(r, UDS_NRC_GeneralReject);
1884 if (UDS_PositiveResponse != err) {
1885 return NegativeResponse(r, err);
1895 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_REQUEST_UPLOAD);
1896 r->
send_buf[1] = lengthFormatIdentifier;
1900 r->
send_buf[UDS_0X35_RESP_BASE_LEN + idx] = byte;
1903 return UDS_PositiveResponse;
1907 UDSErr_t err = UDS_PositiveResponse;
1908 uint16_t request_data_len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN);
1909 uint8_t blockSequenceCounter = 0;
1912 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
1915 if (r->
recv_len < UDS_0X36_REQ_BASE_LEN) {
1916 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
1920 blockSequenceCounter = r->
recv_buf[1];
1924 err = UDS_NRC_RequestSequenceError;
1932 err = UDS_NRC_TransferDataSuspended;
1938 .data = &r->
recv_buf[UDS_0X36_REQ_BASE_LEN],
1939 .len = (uint16_t)(r->
recv_len - UDS_0X36_REQ_BASE_LEN),
1940 .maxRespLen = (uint16_t)(srv->
xferBlockLength - UDS_0X36_RESP_BASE_LEN),
1941 .copyResponse = safe_copy,
1944 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_TRANSFER_DATA);
1945 r->
send_buf[1] = blockSequenceCounter;
1946 r->
send_len = UDS_0X36_RESP_BASE_LEN;
1950 if (err == UDS_PositiveResponse) {
1952 return UDS_PositiveResponse;
1953 }
else if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
1954 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
1962 return NegativeResponse(r, err);
1966 UDSErr_t err = UDS_PositiveResponse;
1969 return NegativeResponse(r, UDS_NRC_UploadDownloadNotAccepted);
1972 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_REQUEST_TRANSFER_EXIT);
1973 r->
send_len = UDS_0X37_RESP_BASE_LEN;
1976 .data = &r->
recv_buf[UDS_0X37_REQ_BASE_LEN],
1977 .len = (uint16_t)(r->
recv_len - UDS_0X37_REQ_BASE_LEN),
1978 .copyResponse = safe_copy,
1983 if (err == UDS_PositiveResponse) {
1985 return UDS_PositiveResponse;
1986 }
else if (err == UDS_NRC_RequestCorrectlyReceived_ResponsePending) {
1987 return NegativeResponse(r, UDS_NRC_RequestCorrectlyReceived_ResponsePending);
1990 return NegativeResponse(r, err);
1995 UDSErr_t err = UDS_PositiveResponse;
1998 return NegativeResponse(r, UDS_NRC_ConditionsNotCorrect);
2000 if (r->
recv_len < UDS_0X38_REQ_BASE_LEN) {
2001 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2004 uint8_t mode_of_operation = r->
recv_buf[1];
2005 if (mode_of_operation < UDS_MOOP_ADDFILE || mode_of_operation > UDS_MOOP_RDFILE) {
2006 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2008 uint16_t file_path_len = (uint16_t)(((uint16_t)r->
recv_buf[2] << 8) + (uint16_t)r->
recv_buf[3]);
2009 uint8_t data_format_identifier = 0;
2010 uint8_t file_size_parameter_length = 0;
2011 size_t file_size_uncompressed = 0;
2012 size_t file_size_compressed = 0;
2013 uint16_t byte_idx = 4 + file_path_len;
2016 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2019 if ((mode_of_operation == UDS_MOOP_DELFILE) || (mode_of_operation == UDS_MOOP_RDDIR)) {
2024 data_format_identifier = r->
recv_buf[byte_idx];
2028 if ((mode_of_operation == UDS_MOOP_DELFILE) || (mode_of_operation == UDS_MOOP_RDFILE) ||
2029 (mode_of_operation == UDS_MOOP_RDDIR)) {
2039 file_size_parameter_length = r->
recv_buf[byte_idx];
2042 static_assert(
sizeof(file_size_uncompressed) ==
sizeof(file_size_compressed),
2043 "Both should be k-byte numbers per Table 480");
2044 if (file_size_parameter_length >
sizeof(file_size_compressed)) {
2045 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
2047 if (byte_idx + 2 * file_size_uncompressed > r->
recv_len) {
2048 return NegativeResponse(r, UDS_NRC_RequestOutOfRange);
2050 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2051 uint8_t data_byte = r->
recv_buf[byte_idx];
2052 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2053 file_size_uncompressed |= (size_t)data_byte << (8 * shift_by_bytes);
2056 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2057 uint8_t data_byte = r->
recv_buf[byte_idx];
2058 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2059 file_size_compressed |= (size_t)data_byte << (8 * shift_by_bytes);
2065 .modeOfOperation = mode_of_operation,
2066 .filePathLen = file_path_len,
2068 .dataFormatIdentifier = data_format_identifier,
2069 .fileSizeUnCompressed = file_size_uncompressed,
2070 .fileSizeCompressed = file_size_compressed,
2075 if (UDS_PositiveResponse != err) {
2076 return NegativeResponse(r, err);
2088 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_REQUEST_FILE_TRANSFER);
2089 r->
send_buf[1] = args.modeOfOperation;
2094 r->
send_buf[UDS_0X38_RESP_BASE_LEN + idx] = byte;
2100 return UDS_PositiveResponse;
2104 UDSErr_t ret = UDS_PositiveResponse;
2108 if (r->
recv_len < UDS_0X3D_REQ_MIN_LEN) {
2109 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2112 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
2113 if (UDS_PositiveResponse != ret) {
2114 return NegativeResponse(r, ret);
2117 uint8_t memorySizeLength = (r->
recv_buf[1] & 0xF0) >> 4;
2118 uint8_t memoryAddressLength = r->
recv_buf[1] & 0x0F;
2120 uint8_t dataOffset = 2 + memorySizeLength + memoryAddressLength;
2122 if (dataOffset + length != r->
recv_len) {
2123 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2133 if (UDS_PositiveResponse != ret) {
2134 return NegativeResponse(r, ret);
2137 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_WRITE_MEMORY_BY_ADDRESS);
2139 memcpy(&r->
send_buf[1], &r->
recv_buf[1], 1 + memorySizeLength + memoryAddressLength);
2140 r->
send_len = UDS_0X3D_RESP_BASE_LEN + memorySizeLength + memoryAddressLength;
2141 return UDS_PositiveResponse;
2145 if ((r->
recv_len < UDS_0X3E_REQ_MIN_LEN) || (r->
recv_len > UDS_0X3E_REQ_MAX_LEN)) {
2146 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2148 uint8_t zeroSubFunction = r->
recv_buf[1];
2150 switch (zeroSubFunction) {
2154 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_TESTER_PRESENT);
2157 return UDS_PositiveResponse;
2159 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
2165 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2166 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2169 uint8_t type = r->
recv_buf[1] & 0x7F;
2174 .len = r->
recv_len > UDS_0X85_REQ_BASE_LEN ? r->
recv_len - UDS_0X85_REQ_BASE_LEN : 0,
2178 if (UDS_PositiveResponse != ret) {
2179 return NegativeResponse(r, ret);
2182 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_CONTROL_DTC_SETTING);
2185 return UDS_PositiveResponse;
2189 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2190 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2193 uint8_t type = r->
recv_buf[1] & 0x7F;
2195 if (type == 0x03 && (r->
recv_buf[1] & 0x80) == 0 &&
2197 UDS_LOGW(__FILE__,
"0x87 LinkControl: Transitioning mode without suppressing response!");
2200 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_LINK_CONTROL);
2207 .len = (r->
recv_len - UDS_0X87_REQ_BASE_LEN),
2208 .data = &r->
recv_buf[UDS_0X87_REQ_BASE_LEN],
2212 if (ret != UDS_PositiveResponse) {
2213 return NegativeResponse(r, ret);
2216 return UDS_PositiveResponse;
2226static UDSService getServiceForSID(uint8_t sid) {
2228 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2229 return &Handle_0x10_DiagnosticSessionControl;
2230 case kSID_ECU_RESET:
2231 return &Handle_0x11_ECUReset;
2232 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2233 return &Handle_0x14_ClearDiagnosticInformation;
2234 case kSID_READ_DTC_INFORMATION:
2235 return Handle_0x19_ReadDTCInformation;
2236 case kSID_READ_DATA_BY_IDENTIFIER:
2237 return &Handle_0x22_ReadDataByIdentifier;
2238 case kSID_READ_MEMORY_BY_ADDRESS:
2239 return &Handle_0x23_ReadMemoryByAddress;
2240 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2242 case kSID_SECURITY_ACCESS:
2243 return &Handle_0x27_SecurityAccess;
2244 case kSID_COMMUNICATION_CONTROL:
2245 return &Handle_0x28_CommunicationControl;
2246 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2248 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2249 return &Handle_0x2C_DynamicDefineDataIdentifier;
2250 case kSID_WRITE_DATA_BY_IDENTIFIER:
2251 return &Handle_0x2E_WriteDataByIdentifier;
2252 case kSID_IO_CONTROL_BY_IDENTIFIER:
2253 return &Handle_0x2F_IOControlByIdentifier;
2254 case kSID_ROUTINE_CONTROL:
2255 return &Handle_0x31_RoutineControl;
2256 case kSID_REQUEST_DOWNLOAD:
2257 return &Handle_0x34_RequestDownload;
2258 case kSID_REQUEST_UPLOAD:
2259 return &Handle_0x35_RequestUpload;
2260 case kSID_TRANSFER_DATA:
2261 return &Handle_0x36_TransferData;
2262 case kSID_REQUEST_TRANSFER_EXIT:
2263 return &Handle_0x37_RequestTransferExit;
2264 case kSID_REQUEST_FILE_TRANSFER:
2265 return &Handle_0x38_RequestFileTransfer;
2266 case kSID_WRITE_MEMORY_BY_ADDRESS:
2267 return &Handle_0x3D_WriteMemoryByAddress;
2268 case kSID_TESTER_PRESENT:
2269 return &Handle_0x3E_TesterPresent;
2270 case kSID_ACCESS_TIMING_PARAMETER:
2272 case kSID_SECURED_DATA_TRANSMISSION:
2274 case kSID_CONTROL_DTC_SETTING:
2275 return &Handle_0x85_ControlDTCSetting;
2276 case kSID_RESPONSE_ON_EVENT:
2278 case kSID_LINK_CONTROL:
2279 return &Handle_0x87_LinkControl;
2281 UDS_LOGI(__FILE__,
"no handler for request SID %x", sid);
2294 UDSErr_t response = UDS_PositiveResponse;
2295 bool suppressResponse =
false;
2297 UDSService service = getServiceForSID(sid);
2299 if (NULL == srv->
fn)
2300 return NegativeResponse(r, UDS_NRC_ServiceNotSupported);
2301 UDS_ASSERT(srv->
fn);
2306 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2307 case kSID_ECU_RESET:
2308 case kSID_SECURITY_ACCESS:
2309 case kSID_COMMUNICATION_CONTROL:
2310 case kSID_ROUTINE_CONTROL:
2311 case kSID_TESTER_PRESENT:
2312 case kSID_CONTROL_DTC_SETTING:
2313 case kSID_LINK_CONTROL: {
2314 UDS_ASSERT(service);
2315 response = service(srv, r);
2317 bool suppressPosRspMsgIndicationBit = r->
recv_buf[1] & 0x80;
2320 if (suppressPosRspMsgIndicationBit && (response == UDS_PositiveResponse) &&
2324 suppressResponse =
true;
2326 suppressResponse =
false;
2333 case kSID_READ_DATA_BY_IDENTIFIER:
2334 case kSID_READ_MEMORY_BY_ADDRESS:
2335 case kSID_WRITE_DATA_BY_IDENTIFIER:
2336 case kSID_REQUEST_DOWNLOAD:
2337 case kSID_REQUEST_UPLOAD:
2338 case kSID_TRANSFER_DATA:
2339 case kSID_REQUEST_FILE_TRANSFER:
2340 case kSID_REQUEST_TRANSFER_EXIT: {
2341 UDS_ASSERT(service);
2342 response = service(srv, r);
2347 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2348 case kSID_READ_DTC_INFORMATION:
2349 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2350 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2351 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2352 case kSID_IO_CONTROL_BY_IDENTIFIER:
2353 case kSID_WRITE_MEMORY_BY_ADDRESS:
2354 case kSID_ACCESS_TIMING_PARAMETER:
2355 case kSID_SECURED_DATA_TRANSMISSION:
2356 case kSID_RESPONSE_ON_EVENT:
2359 response = service(srv, r);
2364 .len = (uint16_t)(r->
recv_len - 1),
2365 .copyResponse = safe_copy,
2368 r->
send_buf[0] = UDS_RESPONSE_SID_OF(sid);
2372 if (UDS_PositiveResponse != response)
2373 return NegativeResponse(r, response);
2380 ((UDS_NRC_ServiceNotSupported == response) ||
2381 (UDS_NRC_SubFunctionNotSupported == response) ||
2382 (UDS_NRC_ServiceNotSupportedInActiveSession == response) ||
2383 (UDS_NRC_SubFunctionNotSupportedInActiveSession == response) ||
2384 (UDS_NRC_RequestOutOfRange == response)) &&
2389 suppressResponse =
true;
2392 if (suppressResponse) {
2406 return UDS_ERR_INVALID_ARG;
2409 srv->
p2_ms = UDS_SERVER_DEFAULT_P2_MS;
2410 srv->
p2_star_ms = UDS_SERVER_DEFAULT_P2_STAR_MS;
2411 srv->
s3_ms = UDS_SERVER_DEFAULT_S3_MS;
2416 UDSMillis() + UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_BOOT_DELAY_MS;
2443 UDSErr_t response = evaluateServiceResponse(srv, r);
2444 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2465 UDSErr_t err = UDS_ERR_TPORT;
2467 UDS_LOGE(__FILE__,
"UDSTpSend failed with %zd\n", ret);
2473 uint32_t wait_time = srv->
p2_star_ms * 3 / 10;
2487 UDS_LOGE(__FILE__,
"UDSTpRecv failed with %zd\n", r->
recv_len);
2494 UDSErr_t response = evaluateServiceResponse(srv, r);
2496 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2508ssize_t UDSTpSend(
struct UDSTp *hdl,
const uint8_t *buf, ssize_t len,
UDSSDU_t *info) {
2510 UDS_ASSERT(hdl->send);
2511 return hdl->send(hdl, (uint8_t *)buf, len, info);
2514ssize_t UDSTpRecv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
2516 UDS_ASSERT(hdl->recv);
2517 return hdl->recv(hdl, buf, bufsize, info);
2520UDSTpStatus_t UDSTpPoll(
struct UDSTp *hdl) {
2522 UDS_ASSERT(hdl->poll);
2523 return hdl->poll(hdl);
2530#if UDS_CUSTOM_MILLIS
2533#if UDS_SYS == UDS_SYS_UNIX
2535 gettimeofday(&te, NULL);
2536 long long milliseconds = (te.tv_sec * 1000LL) + (te.tv_usec / 1000);
2537 return (uint32_t)milliseconds;
2538#elif UDS_SYS == UDS_SYS_WINDOWS
2540 timespec_get(&ts, TIME_UTC);
2541 long long milliseconds = ts.tv_sec * 1000LL + ts.tv_nsec / 1000000;
2542 return (uint32_t)milliseconds;
2543#elif UDS_SYS == UDS_SYS_ARDUINO
2545#elif UDS_SYS == UDS_SYS_ESP32
2546 return esp_timer_get_time() / 1000;
2548#error "UDSMillis() undefined!"
2561 uint8_t securityLevel = subFunction & 0x3F;
2562 if (0u == securityLevel) {
2565 if ((securityLevel >= 0x43u) && (securityLevel <= 0x5Eu)) {
2568 if (securityLevel == 0x7Fu) {
2574const char *UDSErrToStr(UDSErr_t err) {
2580 case UDS_NRC_GeneralReject:
2581 return "UDS_NRC_GeneralReject";
2582 case UDS_NRC_ServiceNotSupported:
2583 return "UDS_NRC_ServiceNotSupported";
2584 case UDS_NRC_SubFunctionNotSupported:
2585 return "UDS_NRC_SubFunctionNotSupported";
2586 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2587 return "UDS_NRC_IncorrectMessageLengthOrInvalidFormat";
2588 case UDS_NRC_ResponseTooLong:
2589 return "UDS_NRC_ResponseTooLong";
2590 case UDS_NRC_BusyRepeatRequest:
2591 return "UDS_NRC_BusyRepeatRequest";
2592 case UDS_NRC_ConditionsNotCorrect:
2593 return "UDS_NRC_ConditionsNotCorrect";
2594 case UDS_NRC_RequestSequenceError:
2595 return "UDS_NRC_RequestSequenceError";
2596 case UDS_NRC_NoResponseFromSubnetComponent:
2597 return "UDS_NRC_NoResponseFromSubnetComponent";
2598 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2599 return "UDS_NRC_FailurePreventsExecutionOfRequestedAction";
2600 case UDS_NRC_RequestOutOfRange:
2601 return "UDS_NRC_RequestOutOfRange";
2602 case UDS_NRC_SecurityAccessDenied:
2603 return "UDS_NRC_SecurityAccessDenied";
2604 case UDS_NRC_AuthenticationRequired:
2605 return "UDS_NRC_AuthenticationRequired";
2606 case UDS_NRC_InvalidKey:
2607 return "UDS_NRC_InvalidKey";
2608 case UDS_NRC_ExceedNumberOfAttempts:
2609 return "UDS_NRC_ExceedNumberOfAttempts";
2610 case UDS_NRC_RequiredTimeDelayNotExpired:
2611 return "UDS_NRC_RequiredTimeDelayNotExpired";
2612 case UDS_NRC_SecureDataTransmissionRequired:
2613 return "UDS_NRC_SecureDataTransmissionRequired";
2614 case UDS_NRC_SecureDataTransmissionNotAllowed:
2615 return "UDS_NRC_SecureDataTransmissionNotAllowed";
2616 case UDS_NRC_SecureDataVerificationFailed:
2617 return "UDS_NRC_SecureDataVerificationFailed";
2618 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2619 return "UDS_NRC_CertficateVerificationFailedInvalidTimePeriod";
2620 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2621 return "UDS_NRC_CertficateVerificationFailedInvalidSignature";
2622 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2623 return "UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust";
2624 case UDS_NRC_CertficateVerificationFailedInvalidType:
2625 return "UDS_NRC_CertficateVerificationFailedInvalidType";
2626 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2627 return "UDS_NRC_CertficateVerificationFailedInvalidFormat";
2628 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2629 return "UDS_NRC_CertficateVerificationFailedInvalidContent";
2630 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2631 return "UDS_NRC_CertficateVerificationFailedInvalidScope";
2632 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2633 return "UDS_NRC_CertficateVerificationFailedInvalidCertificate";
2634 case UDS_NRC_OwnershipVerificationFailed:
2635 return "UDS_NRC_OwnershipVerificationFailed";
2636 case UDS_NRC_ChallengeCalculationFailed:
2637 return "UDS_NRC_ChallengeCalculationFailed";
2638 case UDS_NRC_SettingAccessRightsFailed:
2639 return "UDS_NRC_SettingAccessRightsFailed";
2640 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2641 return "UDS_NRC_SessionKeyCreationOrDerivationFailed";
2642 case UDS_NRC_ConfigurationDataUsageFailed:
2643 return "UDS_NRC_ConfigurationDataUsageFailed";
2644 case UDS_NRC_DeAuthenticationFailed:
2645 return "UDS_NRC_DeAuthenticationFailed";
2646 case UDS_NRC_UploadDownloadNotAccepted:
2647 return "UDS_NRC_UploadDownloadNotAccepted";
2648 case UDS_NRC_TransferDataSuspended:
2649 return "UDS_NRC_TransferDataSuspended";
2650 case UDS_NRC_GeneralProgrammingFailure:
2651 return "UDS_NRC_GeneralProgrammingFailure";
2652 case UDS_NRC_WrongBlockSequenceCounter:
2653 return "UDS_NRC_WrongBlockSequenceCounter";
2654 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2655 return "UDS_NRC_RequestCorrectlyReceived_ResponsePending";
2656 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2657 return "UDS_NRC_SubFunctionNotSupportedInActiveSession";
2658 case UDS_NRC_ServiceNotSupportedInActiveSession:
2659 return "UDS_NRC_ServiceNotSupportedInActiveSession";
2660 case UDS_NRC_RpmTooHigh:
2661 return "UDS_NRC_RpmTooHigh";
2662 case UDS_NRC_RpmTooLow:
2663 return "UDS_NRC_RpmTooLow";
2664 case UDS_NRC_EngineIsRunning:
2665 return "UDS_NRC_EngineIsRunning";
2666 case UDS_NRC_EngineIsNotRunning:
2667 return "UDS_NRC_EngineIsNotRunning";
2668 case UDS_NRC_EngineRunTimeTooLow:
2669 return "UDS_NRC_EngineRunTimeTooLow";
2670 case UDS_NRC_TemperatureTooHigh:
2671 return "UDS_NRC_TemperatureTooHigh";
2672 case UDS_NRC_TemperatureTooLow:
2673 return "UDS_NRC_TemperatureTooLow";
2674 case UDS_NRC_VehicleSpeedTooHigh:
2675 return "UDS_NRC_VehicleSpeedTooHigh";
2676 case UDS_NRC_VehicleSpeedTooLow:
2677 return "UDS_NRC_VehicleSpeedTooLow";
2678 case UDS_NRC_ThrottlePedalTooHigh:
2679 return "UDS_NRC_ThrottlePedalTooHigh";
2680 case UDS_NRC_ThrottlePedalTooLow:
2681 return "UDS_NRC_ThrottlePedalTooLow";
2682 case UDS_NRC_TransmissionRangeNotInNeutral:
2683 return "UDS_NRC_TransmissionRangeNotInNeutral";
2684 case UDS_NRC_TransmissionRangeNotInGear:
2685 return "UDS_NRC_TransmissionRangeNotInGear";
2686 case UDS_NRC_BrakeSwitchNotClosed:
2687 return "UDS_NRC_BrakeSwitchNotClosed";
2688 case UDS_NRC_ShifterLeverNotInPark:
2689 return "UDS_NRC_ShifterLeverNotInPark";
2690 case UDS_NRC_TorqueConverterClutchLocked:
2691 return "UDS_NRC_TorqueConverterClutchLocked";
2692 case UDS_NRC_VoltageTooHigh:
2693 return "UDS_NRC_VoltageTooHigh";
2694 case UDS_NRC_VoltageTooLow:
2695 return "UDS_NRC_VoltageTooLow";
2696 case UDS_NRC_ResourceTemporarilyNotAvailable:
2697 return "UDS_NRC_ResourceTemporarilyNotAvailable";
2698 case UDS_ERR_TIMEOUT:
2699 return "UDS_ERR_TIMEOUT";
2700 case UDS_ERR_DID_MISMATCH:
2701 return "UDS_ERR_DID_MISMATCH";
2702 case UDS_ERR_SID_MISMATCH:
2703 return "UDS_ERR_SID_MISMATCH";
2704 case UDS_ERR_SUBFUNCTION_MISMATCH:
2705 return "UDS_ERR_SUBFUNCTION_MISMATCH";
2707 return "UDS_ERR_TPORT";
2708 case UDS_ERR_RESP_TOO_SHORT:
2709 return "UDS_ERR_RESP_TOO_SHORT";
2710 case UDS_ERR_BUFSIZ:
2711 return "UDS_ERR_BUFSIZ";
2712 case UDS_ERR_INVALID_ARG:
2713 return "UDS_ERR_INVALID_ARG";
2715 return "UDS_ERR_BUSY";
2716 case UDS_ERR_MISUSE:
2717 return "UDS_ERR_MISUSE";
2727 return "UDS_EVT_Custom";
2729 return "UDS_EVT_Err";
2731 return "UDS_EVT_DiagSessCtrl";
2733 return "UDS_EVT_EcuReset";
2735 return "UDS_EVT_ReadDataByIdent";
2737 return "UDS_EVT_ReadMemByAddr";
2739 return "UDS_EVT_CommCtrl";
2741 return "UDS_EVT_SecAccessRequestSeed";
2743 return "UDS_EVT_SecAccessValidateKey";
2745 return "UDS_EVT_WriteDataByIdent";
2747 return "UDS_EVT_RoutineCtrl";
2749 return "UDS_EVT_RequestDownload";
2751 return "UDS_EVT_RequestUpload";
2753 return "UDS_EVT_TransferData";
2755 return "UDS_EVT_RequestTransferExit";
2757 return "UDS_EVT_SessionTimeout";
2759 return "UDS_EVT_DoScheduledReset";
2761 return "UDS_EVT_RequestFileTransfer";
2763 return "UDS_EVT_Poll";
2765 return "UDS_EVT_SendComplete";
2767 return "UDS_EVT_ResponseReceived";
2769 return "UDS_EVT_Idle";
2771 return "UDS_EVT_MAX";
2777bool UDSErrIsNRC(UDSErr_t err) {
2779 case UDS_PositiveResponse:
2780 case UDS_NRC_GeneralReject:
2781 case UDS_NRC_ServiceNotSupported:
2782 case UDS_NRC_SubFunctionNotSupported:
2783 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2784 case UDS_NRC_ResponseTooLong:
2785 case UDS_NRC_BusyRepeatRequest:
2786 case UDS_NRC_ConditionsNotCorrect:
2787 case UDS_NRC_RequestSequenceError:
2788 case UDS_NRC_NoResponseFromSubnetComponent:
2789 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2790 case UDS_NRC_RequestOutOfRange:
2791 case UDS_NRC_SecurityAccessDenied:
2792 case UDS_NRC_AuthenticationRequired:
2793 case UDS_NRC_InvalidKey:
2794 case UDS_NRC_ExceedNumberOfAttempts:
2795 case UDS_NRC_RequiredTimeDelayNotExpired:
2796 case UDS_NRC_SecureDataTransmissionRequired:
2797 case UDS_NRC_SecureDataTransmissionNotAllowed:
2798 case UDS_NRC_SecureDataVerificationFailed:
2799 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2800 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2801 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2802 case UDS_NRC_CertficateVerificationFailedInvalidType:
2803 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2804 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2805 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2806 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2807 case UDS_NRC_OwnershipVerificationFailed:
2808 case UDS_NRC_ChallengeCalculationFailed:
2809 case UDS_NRC_SettingAccessRightsFailed:
2810 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2811 case UDS_NRC_ConfigurationDataUsageFailed:
2812 case UDS_NRC_DeAuthenticationFailed:
2813 case UDS_NRC_UploadDownloadNotAccepted:
2814 case UDS_NRC_TransferDataSuspended:
2815 case UDS_NRC_GeneralProgrammingFailure:
2816 case UDS_NRC_WrongBlockSequenceCounter:
2817 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2818 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2819 case UDS_NRC_ServiceNotSupportedInActiveSession:
2820 case UDS_NRC_RpmTooHigh:
2821 case UDS_NRC_RpmTooLow:
2822 case UDS_NRC_EngineIsRunning:
2823 case UDS_NRC_EngineIsNotRunning:
2824 case UDS_NRC_EngineRunTimeTooLow:
2825 case UDS_NRC_TemperatureTooHigh:
2826 case UDS_NRC_TemperatureTooLow:
2827 case UDS_NRC_VehicleSpeedTooHigh:
2828 case UDS_NRC_VehicleSpeedTooLow:
2829 case UDS_NRC_ThrottlePedalTooHigh:
2830 case UDS_NRC_ThrottlePedalTooLow:
2831 case UDS_NRC_TransmissionRangeNotInNeutral:
2832 case UDS_NRC_TransmissionRangeNotInGear:
2833 case UDS_NRC_BrakeSwitchNotClosed:
2834 case UDS_NRC_ShifterLeverNotInPark:
2835 case UDS_NRC_TorqueConverterClutchLocked:
2836 case UDS_NRC_VoltageTooHigh:
2837 case UDS_NRC_VoltageTooLow:
2838 case UDS_NRC_ResourceTemporarilyNotAvailable:
2852#if UDS_LOG_LEVEL > UDS_LOG_NONE
2853void UDS_LogWrite(UDS_LogLevel_t level,
const char *tag,
const char *format, ...) {
2857 va_start(list, format);
2858 vprintf(format, list);
2862void UDS_LogSDUInternal(UDS_LogLevel_t level,
const char *tag,
const uint8_t *buffer,
2865 for (
unsigned i = 0; i < buff_len; i++) {
2866 UDS_LogWrite(level, tag,
"%02x ", buffer[i]);
2868 UDS_LogWrite(level, tag,
"\n");
2874#line 1 "src/tp/isotp_c.c"
2876#if defined(UDS_TP_ISOTP_C)
2879static UDSTpStatus_t tp_poll(
UDSTp_t *hdl) {
2881 UDSTpStatus_t status = 0;
2884 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
2885 status |= UDS_TP_SEND_IN_PROGRESS;
2890static ssize_t tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
2895 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
2897 case UDS_A_TA_TYPE_PHYSICAL:
2898 link = &tp->phys_link;
2900 case UDS_A_TA_TYPE_FUNCTIONAL:
2901 link = &tp->func_link;
2903 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing\n");
2913 int send_status =
isotp_send(link, buf, len);
2914 switch (send_status) {
2918 case ISOTP_RET_INPROGRESS:
2919 case ISOTP_RET_OVERFLOW:
2928static ssize_t tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
2931 uint16_t out_size = 0;
2934 int ret =
isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
2935 if (ret == ISOTP_RET_OK) {
2936 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
2938 info->
A_TA = tp->phys_sa;
2939 info->
A_SA = tp->phys_ta;
2940 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
2942 }
else if (ret == ISOTP_RET_NO_DATA) {
2943 ret =
isotp_receive(&tp->func_link, buf, bufsize, &out_size);
2944 if (ret == ISOTP_RET_OK) {
2945 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
2947 info->
A_TA = tp->func_sa;
2948 info->
A_SA = tp->func_ta;
2949 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
2951 }
else if (ret == ISOTP_RET_NO_DATA) {
2954 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
2957 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
2963 if (cfg == NULL || tp == NULL) {
2964 return UDS_ERR_INVALID_ARG;
2966 tp->hdl.
poll = tp_poll;
2967 tp->hdl.
send = tp_send;
2968 tp->hdl.
recv = tp_recv;
2969 tp->phys_sa = cfg->source_addr;
2970 tp->phys_ta = cfg->target_addr;
2971 tp->func_sa = cfg->source_addr_func;
2972 tp->func_ta = cfg->target_addr_func;
2974 isotp_init_link(&tp->phys_link, tp->phys_ta, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
2975 sizeof(tp->recv_buf));
2976 isotp_init_link(&tp->func_link, tp->func_ta, tp->recv_buf,
sizeof(tp->send_buf), tp->recv_buf,
2977 sizeof(tp->recv_buf));
2985#line 1 "src/tp/isotp_c_socketcan.c"
2987#if defined(UDS_TP_ISOTP_C_SOCKETCAN)
2989#include <linux/can.h>
2990#include <linux/can/raw.h>
2995#include <sys/ioctl.h>
3000static int SetupSocketCAN(
const char *ifname) {
3001 struct sockaddr_can addr = {0};
3002 struct ifreq ifr = {0};
3005 if ((sockfd = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0) {
3010 memset(&ifr, 0,
sizeof(ifr));
3011 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", ifname) >= (
int)
sizeof(ifr.ifr_name)) {
3012 UDS_LOGE(__FILE__,
"Interface name too long");
3017 ioctl(sockfd, SIOCGIFINDEX, &ifr);
3018 memset(&addr, 0,
sizeof(addr));
3019 addr.can_family = AF_CAN;
3020 addr.can_ifindex = ifr.ifr_ifindex;
3021 if (bind(sockfd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3031__attribute__((format(printf, 1, 2))) void
isotp_user_debug(const
char *message, ...) {
3033 va_start(args, message);
3034 vprintf(message, args);
3038#ifndef ISO_TP_USER_SEND_CAN_ARG
3039#error "ISO_TP_USER_SEND_CAN_ARG must be defined"
3043 (void)fflush(stdout);
3044 UDS_ASSERT(user_data);
3045 int sockfd = *(
int *)user_data;
3046 struct can_frame frame = {0};
3047 frame.can_id = arbitration_id;
3048 frame.can_dlc = size;
3049 memmove(frame.data, data, size);
3050 if (write(sockfd, &frame,
sizeof(
struct can_frame)) !=
sizeof(
struct can_frame)) {
3051 perror(
"Write err");
3052 return ISOTP_RET_ERROR;
3054 return ISOTP_RET_OK;
3059 struct can_frame frame = {0};
3063 nbytes = read(tp->fd, &frame,
sizeof(
struct can_frame));
3065 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3070 }
else if (nbytes == 0) {
3073 if (frame.can_id == tp->phys_sa) {
3075 }
else if (frame.can_id == tp->func_sa) {
3076 if (ISOTP_RECEIVE_STATUS_IDLE != tp->phys_link.receive_status) {
3078 "func frame received but cannot process because link is not idle");
3088static UDSTpStatus_t isotp_c_socketcan_tp_poll(
UDSTp_t *hdl) {
3090 UDSTpStatus_t status = 0;
3092 SocketCANRecv(impl);
3094 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
3095 status |= UDS_TP_SEND_IN_PROGRESS;
3097 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_ERROR) {
3098 status |= UDS_TP_ERR;
3103static ssize_t isotp_c_socketcan_tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3108 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
3109 const uint32_t ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? tp->phys_ta : tp->func_ta;
3111 case UDS_A_TA_TYPE_PHYSICAL:
3112 link = &tp->phys_link;
3114 case UDS_A_TA_TYPE_FUNCTIONAL:
3115 link = &tp->func_link;
3117 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing");
3127 int send_status =
isotp_send(link, buf, len);
3128 switch (send_status) {
3132 case ISOTP_RET_INPROGRESS:
3133 case ISOTP_RET_OVERFLOW:
3139 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", tp->tag, len, ta,
3140 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3141 UDS_LOG_SDU(__FILE__, buf, len, info);
3145static ssize_t isotp_c_socketcan_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
3149 uint16_t out_size = 0;
3152 int ret =
isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
3153 if (ret == ISOTP_RET_OK) {
3154 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
3156 info->
A_TA = tp->phys_sa;
3157 info->
A_SA = tp->phys_ta;
3158 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3160 }
else if (ret == ISOTP_RET_NO_DATA) {
3161 ret =
isotp_receive(&tp->func_link, buf, bufsize, &out_size);
3162 if (ret == ISOTP_RET_OK) {
3163 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
3165 info->
A_TA = tp->func_sa;
3166 info->
A_SA = tp->func_ta;
3167 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3169 }
else if (ret == ISOTP_RET_NO_DATA) {
3172 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
3175 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
3180UDSErr_t UDSTpISOTpCInit(
UDSTpISOTpC_t *tp,
const char *ifname, uint32_t source_addr,
3181 uint32_t target_addr, uint32_t source_addr_func,
3182 uint32_t target_addr_func) {
3185 tp->hdl.
poll = isotp_c_socketcan_tp_poll;
3186 tp->hdl.
send = isotp_c_socketcan_tp_send;
3187 tp->hdl.
recv = isotp_c_socketcan_tp_recv;
3188 tp->phys_sa = source_addr;
3189 tp->phys_ta = target_addr;
3190 tp->func_sa = source_addr_func;
3191 tp->func_ta = target_addr;
3192 tp->fd = SetupSocketCAN(ifname);
3194 isotp_init_link(&tp->phys_link, target_addr, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3195 sizeof(tp->recv_buf));
3196 isotp_init_link(&tp->func_link, target_addr_func, tp->recv_buf,
sizeof(tp->send_buf),
3197 tp->recv_buf,
sizeof(tp->recv_buf));
3199 tp->phys_link.user_send_can_arg = &(tp->fd);
3200 tp->func_link.user_send_can_arg = &(tp->fd);
3215#line 1 "src/tp/isotp_sock.c"
3217#if defined(UDS_TP_ISOTP_SOCK)
3221#include <linux/can.h>
3222#include <linux/can/isotp.h>
3225#include <sys/ioctl.h>
3226#include <sys/socket.h>
3227#include <sys/socket.h>
3228#include <sys/types.h>
3231static UDSTpStatus_t isotp_sock_tp_poll(
UDSTp_t *hdl) {
3233 UDSTpStatus_t status = 0;
3235 int fds[2] = {impl->phys_fd, impl->func_fd};
3236 struct pollfd pfds[2] = {0};
3237 pfds[0].fd = impl->phys_fd;
3238 pfds[0].events = POLLERR | POLLOUT;
3239 pfds[0].revents = 0;
3241 pfds[1].fd = impl->func_fd;
3242 pfds[1].events = POLLERR | POLLOUT;
3243 pfds[1].revents = 0;
3245 ret = poll(pfds, 2, 1);
3247 UDS_LOGE(__FILE__,
"poll failed: %d", ret);
3248 status |= UDS_TP_ERR;
3249 }
else if (ret == 0) {
3253 for (
int i = 0; i < 2; i++) {
3254 struct pollfd pfd = pfds[i];
3257 if (pfd.revents & POLLERR) {
3258 int pending_err = 0;
3259 socklen_t len =
sizeof(pending_err);
3260 if (!getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &pending_err, &len) && pending_err) {
3261 switch (pending_err) {
3263 UDS_LOGE(__FILE__,
"ECOMM: Communication error on send");
3264 status |= UDS_TP_ERR;
3267 UDS_LOGE(__FILE__,
"Asynchronous socket error: %s (%d)",
3268 strerror(pending_err), pending_err);
3269 status |= UDS_TP_ERR;
3273 UDS_LOGE(__FILE__,
"POLLERR was set, but no error returned via SO_ERROR?");
3279 if (fds[i] == impl->phys_fd && pfd.revents != 0) {
3284 if (!(pfd.revents & POLLOUT)) {
3285 status |= UDS_TP_SEND_IN_PROGRESS;
3293static ssize_t tp_recv_once(
int fd, uint8_t *buf,
size_t size) {
3294 ssize_t ret = read(fd, buf, size);
3296 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3299 UDS_LOGI(__FILE__,
"read failed: %ld with errno: %d\n", ret, errno);
3300 if (EILSEQ == errno) {
3301 UDS_LOGI(__FILE__,
"Perhaps I received multiple responses?");
3308static ssize_t isotp_sock_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
3315 ret = tp_recv_once(impl->phys_fd, buf, bufsize);
3317 msg->
A_TA = impl->phys_sa;
3318 msg->
A_SA = impl->phys_ta;
3319 msg->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3321 ret = tp_recv_once(impl->func_fd, buf, bufsize);
3323 msg->
A_TA = impl->func_sa;
3324 msg->
A_SA = impl->func_ta;
3325 msg->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3334 UDS_LOGD(__FILE__,
"'%s' received %ld bytes from 0x%03x (%s), ", impl->tag, ret, msg->
A_TA,
3335 msg->
A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3336 UDS_LOG_SDU(__FILE__, impl->recv_buf, ret, msg);
3342static ssize_t isotp_sock_tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3347 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
3349 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3351 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3353 UDS_LOGI(__FILE__,
"UDSTpIsoTpSock: functional request too large");
3361 ret = write(fd, buf, len);
3366 int ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? impl->phys_ta : impl->func_ta;
3367 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", impl->tag, len, ta,
3368 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3369 UDS_LOG_SDU(__FILE__, buf, len, info);
3374static int LinuxSockBind(
const char *if_name, uint32_t rxid, uint32_t txid,
bool functional) {
3376 if ((fd = socket(AF_CAN, SOCK_DGRAM | SOCK_NONBLOCK, CAN_ISOTP)) < 0) {
3381 struct can_isotp_fc_options fcopts = {
3386 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts,
sizeof(fcopts)) < 0) {
3387 perror(
"setsockopt");
3391 struct can_isotp_options opts;
3392 memset(&opts, 0,
sizeof(opts));
3395 UDS_LOGI(__FILE__,
"configuring fd: %d as functional", fd);
3397 opts.flags |= CAN_ISOTP_LISTEN_MODE;
3400 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts,
sizeof(opts)) < 0) {
3401 perror(
"setsockopt (isotp_options):");
3406 memset(&ifr, 0,
sizeof(ifr));
3407 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", if_name) >= (
int)
sizeof(ifr.ifr_name)) {
3408 UDS_LOGE(__FILE__,
"Interface name too long");
3412 ioctl(fd, SIOCGIFINDEX, &ifr);
3414 struct sockaddr_can addr;
3415 memset(&addr, 0,
sizeof(addr));
3416 addr.can_family = AF_CAN;
3417 addr.can_addr.tp.rx_id = rxid;
3418 addr.can_addr.tp.tx_id = txid;
3419 addr.can_ifindex = ifr.ifr_ifindex;
3421 if (bind(fd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3422 UDS_LOGI(__FILE__,
"Bind: %s %s\n", strerror(errno), if_name);
3428UDSErr_t UDSTpIsoTpSockInitServer(
UDSTpIsoTpSock_t *tp,
const char *ifname, uint32_t source_addr,
3429 uint32_t target_addr, uint32_t source_addr_func) {
3431 memset(tp, 0,
sizeof(*tp));
3432 tp->hdl.
send = isotp_sock_tp_send;
3433 tp->hdl.
recv = isotp_sock_tp_recv;
3434 tp->hdl.
poll = isotp_sock_tp_poll;
3435 tp->phys_sa = source_addr;
3436 tp->phys_ta = target_addr;
3437 tp->func_sa = source_addr_func;
3439 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3440 tp->func_fd = LinuxSockBind(ifname, source_addr_func, 0,
true);
3441 if (tp->phys_fd < 0 || tp->func_fd < 0) {
3442 UDS_LOGI(__FILE__,
"foo\n");
3443 (void)fflush(stdout);
3446 const char *tag =
"server";
3447 memmove(tp->tag, tag, strlen(tag));
3448 UDS_LOGI(__FILE__,
"%s initialized phys link rx 0x%03x tx 0x%03x func link rx 0x%03x tx 0x%03x",
3449 strlen(tp->tag) ? tp->tag :
"server", source_addr, target_addr, source_addr_func,
3454UDSErr_t UDSTpIsoTpSockInitClient(
UDSTpIsoTpSock_t *tp,
const char *ifname, uint32_t source_addr,
3455 uint32_t target_addr, uint32_t target_addr_func) {
3457 memset(tp, 0,
sizeof(*tp));
3458 tp->hdl.
send = isotp_sock_tp_send;
3459 tp->hdl.
recv = isotp_sock_tp_recv;
3460 tp->hdl.
poll = isotp_sock_tp_poll;
3461 tp->func_ta = target_addr_func;
3462 tp->phys_ta = target_addr;
3463 tp->phys_sa = source_addr;
3465 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3466 tp->func_fd = LinuxSockBind(ifname, 0, target_addr_func,
true);
3467 if (tp->phys_fd < 0 || tp->func_fd < 0) {
3470 const char *tag =
"client";
3471 memmove(tp->tag, tag, strlen(tag));
3473 "%s initialized phys link (fd %d) rx 0x%03x tx 0x%03x func link (fd %d) rx 0x%03x tx "
3475 strlen(tp->tag) ? tp->tag :
"client", tp->phys_fd, source_addr, target_addr,
3476 tp->func_fd, source_addr, target_addr_func);
3482 if (close(tp->phys_fd) < 0) {
3483 perror(
"failed to close socket");
3485 if (close(tp->func_fd) < 0) {
3486 perror(
"failed to close socket");
3495#line 1 "src/tp/isotp_mock.c"
3497#if defined(UDS_TP_ISOTP_MOCK)
3505#define MAX_NUM_TP 16
3508static unsigned TPCount = 0;
3509static FILE *LogFile = NULL;
3514 uint32_t scheduled_tx_time;
3517static unsigned MsgCount = 0;
3519static void NetworkPoll(
void) {
3520 for (
unsigned i = 0; i < MsgCount; i++) {
3521 if (UDSTimeAfter(
UDSMillis(), msgs[i].scheduled_tx_time)) {
3523 for (
unsigned j = 0; j < TPCount; j++) {
3525 if (tp->sa_phys == msgs[i].info.A_TA || tp->sa_func == msgs[i].info.A_TA) {
3527 if (tp->recv_len > 0) {
3529 "TPMock: %s recv buffer is already full. Message dropped",
3535 "%s receives %ld bytes from TA=0x%03X (A_TA_Type=%s):", tp->name,
3536 msgs[i].len, msgs[i].info.A_TA,
3537 msgs[i].info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL"
3539 UDS_LOG_SDU(__FILE__, msgs[i].buf, msgs[i].len, &(msgs[i].info));
3541 memmove(tp->recv_buf, msgs[i].buf, msgs[i].len);
3542 tp->recv_len = msgs[i].len;
3543 tp->recv_info = msgs[i].info;
3548 UDS_LOGW(__FILE__,
"TPMock: no matching receiver for message");
3551 for (
unsigned j = i + 1; j < MsgCount; j++) {
3552 msgs[j - 1] = msgs[j];
3560static ssize_t mock_tp_send(
struct UDSTp *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3563 if (MsgCount >= NUM_MSGS) {
3564 UDS_LOGW(__FILE__,
"mock_tp_send: too many messages in the queue");
3567 struct Msg *m = &msgs[MsgCount++];
3568 UDSTpAddr_t ta_type =
3569 info == NULL ? (UDSTpAddr_t)UDS_A_TA_TYPE_PHYSICAL : (UDSTpAddr_t)info->A_TA_Type;
3571 m->info.A_AE = info == NULL ? 0 : info->
A_AE;
3572 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3573 m->info.A_TA = tp->ta_phys;
3574 m->info.A_SA = tp->sa_phys;
3575 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3581 UDS_LOGW(__FILE__,
"mock_tp_send: functional message too long: %ld", len);
3584 m->info.A_TA = tp->ta_func;
3585 m->info.A_SA = tp->sa_func;
3587 UDS_LOGW(__FILE__,
"mock_tp_send: unknown TA type: %d", ta_type);
3590 m->info.A_TA_Type = ta_type;
3591 m->scheduled_tx_time =
UDSMillis() + tp->send_tx_delay_ms;
3592 memmove(m->buf, buf, len);
3594 UDS_LOGD(__FILE__,
"%s sends %ld bytes to TA=0x%03X (A_TA_Type=%s):", tp->name, len,
3595 m->info.A_TA, m->info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL" :
"FUNCTIONAL");
3596 UDS_LOG_SDU(__FILE__, buf, len, &m->info);
3601static ssize_t mock_tp_recv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
3604 if (tp->recv_len == 0) {
3607 if (bufsize < tp->recv_len) {
3608 UDS_LOGW(__FILE__,
"mock_tp_recv: buffer too small: %ld < %ld", bufsize, tp->recv_len);
3611 ssize_t len = (ssize_t)tp->recv_len;
3612 memmove(buf, tp->recv_buf, tp->recv_len);
3614 *info = tp->recv_info;
3620static UDSTpStatus_t mock_tp_poll(
struct UDSTp *hdl) {
3627static_assert(offsetof(
ISOTPMock_t, hdl) == 0,
"ISOTPMock_t must not have any members before hdl");
3632 UDS_ASSERT(TPCount < MAX_NUM_TP);
3633 TPs[TPCount++] = tp;
3634 tp->hdl.
send = mock_tp_send;
3635 tp->hdl.
recv = mock_tp_recv;
3636 tp->hdl.
poll = mock_tp_poll;
3637 tp->sa_func = args->sa_func;
3638 tp->sa_phys = args->sa_phys;
3639 tp->ta_func = args->ta_func;
3640 tp->ta_phys = args->ta_phys;
3642 UDS_LOGV(__FILE__,
"attached %s. TPCount: %d", tp->name, TPCount);
3647 for (
unsigned i = 0; i < TPCount; i++) {
3649 for (
unsigned j = i + 1; j < TPCount; j++) {
3650 TPs[j - 1] = TPs[j];
3653 UDS_LOGV(__FILE__,
"TPMock: detached %s. TPCount: %d", tp->name, TPCount);
3661 if (TPCount >= MAX_NUM_TP) {
3662 UDS_LOGI(__FILE__,
"TPCount: %d, too many TPs\n", TPCount);
3668 if (snprintf(tp->name,
sizeof(tp->name),
"%s", name) >= (
int)
sizeof(tp->name)) {
3669 UDS_LOGE(__FILE__,
"Transport name too long, truncated");
3672 (void)snprintf(tp->name,
sizeof(tp->name),
"TPMock%u", TPCount);
3674 ISOTPMockAttach(tp, args);
3682 (void)fprintf(stderr,
"Log file is already open\n");
3686 (void)fprintf(stderr,
"Filename is NULL\n");
3690 LogFile = fopen(filename,
"w");
3692 (void)fprintf(stderr,
"Failed to open log file %s\n", filename);
3697void ISOTPMockLogToStdout(
void) {
3705 memset(TPs, 0,
sizeof(TPs));
3707 memset(msgs, 0,
sizeof(msgs));
3711void ISOTPMockFree(
UDSTp_t *tp) {
3713 ISOTPMockDetach(tpm);
3719#if defined(UDS_TP_ISOTP_C)
3720#ifndef ISO_TP_USER_SEND_CAN_ARG
3730static uint8_t isotp_us_to_st_min(uint32_t us) {
3732 if (us >= 100 && us <= 900) {
3733 return (uint8_t)(0xF0 + (us / 100));
3735 return (uint8_t)(us / 1000u);
3743static uint32_t isotp_st_min_to_us(uint8_t st_min) {
3744 if (st_min <= 0x7F) {
3745 return st_min * 1000;
3746 }
else if (st_min >= 0xF1 && st_min <= 0xF9) {
3747 return (st_min - 0xF0) * 100;
3752static int isotp_send_flow_control(
const IsoTpLink* link, uint8_t flow_status, uint8_t block_size, uint32_t st_min_us) {
3759 message.as.flow_control.type = ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME;
3760 message.as.flow_control.FS = flow_status;
3761 message.as.flow_control.BS = block_size;
3762 message.as.flow_control.STmin = isotp_us_to_st_min(st_min_us);
3765#ifdef ISO_TP_FRAME_PADDING
3766 (void) memset(message.as.flow_control.reserve, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.flow_control.reserve));
3767 size =
sizeof(message);
3773 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3774 ,link->user_send_can_arg
3781static int isotp_send_single_frame(
const IsoTpLink* link, uint32_t
id) {
3789 assert(link->send_size <= 7);
3792 message.as.single_frame.type = ISOTP_PCI_TYPE_SINGLE;
3793 message.as.single_frame.SF_DL = (uint8_t) link->send_size;
3794 (void) memcpy(message.as.single_frame.data, link->send_buffer, link->send_size);
3797#ifdef ISO_TP_FRAME_PADDING
3798 (void) memset(message.as.single_frame.data + link->send_size, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.single_frame.data) - link->send_size);
3799 size =
sizeof(message);
3801 size = link->send_size + 1;
3805 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3806 ,link->user_send_can_arg
3813static int isotp_send_first_frame(
IsoTpLink* link, uint32_t
id) {
3819 assert(link->send_size > 7);
3822 message.as.first_frame.type = ISOTP_PCI_TYPE_FIRST_FRAME;
3823 message.as.first_frame.FF_DL_low = (uint8_t) link->send_size;
3824 message.as.first_frame.FF_DL_high = (uint8_t) (0x0F & (link->send_size >> 8));
3825 (void) memcpy(message.as.first_frame.data, link->send_buffer,
sizeof(message.as.first_frame.data));
3829 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3830 ,link->user_send_can_arg
3834 if (ISOTP_RET_OK == ret) {
3835 link->send_offset +=
sizeof(message.as.first_frame.data);
3842static int isotp_send_consecutive_frame(
IsoTpLink* link) {
3845 uint16_t data_length;
3850 assert(link->send_size > 7);
3853 message.as.consecutive_frame.type = TSOTP_PCI_TYPE_CONSECUTIVE_FRAME;
3854 message.as.consecutive_frame.SN = link->send_sn;
3855 data_length = link->send_size - link->send_offset;
3856 if (data_length >
sizeof(message.as.consecutive_frame.data)) {
3857 data_length =
sizeof(message.as.consecutive_frame.data);
3859 (void) memcpy(message.as.consecutive_frame.data, link->send_buffer + link->send_offset, data_length);
3862#ifdef ISO_TP_FRAME_PADDING
3863 (void) memset(message.as.consecutive_frame.data + data_length, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.consecutive_frame.data) - data_length);
3864 size =
sizeof(message);
3866 size = data_length + 1;
3870 message.as.data_array.ptr, size
3871#
if defined (ISO_TP_USER_SEND_CAN_ARG)
3872 ,link->user_send_can_arg
3876 if (ISOTP_RET_OK == ret) {
3877 link->send_offset += data_length;
3878 if (++(link->send_sn) > 0x0F) {
3888 if ((0 == message->as.single_frame.SF_DL) || (message->as.single_frame.SF_DL > (len - 1))) {
3890 return ISOTP_RET_LENGTH;
3894 (void) memcpy(link->receive_buffer, message->as.single_frame.data, message->as.single_frame.SF_DL);
3895 link->receive_size = message->as.single_frame.SF_DL;
3897 return ISOTP_RET_OK;
3901 uint16_t payload_length;
3905 return ISOTP_RET_LENGTH;
3909 payload_length = message->as.first_frame.FF_DL_high;
3910 payload_length = (uint16_t)(payload_length << 8) + message->as.first_frame.FF_DL_low;
3913 if (payload_length <= 7) {
3915 return ISOTP_RET_LENGTH;
3918 if (payload_length > link->receive_buf_size) {
3920 return ISOTP_RET_OVERFLOW;
3924 (void) memcpy(link->receive_buffer, message->as.first_frame.data,
sizeof(message->as.first_frame.data));
3925 link->receive_size = payload_length;
3926 link->receive_offset =
sizeof(message->as.first_frame.data);
3927 link->receive_sn = 1;
3929 return ISOTP_RET_OK;
3933 uint16_t remaining_bytes;
3936 if (link->receive_sn != message->as.consecutive_frame.SN) {
3937 return ISOTP_RET_WRONG_SN;
3941 remaining_bytes = link->receive_size - link->receive_offset;
3942 if (remaining_bytes >
sizeof(message->as.consecutive_frame.data)) {
3943 remaining_bytes =
sizeof(message->as.consecutive_frame.data);
3945 if (remaining_bytes > len - 1) {
3947 return ISOTP_RET_LENGTH;
3951 (void) memcpy(link->receive_buffer + link->receive_offset, message->as.consecutive_frame.data, remaining_bytes);
3953 link->receive_offset += remaining_bytes;
3954 if (++(link->receive_sn) > 0x0F) {
3955 link->receive_sn = 0;
3958 return ISOTP_RET_OK;
3969 return ISOTP_RET_LENGTH;
3972 return ISOTP_RET_OK;
3988 return ISOTP_RET_ERROR;
3991 if (size > link->send_buf_size) {
3992 isotp_user_debug(
"Message size too large. Increase ISO_TP_MAX_MESSAGE_SIZE to set a larger buffer\n");
3993 const int32_t messageSize = 128;
3994 char message[messageSize];
3995 int32_t writtenChars = sprintf(&message[0],
"Attempted to send %d bytes; max size is %d!\n", size, link->send_buf_size);
3997 assert(writtenChars <= messageSize);
3998 (void) writtenChars;
4001 return ISOTP_RET_OVERFLOW;
4004 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4006 return ISOTP_RET_INPROGRESS;
4010 link->send_size = size;
4011 link->send_offset = 0;
4012 (void) memcpy(link->send_buffer, payload, size);
4014 if (link->send_size < 8) {
4016 ret = isotp_send_single_frame(link,
id);
4019 ret = isotp_send_first_frame(link,
id);
4022 if (ISOTP_RET_OK == ret) {
4023 link->send_bs_remain = 0;
4024 link->send_st_min_us = 0;
4025 link->send_wtf_count = 0;
4028 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4029 link->send_status = ISOTP_SEND_STATUS_INPROGRESS;
4040 if (len < 2 || len > 8) {
4044 memcpy(message.as.data_array.ptr, data, len);
4045 memset(message.as.data_array.ptr + len, 0,
sizeof(message.as.data_array.ptr) - len);
4047 switch (message.as.common.type) {
4048 case ISOTP_PCI_TYPE_SINGLE: {
4050 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4051 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4053 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4057 ret = isotp_receive_single_frame(link, &message, len);
4059 if (ISOTP_RET_OK == ret) {
4061 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4065 case ISOTP_PCI_TYPE_FIRST_FRAME: {
4067 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4068 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4070 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4074 ret = isotp_receive_first_frame(link, &message, len);
4077 if (ISOTP_RET_OVERFLOW == ret) {
4079 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4081 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4083 isotp_send_flow_control(link, PCI_FLOW_STATUS_OVERFLOW, 0, 0);
4088 if (ISOTP_RET_OK == ret) {
4090 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4092 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4093 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4095 link->receive_timer_cr =
isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4100 case TSOTP_PCI_TYPE_CONSECUTIVE_FRAME: {
4102 if (ISOTP_RECEIVE_STATUS_INPROGRESS != link->receive_status) {
4103 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4108 ret = isotp_receive_consecutive_frame(link, &message, len);
4111 if (ISOTP_RET_WRONG_SN == ret) {
4112 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_WRONG_SN;
4113 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4118 if (ISOTP_RET_OK == ret) {
4120 link->receive_timer_cr =
isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4123 if (link->receive_offset >= link->receive_size) {
4124 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4127 if (0 == --link->receive_bs_count) {
4128 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4129 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4136 case ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME:
4138 if (ISOTP_SEND_STATUS_INPROGRESS != link->send_status) {
4143 ret = isotp_receive_flow_control_frame(link, &message, len);
4145 if (ISOTP_RET_OK == ret) {
4150 if (PCI_FLOW_STATUS_OVERFLOW == message.as.flow_control.FS) {
4151 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4152 link->send_status = ISOTP_SEND_STATUS_ERROR;
4156 else if (PCI_FLOW_STATUS_WAIT == message.as.flow_control.FS) {
4157 link->send_wtf_count += 1;
4159 if (link->send_wtf_count > ISO_TP_MAX_WFT_NUMBER) {
4160 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_WFT_OVRN;
4161 link->send_status = ISOTP_SEND_STATUS_ERROR;
4166 else if (PCI_FLOW_STATUS_CONTINUE == message.as.flow_control.FS) {
4167 if (0 == message.as.flow_control.BS) {
4168 link->send_bs_remain = ISOTP_INVALID_BS;
4170 link->send_bs_remain = message.as.flow_control.BS;
4172 uint32_t message_st_min_us = isotp_st_min_to_us(message.as.flow_control.STmin);
4173 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;
4174 link->send_wtf_count = 0;
4188 if (ISOTP_RECEIVE_STATUS_FULL != link->receive_status) {
4189 return ISOTP_RET_NO_DATA;
4192 copylen = link->receive_size;
4193 if (copylen > payload_size) {
4194 copylen = payload_size;
4197 memcpy(payload, link->receive_buffer, copylen);
4198 *out_size = copylen;
4200 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4202 return ISOTP_RET_OK;
4205void isotp_init_link(
IsoTpLink *link, uint32_t sendid, uint8_t *sendbuf, uint16_t sendbufsize, uint8_t *recvbuf, uint16_t recvbufsize) {
4206 memset(link, 0,
sizeof(*link));
4207 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4208 link->send_status = ISOTP_SEND_STATUS_IDLE;
4209 link->send_arbitration_id = sendid;
4210 link->send_buffer = sendbuf;
4211 link->send_buf_size = sendbufsize;
4212 link->receive_buffer = recvbuf;
4213 link->receive_buf_size = recvbufsize;
4222 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4226 (ISOTP_INVALID_BS == link->send_bs_remain || link->send_bs_remain > 0) &&
4228 (0 == link->send_st_min_us || IsoTpTimeAfter(
isotp_user_get_us(), link->send_timer_st))) {
4230 ret = isotp_send_consecutive_frame(link);
4231 if (ISOTP_RET_OK == ret) {
4232 if (ISOTP_INVALID_BS != link->send_bs_remain) {
4233 link->send_bs_remain -= 1;
4239 if (link->send_offset >= link->send_size) {
4240 link->send_status = ISOTP_SEND_STATUS_IDLE;
4242 }
else if (ISOTP_RET_NOSPACE == ret) {
4245 link->send_status = ISOTP_SEND_STATUS_ERROR;
4251 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_BS;
4252 link->send_status = ISOTP_SEND_STATUS_ERROR;
4257 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4261 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_CR;
4262 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
bool UDSSecurityAccessLevelIsReserved(uint8_t subFunction)
Check if a security level is reserved per ISO14229-1:2020 Table 42.
uint32_t isotp_user_get_us(void)
user implemented, gets the amount of time passed since the last call in microseconds
int isotp_user_send_can(const uint32_t arbitration_id, const uint8_t *data, const uint8_t size, void *user_data)
user implemented, send can message. should return ISOTP_RET_OK when success.
UDSTp_t * ISOTPMockNew(const char *name, ISOTPMockArgs_t *args)
Create a mock transport. It is connected by default to a broadcast network of all other mock transpor...
uint32_t UDSMillis(void)
Get time in milliseconds.
int isotp_receive(IsoTpLink *link, uint8_t *payload, const uint16_t payload_size, uint16_t *out_size)
Receives and parses the received data and copies the parsed data in to the internal buffer.
void isotp_on_can_message(IsoTpLink *link, const uint8_t *data, uint8_t len)
Handles incoming CAN messages. Determines whether an incoming message is a valid ISO-TP frame or not ...
void isotp_init_link(IsoTpLink *link, uint32_t sendid, uint8_t *sendbuf, uint16_t sendbufsize, uint8_t *recvbuf, uint16_t recvbufsize)
Initialises the ISO-TP library.
void isotp_poll(IsoTpLink *link)
Polling function; call this function periodically to handle timeouts, send consecutive frames,...
void ISOTPMockReset(void)
clear all transports and close the log file
int isotp_send_with_id(IsoTpLink *link, uint32_t id, const uint8_t payload[], uint16_t size)
See isotp_send, with the exception that this function is used only for functional addressing.
int isotp_send(IsoTpLink *link, const uint8_t payload[], uint16_t size)
PUBLIC FUNCTIONS ///.
void ISOTPMockLogToFile(const char *filename)
write all messages to a file
ISO14229-1 (UDS) library.
#define UDS_MOOP_ADDFILE
modeOfOperation parameter used in 0x38 RequestFileTransfer ISO14229-1:2020 Table G....
@ 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
void isotp_user_debug(const char *message,...)
user implemented, print debug message
#define UDS_SERVER_DEFAULT_XFER_DATA_MAX_BLOCKLENGTH
#define UDS_LEV_RCTP_STR
0x31 RoutineControl SubFunction = [routineControlType] ISO14229-1:2020 Table 426
Struct containing the data for linking an application to a CAN instance. The data stored in this stru...
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.
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::@9 subFuncArgs
Diagnostic session control arguments.
uint32_t powerDownTimeMillis
Input/output control by identifier arguments.
Read data by identifier arguments.
uint8_t(* copy)(UDSServer_t *srv, const void *src, uint16_t count)
Read data by identifier variable structure.
void *(* UnpackFn)(void *dst, const void *src, size_t n)
Read DTC information arguments.
union UDSRDTCIArgs_t::@0 subFuncArgs
uint8_t(* copy)(UDSServer_t *srv, const void *src, uint16_t count)
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.
uint16_t maxNumberOfBlockLength
const size_t fileSizeCompressed
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...
UDSErr_t(* fn)(struct UDSServer *srv, UDSEvent_t event, void *arg)
uint32_t sec_access_boot_delay_timer
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 ...
UDSTpStatus_t(* poll)(struct UDSTp *hdl)
Poll the transport layer.
ssize_t(* recv)(struct UDSTp *hdl, uint8_t *buf, size_t bufsize, UDSSDU_t *info)
Receive data from the transport.
ssize_t(* send)(struct UDSTp *hdl, uint8_t *buf, size_t len, UDSSDU_t *info)
Send data to the transport.
Write data by identifier arguments.
Write memory by address arguments.
const uint8_t *const data