rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
isotp.cpp
Go to the documentation of this file.
1/**
2 *
3 * https://en.wikipedia.org/wiki/ISO_15765-2
4 */
5
6#include "pch.h"
7#include "isotp.h"
8#include "can_rx.h"
9
10#if HAL_USE_CAN || EFI_UNIT_TEST
11
12int IsoTpBase::sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout) {
13 int dlc = 8; // standard 8 bytes
14 CanTxMessage txmsg(CanCategory::SERIAL, txFrameId, dlc, busIndex, IS_EXT_RANGE_ID(txFrameId));
15
16 // fill the frame data according to the CAN-TP protocol (ISO 15765-2)
17 txmsg[isoHeaderByteIndex] = (uint8_t)((header.frameType & 0xf) << 4);
18 int offset, maxNumBytes;
19 switch (header.frameType) {
22 maxNumBytes = minI(header.numBytes, dlc - offset);
23 txmsg[isoHeaderByteIndex] |= maxNumBytes;
24 break;
26 txmsg[isoHeaderByteIndex] |= (header.numBytes >> 8) & 0xf;
27 txmsg[isoHeaderByteIndex + 1] = (uint8_t)(header.numBytes & 0xff);
29 maxNumBytes = minI(header.numBytes, dlc - offset);
30 break;
32 txmsg[isoHeaderByteIndex] |= header.index & 0xf;
34 // todo: is it correct?
35 maxNumBytes = dlc - offset;
36 break;
38 txmsg[isoHeaderByteIndex] |= header.fcFlag & 0xf;
39 txmsg[isoHeaderByteIndex + 1] = (uint8_t)(header.blockSize);
40 txmsg[isoHeaderByteIndex + 2] = (uint8_t)(header.separationTime);
42 maxNumBytes = 0; // no data is sent with 'flow control' frame
43 break;
44 default:
45 // bad frame type
46 return 0;
47 }
48
49 int numBytes = minI(maxNumBytes, num);
50 // copy the contents
51 if (data != nullptr) {
52 for (int i = 0; i < numBytes; i++) {
53 txmsg[i + offset] = data[i];
54 }
55 }
56
57 // send the frame!
58 if (transmit(txmsg, timeout) == CAN_MSG_OK)
59 return numBytes;
60 return 0;
61}
62
63// returns the number of copied bytes
64int CanStreamerState::receiveFrame(const CANRxFrame &rxmsg, uint8_t *destinationBuff, int availableAtBuffer, can_sysinterval_t timeout) {
65 if (rxmsg.DLC < 1 + isoHeaderByteIndex)
66 return 0;
68 int frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
70 efiPrintf("receiveFrame frameType=%d", frameType);
71#if EFI_PROD_CODE
72 printCANRxFrame(-1, rxmsg);
73#endif // EFI_PROD_CODE
74 }
75 int numBytesAvailable, frameIdx;
76 const uint8_t *srcBuf;
77 switch (frameType) {
79 numBytesAvailable = rxmsg.data8[isoHeaderByteIndex] & 0xf;
80 this->waitingForNumBytes = numBytesAvailable;
81 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
82 break;
84 this->waitingForNumBytes = ((rxmsg.data8[isoHeaderByteIndex] & 0xf) << 8) | rxmsg.data8[isoHeaderByteIndex + 1];
85 this->waitingForFrameIndex = 1;
86 numBytesAvailable = minI(this->waitingForNumBytes, 6 - isoHeaderByteIndex);
87 srcBuf = rxmsg.data8 + 2 + isoHeaderByteIndex;
88 if (rxTransport) {
89 rxTransport->onTpFirstFrame(); // used to send flow control message
90 }
91 break;
93 frameIdx = rxmsg.data8[isoHeaderByteIndex] & 0xf;
94 if (this->waitingForNumBytes < 0 || this->waitingForFrameIndex != frameIdx) {
95 // todo: that's an abnormal situation, and we probably should react?
96 return 0;
97 }
98 numBytesAvailable = minI(this->waitingForNumBytes, 7 - isoHeaderByteIndex);
99 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
100 this->waitingForFrameIndex = (this->waitingForFrameIndex + 1) & 0xf;
101 break;
103 // todo: currently we just ignore the FC frame
104 return 0;
105 default:
106 // bad frame type
107 return 0;
108 }
109
110/** performance optimization specific to TS over CAN tunnelling
111TODO: refactor into child class if we ever choose to revive this logic
112#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
113 if (frameType == ISO_TP_FRAME_SINGLE) {
114 // restore the CRC on the whole packet
115 uint32_t crc = crc32((void *) srcBuf, numBytesAvailable);
116 // we need a separate buffer for crc because srcBuf may not be word-aligned for direct copy
117 uint8_t crcBuffer[sizeof(uint32_t)];
118 *(uint32_t *) (crcBuffer) = SWAP_UINT32(crc);
119
120 // now set the packet size
121 *(uint16_t *) shortCrcPacketStagingArea = SWAP_UINT16(numBytesAvailable);
122 // copy the data
123 if (numBytesAvailable > 0)
124 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t), srcBuf, numBytesAvailable);
125 // copy the crc to the end
126 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));
127
128 // use the reconstructed tmp buffer as a source buffer
129 srcBuf = shortCrcPacketStagingArea;
130 // we added the 16-bit size & 32-bit crc bytes
131 numBytesAvailable += sizeof(uint16_t) + sizeof(crcBuffer);
132 }
133#endif *//* TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME */
134
135 int numBytesToCopy = minI(availableAtBuffer, numBytesAvailable);
136 if (destinationBuff != nullptr) {
137 memcpy(destinationBuff, srcBuf, numBytesToCopy);
138 }
139 srcBuf += numBytesToCopy;
140 waitingForNumBytes -= numBytesAvailable;
142 numBytesAvailable -= numBytesToCopy;
143 // if there are some more bytes left, we save them for the next time
144 for (int i = 0; i < numBytesAvailable; i++) {
145 rxFifoBuf.put(srcBuf[i]);
146 }
147
148 // according to the specs, we need to acknowledge the received multi-frame start frame
149 if (frameType == ISO_TP_FRAME_FIRST) {
150 IsoTpFrameHeader header;
152 header.fcFlag = 0; // = "continue to send"
153 header.blockSize = 0; // = the remaining "frames" to be sent without flow control or delay
154 header.separationTime = 0; // = wait 0 milliseconds, send immediately
155 IsoTpBase::sendFrame(header, nullptr, 0, timeout);
156 }
157
158 return numBytesToCopy;
159}
160
166
167int CanStreamerState::sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout) {
168 int offset = 0;
169
171 PRINT("*** INFO: sendDataTimeout %d" PRINT_EOL, numBytes);
172 }
173
174 if (numBytes < 1)
175 return 0;
176
177 // 1 frame
178 if (numBytes <= 7 - isoHeaderByteIndex) {
179 IsoTpFrameHeader header;
181 header.numBytes = numBytes;
182 return IsoTpBase::sendFrame(header, txbuf, numBytes, timeout);
183 }
184
185 // multiple frames
186
187 // send the first header frame (FF)
188 IsoTpFrameHeader header;
190 header.numBytes = numBytes;
191 int numSent = IsoTpBase::sendFrame(header, txbuf + offset, numBytes, timeout);
192 offset += numSent;
193 numBytes -= numSent;
194 int totalNumSent = numSent;
195
196 // get a flow control (FC) frame
197#if !EFI_UNIT_TEST // todo: add FC to unit-tests?
198 CANRxFrame rxmsg;
199 for (size_t numFcReceived = 0; ; numFcReceived++) {
200 if (rxTransport->receive(&rxmsg, timeout) != CAN_MSG_OK) {
201#ifdef SERIAL_CAN_DEBUG
202 PRINT("*** ERROR: CAN Flow Control frame not received" PRINT_EOL);
203#endif /* SERIAL_CAN_DEBUG */
204 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control frame not received");
205 return 0;
206 }
207 receiveFrame(rxmsg, nullptr, 0, timeout);
208 uint8_t frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
209 uint8_t flowStatus = rxmsg.data8[isoHeaderByteIndex] & 0xf;
210 // if something is not ok
211 if ((frameType != ISO_TP_FRAME_FLOW_CONTROL) || (flowStatus != CAN_FLOW_STATUS_OK)) {
212 // if the receiver is not ready yet and asks to wait for the next FC frame (give it 3 attempts)
213 if ((frameType == ISO_TP_FRAME_FLOW_CONTROL) && (flowStatus == CAN_FLOW_STATUS_WAIT_MORE) && (numFcReceived < 3)) {
214 continue;
215 }
216#ifdef SERIAL_CAN_DEBUG
217 efiPrintf("*** ERROR: CAN Flow Control mode not supported");
218#endif /* SERIAL_CAN_DEBUG */
219 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control mode not supported");
220 return 0;
221 }
222 uint8_t blockSize = rxmsg.data8[isoHeaderByteIndex + 1];
223 uint8_t minSeparationTime = rxmsg.data8[isoHeaderByteIndex + 2];
224 if (blockSize != 0 || minSeparationTime != 0) {
225 // todo: process other Flow Control fields (see ISO 15765-2)
226#ifdef SERIAL_CAN_DEBUG
227 efiPrintf("*** ERROR: CAN Flow Control fields not supported");
228#endif /* SERIAL_CAN_DEBUG */
229 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control fields not supported");
230 }
231 break;
232 }
233#endif /* EFI_UNIT_TEST */
234
235 // send the rest of the data
236 int idx = 1;
237 while (numBytes > 0) {
238 int len = minI(numBytes, 7 - isoHeaderByteIndex);
239 // send the consecutive frames
241 header.index = ((idx++) & 0x0f);
242 header.numBytes = len;
243 numSent = IsoTpBase::sendFrame(header, txbuf + offset, len, timeout);
244 if (numSent < 1)
245 break;
246 totalNumSent += numSent;
247 offset += numSent;
248 numBytes -= numSent;
249 }
250 return totalNumSent;
251}
252
253int CanStreamerState::getDataFromFifo(uint8_t *rxbuf, size_t &numBytes) {
254 if (rxFifoBuf.isEmpty())
255 return 0;
256 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
257 // move bytes from the FIFO buffer
258 int i;
259 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
260 rxbuf[i] = rxFifoBuf.get();
261 numBytes--;
262 }
263 return i;
264}
265
266can_msg_t CanStreamerState::streamAddToTxTimeout(size_t *np, const uint8_t *txbuf, can_sysinterval_t timeout) {
267 int numBytes = *np;
268 int offset = 0;
269
271 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
272 }
273
274 // we send here only if the TX FIFO buffer is getting overflowed
275 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
276 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
277 txFifoBuf.put(txbuf + offset, numBytesToAdd);
278 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
279
281 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
282 }
283
284 if (numSent < 1)
285 break;
286 txFifoBuf.clear();
287 offset += numBytesToAdd;
288 numBytes -= numBytesToAdd;
289 }
290
292 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
293 }
294
295 // now we put the rest on hold
296 txFifoBuf.put(txbuf + offset, numBytes);
297
298
300 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
301 }
302
303 return CAN_MSG_OK;
304}
305
307 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
308 if (numSent != txFifoBuf.getCount()) {
309 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
310 }
311 txFifoBuf.clear();
312
313 return CAN_MSG_OK;
314}
315
317 size_t availableBufferSpace = *np;
318
319 // first, fill the data from the stored buffer (saved from the previous CAN frame)
320 int receivedSoFar = getDataFromFifo(rxbuf, availableBufferSpace);
321
322 // if even more data is needed, then we receive more CAN frames
323 while (availableBufferSpace > 0) {
324 CANRxFrame rxmsg;
325 if (rxTransport->receive(&rxmsg, timeout) == CAN_MSG_OK) {
326 int numReceived = receiveFrame(rxmsg, rxbuf + receivedSoFar, availableBufferSpace, timeout);
327
328 if (numReceived < 1)
329 break;
330 availableBufferSpace -= numReceived;
331 receivedSoFar += numReceived;
332 } else {
333 break;
334 }
335 }
336 *np -= availableBufferSpace;
337
338#ifdef SERIAL_CAN_DEBUG
339 efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
340 for (int j = 0; j < receivedSoFar; j++) {
341 efiPrintf("* [%d]: %02x", j, rxbuf[j]);
342 }
343#endif /* SERIAL_CAN_DEBUG */
344
345 return CAN_MSG_OK;
346}
347
348int IsoTpRx::readTimeout(uint8_t *rxbuf, size_t *size, sysinterval_t timeout)
349{
350 //is fxbuf is too small?
351 bool overflow = false;
352 bool isFirstFrame = true;
353 size_t availableAtBuffer = *size;
354 uint8_t *buf = rxbuf;
355
356 do {
357 CANRxFrame rxmsg;
358
359 // TODO: adjust timeout!
360 if (!rxFifoBuf.get(rxmsg, timeout)) {
361 // TODO: error codes
362 if (isFirstFrame) {
363 efiPrintf("IsoTp: rx timeout, nothing received");
364 } else {
365 efiPrintf("IsoTP: rx timeout, %d left to receive", waitingForNumBytes);
366 }
367 return -1;
368 }
369
370 uint8_t frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
372 efiPrintf("receiveFrame frameType=%d", frameType);
373 #if EFI_PROD_CODE
374 printCANRxFrame(-1, rxmsg);
375 #endif // EFI_PROD_CODE
376 }
377 size_t numBytesAvailable;
378 uint8_t frameIdx;
379 const uint8_t *srcBuf;
380 switch (frameType) {
382 // TODO: check that this is first packet! see isFirstFrame
383 numBytesAvailable = rxmsg.data8[isoHeaderByteIndex] & 0xf;
384 waitingForNumBytes = numBytesAvailable;
385 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
386 break;
388 // TODO: check that this is first packet! see isFirstFrame
389 waitingForNumBytes = ((rxmsg.data8[isoHeaderByteIndex] & 0xf) << 8) | rxmsg.data8[isoHeaderByteIndex + 1];
391 numBytesAvailable = minI(waitingForNumBytes, 6 - isoHeaderByteIndex);
392 srcBuf = rxmsg.data8 + 2 + isoHeaderByteIndex;
393// rxTransport->onTpFirstFrame(); // used to send flow control message
394 break;
396 frameIdx = rxmsg.data8[isoHeaderByteIndex] & 0xf;
397 if (waitingForNumBytes < 0 || waitingForFrameIndex != frameIdx) {
398 // todo: that's an abnormal situation, and we probably should react?
399 // TODO: error codes
400 return -2;
401 }
402 numBytesAvailable = minI(waitingForNumBytes, 7 - isoHeaderByteIndex);
403 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
405 break;
407 // todo: currently we just ignore the FC frame
408 // TODO: we should not receive FC frame while receiving data
409 break;
410 default:
411 // bad frame type
412 // TODO: error codes
413 return -3;
414 }
415
416 if (isFirstFrame) {
417 if ((buf) && (waitingForNumBytes > availableAtBuffer)) {
418 efiPrintf("receive buffer is not enough %d > %d", waitingForNumBytes, availableAtBuffer);
419 }
420 isFirstFrame = false;
421 }
422
423 if (buf != nullptr) {
424 int numBytesToCopy = minI(availableAtBuffer, numBytesAvailable);
425
426 memcpy(buf, srcBuf, numBytesToCopy);
427 buf += numBytesToCopy;
428 availableAtBuffer -= numBytesToCopy;
429
430 // if there are some more bytes left, receive and drop
431 if (numBytesAvailable > numBytesToCopy) {
432 overflow = true;
433 }
434 }
435
436 // according to the specs, we need to acknowledge the received multi-frame start frame
437 if (frameType == ISO_TP_FRAME_FIRST) {
438 IsoTpFrameHeader header;
440 header.fcFlag = 0; // = "continue to send"
441 header.blockSize = 0; // = the remaining "frames" to be sent without flow control or delay
442 header.separationTime = 0; // = wait 0 milliseconds, send immediately
443 sendFrame(header, nullptr, 0, timeout);
444 }
445
446 waitingForNumBytes -= numBytesAvailable;
447 } while (waitingForNumBytes > 0);
448
449 // received size
450 *size = buf - rxbuf;
451
452 return overflow ? 1 : 0;
453}
454
455int IsoTpRxTx::writeTimeout(const uint8_t *txbuf, size_t size, sysinterval_t timeout) {
456 int offset = 0;
457
459 PRINT("*** INFO: sendDataTimeout %d" PRINT_EOL, size);
460 }
461
462 if (size < 1)
463 return 0;
464
465 // 1 frame
466 if (size <= 7 - isoHeaderByteIndex) {
467 IsoTpFrameHeader header;
469 header.numBytes = size;
470 return IsoTpBase::sendFrame(header, txbuf, size, timeout);
471 }
472
473 // multiple frames
474
475 // send the first header frame (FF)
476 IsoTpFrameHeader header;
478 header.numBytes = size;
479 int numSent = IsoTpBase::sendFrame(header, txbuf + offset, size, timeout);
480 offset += numSent;
481 size -= numSent;
482
483 // get a flow control (FC) frame
484#if !EFI_UNIT_TEST // todo: add FC to unit-tests?
485 CANRxFrame rxmsg;
486 size_t numFcReceived = 0;
487 int separationTimeUs = 0;
488 while (numFcReceived < 3) {
489 // TODO: adjust timeout!
490 if (!rxFifoBuf.get(rxmsg, timeout)) {
491 efiPrintf("IsoTp: Flow Control frame not received");
492 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control frame not received");
493 return 0;
494 }
495 uint8_t frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
496
497 // if something is not ok
498 if (frameType != ISO_TP_FRAME_FLOW_CONTROL) {
499 // should we expect only FC here?
500 continue;
501 }
502
503 // Ok, frame is FC
504 numFcReceived++;
505 uint8_t flowStatus = rxmsg.data8[isoHeaderByteIndex] & 0xf;
506
507 if (flowStatus == CAN_FLOW_STATUS_ABORT) {
508 efiPrintf("IsoTp: Flow Control ABORT");
509 // TODO: error codes
510 return -4;
511 }
512
513 if (flowStatus == CAN_FLOW_STATUS_WAIT_MORE) {
514 // if the receiver is not ready yet and asks to wait for the next FC frame (give it 3 attempts)
515 if (numFcReceived < 3) {
516 continue;
517 }
518 // TODO: error codes
519 return -5;
520 }
521
522 if (flowStatus != CAN_FLOW_STATUS_OK) {
523 efiPrintf("IsoTp: Flow Control unknown Status %d", flowStatus);
524 // TODO: error codes
525 return -6;
526 }
527
528 uint8_t blockSize = rxmsg.data8[isoHeaderByteIndex + 1];
529 uint8_t minSeparationTime = rxmsg.data8[isoHeaderByteIndex + 2];
530 if (blockSize != 0) {
531 // todo: process other Flow Control fields (see ISO 15765-2)
532 efiPrintf("IsoTp: Flow Control blockSize is not supported %d", blockSize);
533 // TODO: error codes
534 return -7;
535 }
536
537 if (minSeparationTime <= 0x7f) {
538 // mS units
539 separationTimeUs = minSeparationTime * 1000;
540 } else if ((minSeparationTime >= 0xf1) && (minSeparationTime <= 0xf9)) {
541 // 100 uS units
542 separationTimeUs = (minSeparationTime - 0xf0) * 100;
543 }
544
545 break;
546 }
547#endif /* EFI_UNIT_TEST */
548
549 // send the rest of the data
550 uint8_t idx = 1;
551 while (size > 0) {
552 int len = minI(size, 7 - isoHeaderByteIndex);
553 // send the consecutive frames
555 header.index = ((idx++) & 0x0f);
556 header.numBytes = len;
557 numSent = IsoTpBase::sendFrame(header, txbuf + offset, len, timeout);
558 if (numSent < 1)
559 break;
560 offset += numSent;
561 size -= numSent;
562
563#if ! EFI_UNIT_TEST
564 if (separationTimeUs) {
565 chThdSleepMicroseconds(separationTimeUs);
566 }
567#endif // EFI_UNIT_TEST
568 }
569 return offset;
570}
571
572#endif // HAL_USE_CAN || EFI_UNIT_TEST
int32_t can_msg_t
Definition can_mocks.h:6
int32_t can_sysinterval_t
Definition can_mocks.h:7
void printCANRxFrame(const size_t busIndex, const CANRxFrame &rx)
Definition can_rx.cpp:29
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
Definition isotp.h:137
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
Definition isotp.h:136
can_msg_t streamFlushTx(can_sysinterval_t timeout)
Definition isotp.cpp:306
int sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
Definition isotp.cpp:167
int receiveFrame(const CANRxFrame &rxmsg, uint8_t *buf, int num, can_sysinterval_t timeout)
Definition isotp.cpp:64
ICanReceiver * rxTransport
Definition isotp.h:149
can_msg_t streamReceiveTimeout(size_t *np, uint8_t *rxbuf, can_sysinterval_t timeout)
Definition isotp.cpp:316
int waitingForNumBytes
Definition isotp.h:146
bool isComplete
Definition isotp.h:158
int waitingForFrameIndex
Definition isotp.h:147
int getDataFromFifo(uint8_t *rxbuf, size_t &numBytes)
Definition isotp.cpp:253
can_msg_t streamAddToTxTimeout(size_t *np, const uint8_t *txbuf, can_sysinterval_t timeout)
Definition isotp.cpp:266
bool pauseCANdueToSerial
Definition engine.h:123
virtual can_msg_t receive(CANRxFrame *crfp, can_sysinterval_t timeout)=0
virtual void onTpFirstFrame()=0
size_t busIndex
Definition isotp.h:116
can_msg_t transmit(CanTxMessage &ctfp, can_sysinterval_t timeout)
Definition isotp.h:99
uint32_t txFrameId
Definition isotp.h:118
int sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
Definition isotp.cpp:12
size_t isoHeaderByteIndex
Definition isotp.h:112
IsoTpFrameType frameType
Definition isotp.h:38
int separationTime
Definition isotp.h:47
int readTimeout(uint8_t *rxbuf, size_t *size, sysinterval_t timeout)
Definition isotp.cpp:348
int waitingForNumBytes
Definition isotp.h:221
uint8_t waitingForFrameIndex
Definition isotp.h:222
fifo_buffer_sync< CANRxFrame, ISOTP_RX_QUEUE_LEN > rxFifoBuf
Definition isotp.h:225
int writeTimeout(const uint8_t *txbuf, size_t size, sysinterval_t timeout)
Definition isotp.cpp:455
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
@ ISO_TP_FRAME_CONSECUTIVE
Definition isotp.h:32
@ ISO_TP_FRAME_FIRST
Definition isotp.h:31
@ ISO_TP_FRAME_FLOW_CONTROL
Definition isotp.h:33
@ ISO_TP_FRAME_SINGLE
Definition isotp.h:30
uint8_t data8[8]
Frame data.
Definition can_mocks.h:55
uint8_t DLC
Data length.
Definition can_mocks.h:42
composite packet size
uint16_t offset
Definition tunerstudio.h:0