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 err = UDS_NRC_ConditionsNotCorrect;
2001 if (r->
recv_len < UDS_0X38_REQ_BASE_LEN) {
2002 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2006 uint8_t mode_of_operation = r->
recv_buf[1];
2008 switch (mode_of_operation) {
2010 case UDS_MOOP_DELFILE:
2011 case UDS_MOOP_REPLFILE:
2012 case UDS_MOOP_RDFILE:
2013 case UDS_MOOP_RDDIR:
2015 case UDS_MOOP_RSFILE:
2016 err = UDS_NRC_SubFunctionNotSupported;
2019 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2023 uint16_t file_path_len = (uint16_t)(((uint16_t)r->
recv_buf[2] << 8) + (uint16_t)r->
recv_buf[3]);
2024 uint8_t data_format_identifier = 0;
2025 uint8_t file_size_parameter_length = 0;
2026 size_t file_size_uncompressed = 0;
2027 size_t file_size_compressed = 0;
2028 uint16_t byte_idx = 4 + file_path_len;
2031 err = UDS_NRC_IncorrectMessageLengthOrInvalidFormat;
2035 if ((mode_of_operation == UDS_MOOP_DELFILE) || (mode_of_operation == UDS_MOOP_RDDIR)) {
2040 data_format_identifier = r->
recv_buf[byte_idx];
2044 if ((mode_of_operation == UDS_MOOP_DELFILE) || (mode_of_operation == UDS_MOOP_RDFILE) ||
2045 (mode_of_operation == UDS_MOOP_RDDIR)) {
2055 file_size_parameter_length = r->
recv_buf[byte_idx];
2058 static_assert(
sizeof(file_size_uncompressed) ==
sizeof(file_size_compressed),
2059 "Both should be k-byte numbers per Table 480");
2060 if (file_size_parameter_length >
sizeof(file_size_compressed)) {
2061 err = UDS_NRC_RequestOutOfRange;
2066 if ((
size_t)byte_idx + 2 * file_size_parameter_length > r->
recv_len) {
2067 err = UDS_NRC_RequestOutOfRange;
2070 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2071 uint8_t data_byte = r->
recv_buf[byte_idx];
2072 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2073 file_size_uncompressed |= (size_t)data_byte << (8 * shift_by_bytes);
2076 for (
size_t i = 0; i < file_size_parameter_length; i++) {
2077 uint8_t data_byte = r->
recv_buf[byte_idx];
2078 uint8_t shift_by_bytes = (uint8_t)(file_size_parameter_length - i - 1);
2079 file_size_compressed |= (size_t)data_byte << (8 * shift_by_bytes);
2085 .modeOfOperation = mode_of_operation,
2086 .filePathLen = file_path_len,
2087 .filePath = file_path_len == 0 ? NULL : &r->
recv_buf[4],
2088 .dataFormatIdentifier = data_format_identifier,
2089 .fileSizeUnCompressed = file_size_uncompressed,
2090 .fileSizeCompressed = file_size_compressed,
2095 if (UDS_PositiveResponse != err) {
2099 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_REQUEST_FILE_TRANSFER);
2100 r->
send_buf[1] = args.modeOfOperation;
2102 if (mode_of_operation == UDS_MOOP_DELFILE) {
2136 UDSErr_t ret = UDS_PositiveResponse;
2140 if (r->
recv_len < UDS_0X3D_REQ_MIN_LEN) {
2141 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2144 ret = decodeAddressAndLength(r, &r->
recv_buf[1], &address, &length);
2145 if (UDS_PositiveResponse != ret) {
2146 return NegativeResponse(r, ret);
2149 uint8_t memorySizeLength = (r->
recv_buf[1] & 0xF0) >> 4;
2150 uint8_t memoryAddressLength = r->
recv_buf[1] & 0x0F;
2152 uint8_t dataOffset = 2 + memorySizeLength + memoryAddressLength;
2154 if (dataOffset + length != r->
recv_len) {
2155 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2165 if (UDS_PositiveResponse != ret) {
2166 return NegativeResponse(r, ret);
2169 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_WRITE_MEMORY_BY_ADDRESS);
2171 memcpy(&r->
send_buf[1], &r->
recv_buf[1], 1 + memorySizeLength + memoryAddressLength);
2172 r->
send_len = UDS_0X3D_RESP_BASE_LEN + memorySizeLength + memoryAddressLength;
2173 return UDS_PositiveResponse;
2177 if ((r->
recv_len < UDS_0X3E_REQ_MIN_LEN) || (r->
recv_len > UDS_0X3E_REQ_MAX_LEN)) {
2178 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2180 uint8_t zeroSubFunction = r->
recv_buf[1];
2182 switch (zeroSubFunction) {
2186 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_TESTER_PRESENT);
2189 return UDS_PositiveResponse;
2191 return NegativeResponse(r, UDS_NRC_SubFunctionNotSupported);
2197 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2198 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2201 uint8_t type = r->
recv_buf[1] & 0x7F;
2206 .len = r->
recv_len > UDS_0X85_REQ_BASE_LEN ? r->
recv_len - UDS_0X85_REQ_BASE_LEN : 0,
2210 if (UDS_PositiveResponse != ret) {
2211 return NegativeResponse(r, ret);
2214 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_CONTROL_DTC_SETTING);
2217 return UDS_PositiveResponse;
2221 if (r->
recv_len < UDS_0X85_REQ_BASE_LEN) {
2222 return NegativeResponse(r, UDS_NRC_IncorrectMessageLengthOrInvalidFormat);
2225 uint8_t type = r->
recv_buf[1] & 0x7F;
2227 if (type == 0x03 && (r->
recv_buf[1] & 0x80) == 0 &&
2229 UDS_LOGW(__FILE__,
"0x87 LinkControl: Transitioning mode without suppressing response!");
2232 r->
send_buf[0] = UDS_RESPONSE_SID_OF(kSID_LINK_CONTROL);
2239 .len = (r->
recv_len - UDS_0X87_REQ_BASE_LEN),
2240 .data = &r->
recv_buf[UDS_0X87_REQ_BASE_LEN],
2244 if (ret != UDS_PositiveResponse) {
2245 return NegativeResponse(r, ret);
2248 return UDS_PositiveResponse;
2258static UDSService getServiceForSID(uint8_t sid) {
2260 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2261 return &Handle_0x10_DiagnosticSessionControl;
2262 case kSID_ECU_RESET:
2263 return &Handle_0x11_ECUReset;
2264 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2265 return &Handle_0x14_ClearDiagnosticInformation;
2266 case kSID_READ_DTC_INFORMATION:
2267 return Handle_0x19_ReadDTCInformation;
2268 case kSID_READ_DATA_BY_IDENTIFIER:
2269 return &Handle_0x22_ReadDataByIdentifier;
2270 case kSID_READ_MEMORY_BY_ADDRESS:
2271 return &Handle_0x23_ReadMemoryByAddress;
2272 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2274 case kSID_SECURITY_ACCESS:
2275 return &Handle_0x27_SecurityAccess;
2276 case kSID_COMMUNICATION_CONTROL:
2277 return &Handle_0x28_CommunicationControl;
2278 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2280 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2281 return &Handle_0x2C_DynamicDefineDataIdentifier;
2282 case kSID_WRITE_DATA_BY_IDENTIFIER:
2283 return &Handle_0x2E_WriteDataByIdentifier;
2284 case kSID_IO_CONTROL_BY_IDENTIFIER:
2285 return &Handle_0x2F_IOControlByIdentifier;
2286 case kSID_ROUTINE_CONTROL:
2287 return &Handle_0x31_RoutineControl;
2288 case kSID_REQUEST_DOWNLOAD:
2289 return &Handle_0x34_RequestDownload;
2290 case kSID_REQUEST_UPLOAD:
2291 return &Handle_0x35_RequestUpload;
2292 case kSID_TRANSFER_DATA:
2293 return &Handle_0x36_TransferData;
2294 case kSID_REQUEST_TRANSFER_EXIT:
2295 return &Handle_0x37_RequestTransferExit;
2296 case kSID_REQUEST_FILE_TRANSFER:
2297 return &Handle_0x38_RequestFileTransfer;
2298 case kSID_WRITE_MEMORY_BY_ADDRESS:
2299 return &Handle_0x3D_WriteMemoryByAddress;
2300 case kSID_TESTER_PRESENT:
2301 return &Handle_0x3E_TesterPresent;
2302 case kSID_ACCESS_TIMING_PARAMETER:
2304 case kSID_SECURED_DATA_TRANSMISSION:
2306 case kSID_CONTROL_DTC_SETTING:
2307 return &Handle_0x85_ControlDTCSetting;
2308 case kSID_RESPONSE_ON_EVENT:
2310 case kSID_LINK_CONTROL:
2311 return &Handle_0x87_LinkControl;
2313 UDS_LOGI(__FILE__,
"no handler for request SID %x", sid);
2326 UDSErr_t response = UDS_PositiveResponse;
2327 bool suppressResponse =
false;
2329 UDSService service = getServiceForSID(sid);
2331 if (NULL == srv->
fn)
2332 return NegativeResponse(r, UDS_NRC_ServiceNotSupported);
2333 UDS_ASSERT(srv->
fn);
2338 case kSID_DIAGNOSTIC_SESSION_CONTROL:
2339 case kSID_ECU_RESET:
2340 case kSID_SECURITY_ACCESS:
2341 case kSID_COMMUNICATION_CONTROL:
2342 case kSID_ROUTINE_CONTROL:
2343 case kSID_TESTER_PRESENT:
2344 case kSID_CONTROL_DTC_SETTING:
2345 case kSID_LINK_CONTROL: {
2346 UDS_ASSERT(service);
2347 response = service(srv, r);
2349 bool suppressPosRspMsgIndicationBit = r->
recv_buf[1] & 0x80;
2352 if (suppressPosRspMsgIndicationBit && (response == UDS_PositiveResponse) &&
2356 suppressResponse =
true;
2358 suppressResponse =
false;
2365 case kSID_READ_DATA_BY_IDENTIFIER:
2366 case kSID_READ_MEMORY_BY_ADDRESS:
2367 case kSID_WRITE_DATA_BY_IDENTIFIER:
2368 case kSID_REQUEST_DOWNLOAD:
2369 case kSID_REQUEST_UPLOAD:
2370 case kSID_TRANSFER_DATA:
2371 case kSID_REQUEST_FILE_TRANSFER:
2372 case kSID_REQUEST_TRANSFER_EXIT: {
2373 UDS_ASSERT(service);
2374 response = service(srv, r);
2379 case kSID_CLEAR_DIAGNOSTIC_INFORMATION:
2380 case kSID_READ_DTC_INFORMATION:
2381 case kSID_READ_SCALING_DATA_BY_IDENTIFIER:
2382 case kSID_READ_PERIODIC_DATA_BY_IDENTIFIER:
2383 case kSID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER:
2384 case kSID_IO_CONTROL_BY_IDENTIFIER:
2385 case kSID_WRITE_MEMORY_BY_ADDRESS:
2386 case kSID_ACCESS_TIMING_PARAMETER:
2387 case kSID_SECURED_DATA_TRANSMISSION:
2388 case kSID_RESPONSE_ON_EVENT:
2391 response = service(srv, r);
2396 .len = (uint16_t)(r->
recv_len - 1),
2397 .copyResponse = safe_copy,
2400 r->
send_buf[0] = UDS_RESPONSE_SID_OF(sid);
2404 if (UDS_PositiveResponse != response)
2405 return NegativeResponse(r, response);
2412 ((UDS_NRC_ServiceNotSupported == response) ||
2413 (UDS_NRC_SubFunctionNotSupported == response) ||
2414 (UDS_NRC_ServiceNotSupportedInActiveSession == response) ||
2415 (UDS_NRC_SubFunctionNotSupportedInActiveSession == response) ||
2416 (UDS_NRC_RequestOutOfRange == response)) &&
2421 suppressResponse =
true;
2424 if (suppressResponse) {
2438 return UDS_ERR_INVALID_ARG;
2441 srv->
p2_ms = UDS_SERVER_DEFAULT_P2_MS;
2442 srv->
p2_star_ms = UDS_SERVER_DEFAULT_P2_STAR_MS;
2443 srv->
s3_ms = UDS_SERVER_DEFAULT_S3_MS;
2448 UDSMillis() + UDS_SERVER_0x27_BRUTE_FORCE_MITIGATION_BOOT_DELAY_MS;
2475 UDSErr_t response = evaluateServiceResponse(srv, r);
2476 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2497 UDSErr_t err = UDS_ERR_TPORT;
2499 UDS_LOGE(__FILE__,
"UDSTpSend failed with %zd\n", ret);
2505 uint32_t wait_time = srv->
p2_star_ms * 3 / 10;
2519 UDS_LOGE(__FILE__,
"UDSTpRecv failed with %zd\n", r->
recv_len);
2526 UDSErr_t response = evaluateServiceResponse(srv, r);
2528 if (UDS_NRC_RequestCorrectlyReceived_ResponsePending == response) {
2540ssize_t UDSTpSend(
struct UDSTp *hdl,
const uint8_t *buf, ssize_t len,
UDSSDU_t *info) {
2542 UDS_ASSERT(hdl->send);
2543 return hdl->send(hdl, (uint8_t *)buf, len, info);
2546ssize_t UDSTpRecv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
2548 UDS_ASSERT(hdl->recv);
2549 return hdl->recv(hdl, buf, bufsize, info);
2552UDSTpStatus_t UDSTpPoll(
struct UDSTp *hdl) {
2554 UDS_ASSERT(hdl->poll);
2555 return hdl->poll(hdl);
2562#if UDS_CUSTOM_MILLIS
2565#if UDS_SYS == UDS_SYS_UNIX
2567 gettimeofday(&te, NULL);
2568 long long milliseconds = (te.tv_sec * 1000LL) + (te.tv_usec / 1000);
2569 return (uint32_t)milliseconds;
2570#elif UDS_SYS == UDS_SYS_WINDOWS
2572 timespec_get(&ts, TIME_UTC);
2573 long long milliseconds = ts.tv_sec * 1000LL + ts.tv_nsec / 1000000;
2574 return (uint32_t)milliseconds;
2575#elif UDS_SYS == UDS_SYS_ARDUINO
2577#elif UDS_SYS == UDS_SYS_ESP32
2578 return esp_timer_get_time() / 1000;
2580#error "UDSMillis() undefined!"
2593 uint8_t securityLevel = subFunction & 0x3F;
2594 if (0u == securityLevel) {
2597 if ((securityLevel >= 0x43u) && (securityLevel <= 0x5Eu)) {
2600 if (securityLevel == 0x7Fu) {
2606const char *UDSErrToStr(UDSErr_t err) {
2612 case UDS_NRC_GeneralReject:
2613 return "UDS_NRC_GeneralReject";
2614 case UDS_NRC_ServiceNotSupported:
2615 return "UDS_NRC_ServiceNotSupported";
2616 case UDS_NRC_SubFunctionNotSupported:
2617 return "UDS_NRC_SubFunctionNotSupported";
2618 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2619 return "UDS_NRC_IncorrectMessageLengthOrInvalidFormat";
2620 case UDS_NRC_ResponseTooLong:
2621 return "UDS_NRC_ResponseTooLong";
2622 case UDS_NRC_BusyRepeatRequest:
2623 return "UDS_NRC_BusyRepeatRequest";
2624 case UDS_NRC_ConditionsNotCorrect:
2625 return "UDS_NRC_ConditionsNotCorrect";
2626 case UDS_NRC_RequestSequenceError:
2627 return "UDS_NRC_RequestSequenceError";
2628 case UDS_NRC_NoResponseFromSubnetComponent:
2629 return "UDS_NRC_NoResponseFromSubnetComponent";
2630 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2631 return "UDS_NRC_FailurePreventsExecutionOfRequestedAction";
2632 case UDS_NRC_RequestOutOfRange:
2633 return "UDS_NRC_RequestOutOfRange";
2634 case UDS_NRC_SecurityAccessDenied:
2635 return "UDS_NRC_SecurityAccessDenied";
2636 case UDS_NRC_AuthenticationRequired:
2637 return "UDS_NRC_AuthenticationRequired";
2638 case UDS_NRC_InvalidKey:
2639 return "UDS_NRC_InvalidKey";
2640 case UDS_NRC_ExceedNumberOfAttempts:
2641 return "UDS_NRC_ExceedNumberOfAttempts";
2642 case UDS_NRC_RequiredTimeDelayNotExpired:
2643 return "UDS_NRC_RequiredTimeDelayNotExpired";
2644 case UDS_NRC_SecureDataTransmissionRequired:
2645 return "UDS_NRC_SecureDataTransmissionRequired";
2646 case UDS_NRC_SecureDataTransmissionNotAllowed:
2647 return "UDS_NRC_SecureDataTransmissionNotAllowed";
2648 case UDS_NRC_SecureDataVerificationFailed:
2649 return "UDS_NRC_SecureDataVerificationFailed";
2650 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2651 return "UDS_NRC_CertficateVerificationFailedInvalidTimePeriod";
2652 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2653 return "UDS_NRC_CertficateVerificationFailedInvalidSignature";
2654 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2655 return "UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust";
2656 case UDS_NRC_CertficateVerificationFailedInvalidType:
2657 return "UDS_NRC_CertficateVerificationFailedInvalidType";
2658 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2659 return "UDS_NRC_CertficateVerificationFailedInvalidFormat";
2660 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2661 return "UDS_NRC_CertficateVerificationFailedInvalidContent";
2662 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2663 return "UDS_NRC_CertficateVerificationFailedInvalidScope";
2664 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2665 return "UDS_NRC_CertficateVerificationFailedInvalidCertificate";
2666 case UDS_NRC_OwnershipVerificationFailed:
2667 return "UDS_NRC_OwnershipVerificationFailed";
2668 case UDS_NRC_ChallengeCalculationFailed:
2669 return "UDS_NRC_ChallengeCalculationFailed";
2670 case UDS_NRC_SettingAccessRightsFailed:
2671 return "UDS_NRC_SettingAccessRightsFailed";
2672 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2673 return "UDS_NRC_SessionKeyCreationOrDerivationFailed";
2674 case UDS_NRC_ConfigurationDataUsageFailed:
2675 return "UDS_NRC_ConfigurationDataUsageFailed";
2676 case UDS_NRC_DeAuthenticationFailed:
2677 return "UDS_NRC_DeAuthenticationFailed";
2678 case UDS_NRC_UploadDownloadNotAccepted:
2679 return "UDS_NRC_UploadDownloadNotAccepted";
2680 case UDS_NRC_TransferDataSuspended:
2681 return "UDS_NRC_TransferDataSuspended";
2682 case UDS_NRC_GeneralProgrammingFailure:
2683 return "UDS_NRC_GeneralProgrammingFailure";
2684 case UDS_NRC_WrongBlockSequenceCounter:
2685 return "UDS_NRC_WrongBlockSequenceCounter";
2686 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2687 return "UDS_NRC_RequestCorrectlyReceived_ResponsePending";
2688 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2689 return "UDS_NRC_SubFunctionNotSupportedInActiveSession";
2690 case UDS_NRC_ServiceNotSupportedInActiveSession:
2691 return "UDS_NRC_ServiceNotSupportedInActiveSession";
2692 case UDS_NRC_RpmTooHigh:
2693 return "UDS_NRC_RpmTooHigh";
2694 case UDS_NRC_RpmTooLow:
2695 return "UDS_NRC_RpmTooLow";
2696 case UDS_NRC_EngineIsRunning:
2697 return "UDS_NRC_EngineIsRunning";
2698 case UDS_NRC_EngineIsNotRunning:
2699 return "UDS_NRC_EngineIsNotRunning";
2700 case UDS_NRC_EngineRunTimeTooLow:
2701 return "UDS_NRC_EngineRunTimeTooLow";
2702 case UDS_NRC_TemperatureTooHigh:
2703 return "UDS_NRC_TemperatureTooHigh";
2704 case UDS_NRC_TemperatureTooLow:
2705 return "UDS_NRC_TemperatureTooLow";
2706 case UDS_NRC_VehicleSpeedTooHigh:
2707 return "UDS_NRC_VehicleSpeedTooHigh";
2708 case UDS_NRC_VehicleSpeedTooLow:
2709 return "UDS_NRC_VehicleSpeedTooLow";
2710 case UDS_NRC_ThrottlePedalTooHigh:
2711 return "UDS_NRC_ThrottlePedalTooHigh";
2712 case UDS_NRC_ThrottlePedalTooLow:
2713 return "UDS_NRC_ThrottlePedalTooLow";
2714 case UDS_NRC_TransmissionRangeNotInNeutral:
2715 return "UDS_NRC_TransmissionRangeNotInNeutral";
2716 case UDS_NRC_TransmissionRangeNotInGear:
2717 return "UDS_NRC_TransmissionRangeNotInGear";
2718 case UDS_NRC_BrakeSwitchNotClosed:
2719 return "UDS_NRC_BrakeSwitchNotClosed";
2720 case UDS_NRC_ShifterLeverNotInPark:
2721 return "UDS_NRC_ShifterLeverNotInPark";
2722 case UDS_NRC_TorqueConverterClutchLocked:
2723 return "UDS_NRC_TorqueConverterClutchLocked";
2724 case UDS_NRC_VoltageTooHigh:
2725 return "UDS_NRC_VoltageTooHigh";
2726 case UDS_NRC_VoltageTooLow:
2727 return "UDS_NRC_VoltageTooLow";
2728 case UDS_NRC_ResourceTemporarilyNotAvailable:
2729 return "UDS_NRC_ResourceTemporarilyNotAvailable";
2730 case UDS_ERR_TIMEOUT:
2731 return "UDS_ERR_TIMEOUT";
2732 case UDS_ERR_DID_MISMATCH:
2733 return "UDS_ERR_DID_MISMATCH";
2734 case UDS_ERR_SID_MISMATCH:
2735 return "UDS_ERR_SID_MISMATCH";
2736 case UDS_ERR_SUBFUNCTION_MISMATCH:
2737 return "UDS_ERR_SUBFUNCTION_MISMATCH";
2739 return "UDS_ERR_TPORT";
2740 case UDS_ERR_RESP_TOO_SHORT:
2741 return "UDS_ERR_RESP_TOO_SHORT";
2742 case UDS_ERR_BUFSIZ:
2743 return "UDS_ERR_BUFSIZ";
2744 case UDS_ERR_INVALID_ARG:
2745 return "UDS_ERR_INVALID_ARG";
2747 return "UDS_ERR_BUSY";
2748 case UDS_ERR_MISUSE:
2749 return "UDS_ERR_MISUSE";
2759 return "UDS_EVT_Custom";
2761 return "UDS_EVT_Err";
2763 return "UDS_EVT_DiagSessCtrl";
2765 return "UDS_EVT_EcuReset";
2767 return "UDS_EVT_ReadDataByIdent";
2769 return "UDS_EVT_ReadMemByAddr";
2771 return "UDS_EVT_CommCtrl";
2773 return "UDS_EVT_SecAccessRequestSeed";
2775 return "UDS_EVT_SecAccessValidateKey";
2777 return "UDS_EVT_WriteDataByIdent";
2779 return "UDS_EVT_RoutineCtrl";
2781 return "UDS_EVT_RequestDownload";
2783 return "UDS_EVT_RequestUpload";
2785 return "UDS_EVT_TransferData";
2787 return "UDS_EVT_RequestTransferExit";
2789 return "UDS_EVT_SessionTimeout";
2791 return "UDS_EVT_DoScheduledReset";
2793 return "UDS_EVT_RequestFileTransfer";
2795 return "UDS_EVT_Poll";
2797 return "UDS_EVT_SendComplete";
2799 return "UDS_EVT_ResponseReceived";
2801 return "UDS_EVT_Idle";
2803 return "UDS_EVT_MAX";
2809bool UDSErrIsNRC(UDSErr_t err) {
2811 case UDS_PositiveResponse:
2812 case UDS_NRC_GeneralReject:
2813 case UDS_NRC_ServiceNotSupported:
2814 case UDS_NRC_SubFunctionNotSupported:
2815 case UDS_NRC_IncorrectMessageLengthOrInvalidFormat:
2816 case UDS_NRC_ResponseTooLong:
2817 case UDS_NRC_BusyRepeatRequest:
2818 case UDS_NRC_ConditionsNotCorrect:
2819 case UDS_NRC_RequestSequenceError:
2820 case UDS_NRC_NoResponseFromSubnetComponent:
2821 case UDS_NRC_FailurePreventsExecutionOfRequestedAction:
2822 case UDS_NRC_RequestOutOfRange:
2823 case UDS_NRC_SecurityAccessDenied:
2824 case UDS_NRC_AuthenticationRequired:
2825 case UDS_NRC_InvalidKey:
2826 case UDS_NRC_ExceedNumberOfAttempts:
2827 case UDS_NRC_RequiredTimeDelayNotExpired:
2828 case UDS_NRC_SecureDataTransmissionRequired:
2829 case UDS_NRC_SecureDataTransmissionNotAllowed:
2830 case UDS_NRC_SecureDataVerificationFailed:
2831 case UDS_NRC_CertficateVerificationFailedInvalidTimePeriod:
2832 case UDS_NRC_CertficateVerificationFailedInvalidSignature:
2833 case UDS_NRC_CertficateVerificationFailedInvalidChainOfTrust:
2834 case UDS_NRC_CertficateVerificationFailedInvalidType:
2835 case UDS_NRC_CertficateVerificationFailedInvalidFormat:
2836 case UDS_NRC_CertficateVerificationFailedInvalidContent:
2837 case UDS_NRC_CertficateVerificationFailedInvalidScope:
2838 case UDS_NRC_CertficateVerificationFailedInvalidCertificate:
2839 case UDS_NRC_OwnershipVerificationFailed:
2840 case UDS_NRC_ChallengeCalculationFailed:
2841 case UDS_NRC_SettingAccessRightsFailed:
2842 case UDS_NRC_SessionKeyCreationOrDerivationFailed:
2843 case UDS_NRC_ConfigurationDataUsageFailed:
2844 case UDS_NRC_DeAuthenticationFailed:
2845 case UDS_NRC_UploadDownloadNotAccepted:
2846 case UDS_NRC_TransferDataSuspended:
2847 case UDS_NRC_GeneralProgrammingFailure:
2848 case UDS_NRC_WrongBlockSequenceCounter:
2849 case UDS_NRC_RequestCorrectlyReceived_ResponsePending:
2850 case UDS_NRC_SubFunctionNotSupportedInActiveSession:
2851 case UDS_NRC_ServiceNotSupportedInActiveSession:
2852 case UDS_NRC_RpmTooHigh:
2853 case UDS_NRC_RpmTooLow:
2854 case UDS_NRC_EngineIsRunning:
2855 case UDS_NRC_EngineIsNotRunning:
2856 case UDS_NRC_EngineRunTimeTooLow:
2857 case UDS_NRC_TemperatureTooHigh:
2858 case UDS_NRC_TemperatureTooLow:
2859 case UDS_NRC_VehicleSpeedTooHigh:
2860 case UDS_NRC_VehicleSpeedTooLow:
2861 case UDS_NRC_ThrottlePedalTooHigh:
2862 case UDS_NRC_ThrottlePedalTooLow:
2863 case UDS_NRC_TransmissionRangeNotInNeutral:
2864 case UDS_NRC_TransmissionRangeNotInGear:
2865 case UDS_NRC_BrakeSwitchNotClosed:
2866 case UDS_NRC_ShifterLeverNotInPark:
2867 case UDS_NRC_TorqueConverterClutchLocked:
2868 case UDS_NRC_VoltageTooHigh:
2869 case UDS_NRC_VoltageTooLow:
2870 case UDS_NRC_ResourceTemporarilyNotAvailable:
2884#if UDS_LOG_LEVEL > UDS_LOG_NONE
2885void UDS_LogWrite(UDS_LogLevel_t level,
const char *tag,
const char *format, ...) {
2889 va_start(list, format);
2890 vprintf(format, list);
2894void UDS_LogSDUInternal(UDS_LogLevel_t level,
const char *tag,
const uint8_t *buffer,
2897 for (
unsigned i = 0; i < buff_len; i++) {
2898 UDS_LogWrite(level, tag,
"%02x ", buffer[i]);
2900 UDS_LogWrite(level, tag,
"\n");
2906#line 1 "src/tp/isotp_c.c"
2908#if defined(UDS_TP_ISOTP_C)
2911static UDSTpStatus_t tp_poll(
UDSTp_t *hdl) {
2913 UDSTpStatus_t status = 0;
2916 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
2917 status |= UDS_TP_SEND_IN_PROGRESS;
2922static ssize_t tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
2927 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
2929 case UDS_A_TA_TYPE_PHYSICAL:
2930 link = &tp->phys_link;
2932 case UDS_A_TA_TYPE_FUNCTIONAL:
2933 link = &tp->func_link;
2935 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing\n");
2945 int send_status =
isotp_send(link, buf, len);
2946 switch (send_status) {
2950 case ISOTP_RET_INPROGRESS:
2951 case ISOTP_RET_OVERFLOW:
2960static ssize_t tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
2963 uint16_t out_size = 0;
2966 int ret =
isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
2967 if (ret == ISOTP_RET_OK) {
2968 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
2970 info->
A_TA = tp->phys_sa;
2971 info->
A_SA = tp->phys_ta;
2972 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
2974 }
else if (ret == ISOTP_RET_NO_DATA) {
2975 ret =
isotp_receive(&tp->func_link, buf, bufsize, &out_size);
2976 if (ret == ISOTP_RET_OK) {
2977 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
2979 info->
A_TA = tp->func_sa;
2980 info->
A_SA = tp->func_ta;
2981 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
2983 }
else if (ret == ISOTP_RET_NO_DATA) {
2986 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
2989 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
2995 if (cfg == NULL || tp == NULL) {
2996 return UDS_ERR_INVALID_ARG;
2998 tp->hdl.
poll = tp_poll;
2999 tp->hdl.
send = tp_send;
3000 tp->hdl.
recv = tp_recv;
3001 tp->phys_sa = cfg->source_addr;
3002 tp->phys_ta = cfg->target_addr;
3003 tp->func_sa = cfg->source_addr_func;
3004 tp->func_ta = cfg->target_addr_func;
3006 isotp_init_link(&tp->phys_link, tp->phys_ta, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3007 sizeof(tp->recv_buf));
3008 isotp_init_link(&tp->func_link, tp->func_ta, tp->recv_buf,
sizeof(tp->send_buf), tp->recv_buf,
3009 sizeof(tp->recv_buf));
3017#line 1 "src/tp/isotp_c_socketcan.c"
3019#if defined(UDS_TP_ISOTP_C_SOCKETCAN)
3021#include <linux/can.h>
3022#include <linux/can/raw.h>
3027#include <sys/ioctl.h>
3032static int SetupSocketCAN(
const char *ifname) {
3033 struct sockaddr_can addr = {0};
3034 struct ifreq ifr = {0};
3037 if ((sockfd = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0) {
3042 memset(&ifr, 0,
sizeof(ifr));
3043 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", ifname) >= (
int)
sizeof(ifr.ifr_name)) {
3044 UDS_LOGE(__FILE__,
"Interface name too long");
3049 ioctl(sockfd, SIOCGIFINDEX, &ifr);
3050 memset(&addr, 0,
sizeof(addr));
3051 addr.can_family = AF_CAN;
3052 addr.can_ifindex = ifr.ifr_ifindex;
3053 if (bind(sockfd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3063__attribute__((format(printf, 1, 2))) void
isotp_user_debug(const
char *message, ...) {
3065 va_start(args, message);
3066 vprintf(message, args);
3070#ifndef ISO_TP_USER_SEND_CAN_ARG
3071#error "ISO_TP_USER_SEND_CAN_ARG must be defined"
3075 (void)fflush(stdout);
3076 UDS_ASSERT(user_data);
3077 int sockfd = *(
int *)user_data;
3078 struct can_frame frame = {0};
3079 frame.can_id = arbitration_id;
3080 frame.can_dlc = size;
3081 memmove(frame.data, data, size);
3082 if (write(sockfd, &frame,
sizeof(
struct can_frame)) !=
sizeof(
struct can_frame)) {
3083 perror(
"Write err");
3084 return ISOTP_RET_ERROR;
3086 return ISOTP_RET_OK;
3091 struct can_frame frame = {0};
3095 nbytes = read(tp->fd, &frame,
sizeof(
struct can_frame));
3097 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3102 }
else if (nbytes == 0) {
3105 if (frame.can_id == tp->phys_sa) {
3107 }
else if (frame.can_id == tp->func_sa) {
3108 if (ISOTP_RECEIVE_STATUS_IDLE != tp->phys_link.receive_status) {
3110 "func frame received but cannot process because link is not idle");
3120static UDSTpStatus_t isotp_c_socketcan_tp_poll(
UDSTp_t *hdl) {
3122 UDSTpStatus_t status = 0;
3124 SocketCANRecv(impl);
3126 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_INPROGRESS) {
3127 status |= UDS_TP_SEND_IN_PROGRESS;
3129 if (impl->phys_link.send_status == ISOTP_SEND_STATUS_ERROR) {
3130 status |= UDS_TP_ERR;
3135static ssize_t isotp_c_socketcan_tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3140 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
3141 const uint32_t ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? tp->phys_ta : tp->func_ta;
3143 case UDS_A_TA_TYPE_PHYSICAL:
3144 link = &tp->phys_link;
3146 case UDS_A_TA_TYPE_FUNCTIONAL:
3147 link = &tp->func_link;
3149 UDS_LOGI(__FILE__,
"Cannot send more than 7 bytes via functional addressing");
3159 int send_status =
isotp_send(link, buf, len);
3160 switch (send_status) {
3164 case ISOTP_RET_INPROGRESS:
3165 case ISOTP_RET_OVERFLOW:
3171 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", tp->tag, len, ta,
3172 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3173 UDS_LOG_SDU(__FILE__, buf, len, info);
3177static ssize_t isotp_c_socketcan_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
3181 uint16_t out_size = 0;
3184 int ret =
isotp_receive(&tp->phys_link, buf, bufsize, &out_size);
3185 if (ret == ISOTP_RET_OK) {
3186 UDS_LOGI(__FILE__,
"phys link received %d bytes", out_size);
3188 info->
A_TA = tp->phys_sa;
3189 info->
A_SA = tp->phys_ta;
3190 info->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3192 }
else if (ret == ISOTP_RET_NO_DATA) {
3193 ret =
isotp_receive(&tp->func_link, buf, bufsize, &out_size);
3194 if (ret == ISOTP_RET_OK) {
3195 UDS_LOGI(__FILE__,
"func link received %d bytes", out_size);
3197 info->
A_TA = tp->func_sa;
3198 info->
A_SA = tp->func_ta;
3199 info->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3201 }
else if (ret == ISOTP_RET_NO_DATA) {
3204 UDS_LOGE(__FILE__,
"unhandled return code from func link %d\n", ret);
3207 UDS_LOGE(__FILE__,
"unhandled return code from phys link %d\n", ret);
3212UDSErr_t UDSTpISOTpCInit(
UDSTpISOTpC_t *tp,
const char *ifname, uint32_t source_addr,
3213 uint32_t target_addr, uint32_t source_addr_func,
3214 uint32_t target_addr_func) {
3217 tp->hdl.
poll = isotp_c_socketcan_tp_poll;
3218 tp->hdl.
send = isotp_c_socketcan_tp_send;
3219 tp->hdl.
recv = isotp_c_socketcan_tp_recv;
3220 tp->phys_sa = source_addr;
3221 tp->phys_ta = target_addr;
3222 tp->func_sa = source_addr_func;
3223 tp->func_ta = target_addr;
3224 tp->fd = SetupSocketCAN(ifname);
3226 isotp_init_link(&tp->phys_link, target_addr, tp->send_buf,
sizeof(tp->send_buf), tp->recv_buf,
3227 sizeof(tp->recv_buf));
3228 isotp_init_link(&tp->func_link, target_addr_func, tp->recv_buf,
sizeof(tp->send_buf),
3229 tp->recv_buf,
sizeof(tp->recv_buf));
3231 tp->phys_link.user_send_can_arg = &(tp->fd);
3232 tp->func_link.user_send_can_arg = &(tp->fd);
3247#line 1 "src/tp/isotp_sock.c"
3249#if defined(UDS_TP_ISOTP_SOCK)
3253#include <linux/can.h>
3254#include <linux/can/isotp.h>
3257#include <sys/ioctl.h>
3258#include <sys/socket.h>
3259#include <sys/socket.h>
3260#include <sys/types.h>
3263static UDSTpStatus_t isotp_sock_tp_poll(
UDSTp_t *hdl) {
3265 UDSTpStatus_t status = 0;
3267 int fds[2] = {impl->phys_fd, impl->func_fd};
3268 struct pollfd pfds[2] = {0};
3269 pfds[0].fd = impl->phys_fd;
3270 pfds[0].events = POLLERR | POLLOUT;
3271 pfds[0].revents = 0;
3273 pfds[1].fd = impl->func_fd;
3274 pfds[1].events = POLLERR | POLLOUT;
3275 pfds[1].revents = 0;
3277 ret = poll(pfds, 2, 1);
3279 UDS_LOGE(__FILE__,
"poll failed: %d", ret);
3280 status |= UDS_TP_ERR;
3281 }
else if (ret == 0) {
3285 for (
int i = 0; i < 2; i++) {
3286 struct pollfd pfd = pfds[i];
3289 if (pfd.revents & POLLERR) {
3290 int pending_err = 0;
3291 socklen_t len =
sizeof(pending_err);
3292 if (!getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &pending_err, &len) && pending_err) {
3293 switch (pending_err) {
3295 UDS_LOGE(__FILE__,
"ECOMM: Communication error on send");
3296 status |= UDS_TP_ERR;
3299 UDS_LOGE(__FILE__,
"Asynchronous socket error: %s (%d)",
3300 strerror(pending_err), pending_err);
3301 status |= UDS_TP_ERR;
3305 UDS_LOGE(__FILE__,
"POLLERR was set, but no error returned via SO_ERROR?");
3311 if (fds[i] == impl->phys_fd && pfd.revents != 0) {
3316 if (!(pfd.revents & POLLOUT)) {
3317 status |= UDS_TP_SEND_IN_PROGRESS;
3325static ssize_t tp_recv_once(
int fd, uint8_t *buf,
size_t size) {
3326 ssize_t ret = read(fd, buf, size);
3328 if (EAGAIN == errno || EWOULDBLOCK == errno) {
3331 UDS_LOGI(__FILE__,
"read failed: %ld with errno: %d\n", ret, errno);
3332 if (EILSEQ == errno) {
3333 UDS_LOGI(__FILE__,
"Perhaps I received multiple responses?");
3340static ssize_t isotp_sock_tp_recv(
UDSTp_t *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
3347 ret = tp_recv_once(impl->phys_fd, buf, bufsize);
3349 msg->
A_TA = impl->phys_sa;
3350 msg->
A_SA = impl->phys_ta;
3351 msg->
A_TA_Type = UDS_A_TA_TYPE_PHYSICAL;
3353 ret = tp_recv_once(impl->func_fd, buf, bufsize);
3355 msg->
A_TA = impl->func_sa;
3356 msg->
A_SA = impl->func_ta;
3357 msg->
A_TA_Type = UDS_A_TA_TYPE_FUNCTIONAL;
3366 UDS_LOGD(__FILE__,
"'%s' received %ld bytes from 0x%03x (%s), ", impl->tag, ret, msg->
A_TA,
3367 msg->
A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3368 UDS_LOG_SDU(__FILE__, impl->recv_buf, ret, msg);
3374static ssize_t isotp_sock_tp_send(
UDSTp_t *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3379 const UDSTpAddr_t ta_type = info ? info->
A_TA_Type : UDS_A_TA_TYPE_PHYSICAL;
3381 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3383 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3385 UDS_LOGI(__FILE__,
"UDSTpIsoTpSock: functional request too large");
3393 ret = write(fd, buf, len);
3398 int ta = ta_type == UDS_A_TA_TYPE_PHYSICAL ? impl->phys_ta : impl->func_ta;
3399 UDS_LOGD(__FILE__,
"'%s' sends %ld bytes to 0x%03x (%s)", impl->tag, len, ta,
3400 ta_type == UDS_A_TA_TYPE_PHYSICAL ?
"phys" :
"func");
3401 UDS_LOG_SDU(__FILE__, buf, len, info);
3406static int LinuxSockBind(
const char *if_name, uint32_t rxid, uint32_t txid,
bool functional) {
3408 if ((fd = socket(AF_CAN, SOCK_DGRAM | SOCK_NONBLOCK, CAN_ISOTP)) < 0) {
3413 struct can_isotp_fc_options fcopts = {
3418 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts,
sizeof(fcopts)) < 0) {
3419 perror(
"setsockopt");
3423 struct can_isotp_options opts;
3424 memset(&opts, 0,
sizeof(opts));
3427 UDS_LOGI(__FILE__,
"configuring fd: %d as functional", fd);
3429 opts.flags |= CAN_ISOTP_LISTEN_MODE;
3432 if (setsockopt(fd, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts,
sizeof(opts)) < 0) {
3433 perror(
"setsockopt (isotp_options):");
3438 memset(&ifr, 0,
sizeof(ifr));
3439 if (snprintf(ifr.ifr_name,
sizeof(ifr.ifr_name),
"%s", if_name) >= (
int)
sizeof(ifr.ifr_name)) {
3440 UDS_LOGE(__FILE__,
"Interface name too long");
3444 ioctl(fd, SIOCGIFINDEX, &ifr);
3446 struct sockaddr_can addr;
3447 memset(&addr, 0,
sizeof(addr));
3448 addr.can_family = AF_CAN;
3449 addr.can_addr.tp.rx_id = rxid;
3450 addr.can_addr.tp.tx_id = txid;
3451 addr.can_ifindex = ifr.ifr_ifindex;
3453 if (bind(fd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
3454 UDS_LOGI(__FILE__,
"Bind: %s %s\n", strerror(errno), if_name);
3460UDSErr_t UDSTpIsoTpSockInitServer(
UDSTpIsoTpSock_t *tp,
const char *ifname, uint32_t source_addr,
3461 uint32_t target_addr, uint32_t source_addr_func) {
3463 memset(tp, 0,
sizeof(*tp));
3464 tp->hdl.
send = isotp_sock_tp_send;
3465 tp->hdl.
recv = isotp_sock_tp_recv;
3466 tp->hdl.
poll = isotp_sock_tp_poll;
3467 tp->phys_sa = source_addr;
3468 tp->phys_ta = target_addr;
3469 tp->func_sa = source_addr_func;
3471 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3472 tp->func_fd = LinuxSockBind(ifname, source_addr_func, 0,
true);
3473 if (tp->phys_fd < 0 || tp->func_fd < 0) {
3474 UDS_LOGI(__FILE__,
"foo\n");
3475 (void)fflush(stdout);
3478 const char *tag =
"server";
3479 memmove(tp->tag, tag, strlen(tag));
3480 UDS_LOGI(__FILE__,
"%s initialized phys link rx 0x%03x tx 0x%03x func link rx 0x%03x tx 0x%03x",
3481 strlen(tp->tag) ? tp->tag :
"server", source_addr, target_addr, source_addr_func,
3486UDSErr_t UDSTpIsoTpSockInitClient(
UDSTpIsoTpSock_t *tp,
const char *ifname, uint32_t source_addr,
3487 uint32_t target_addr, uint32_t target_addr_func) {
3489 memset(tp, 0,
sizeof(*tp));
3490 tp->hdl.
send = isotp_sock_tp_send;
3491 tp->hdl.
recv = isotp_sock_tp_recv;
3492 tp->hdl.
poll = isotp_sock_tp_poll;
3493 tp->func_ta = target_addr_func;
3494 tp->phys_ta = target_addr;
3495 tp->phys_sa = source_addr;
3497 tp->phys_fd = LinuxSockBind(ifname, source_addr, target_addr,
false);
3498 tp->func_fd = LinuxSockBind(ifname, 0, target_addr_func,
true);
3499 if (tp->phys_fd < 0 || tp->func_fd < 0) {
3502 const char *tag =
"client";
3503 memmove(tp->tag, tag, strlen(tag));
3505 "%s initialized phys link (fd %d) rx 0x%03x tx 0x%03x func link (fd %d) rx 0x%03x tx "
3507 strlen(tp->tag) ? tp->tag :
"client", tp->phys_fd, source_addr, target_addr,
3508 tp->func_fd, source_addr, target_addr_func);
3514 if (close(tp->phys_fd) < 0) {
3515 perror(
"failed to close socket");
3517 if (close(tp->func_fd) < 0) {
3518 perror(
"failed to close socket");
3527#line 1 "src/tp/isotp_mock.c"
3529#if defined(UDS_TP_ISOTP_MOCK)
3537#define MAX_NUM_TP 16
3540static unsigned TPCount = 0;
3541static FILE *LogFile = NULL;
3546 uint32_t scheduled_tx_time;
3549static unsigned MsgCount = 0;
3551static void NetworkPoll(
void) {
3552 for (
unsigned i = 0; i < MsgCount; i++) {
3553 if (UDSTimeAfter(
UDSMillis(), msgs[i].scheduled_tx_time)) {
3555 for (
unsigned j = 0; j < TPCount; j++) {
3557 if (tp->sa_phys == msgs[i].info.A_TA || tp->sa_func == msgs[i].info.A_TA) {
3559 if (tp->recv_len > 0) {
3561 "TPMock: %s recv buffer is already full. Message dropped",
3567 "%s receives %ld bytes from TA=0x%03X (A_TA_Type=%s):", tp->name,
3568 msgs[i].len, msgs[i].info.A_TA,
3569 msgs[i].info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL"
3571 UDS_LOG_SDU(__FILE__, msgs[i].buf, msgs[i].len, &(msgs[i].info));
3573 memmove(tp->recv_buf, msgs[i].buf, msgs[i].len);
3574 tp->recv_len = msgs[i].len;
3575 tp->recv_info = msgs[i].info;
3580 UDS_LOGW(__FILE__,
"TPMock: no matching receiver for message");
3583 for (
unsigned j = i + 1; j < MsgCount; j++) {
3584 msgs[j - 1] = msgs[j];
3592static ssize_t mock_tp_send(
struct UDSTp *hdl, uint8_t *buf,
size_t len,
UDSSDU_t *info) {
3595 if (MsgCount >= NUM_MSGS) {
3596 UDS_LOGW(__FILE__,
"mock_tp_send: too many messages in the queue");
3599 struct Msg *m = &msgs[MsgCount++];
3600 UDSTpAddr_t ta_type =
3601 info == NULL ? (UDSTpAddr_t)UDS_A_TA_TYPE_PHYSICAL : (UDSTpAddr_t)info->A_TA_Type;
3603 m->info.A_AE = info == NULL ? 0 : info->
A_AE;
3604 if (UDS_A_TA_TYPE_PHYSICAL == ta_type) {
3605 m->info.A_TA = tp->ta_phys;
3606 m->info.A_SA = tp->sa_phys;
3607 }
else if (UDS_A_TA_TYPE_FUNCTIONAL == ta_type) {
3613 UDS_LOGW(__FILE__,
"mock_tp_send: functional message too long: %ld", len);
3616 m->info.A_TA = tp->ta_func;
3617 m->info.A_SA = tp->sa_func;
3619 UDS_LOGW(__FILE__,
"mock_tp_send: unknown TA type: %d", ta_type);
3622 m->info.A_TA_Type = ta_type;
3623 m->scheduled_tx_time =
UDSMillis() + tp->send_tx_delay_ms;
3624 memmove(m->buf, buf, len);
3626 UDS_LOGD(__FILE__,
"%s sends %ld bytes to TA=0x%03X (A_TA_Type=%s):", tp->name, len,
3627 m->info.A_TA, m->info.A_TA_Type == UDS_A_TA_TYPE_PHYSICAL ?
"PHYSICAL" :
"FUNCTIONAL");
3628 UDS_LOG_SDU(__FILE__, buf, len, &m->info);
3633static ssize_t mock_tp_recv(
struct UDSTp *hdl, uint8_t *buf,
size_t bufsize,
UDSSDU_t *info) {
3636 if (tp->recv_len == 0) {
3639 if (bufsize < tp->recv_len) {
3640 UDS_LOGW(__FILE__,
"mock_tp_recv: buffer too small: %ld < %ld", bufsize, tp->recv_len);
3643 ssize_t len = (ssize_t)tp->recv_len;
3644 memmove(buf, tp->recv_buf, tp->recv_len);
3646 *info = tp->recv_info;
3652static UDSTpStatus_t mock_tp_poll(
struct UDSTp *hdl) {
3659static_assert(offsetof(
ISOTPMock_t, hdl) == 0,
"ISOTPMock_t must not have any members before hdl");
3664 UDS_ASSERT(TPCount < MAX_NUM_TP);
3665 TPs[TPCount++] = tp;
3666 tp->hdl.
send = mock_tp_send;
3667 tp->hdl.
recv = mock_tp_recv;
3668 tp->hdl.
poll = mock_tp_poll;
3669 tp->sa_func = args->sa_func;
3670 tp->sa_phys = args->sa_phys;
3671 tp->ta_func = args->ta_func;
3672 tp->ta_phys = args->ta_phys;
3674 UDS_LOGV(__FILE__,
"attached %s. TPCount: %d", tp->name, TPCount);
3679 for (
unsigned i = 0; i < TPCount; i++) {
3681 for (
unsigned j = i + 1; j < TPCount; j++) {
3682 TPs[j - 1] = TPs[j];
3685 UDS_LOGV(__FILE__,
"TPMock: detached %s. TPCount: %d", tp->name, TPCount);
3693 if (TPCount >= MAX_NUM_TP) {
3694 UDS_LOGI(__FILE__,
"TPCount: %d, too many TPs\n", TPCount);
3700 if (snprintf(tp->name,
sizeof(tp->name),
"%s", name) >= (
int)
sizeof(tp->name)) {
3701 UDS_LOGE(__FILE__,
"Transport name too long, truncated");
3704 (void)snprintf(tp->name,
sizeof(tp->name),
"TPMock%u", TPCount);
3706 ISOTPMockAttach(tp, args);
3714 (void)fprintf(stderr,
"Log file is already open\n");
3718 (void)fprintf(stderr,
"Filename is NULL\n");
3722 LogFile = fopen(filename,
"w");
3724 (void)fprintf(stderr,
"Failed to open log file %s\n", filename);
3729void ISOTPMockLogToStdout(
void) {
3737 memset(TPs, 0,
sizeof(TPs));
3739 memset(msgs, 0,
sizeof(msgs));
3743void ISOTPMockFree(
UDSTp_t *tp) {
3745 ISOTPMockDetach(tpm);
3751#if defined(UDS_TP_ISOTP_C)
3752#ifndef ISO_TP_USER_SEND_CAN_ARG
3762static uint8_t isotp_us_to_st_min(uint32_t us) {
3764 if (us >= 100 && us <= 900) {
3765 return (uint8_t)(0xF0 + (us / 100));
3767 return (uint8_t)(us / 1000u);
3775static uint32_t isotp_st_min_to_us(uint8_t st_min) {
3776 if (st_min <= 0x7F) {
3777 return st_min * 1000;
3778 }
else if (st_min >= 0xF1 && st_min <= 0xF9) {
3779 return (st_min - 0xF0) * 100;
3784static int isotp_send_flow_control(
const IsoTpLink* link, uint8_t flow_status, uint8_t block_size, uint32_t st_min_us) {
3791 message.as.flow_control.type = ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME;
3792 message.as.flow_control.FS = flow_status;
3793 message.as.flow_control.BS = block_size;
3794 message.as.flow_control.STmin = isotp_us_to_st_min(st_min_us);
3797#ifdef ISO_TP_FRAME_PADDING
3798 (void) memset(message.as.flow_control.reserve, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.flow_control.reserve));
3799 size =
sizeof(message);
3805 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3806 ,link->user_send_can_arg
3813static int isotp_send_single_frame(
const IsoTpLink* link, uint32_t
id) {
3821 assert(link->send_size <= 7);
3824 message.as.single_frame.type = ISOTP_PCI_TYPE_SINGLE;
3825 message.as.single_frame.SF_DL = (uint8_t) link->send_size;
3826 (void) memcpy(message.as.single_frame.data, link->send_buffer, link->send_size);
3829#ifdef ISO_TP_FRAME_PADDING
3830 (void) memset(message.as.single_frame.data + link->send_size, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.single_frame.data) - link->send_size);
3831 size =
sizeof(message);
3833 size = link->send_size + 1;
3837 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3838 ,link->user_send_can_arg
3845static int isotp_send_first_frame(
IsoTpLink* link, uint32_t
id) {
3851 assert(link->send_size > 7);
3854 message.as.first_frame.type = ISOTP_PCI_TYPE_FIRST_FRAME;
3855 message.as.first_frame.FF_DL_low = (uint8_t) link->send_size;
3856 message.as.first_frame.FF_DL_high = (uint8_t) (0x0F & (link->send_size >> 8));
3857 (void) memcpy(message.as.first_frame.data, link->send_buffer,
sizeof(message.as.first_frame.data));
3861 #
if defined (ISO_TP_USER_SEND_CAN_ARG)
3862 ,link->user_send_can_arg
3866 if (ISOTP_RET_OK == ret) {
3867 link->send_offset +=
sizeof(message.as.first_frame.data);
3874static int isotp_send_consecutive_frame(
IsoTpLink* link) {
3877 uint16_t data_length;
3882 assert(link->send_size > 7);
3885 message.as.consecutive_frame.type = TSOTP_PCI_TYPE_CONSECUTIVE_FRAME;
3886 message.as.consecutive_frame.SN = link->send_sn;
3887 data_length = link->send_size - link->send_offset;
3888 if (data_length >
sizeof(message.as.consecutive_frame.data)) {
3889 data_length =
sizeof(message.as.consecutive_frame.data);
3891 (void) memcpy(message.as.consecutive_frame.data, link->send_buffer + link->send_offset, data_length);
3894#ifdef ISO_TP_FRAME_PADDING
3895 (void) memset(message.as.consecutive_frame.data + data_length, ISO_TP_FRAME_PADDING_VALUE,
sizeof(message.as.consecutive_frame.data) - data_length);
3896 size =
sizeof(message);
3898 size = data_length + 1;
3902 message.as.data_array.ptr, size
3903#
if defined (ISO_TP_USER_SEND_CAN_ARG)
3904 ,link->user_send_can_arg
3908 if (ISOTP_RET_OK == ret) {
3909 link->send_offset += data_length;
3910 if (++(link->send_sn) > 0x0F) {
3920 if ((0 == message->as.single_frame.SF_DL) || (message->as.single_frame.SF_DL > (len - 1))) {
3922 return ISOTP_RET_LENGTH;
3926 (void) memcpy(link->receive_buffer, message->as.single_frame.data, message->as.single_frame.SF_DL);
3927 link->receive_size = message->as.single_frame.SF_DL;
3929 return ISOTP_RET_OK;
3933 uint16_t payload_length;
3937 return ISOTP_RET_LENGTH;
3941 payload_length = message->as.first_frame.FF_DL_high;
3942 payload_length = (uint16_t)(payload_length << 8) + message->as.first_frame.FF_DL_low;
3945 if (payload_length <= 7) {
3947 return ISOTP_RET_LENGTH;
3950 if (payload_length > link->receive_buf_size) {
3952 return ISOTP_RET_OVERFLOW;
3956 (void) memcpy(link->receive_buffer, message->as.first_frame.data,
sizeof(message->as.first_frame.data));
3957 link->receive_size = payload_length;
3958 link->receive_offset =
sizeof(message->as.first_frame.data);
3959 link->receive_sn = 1;
3961 return ISOTP_RET_OK;
3965 uint16_t remaining_bytes;
3968 if (link->receive_sn != message->as.consecutive_frame.SN) {
3969 return ISOTP_RET_WRONG_SN;
3973 remaining_bytes = link->receive_size - link->receive_offset;
3974 if (remaining_bytes >
sizeof(message->as.consecutive_frame.data)) {
3975 remaining_bytes =
sizeof(message->as.consecutive_frame.data);
3977 if (remaining_bytes > len - 1) {
3979 return ISOTP_RET_LENGTH;
3983 (void) memcpy(link->receive_buffer + link->receive_offset, message->as.consecutive_frame.data, remaining_bytes);
3985 link->receive_offset += remaining_bytes;
3986 if (++(link->receive_sn) > 0x0F) {
3987 link->receive_sn = 0;
3990 return ISOTP_RET_OK;
4001 return ISOTP_RET_LENGTH;
4004 return ISOTP_RET_OK;
4020 return ISOTP_RET_ERROR;
4023 if (size > link->send_buf_size) {
4024 isotp_user_debug(
"Message size too large. Increase ISO_TP_MAX_MESSAGE_SIZE to set a larger buffer\n");
4025 const int32_t messageSize = 128;
4026 char message[messageSize];
4027 int32_t writtenChars = sprintf(&message[0],
"Attempted to send %d bytes; max size is %d!\n", size, link->send_buf_size);
4029 assert(writtenChars <= messageSize);
4030 (void) writtenChars;
4033 return ISOTP_RET_OVERFLOW;
4036 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4038 return ISOTP_RET_INPROGRESS;
4042 link->send_size = size;
4043 link->send_offset = 0;
4044 (void) memcpy(link->send_buffer, payload, size);
4046 if (link->send_size < 8) {
4048 ret = isotp_send_single_frame(link,
id);
4051 ret = isotp_send_first_frame(link,
id);
4054 if (ISOTP_RET_OK == ret) {
4055 link->send_bs_remain = 0;
4056 link->send_st_min_us = 0;
4057 link->send_wtf_count = 0;
4060 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4061 link->send_status = ISOTP_SEND_STATUS_INPROGRESS;
4072 if (len < 2 || len > 8) {
4076 memcpy(message.as.data_array.ptr, data, len);
4077 memset(message.as.data_array.ptr + len, 0,
sizeof(message.as.data_array.ptr) - len);
4079 switch (message.as.common.type) {
4080 case ISOTP_PCI_TYPE_SINGLE: {
4082 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4083 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4085 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4089 ret = isotp_receive_single_frame(link, &message, len);
4091 if (ISOTP_RET_OK == ret) {
4093 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4097 case ISOTP_PCI_TYPE_FIRST_FRAME: {
4099 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4100 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4102 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_OK;
4106 ret = isotp_receive_first_frame(link, &message, len);
4109 if (ISOTP_RET_OVERFLOW == ret) {
4111 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4113 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4115 isotp_send_flow_control(link, PCI_FLOW_STATUS_OVERFLOW, 0, 0);
4120 if (ISOTP_RET_OK == ret) {
4122 link->receive_status = ISOTP_RECEIVE_STATUS_INPROGRESS;
4124 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4125 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4127 link->receive_timer_cr =
isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4132 case TSOTP_PCI_TYPE_CONSECUTIVE_FRAME: {
4134 if (ISOTP_RECEIVE_STATUS_INPROGRESS != link->receive_status) {
4135 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
4140 ret = isotp_receive_consecutive_frame(link, &message, len);
4143 if (ISOTP_RET_WRONG_SN == ret) {
4144 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_WRONG_SN;
4145 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4150 if (ISOTP_RET_OK == ret) {
4152 link->receive_timer_cr =
isotp_user_get_us() + ISO_TP_DEFAULT_RESPONSE_TIMEOUT_US;
4155 if (link->receive_offset >= link->receive_size) {
4156 link->receive_status = ISOTP_RECEIVE_STATUS_FULL;
4159 if (0 == --link->receive_bs_count) {
4160 link->receive_bs_count = ISO_TP_DEFAULT_BLOCK_SIZE;
4161 isotp_send_flow_control(link, PCI_FLOW_STATUS_CONTINUE, link->receive_bs_count, ISO_TP_DEFAULT_ST_MIN_US);
4168 case ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME:
4170 if (ISOTP_SEND_STATUS_INPROGRESS != link->send_status) {
4175 ret = isotp_receive_flow_control_frame(link, &message, len);
4177 if (ISOTP_RET_OK == ret) {
4182 if (PCI_FLOW_STATUS_OVERFLOW == message.as.flow_control.FS) {
4183 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
4184 link->send_status = ISOTP_SEND_STATUS_ERROR;
4188 else if (PCI_FLOW_STATUS_WAIT == message.as.flow_control.FS) {
4189 link->send_wtf_count += 1;
4191 if (link->send_wtf_count > ISO_TP_MAX_WFT_NUMBER) {
4192 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_WFT_OVRN;
4193 link->send_status = ISOTP_SEND_STATUS_ERROR;
4198 else if (PCI_FLOW_STATUS_CONTINUE == message.as.flow_control.FS) {
4199 if (0 == message.as.flow_control.BS) {
4200 link->send_bs_remain = ISOTP_INVALID_BS;
4202 link->send_bs_remain = message.as.flow_control.BS;
4204 uint32_t message_st_min_us = isotp_st_min_to_us(message.as.flow_control.STmin);
4205 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;
4206 link->send_wtf_count = 0;
4220 if (ISOTP_RECEIVE_STATUS_FULL != link->receive_status) {
4221 return ISOTP_RET_NO_DATA;
4224 copylen = link->receive_size;
4225 if (copylen > payload_size) {
4226 copylen = payload_size;
4229 memcpy(payload, link->receive_buffer, copylen);
4230 *out_size = copylen;
4232 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4234 return ISOTP_RET_OK;
4237void isotp_init_link(
IsoTpLink *link, uint32_t sendid, uint8_t *sendbuf, uint16_t sendbufsize, uint8_t *recvbuf, uint16_t recvbufsize) {
4238 memset(link, 0,
sizeof(*link));
4239 link->receive_status = ISOTP_RECEIVE_STATUS_IDLE;
4240 link->send_status = ISOTP_SEND_STATUS_IDLE;
4241 link->send_arbitration_id = sendid;
4242 link->send_buffer = sendbuf;
4243 link->send_buf_size = sendbufsize;
4244 link->receive_buffer = recvbuf;
4245 link->receive_buf_size = recvbufsize;
4254 if (ISOTP_SEND_STATUS_INPROGRESS == link->send_status) {
4258 (ISOTP_INVALID_BS == link->send_bs_remain || link->send_bs_remain > 0) &&
4260 (0 == link->send_st_min_us || IsoTpTimeAfter(
isotp_user_get_us(), link->send_timer_st))) {
4262 ret = isotp_send_consecutive_frame(link);
4263 if (ISOTP_RET_OK == ret) {
4264 if (ISOTP_INVALID_BS != link->send_bs_remain) {
4265 link->send_bs_remain -= 1;
4271 if (link->send_offset >= link->send_size) {
4272 link->send_status = ISOTP_SEND_STATUS_IDLE;
4274 }
else if (ISOTP_RET_NOSPACE == ret) {
4277 link->send_status = ISOTP_SEND_STATUS_ERROR;
4283 link->send_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_BS;
4284 link->send_status = ISOTP_SEND_STATUS_ERROR;
4289 if (ISOTP_RECEIVE_STATUS_INPROGRESS == link->receive_status) {
4293 link->receive_protocol_result = ISOTP_PROTOCOL_RESULT_TIMEOUT_CR;
4294 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