]> rtime.felk.cvut.cz Git - arc.git/blob - communication/CanTp/CanTp.c
c5d3a8b6dcee218cffb5822dafe97432e59e276d
[arc.git] / communication / CanTp / CanTp.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.                                           \r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 /** @addtogroup TBD\r
17  *  @{ */\r
18 \r
19 /** @file CanTp.c\r
20  * TBD.\r
21  */\r
22 \r
23 /*\r
24  *  General requirements\r
25  */\r
26 \r
27 /** @req CANTP001 */\r
28 /** @req CANTP019 */\r
29 /** @req CANTP020 */\r
30 /** @req CANTP156.Partially */\r
31 /** @req CANTP150 */\r
32 /** @req CANTP151 */\r
33 /** @req CANTP152 */\r
34 /** @req CANTP153 */\r
35 /** @req CANTP155 */\r
36 /** @req CANTP158 */\r
37 /** @req CANTP003 */\r
38 /** @req CANTP216 */\r
39 /** @req CANTP217 */\r
40 \r
41 /*\r
42  * Environmental requirements
43  */\r
44 /** @req CANTP164 */\r
45 /** @req CANTP199 */\r
46 \r
47 \r
48 #include "CanTp.h" /** @req CANTP219 */\r
49 #include "CanTp_Cbk.h" /** @req CANTP233 */\r
50 #include "Det.h"\r
51 #include "CanIf.h"\r
52 #include "SchM_CanTp.h"\r
53 #include "PduR_CanTp.h"\r
54 //#include "MemMap.h"\r
55 #include <string.h>\r
56 //#define USE_DEBUG_PRINTF\r
57 #include "debug.h"\r
58 \r
59 #define CANTP_IMMEDIATE_TX_CONFIRMATION         STD_OFF\r
60 \r
61 #if  ( CANTP_DEV_ERROR_DETECT == STD_ON ) /** @req CANTP006 *//** @req CANTP134 */\r
62 \r
63 /** @req CANTP132 */ /** @req CANTP021 */\r
64 #define VALIDATE(_exp,_api,_err ) \\r
65         if( !(_exp) ) { \\r
66           Det_ReportError(MODULE_ID_CANTP, 0, _api, _err); \\r
67           return E_NOT_OK; \\r
68         }\r
69           /** @req CANTP132 */ /** @req CANTP021 */\r
70 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
71   if( !(_exp) ) { \\r
72           Det_ReportError(MODULE_ID_CANTP, 0, _api, _err); \\r
73           return; \\r
74         }\r
75 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)\r
76 \r
77 #else\r
78 #define VALIDATE(_exp,_api,_err )\r
79 #define VALIDATE_NO_RV(_exp,_api,_err )\r
80 #define DET_REPORTERROR(_x,_y,_z,_q)\r
81 #endif\r
82 \r
83 \r
84 #if 0\r
85 \r
86 NotifResultType PduR_CanTpRxIndication(PduIdType CanTpRxPduId,\r
87                 NotifResultType Result) {\r
88         ;\r
89 \r
90 }\r
91 \r
92 BufReq_ReturnType PduR_CanTpProvideRxBuffer(PduIdType id, PduLengthType length,\r
93                 PduInfoType **PduInfoPtr) {\r
94         ;\r
95 }\r
96 \r
97 BufReq_ReturnType PduR_CanTpProvideTxBuffer(PduIdType CanTpTxId,\r
98                 PduInfoType** PduinfoPtr, uint16 Length) {\r
99         ;\r
100 }\r
101 \r
102 void PduR_CanTpTxConfirmation(PduIdType CanTpTxPduId, NotifResultType Result) {\r
103         ;\r
104 \r
105 }\r
106 \r
107 #endif\r
108 \r
109 //#define INLINE\r
110 #define INLINE inline\r
111 \r
112 #define TIMER_DECREMENT(timer) \\r
113         if (timer > 0) { \\r
114                 timer = timer - 1; \\r
115         } \\r
116 \r
117 #define COUNT_DECREMENT(timer) \\r
118         if (timer > 0) { \\r
119                 timer = timer - 1; \\r
120         } \\r
121 \r
122 \r
123 #define CANTP_ERR                              -1\r
124 #define ISO15765_FLOW_CONTROL_STATUS_CTS        0\r
125 #define ISO15765_FLOW_CONTROL_STATUS_WAIT       1\r
126 #define ISO15765_FLOW_CONTROL_STATUS_OVFLW      2\r
127 \r
128 // - - - - - - - - - - - - - -\r
129 \r
130 #define ISO15765_TPCI_MASK      0x30\r
131 #define ISO15765_TPCI_SF        0x00  /* Single Frame */\r
132 #define ISO15765_TPCI_FF        0x10  /* First Frame */\r
133 #define ISO15765_TPCI_CF        0x20  /* Consecutive Frame */\r
134 #define ISO15765_TPCI_FC        0x30  /* Flow Control */\r
135 #define ISO15765_TPCI_DL        0x7   /* Single frame data length mask */\r
136 #define ISO15765_TPCI_FS_MASK   0x0F  /* Flowcontrol status mask */\r
137 \r
138 // - - - - - - - - - - - - - -\r
139 \r
140 #define MAX_PAYLOAD_SF_STD_ADDR         7\r
141 #define MAX_PAYLOAD_SF_EXT_ADDR         6\r
142 \r
143 #define MAX_PAYLOAD_FF_STD_ADDR         6\r
144 #define MAX_PAYLOAD_FF_EXT_ADDR         5\r
145 \r
146 #define MAX_PAYLOAD_CF_STD_ADDR         7\r
147 #define MAX_PAYLOAD_CF_EXT_ADDR         6\r
148 \r
149 #define SEGMENT_NUMBER_MASK                     0x0f\r
150 \r
151 #define MAX_SEGMENT_DATA_SIZE           8       // Size of a CAN frame data bytes.\r
152 \r
153 /*\r
154  *\r
155  */\r
156 typedef enum {\r
157         UNINITIALIZED, IDLE, SF_OR_FF_RECEIVED_WAITING_PDUR_BUFFER, /** @req CANTP079 */\r
158         RX_WAIT_CONSECUTIVE_FRAME, RX_WAIT_SDU_BUFFER,\r
159 \r
160         TX_WAIT_CAN_TP_TRANSMIT_CAN_TP_PROVIDE_TX_BUFFER, /** @req CANTP226 */\r
161         TX_WAIT_CAN_TP_TRANSMIT_PENDING, /* CanTP_Transmit was called but no buffer was received (BUSY). */\r
162         TX_WAIT_SEND_CONSECUTIVE_FRAME, TX_WAIT_FLOW_CONTROL,\r
163         TX_WAIT_TX_CONFIRMATION\r
164 } ISO15765TransferStateTypes;\r
165 \r
166 typedef enum {\r
167         INVALID_FRAME, /* Not specified by ISO15765 - used as error return type when decoding frame. */\r
168         SINGLE_FRAME, FIRST_FRAME, CONSECUTIVE_FRAME, FLOW_CONTROL_CTS_FRAME, /* Clear to send */\r
169         FLOW_CONTROL_WAIT_FRAME, FLOW_CONTROL_OVERFLOW_FRAME\r
170 } ISO15765FrameType;\r
171 \r
172 typedef enum {\r
173         SEND_NEXT_CONSECUTIVE_FRAME, WAIT_FLOW_CONTROL, TRANSFER_FINISHED\r
174 } ISO15765TxStateTypes;\r
175 \r
176 /*\r
177  *  In case no buffer is available at some cases the data needs to be\r
178  *  temporarly stored away.\r
179  */\r
180 \r
181 typedef struct {\r
182         uint8 data[MAX_SEGMENT_DATA_SIZE];\r
183         PduLengthType byteCount;\r
184 } CanIfSduType;\r
185 \r
186 /*\r
187  *  Structure that is keeping track on the run-time variables for the ongoing\r
188  *  transfer.\r
189  */\r
190 typedef struct {\r
191         uint16 nextFlowControlCount; // Count down to next Flow Control.\r
192         uint16 framesHandledCount; // Counter keeping track total frames handled.\r
193         uint8 extendedAddress; // Not always used but need to be available.\r
194         uint32 stateTimeoutCount; // Counter for timeout.\r
195         uint8 STmin; // In case we are transmitters the remote node can configure this value (only valid for TX).\r
196         uint8 BS; // Blocksize (only valid for TX).\r
197         boolean NasNarPending;\r
198 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
199         boolean txConfirmed;\r
200 #endif\r
201         uint32 NasNarTimeoutCount; // CanTpNas, CanTpNar.\r
202         ISO15765TransferStateTypes state; // Transfer state machine. TODO: Can this be initialized here?\r
203 } ISO15765TransferControlType;\r
204 \r
205 /*\r
206  *      Container for TX or RX runtime paramters (TX/RX are identical?)\r
207  */\r
208 typedef struct {\r
209         ISO15765TransferControlType iso15765;\r
210         PduInfoType *pdurBuffer; // The PDUR make an instance of this.\r
211         PduLengthType pdurBufferCount; // Number of bytes in PDUR buffer.\r
212         PduLengthType transferTotal; // Total length of the PDU.\r
213         PduLengthType transferCount; // Counter ongoing transfer.\r
214         CanIfSduType canFrameBuffer; // Temp storage of SDU data.\r
215         CanTp_TransferInstanceMode mode; // CanTp030.\r
216 } CanTp_ChannelPrivateType;\r
217 \r
218 \r
219 #define CANIF_PDU_MAX_LENGTH                                    0x08  // Max length is 8 (it is CAN dlc=8).\r
220 \r
221 typedef struct {\r
222         PduIdType PduId;\r
223         uint8 SduData[CANIF_PDU_MAX_LENGTH];\r
224         PduLengthType SduLength;\r
225 } CanTpFifoQueueItem;\r
226 \r
227 #define FIFO_QUEUE_DEPTH        10\r
228 \r
229 typedef struct {\r
230         int fifoQueueReadIndex;\r
231         int fifoQueueWriteIndex;\r
232         CanTpFifoQueueItem queueList[FIFO_QUEUE_DEPTH];\r
233 } CanTpFifo;\r
234 \r
235 // - - - - - - - - - - - - - -\r
236 \r
237 typedef struct {\r
238         boolean initRun;\r
239         CanTpFifo fifo;\r
240         CanTp_StateType internalState; /** @req CANTP027 */\r
241         CanTp_ChannelPrivateType runtimeDataList[CANTP_NSDU_RUNTIME_LIST_SIZE];\r
242 } CanTp_RunTimeDataType;\r
243 \r
244 // - - - - - - - - - - - - - -\r
245 \r
246 CanTp_RunTimeDataType CanTpRunTimeData = { .initRun = FALSE,\r
247                 .internalState = CANTP_OFF }; /** @req CANTP168 */\r
248 \r
249 static INLINE void fifoQueueInit( CanTpFifo *fifoQueue ) {\r
250         fifoQueue->fifoQueueReadIndex = 0;\r
251         fifoQueue->fifoQueueWriteIndex = 0;\r
252 }\r
253 \r
254 // - - - - - - - - - - - - - -\r
255 \r
256 static INLINE boolean fifoQueueRead( CanTpFifo *fifoQueue, CanTpFifoQueueItem *item ) {\r
257         boolean ret = FALSE;\r
258         int readIndex = 0;\r
259         readIndex = fifoQueue->fifoQueueReadIndex;\r
260         if ( fifoQueue->fifoQueueReadIndex != fifoQueue->fifoQueueWriteIndex ) {\r
261 \r
262                 if (++readIndex == FIFO_QUEUE_DEPTH) {\r
263                         readIndex = 0;\r
264                 }\r
265                 item->PduId = fifoQueue->queueList[fifoQueue->fifoQueueReadIndex].PduId;\r
266                 item->SduLength = fifoQueue->queueList[fifoQueue->fifoQueueReadIndex].SduLength;\r
267                 for (int i=0; i<item->SduLength; i++) {\r
268                         item->SduData[i] = fifoQueue->queueList[fifoQueue->fifoQueueReadIndex].SduData[i];\r
269                 }\r
270                 fifoQueue->fifoQueueReadIndex = readIndex;\r
271                 ret = TRUE;\r
272         } else {\r
273                 ret = FALSE;\r
274         }\r
275         return ret;\r
276 }\r
277 \r
278 // - - - - - - - - - - - - - -\r
279 \r
280 static INLINE boolean fifoQueueWrite( CanTpFifo *fifoQueue, CanTpFifoQueueItem *item ) {\r
281         boolean ret = FALSE;\r
282         int writeIndex;\r
283         writeIndex = fifoQueue->fifoQueueWriteIndex;\r
284         if (++writeIndex == FIFO_QUEUE_DEPTH) {\r
285                 writeIndex = 0;\r
286         }\r
287         if ( writeIndex != fifoQueue->fifoQueueReadIndex ) { // Check if space left.\r
288                 fifoQueue->queueList[fifoQueue->fifoQueueWriteIndex].PduId = item->PduId;\r
289                 fifoQueue->queueList[fifoQueue->fifoQueueWriteIndex].SduLength = item->SduLength;\r
290                 for (int i=0; i<item->SduLength;i++) {\r
291                         fifoQueue->queueList[fifoQueue->fifoQueueWriteIndex].SduData[i] = item->SduData[i];\r
292                 }\r
293                 fifoQueue->fifoQueueWriteIndex = writeIndex;\r
294                 ret = TRUE;\r
295         }\r
296         return ret;\r
297 }\r
298 \r
299 // - - - - - - - - - - - - - -\r
300 \r
301 static inline ISO15765FrameType getFrameType(\r
302                 const CanTp_AddressingFormantType *formatType,\r
303                 const PduInfoType *CanTpRxPduPtr) {\r
304         ISO15765FrameType res = INVALID_FRAME;\r
305         uint8 tpci = 0;\r
306 \r
307         switch (*formatType) {\r
308         case CANTP_STANDARD:\r
309                 DEBUG( DEBUG_MEDIUM, "CANTP_STANDARD\n");\r
310                 tpci = CanTpRxPduPtr->SduDataPtr[0];\r
311                 break;\r
312         case CANTP_EXTENDED:\r
313                 DEBUG( DEBUG_MEDIUM, "CANTP_EXTENDED\n");\r
314                 tpci = CanTpRxPduPtr->SduDataPtr[1];\r
315                 break;\r
316         default:\r
317                 break;\r
318         }\r
319 \r
320         switch (tpci & ISO15765_TPCI_MASK) {\r
321         case ISO15765_TPCI_SF:\r
322                 res = SINGLE_FRAME;\r
323                 break;\r
324         case ISO15765_TPCI_FF:\r
325                 res = FIRST_FRAME;\r
326                 break;\r
327         case ISO15765_TPCI_CF:\r
328                 res = CONSECUTIVE_FRAME;\r
329                 break;\r
330         case ISO15765_TPCI_FC: // Some kind of flow control.\r
331                 switch (tpci & ISO15765_TPCI_FS_MASK) {\r
332                 case ISO15765_FLOW_CONTROL_STATUS_CTS:\r
333                         res = FLOW_CONTROL_CTS_FRAME;\r
334                         break;\r
335                 case ISO15765_FLOW_CONTROL_STATUS_WAIT:\r
336                         res = FLOW_CONTROL_CTS_FRAME;\r
337                         break;\r
338                 case ISO15765_FLOW_CONTROL_STATUS_OVFLW:\r
339                         res = FLOW_CONTROL_CTS_FRAME;\r
340                         break;\r
341                 }\r
342         }\r
343         return res;\r
344 }\r
345 \r
346 // - - - - - - - - - - - - - -\r
347 \r
348 static inline PduLengthType getPduLength(\r
349                 const CanTp_AddressingFormantType *formatType,\r
350                 const ISO15765FrameType iso15765Frame, const PduInfoType *CanTpRxPduPtr) {\r
351         PduLengthType res = 0;\r
352         uint8 tpci_offset = 0;\r
353 \r
354         switch (*formatType) {\r
355         case CANTP_STANDARD:\r
356                 tpci_offset = 0;\r
357                 break;\r
358         case CANTP_EXTENDED:\r
359                 tpci_offset = 1;\r
360                 break;\r
361         default:\r
362                 return 0;\r
363         }\r
364 \r
365         switch (iso15765Frame) {\r
366         case SINGLE_FRAME:\r
367                 // Parse the data length from the single frame header.\r
368                 res = CanTpRxPduPtr->SduDataPtr[tpci_offset] & ISO15765_TPCI_DL;\r
369                 break;\r
370         case FIRST_FRAME:\r
371                 // Parse the data length form the first frame.\r
372                 res = CanTpRxPduPtr->SduDataPtr[tpci_offset + 1] + ((PduLengthType)((CanTpRxPduPtr->SduDataPtr[tpci_offset]) & 0xf) << 8);\r
373                 break;\r
374         default:\r
375                 res = 0; // TODO: maybe we should have an error code here.\r
376                 break;\r
377         }\r
378         return res;\r
379 }\r
380 \r
381 // - - - - - - - - - - - - - -\r
382 \r
383 static void initRx15765RuntimeData(const CanTp_RxNSduType *rxConfigParams,\r
384                 CanTp_ChannelPrivateType *rxRuntimeParams) {\r
385 \r
386         rxRuntimeParams->iso15765.state = IDLE;\r
387         rxRuntimeParams->iso15765.NasNarPending = FALSE;\r
388         rxRuntimeParams->iso15765.framesHandledCount = 0;\r
389         rxRuntimeParams->iso15765.nextFlowControlCount = 0;\r
390         rxRuntimeParams->pdurBufferCount = 0;\r
391         rxRuntimeParams->transferTotal = 0;\r
392         rxRuntimeParams->transferCount = 0;\r
393         rxRuntimeParams->mode = CANTP_RX_WAIT; /** @req CANTP030 */\r
394         rxRuntimeParams->pdurBuffer = NULL;\r
395 }\r
396 \r
397 // - - - - - - - - - - - - - -\r
398 \r
399 static void initTx15765RuntimeData(const CanTp_TxNSduType *txConfigParams,\r
400                 CanTp_ChannelPrivateType *txRuntimeParams) {\r
401 \r
402         txRuntimeParams->iso15765.state = IDLE;\r
403         txRuntimeParams->iso15765.NasNarPending = FALSE;\r
404         txRuntimeParams->iso15765.framesHandledCount = 0;\r
405         txRuntimeParams->iso15765.nextFlowControlCount = 0;\r
406         txRuntimeParams->pdurBufferCount = 0;\r
407         txRuntimeParams->transferTotal = 0;\r
408         txRuntimeParams->transferCount = 0;\r
409         txRuntimeParams->mode = CANTP_TX_WAIT; /** @req CANTP030 */\r
410         txRuntimeParams->pdurBuffer = NULL;\r
411 \r
412 }\r
413 \r
414 // - - - - - - - - - - - - - -\r
415 \r
416 static INLINE BufReq_ReturnType copySegmentToPduRRxBuffer(const CanTp_RxNSduType *rxConfig,\r
417                 CanTp_ChannelPrivateType *rxRuntime, uint8 *segment,\r
418                 PduLengthType segmentSize, PduLengthType *bytesWrittenSuccessfully) {\r
419 \r
420         BufReq_ReturnType ret = BUFREQ_NOT_OK;\r
421         boolean endLoop = FALSE;\r
422         *bytesWrittenSuccessfully = 0;\r
423 \r
424         while ((*bytesWrittenSuccessfully < segmentSize) && (!endLoop)) {\r
425                 // Copy the data that resides in the buffer.\r
426                 if (rxRuntime->pdurBuffer != NULL) {\r
427                         while ((*bytesWrittenSuccessfully < segmentSize ) && (rxRuntime->pdurBuffer->SduLength > rxRuntime->pdurBufferCount)) {\r
428                                 rxRuntime->pdurBuffer->SduDataPtr[rxRuntime->pdurBufferCount++] = segment[(*bytesWrittenSuccessfully)++];\r
429                         }\r
430                 }\r
431                 if (*bytesWrittenSuccessfully < segmentSize ) {\r
432                         // We need to request a new buffer from the SDUR.\r
433                         // TODO: We should do a timeout here.\r
434                         ret = PduR_CanTpProvideRxBuffer(rxConfig->PduR_PduId, rxRuntime->transferTotal, &rxRuntime->pdurBuffer);  /** @req CANTP079 */ /** @req CANTP080 */ /** @req CANTP064 */\r
435                         if (ret == BUFREQ_OK) {\r
436                                 VALIDATE( rxRuntime->pdurBuffer->SduDataPtr != NULL,\r
437                                                 SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_RX_BUFFER );\r
438                                 rxRuntime->pdurBufferCount = 0; // The buffer is emptied.\r
439                         } else if (ret == BUFREQ_BUSY) {\r
440                                 rxRuntime->transferCount += *bytesWrittenSuccessfully;\r
441                                 endLoop = TRUE;\r
442                         } else {\r
443                                 endLoop = TRUE; // Let calling function handle this error.\r
444                         }\r
445                 } else {\r
446                         rxRuntime->transferCount += segmentSize; //== bytesWrittenSuccessfully\r
447                         ret = BUFREQ_OK;\r
448                         endLoop = TRUE;\r
449                 }\r
450         }\r
451         return ret;\r
452 }\r
453 \r
454 // - - - - - - - - - - - - - -\r
455 \r
456 static INLINE boolean copySegmentToLocalRxBuffer /*writeDataSegmentToLocalBuffer*/(\r
457                 CanTp_ChannelPrivateType *rxRuntime, uint8 *segment,\r
458                 PduLengthType segmentSize) {\r
459         boolean ret = FALSE;\r
460 \r
461         if ( segmentSize < MAX_SEGMENT_DATA_SIZE ) {\r
462                 for (int i=0; i < segmentSize; i++) {\r
463                         rxRuntime->canFrameBuffer.data[i] = segment[i];\r
464                 }\r
465                 rxRuntime->canFrameBuffer.byteCount = segmentSize;\r
466                 ret = TRUE;\r
467         }\r
468         return ret;\r
469 }\r
470 \r
471 // - - - - - - - - - - - - - -\r
472 \r
473 static INLINE Std_ReturnType canReceivePaddingHelper(\r
474                 const CanTp_RxNSduType *rxConfig, CanTp_ChannelPrivateType *rxRuntime,\r
475                 PduInfoType *PduInfoPtr) {\r
476         if (rxConfig->CanTpRxPaddingActivation == CANTP_ON) {\r
477                 for (int i = PduInfoPtr->SduLength; i < CANIF_PDU_MAX_LENGTH; i++) {\r
478                         PduInfoPtr->SduDataPtr[i] = 0x0; // TODO: Does it have to be padded with zeroes?\r
479                 }\r
480                 PduInfoPtr->SduLength = CANIF_PDU_MAX_LENGTH;\r
481         }\r
482         rxRuntime->iso15765.NasNarTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNar); /** @req CANTP075 */\r
483         rxRuntime->iso15765.NasNarPending = TRUE;\r
484         return CanIf_Transmit(rxConfig->CanIf_FcPduId, PduInfoPtr);\r
485 }\r
486 \r
487 // - - - - - - - - - - - - - -\r
488 \r
489 static INLINE Std_ReturnType canTansmitPaddingHelper(\r
490                 const CanTp_TxNSduType *txConfig, CanTp_ChannelPrivateType *txRuntime,\r
491                 PduInfoType *PduInfoPtr) {\r
492 \r
493         /** @req CANTP114 */\r
494         /** @req CANTP040 */\r
495         /** @req CANTP098 */\r
496         /** @req CANTP116 */\r
497         /** @req CANTP059 */\r
498 \r
499         if (txConfig->CanTpTxPaddingActivation == CANTP_ON) { /** @req CANTP225 */\r
500                 for (int i = PduInfoPtr->SduLength; i < CANIF_PDU_MAX_LENGTH; i++) {\r
501                         PduInfoPtr->SduDataPtr[i] = 0x0; // TODO: Does it have to be padded with zeroes?\r
502                 }\r
503                 PduInfoPtr->SduLength = CANIF_PDU_MAX_LENGTH;\r
504         }\r
505         txRuntime->iso15765.NasNarTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNas); /** @req CANTP075 */\r
506         txRuntime->iso15765.NasNarPending = TRUE;\r
507 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
508         txRuntime->iso15765.txConfirmed = FALSE;\r
509 #endif\r
510         return CanIf_Transmit(txConfig->CanIf_PduId, PduInfoPtr);\r
511 }\r
512 \r
513 // - - - - - - - - - - - - - -\r
514 \r
515 static INLINE void sendFlowControlFrame(const CanTp_RxNSduType *rxConfig, CanTp_ChannelPrivateType *rxRuntime, BufReq_ReturnType flowStatus) {\r
516         uint8 indexCount = 0;\r
517         Std_ReturnType ret = E_NOT_OK;\r
518         PduInfoType pduInfo;\r
519         uint8 sduData[8]; // Note that buffer in declared on the stack.\r
520         uint16 spaceFreePduRBuffer = 0;\r
521         uint16 computedBs = 0;\r
522 \r
523         DEBUG( DEBUG_MEDIUM, "sendFlowControlFrame called!\n");\r
524         pduInfo.SduDataPtr = &sduData[0];\r
525         if (rxConfig->CanTpAddressingFormant == CANTP_EXTENDED) {\r
526                 sduData[indexCount++] = rxRuntime->iso15765.extendedAddress;\r
527         }\r
528         switch (flowStatus) {\r
529         case BUFREQ_OK:\r
530         {\r
531                 sduData[indexCount++] = ISO15765_TPCI_FC | ISO15765_FLOW_CONTROL_STATUS_CTS;\r
532                 spaceFreePduRBuffer = rxRuntime->pdurBuffer->SduLength - rxRuntime->pdurBufferCount;\r
533                 if (rxConfig->CanTpAddressingFormant == CANTP_EXTENDED) { /** @req CANTP094 *//** @req CANTP095 */\r
534                         computedBs = (spaceFreePduRBuffer / MAX_PAYLOAD_SF_EXT_ADDR) + 1;  // + 1 is for local buffer.\r
535                 } else {\r
536                         computedBs = (spaceFreePduRBuffer / MAX_PAYLOAD_SF_STD_ADDR) + 1;  // + 1 is for local buffer.\r
537                 }\r
538                 if (computedBs > rxConfig->CanTpBs) { // /** @req CANTP091 *//** @req CANTP084 */\r
539                         computedBs = rxConfig->CanTpBs;\r
540                 }\r
541                 DEBUG( DEBUG_MEDIUM, "computedBs:%d\n", computedBs);\r
542                 sduData[indexCount++] = computedBs; // 734 PC-lint: Okej att casta till uint8?\r
543                 sduData[indexCount++] = (uint8) rxConfig->CanTpSTmin;\r
544                 rxRuntime->iso15765.nextFlowControlCount = computedBs;\r
545                 pduInfo.SduLength = indexCount;\r
546                 break;\r
547         }\r
548         case BUFREQ_NOT_OK:\r
549                 break;\r
550         case BUFREQ_BUSY:\r
551                 sduData[indexCount++] = ISO15765_TPCI_FC | ISO15765_FLOW_CONTROL_STATUS_WAIT;\r
552                 pduInfo.SduLength = indexCount;\r
553                 break;\r
554         case BUFREQ_OVFL: /** @req CANTP081 */\r
555                 sduData[indexCount++] = ISO15765_TPCI_FC | ISO15765_FLOW_CONTROL_STATUS_OVFLW;\r
556                 pduInfo.SduLength = indexCount;\r
557                 break;\r
558         default:\r
559                 break;\r
560         }\r
561         ret = canReceivePaddingHelper(rxConfig, rxRuntime, &pduInfo);\r
562         if (ret != E_OK) {\r
563                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_NOT_OK);  /** @req CANTP084 */\r
564                 rxRuntime->iso15765.state = IDLE;\r
565                 rxRuntime->mode = CANTP_RX_WAIT;\r
566         }\r
567 }\r
568 \r
569 // - - - - - - - - - - - - - -\r
570 \r
571 \r
572 static INLINE void handleConsecutiveFrame(const CanTp_RxNSduType *rxConfig,\r
573                 CanTp_ChannelPrivateType *rxRuntime, const PduInfoType *rxPduData) {\r
574         uint8 indexCount = 0;\r
575         uint8 segmentNumber = 0;\r
576         uint8 extendedAddress = 0;\r
577         PduLengthType bytesLeftToCopy = 0;\r
578         PduLengthType bytesLeftToTransfer = 0;\r
579         PduLengthType currentSegmentSize = 0;\r
580         PduLengthType currentSegmentMaxSize = 0;\r
581         PduLengthType bytesCopiedToPdurRxBuffer = 0;\r
582         BufReq_ReturnType ret = BUFREQ_NOT_OK;\r
583 \r
584         if (rxRuntime->iso15765.state == RX_WAIT_CONSECUTIVE_FRAME) {\r
585                 if (rxConfig->CanTpAddressingFormant == CANTP_EXTENDED) {\r
586                         extendedAddress = rxPduData->SduDataPtr[indexCount++];\r
587                 }\r
588                 segmentNumber = rxPduData->SduDataPtr[indexCount++] & SEGMENT_NUMBER_MASK;\r
589                 if (segmentNumber != (rxRuntime->iso15765.framesHandledCount & SEGMENT_NUMBER_MASK)) {\r
590                         DEBUG(DEBUG_MEDIUM,"Segmentation number error detected - is the sending"\r
591                                         "unit too fast? Increase STmin (cofig) to slow it down!\n");\r
592                         PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_WRONG_SN); /** @req CANTP084 */\r
593                         rxRuntime->iso15765.state = IDLE;\r
594                         rxRuntime->mode = CANTP_RX_WAIT;\r
595                 } else {\r
596                         currentSegmentMaxSize = CANIF_PDU_MAX_LENGTH - indexCount;\r
597                         bytesLeftToCopy = rxRuntime->transferTotal - rxRuntime->transferCount;\r
598                         if (bytesLeftToCopy < currentSegmentMaxSize) {\r
599                                 currentSegmentSize = bytesLeftToCopy; // 1-5.\r
600                         } else {\r
601                                 currentSegmentSize = currentSegmentMaxSize; // 6 or 7, depends on addressing format used.\r
602                         }\r
603                         // Copy received data to buffer provided by SDUR.\r
604                         ret = copySegmentToPduRRxBuffer(rxConfig, rxRuntime,\r
605                                         &rxPduData->SduDataPtr[indexCount],\r
606                                         currentSegmentSize,\r
607                                         &bytesCopiedToPdurRxBuffer);\r
608                         if (ret == BUFREQ_NOT_OK) {\r
609                                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_NO_BUFFER); /** @req CANTP084 */\r
610                                 rxRuntime->iso15765.state = IDLE;\r
611                                 rxRuntime->mode = CANTP_RX_WAIT;\r
612                         } else if (ret == BUFREQ_BUSY) {\r
613                                 boolean dataCopyFailure = FALSE;\r
614                                 PduLengthType bytesNotCopiedToPdurRxBuffer = currentSegmentSize - bytesCopiedToPdurRxBuffer;\r
615                                 if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) {\r
616                                         if ( copySegmentToLocalRxBuffer(rxRuntime,      /** @req CANTP067 */\r
617                                                         &rxPduData->SduDataPtr[1 + bytesCopiedToPdurRxBuffer],\r
618                                                         bytesNotCopiedToPdurRxBuffer ) != TRUE ) {\r
619                                                 rxRuntime->iso15765.state = IDLE;\r
620                                                 rxRuntime->mode = CANTP_RX_WAIT;\r
621                                                 dataCopyFailure = TRUE;\r
622                                                 DEBUG( DEBUG_MEDIUM, "Unexpected error, could not copy 'unaligned leftover' " "data to local buffer!\n");\r
623                                         }\r
624                                 } else {\r
625                                         if ( copySegmentToLocalRxBuffer(rxRuntime,  /** @req CANTP067 */\r
626                                                         &rxPduData->SduDataPtr[2 + bytesCopiedToPdurRxBuffer],\r
627                                                         bytesNotCopiedToPdurRxBuffer) != TRUE ) {\r
628                                                 rxRuntime->iso15765.state = IDLE;\r
629                                                 rxRuntime->mode = CANTP_RX_WAIT;\r
630                                                 dataCopyFailure = TRUE;\r
631                                                 DEBUG( DEBUG_MEDIUM, "Unexpected error, could not copy 'unaligned leftover' " "data to local buffer!\n");\r
632                                         }\r
633                                 }\r
634                                 if ( !dataCopyFailure ) {\r
635                                         rxRuntime->iso15765.framesHandledCount++;\r
636                                         rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNbr);\r
637                                         rxRuntime->iso15765.state = RX_WAIT_SDU_BUFFER;\r
638                                         rxRuntime->mode = CANTP_RX_PROCESSING;\r
639                                         sendFlowControlFrame(rxConfig, rxRuntime, ret);  /** @req CANTP082 */\r
640                                 }\r
641                         } else if (ret == BUFREQ_OK) {\r
642                                 bytesLeftToTransfer = rxRuntime->transferTotal - rxRuntime->transferCount;\r
643                                 if (bytesLeftToTransfer > 0) {\r
644                                         rxRuntime->iso15765.framesHandledCount++;\r
645                                         COUNT_DECREMENT(rxRuntime->iso15765.nextFlowControlCount);\r
646                                         if (rxRuntime->iso15765.nextFlowControlCount == 0) {\r
647                                                 sendFlowControlFrame(rxConfig, rxRuntime, BUFREQ_OK);\r
648                                         } else {\r
649                                                 rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNcr);  //UH\r
650                                         }\r
651                                 } else {\r
652                                         DEBUG( DEBUG_MEDIUM,"ISO15765-Rx session finished, going back to IDLE!\n");\r
653                                         rxRuntime->iso15765.state = IDLE;\r
654                                         rxRuntime->mode = CANTP_RX_WAIT;\r
655                                         PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_OK); /** @req CANTP084 */\r
656                                 }\r
657                         }\r
658                 }\r
659         }\r
660 } // 438, 550 PC-lint: extendedAdress not accessed. Extended adress needs to be implemented. Ticket #136\r
661 \r
662 // - - - - - - - - - - - - - -\r
663 \r
664 static INLINE Std_ReturnType sendConsecutiveFrame(\r
665                 const CanTp_TxNSduType *txConfig, CanTp_ChannelPrivateType *txRuntime) {\r
666         BufReq_ReturnType ret = BUFREQ_NOT_OK;\r
667         uint8 sduData[CANIF_PDU_MAX_LENGTH];\r
668         PduLengthType consecutiveFrameMaxPayload = 0;\r
669         PduLengthType consecutiveFrameActualPayload = 0;\r
670         PduLengthType remaningSduDataSize = 0;\r
671         PduInfoType pduInfo;\r
672         uint16 copyCount = 0;\r
673         uint16 indexCount = 0;\r
674 \r
675         if (txConfig->CanTpAddressingMode == CANTP_EXTENDED) { /** @req CANTP094 *//** @req CANTP095 */\r
676                 sduData[indexCount++] = (uint8) txConfig->CanTpNTa->CanTpNTa; // Target address.\r
677         }\r
678         sduData[indexCount++] = ISO15765_TPCI_CF | (uint8)(\r
679                         (txRuntime->iso15765.framesHandledCount + 1) & ISO15765_TPCI_FS_MASK); // + 1 is because the consecutive frame numbering begins with 1 and not 0.\r
680 \r
681         // Always copy from the PDUR buffer data to the canFrameBuffer because if\r
682         // we are unlucky the application give us very small buffers.\r
683         consecutiveFrameMaxPayload  = CANIF_PDU_MAX_LENGTH - indexCount;\r
684         remaningSduDataSize = txRuntime->transferTotal - txRuntime->transferCount;\r
685 \r
686         // Calculate number of valid bytes that reside in this CF.\r
687         if ( remaningSduDataSize < consecutiveFrameMaxPayload  ) {\r
688                 consecutiveFrameActualPayload = remaningSduDataSize; // Last frame.\r
689         } else {\r
690                 consecutiveFrameActualPayload = consecutiveFrameMaxPayload;\r
691         }\r
692         copyCount = txRuntime->canFrameBuffer.byteCount; // maybe some bytes already reside in the local buffer before we proceed asking for more data from application.\r
693         while (copyCount < consecutiveFrameActualPayload) {\r
694                 if ( txRuntime->pdurBuffer->SduLength > txRuntime->pdurBufferCount ) {\r
695                         txRuntime->canFrameBuffer.data[copyCount] =  txRuntime->pdurBuffer->SduDataPtr[txRuntime->pdurBufferCount++];\r
696                         copyCount++;\r
697                         txRuntime->canFrameBuffer.byteCount++;\r
698                 } else {\r
699                         BufReq_ReturnType pdurResp = PduR_CanTpProvideTxBuffer(txConfig->PduR_PduId, &txRuntime->pdurBuffer, 0); /** @req CANTP226 */ /** @req CANTP086 */ /** @req CANTP117 */\r
700                         if (pdurResp == BUFREQ_OK) {\r
701                                 txRuntime->pdurBufferCount = 0;\r
702                                 continue;\r
703                         } else if (pdurResp == BUFREQ_BUSY) {\r
704                                 ret = E_OK; // We will remain in this state, called again later, not data lost/destroyed?\r
705                         } else {\r
706                                 /** @req CANTP087 */\r
707                                 DEBUG( DEBUG_MEDIUM, "sendConsecutiveFrame failed, no buffer provided!\n");\r
708                                 ret = E_NOT_OK; // Serious malfunction, function caller should cancel this transfer.\r
709                                 break;\r
710                         }\r
711                 }\r
712         }\r
713         if (copyCount == consecutiveFrameActualPayload) {\r
714                 for (int i=0; i<txRuntime->canFrameBuffer.byteCount; i++) {\r
715                         sduData[indexCount++] = txRuntime->canFrameBuffer.data[i];\r
716                 }\r
717                 pduInfo.SduDataPtr = sduData;\r
718                 pduInfo.SduLength = indexCount; // also includes consecutive frame header.\r
719                 ret = canTansmitPaddingHelper(txConfig, txRuntime, &pduInfo);\r
720                 if (ret == E_OK) {\r
721                         // Now we consider this frame sent and we can not handle\r
722                         // the scenario where the CAN queue is full.\r
723                         txRuntime->iso15765.framesHandledCount++;\r
724                         COUNT_DECREMENT(txRuntime->iso15765.nextFlowControlCount);\r
725                         txRuntime->transferCount += txRuntime->canFrameBuffer.byteCount;\r
726                         txRuntime->canFrameBuffer.byteCount = 0;\r
727                         DEBUG( DEBUG_MEDIUM, "transferCount:%d\n", txRuntime->transferCount);\r
728                 }\r
729         } else {\r
730                 DEBUG( DEBUG_MEDIUM, "Unexpected error, should not happen!\n");\r
731         }\r
732         return ret;\r
733 }\r
734 \r
735 // - - - - - - - - - - - - - -\r
736 \r
737 static INLINE void handleConsecutiveFrameSent(\r
738                 const CanTp_TxNSduType *txConfig, CanTp_ChannelPrivateType *txRuntime) {\r
739 \r
740         if (txRuntime->transferTotal <= txRuntime->transferCount) {\r
741                 // Transfer finished!\r
742 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
743                 txRuntime->iso15765.state = TX_WAIT_TX_CONFIRMATION;\r
744 #else\r
745                 PduR_CanTpTxConfirmation(txConfig->PduR_PduId, NTFRSLT_OK); /** @req CANTP074 *//** @req CANTP09 *//** @req CANTP204 */\r
746                 txRuntime->iso15765.state = IDLE;\r
747                 txRuntime->mode = CANTP_TX_WAIT;\r
748 #endif\r
749         } else if (txRuntime->iso15765.nextFlowControlCount == 0) {\r
750                 if (txRuntime->iso15765.BS) { // Check if receiver expects flow control.\r
751                         // Time to send flow control!\r
752                         txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNbs);  /** @req CANTP264 */\r
753                         txRuntime->iso15765.state = TX_WAIT_FLOW_CONTROL;\r
754                 } else {\r
755                         // Send next consecutive frame!\r
756                         txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txRuntime->iso15765.STmin);\r
757                         txRuntime->iso15765.state = TX_WAIT_SEND_CONSECUTIVE_FRAME;\r
758                 }\r
759         } else {\r
760                 // Send next consecutive frame!\r
761                 txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txRuntime->iso15765.STmin);\r
762                 txRuntime->iso15765.state = TX_WAIT_SEND_CONSECUTIVE_FRAME;\r
763         }\r
764 }\r
765 \r
766 // - - - - - - - - - - - - - -\r
767 \r
768 static INLINE void handleFlowControlFrame(const CanTp_TxNSduType *txConfig,\r
769                 CanTp_ChannelPrivateType *txRuntime, const PduInfoType *txPduData) {\r
770         int indexCount = 0;\r
771         uint8 extendedAddress = 0;\r
772         Std_ReturnType ret;\r
773 \r
774 \r
775         if ( txRuntime->iso15765.state == TX_WAIT_FLOW_CONTROL ) {\r
776                 if (txConfig->CanTpAddressingMode == CANTP_EXTENDED) { /** @req CANTP094 *//** @req CANTP095 */\r
777                         extendedAddress = txPduData->SduDataPtr[indexCount++];\r
778                 }\r
779                 switch (txPduData->SduDataPtr[indexCount++] & ISO15765_TPCI_FS_MASK) {\r
780                 case ISO15765_FLOW_CONTROL_STATUS_CTS:\r
781 #if 1\r
782                         {       // This construction is added to make the hcs12 compiler happy.\r
783                                 const uint8 bs = txPduData->SduDataPtr[indexCount++];\r
784                                 txRuntime->iso15765.BS = bs;\r
785                                 txRuntime->iso15765.nextFlowControlCount = bs;\r
786                         }\r
787                         txRuntime->iso15765.STmin = txPduData->SduDataPtr[indexCount++];\r
788 #else\r
789                         txRuntime->iso15765.BS = txPduData->SduDataPtr[indexCount++];\r
790                         txRuntime->iso15765.nextFlowControlCount = txRuntime->iso15765.BS;\r
791                         txRuntime->iso15765.STmin = txPduData->SduDataPtr[indexCount++];\r
792 #endif\r
793                         DEBUG( DEBUG_MEDIUM, "txRuntime->iso15765.STmin = %d\n", txRuntime->iso15765.STmin);\r
794                         ret = sendConsecutiveFrame(txConfig, txRuntime);\r
795                         if (ret == E_OK) {\r
796                                 handleConsecutiveFrameSent(txConfig, txRuntime);\r
797                         } else {\r
798                                 PduR_CanTpRxIndication(txConfig->PduR_PduId, NTFRSLT_E_NOT_OK);  /** @req CANTP177 */ /** @req CANTP084 */\r
799                                 txRuntime->iso15765.state = IDLE;\r
800                                 txRuntime->mode = CANTP_TX_WAIT;\r
801                         }\r
802                         break;\r
803                 case ISO15765_FLOW_CONTROL_STATUS_WAIT:\r
804                         txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNbs);  /*CanTp: 264*/\r
805                         txRuntime->iso15765.state = TX_WAIT_FLOW_CONTROL;\r
806                         break;\r
807                 case ISO15765_FLOW_CONTROL_STATUS_OVFLW:\r
808                         PduR_CanTpRxIndication(txConfig->PduR_PduId, NTFRSLT_E_NOT_OK);\r
809                         txRuntime->iso15765.state = IDLE;\r
810                         txRuntime->mode = CANTP_TX_WAIT;\r
811                         break;\r
812                 }\r
813         } else {\r
814                 DEBUG( DEBUG_MEDIUM, "Ignoring flow control, we do not expect it!");\r
815         }\r
816 } // 438, 550 PC-lint: extendAdress används inte. EN BUG? Behöver fixas\r
817 \r
818 \r
819 // - - - - - - - - - - - - - -\r
820 \r
821 static INLINE void handleSingleFrame(const CanTp_RxNSduType *rxConfig,\r
822                 CanTp_ChannelPrivateType *rxRuntime, const PduInfoType *rxPduData) {\r
823         BufReq_ReturnType ret;\r
824         PduLengthType pduLength;\r
825         uint8 *data = NULL;\r
826         PduLengthType bytesWrittenToSduRBuffer;\r
827 \r
828 \r
829         if (rxRuntime->iso15765.state != IDLE) {\r
830                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_NOT_OK);  // Abort current reception, we need to tell the current receiver it has been aborted.\r
831                 DEBUG( DEBUG_MEDIUM, "Single frame received and channel not IDLE!\n");\r
832         }\r
833         (void) initRx15765RuntimeData(rxConfig, rxRuntime); /** @req CANTP124 */\r
834         pduLength = getPduLength(&rxConfig->CanTpAddressingFormant, SINGLE_FRAME, rxPduData);\r
835 \r
836         if (rxRuntime->pdurBuffer != NULL) {\r
837                 VALIDATE_NO_RV( rxRuntime->pdurBuffer->SduDataPtr != NULL,\r
838                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_INVALID_RX_LENGTH );\r
839         }\r
840 \r
841         if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) { /** @req CANTP094 *//** @req CANTP095 */\r
842                 data = &rxPduData->SduDataPtr[1];\r
843         } else {\r
844                 data = &rxPduData->SduDataPtr[2];\r
845         }\r
846         rxRuntime->transferTotal = pduLength;\r
847         rxRuntime->iso15765.state = SF_OR_FF_RECEIVED_WAITING_PDUR_BUFFER;\r
848         rxRuntime->mode = CANTP_RX_PROCESSING;\r
849         rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNbr);  /** @req CANTP166 */\r
850 \r
851         ret = copySegmentToPduRRxBuffer(rxConfig, rxRuntime, data, pduLength, &bytesWrittenToSduRBuffer);\r
852 \r
853         if (ret == BUFREQ_OK) {\r
854                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_OK);\r
855                 rxRuntime->iso15765.state = IDLE;\r
856                 rxRuntime->mode = CANTP_RX_WAIT;\r
857         } else if (ret == BUFREQ_BUSY) {\r
858                 if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) {\r
859                         data = &rxPduData->SduDataPtr[1];\r
860                 } else {\r
861                         data = &rxPduData->SduDataPtr[2];\r
862                 }\r
863                 (void)copySegmentToLocalRxBuffer(rxRuntime, data, pduLength ); /** @req CANTP067 */\r
864                 rxRuntime->iso15765.state = RX_WAIT_SDU_BUFFER;\r
865                 rxRuntime->mode = CANTP_RX_PROCESSING;\r
866         } else {\r
867                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_NO_BUFFER);\r
868                 rxRuntime->iso15765.state = IDLE;\r
869                 rxRuntime->mode = CANTP_RX_WAIT;\r
870         }\r
871 }\r
872 \r
873 // - - - - - - - - - - - - - -\r
874 \r
875 \r
876 static INLINE void handleFirstFrame(const CanTp_RxNSduType *rxConfig,\r
877                 CanTp_ChannelPrivateType *rxRuntime, const PduInfoType *rxPduData) {\r
878         BufReq_ReturnType ret;\r
879         PduLengthType pduLength = 0;\r
880         PduLengthType bytesWrittenToSduRBuffer;\r
881 \r
882         if (rxRuntime->iso15765.state != IDLE) {\r
883                 DEBUG( DEBUG_MEDIUM, "First frame received during Rx-session!\n" );\r
884                 PduR_CanTpRxIndication(rxConfig->PduR_PduId, NTFRSLT_E_NOT_OK);  // Abort current reception, we need to tell the current receiver it has been aborted.\r
885         }\r
886 \r
887         (void) initRx15765RuntimeData(rxConfig, rxRuntime); /** @req CANTP124 */\r
888         pduLength = getPduLength(&rxConfig->CanTpAddressingFormant, FIRST_FRAME,\r
889                         rxPduData);\r
890         rxRuntime->transferTotal = pduLength;\r
891 \r
892         VALIDATE_NO_RV( rxRuntime->transferTotal != 0,\r
893                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_INVALID_RX_LENGTH );\r
894 \r
895         // Validate that that there is a reason for using the segmented transfers and\r
896         // if not simply skip (single frame should have been used).\r
897         if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) { /** @req CANTP094 *//** @req CANTP095 */\r
898                 if (pduLength <= MAX_PAYLOAD_SF_STD_ADDR){\r
899                         return;\r
900                 }\r
901         } else {\r
902                 if (pduLength <= MAX_PAYLOAD_SF_EXT_ADDR){\r
903                         return;\r
904                 }\r
905         }\r
906         // Validate that the SDU is full length in this first frame.\r
907         if (rxPduData->SduLength < CANIF_PDU_MAX_LENGTH) {\r
908                 return;\r
909         }\r
910 \r
911         rxRuntime->iso15765.framesHandledCount = 1; // Segment count begins with 1 (FirstFrame has the 0).\r
912         rxRuntime->iso15765.state = SF_OR_FF_RECEIVED_WAITING_PDUR_BUFFER;\r
913         rxRuntime->mode = CANTP_RX_PROCESSING;\r
914         rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNbr); /** @req CANTP166 */\r
915 \r
916         if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) {\r
917                 ret = copySegmentToPduRRxBuffer(rxConfig, rxRuntime,\r
918                                 &rxPduData->SduDataPtr[2],\r
919                                 MAX_PAYLOAD_FF_STD_ADDR,\r
920                                 &bytesWrittenToSduRBuffer);\r
921         } else {\r
922                 ret = copySegmentToPduRRxBuffer(rxConfig, rxRuntime,\r
923                                 &rxPduData->SduDataPtr[3],\r
924                                 MAX_PAYLOAD_FF_EXT_ADDR,\r
925                                 &bytesWrittenToSduRBuffer);\r
926         }\r
927         if (ret == BUFREQ_OK) {\r
928                 rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNcr);\r
929                 rxRuntime->iso15765.state = RX_WAIT_CONSECUTIVE_FRAME;\r
930                 rxRuntime->mode = CANTP_RX_PROCESSING;\r
931                 sendFlowControlFrame(rxConfig, rxRuntime, ret);\r
932         } else if (ret == BUFREQ_BUSY) {\r
933                 /** @req CANTP222 */\r
934                 if (rxConfig->CanTpAddressingFormant == CANTP_STANDARD) {\r
935                         (void)copySegmentToLocalRxBuffer(rxRuntime, &rxPduData->SduDataPtr[2], MAX_PAYLOAD_FF_STD_ADDR );\r
936                 } else {\r
937                         (void)copySegmentToLocalRxBuffer(rxRuntime, &rxPduData->SduDataPtr[3], MAX_PAYLOAD_FF_EXT_ADDR );\r
938                 }\r
939                 rxRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfig->CanTpNbr);\r
940                 rxRuntime->iso15765.state = RX_WAIT_SDU_BUFFER;\r
941                 rxRuntime->mode = CANTP_RX_PROCESSING;\r
942                 sendFlowControlFrame(rxConfig, rxRuntime, ret);  /** @req CANTP082 */\r
943         } else if (ret == BUFREQ_OVFL) {\r
944                 sendFlowControlFrame(rxConfig, rxRuntime, ret); /** @req CANTP081 */\r
945                 rxRuntime->iso15765.state = IDLE;\r
946                 rxRuntime->mode = CANTP_RX_WAIT;\r
947         }\r
948 }\r
949 \r
950 // - - - - - - - - - - - - - -\r
951 \r
952 static INLINE ISO15765FrameType calcRequiredProtocolFrameType(\r
953                 const CanTp_TxNSduType *txConfig, CanTp_ChannelPrivateType *txRuntime) {\r
954 \r
955         ISO15765FrameType ret = INVALID_FRAME;\r
956         if (txConfig->CanTpAddressingMode == CANTP_EXTENDED) {\r
957                 if (txRuntime->transferTotal <= MAX_PAYLOAD_CF_EXT_ADDR) {\r
958                         ret = SINGLE_FRAME;\r
959                 } else {\r
960                         if (txConfig->CanTpTxTaType == CANTP_PHYSICAL) {\r
961                                 ret = FIRST_FRAME;\r
962                         } else {\r
963                                 DET_REPORTERROR( MODULE_ID_CANTP, 0, SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_TATYPE );\r
964                         }\r
965                 }\r
966         } else {        // CANTP_STANDARD\r
967                 if (txRuntime->transferTotal <= MAX_PAYLOAD_CF_STD_ADDR) {\r
968                         ret = SINGLE_FRAME;\r
969                 } else {\r
970                         if (txConfig->CanTpTxTaType == CANTP_PHYSICAL) {\r
971                                 ret = FIRST_FRAME;\r
972                         } else {\r
973                                 DET_REPORTERROR( MODULE_ID_CANTP, 0, SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_TATYPE );\r
974                         }\r
975                 }\r
976         }\r
977 \r
978         return ret;\r
979 }\r
980 \r
981 // - - - - - - - - - - - - - -\r
982 \r
983 \r
984 static INLINE Std_ReturnType sendSingleFrame(const CanTp_TxNSduType *txConfig,\r
985                 CanTp_ChannelPrivateType *txRuntime) {\r
986         Std_ReturnType ret;\r
987         uint16 indexCount = 0;\r
988         PduInfoType pduInfo;\r
989         uint8 sduData[CANIF_PDU_MAX_LENGTH];\r
990 \r
991 \r
992         if (txConfig->CanTpAddressingMode == CANTP_EXTENDED) { /** @req CANTP094 *//** @req CANTP095 */\r
993                 sduData[indexCount++] = (uint8) txConfig->CanTpNTa->CanTpNTa; // Target address.\r
994         }\r
995         sduData[indexCount++] = ISO15765_TPCI_SF | txRuntime->transferTotal; // 734 PC-lint: Okej att casta till uint8?\r
996         for (int i = 0; i < txRuntime->transferTotal; i++) {\r
997                 sduData[indexCount++] = txRuntime->pdurBuffer->SduDataPtr[i];\r
998         }\r
999 \r
1000         pduInfo.SduDataPtr = sduData;\r
1001         pduInfo.SduLength = indexCount;\r
1002         ret = canTansmitPaddingHelper(txConfig, txRuntime, &pduInfo);\r
1003         return ret;\r
1004 }\r
1005 \r
1006 // - - - - - - - - - - - - - -\r
1007 \r
1008 static INLINE Std_ReturnType sendFirstFrame(const CanTp_TxNSduType *txConfig,\r
1009                 CanTp_ChannelPrivateType *txRuntime) {\r
1010         Std_ReturnType ret;\r
1011         uint8 indexCount = 0;\r
1012         uint8 i = 0;\r
1013         PduInfoType pduInfo;\r
1014         uint8 sduData[CANIF_PDU_MAX_LENGTH];\r
1015 \r
1016         DEBUG( DEBUG_MEDIUM, "sendFirstFrame called!\n");\r
1017 \r
1018         if (txConfig->CanTpAddressingMode == CANTP_EXTENDED) { /** @req CANTP094 *//** @req CANTP095 */\r
1019                 sduData[indexCount++] = (uint8) txConfig->CanTpNTa->CanTpNTa; // Target address.\r
1020         }\r
1021         sduData[indexCount++] = ISO15765_TPCI_FF | (uint8)(\r
1022                         (txRuntime->transferTotal & 0xf00) >> 8);\r
1023         sduData[indexCount++] = (uint8)(txRuntime->transferTotal & 0xff);\r
1024         for (i = 0; indexCount < CANIF_PDU_MAX_LENGTH; i++) {\r
1025                 sduData[indexCount++] = txRuntime->pdurBuffer->SduDataPtr[i];\r
1026                 txRuntime->pdurBufferCount++;\r
1027                 if (txRuntime->pdurBufferCount > txRuntime->pdurBuffer->SduLength) {\r
1028                         // TODO: Report failure - this is unexpected.\r
1029                 }\r
1030                 txRuntime->transferCount++;\r
1031         }\r
1032         pduInfo.SduDataPtr = sduData;\r
1033         pduInfo.SduLength = indexCount;\r
1034         ret = canTansmitPaddingHelper(txConfig, txRuntime, &pduInfo);\r
1035         return ret;\r
1036 }\r
1037 \r
1038 // - - - - - - - - - - - - - -\r
1039 \r
1040 static INLINE BufReq_ReturnType canTpTransmitHelper(const CanTp_TxNSduType *txConfig,\r
1041                 CanTp_ChannelPrivateType *txRuntime) {\r
1042 \r
1043         BufReq_ReturnType pdurResp = BUFREQ_NOT_OK;\r
1044         Std_ReturnType res = E_NOT_OK;\r
1045         ISO15765FrameType iso15765Frame = INVALID_FRAME;\r
1046 \r
1047         pdurResp = PduR_CanTpProvideTxBuffer(txConfig->PduR_PduId, &txRuntime->pdurBuffer, 0);  /** @req CANTP226 */ /** @req CANTP186 */\r
1048         //if (txRuntime->iso15765.stateTimeoutCount != 0) {   TODO: WHY WAS THIS DONE?\r
1049                 VALIDATE( txRuntime->pdurBuffer->SduDataPtr != NULL,\r
1050                                 SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_TX_BUFFER );\r
1051                 if (pdurResp == BUFREQ_OK) {\r
1052                         iso15765Frame = calcRequiredProtocolFrameType(txConfig, txRuntime);\r
1053                         switch (iso15765Frame) {\r
1054                         case SINGLE_FRAME:\r
1055                                 res = sendSingleFrame(txConfig, txRuntime); /** @req CANTP231 */\r
1056                                 if (res == E_OK) {\r
1057 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
1058                                         txRuntime->iso15765.state = TX_WAIT_TX_CONFIRMATION;\r
1059 #else\r
1060                                         PduR_CanTpTxConfirmation(txConfig->PduR_PduId, NTFRSLT_OK); /** @req CANTP204 */\r
1061                                         txRuntime->iso15765.state = IDLE;\r
1062                                         txRuntime->mode = CANTP_TX_WAIT;\r
1063 #endif\r
1064                                 } else {\r
1065                                         PduR_CanTpTxConfirmation(txConfig->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1066                                         txRuntime->iso15765.state = IDLE;\r
1067                                         txRuntime->mode = CANTP_TX_WAIT;\r
1068                                 }\r
1069                                 break;\r
1070                         case FIRST_FRAME: {\r
1071                                 txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNbs);  /** @req CANTP264 */\r
1072                                 if ( txRuntime->iso15765.stateTimeoutCount == 0 ) {\r
1073                                         DEBUG( DEBUG_MEDIUM, "WARNING! Too low CanTpNbs timeout!\n" );\r
1074                                 }\r
1075                                 txRuntime->iso15765.state = TX_WAIT_FLOW_CONTROL; // We will always expect a flow control at this stage.\r
1076                                 res = sendFirstFrame(txConfig, txRuntime); /** @req CANTP231 */\r
1077                                 if (res == E_OK) {\r
1078                                         txRuntime->mode = CANTP_TX_PROCESSING;\r
1079                                 }\r
1080                                 break;\r
1081                         }\r
1082                         case INVALID_FRAME:\r
1083                         default:\r
1084                                 PduR_CanTpTxConfirmation(txConfig->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1085                                 txRuntime->iso15765.state = IDLE;\r
1086                                 txRuntime->mode = CANTP_TX_WAIT;\r
1087                                 break;\r
1088                         }\r
1089                 } else if (pdurResp == BUFREQ_NOT_OK) {\r
1090                         PduR_CanTpTxConfirmation(txConfig->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1091                         txRuntime->iso15765.state = IDLE;\r
1092                         txRuntime->mode = CANTP_TX_WAIT;\r
1093                 } else if (pdurResp == BUFREQ_BUSY) {\r
1094                         /** @req CANTP184 */\r
1095                         txRuntime->iso15765.state = TX_WAIT_CAN_TP_TRANSMIT_PENDING; // We have to issue this request later from main until timeout.\r
1096                         txRuntime->mode = CANTP_TX_PROCESSING;\r
1097                 }\r
1098         //} else {\r
1099                 // TDDO: Put this in a logfile? Error response should have been sent from main.\r
1100         //}\r
1101         return pdurResp;\r
1102 }\r
1103 \r
1104 // - - - - - - - - - - - - - -\r
1105 \r
1106 \r
1107 Std_ReturnType CanTp_Transmit(PduIdType CanTpTxSduId,\r
1108                 const PduInfoType *CanTpTxInfoPtr)  /** @req CANTP176 */\r
1109 {\r
1110         const CanTp_TxNSduType *txConfig = NULL;\r
1111         CanTp_ChannelPrivateType *txRuntime = NULL;\r
1112         BufReq_ReturnType res = BUFREQ_NOT_OK;\r
1113         Std_ReturnType ret = 0;\r
1114 \r
1115         DEBUG( DEBUG_MEDIUM, "CanTp_Transmit called in polite index: %d!\n", CanTpTxSduId);\r
1116 \r
1117         VALIDATE( CanTpTxInfoPtr != NULL,\r
1118                         SERVICE_ID_CANTP_TRANSMIT, CANTP_E_PARAM_ADDRESS ); /** @req CANTP031 */\r
1119         VALIDATE( CanTpRunTimeData.internalState == CANTP_ON, /** @req CANTP238 */\r
1120                         SERVICE_ID_CANTP_TRANSMIT, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1121         VALIDATE( CanTpTxSduId < CANTP_NSDU_CONFIG_LIST_SIZE, SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_TX_ID );\r
1122 \r
1123         txConfig =&CanTpConfig.CanTpNSduList[CanTpTxSduId].configData.CanTpTxNSdu;\r
1124 \r
1125         txRuntime = &CanTpRunTimeData.runtimeDataList[txConfig->CanTpTxChannel]; // Runtime data.\r
1126         if (txRuntime->iso15765.state == IDLE) {\r
1127                 txRuntime->pdurBufferCount = 0;\r
1128                 txRuntime->pdurBufferCount = 0;\r
1129                 txRuntime->transferCount = 0;\r
1130                 txRuntime->iso15765.framesHandledCount = 0;\r
1131                 txRuntime->transferTotal = CanTpTxInfoPtr->SduLength; /** @req CANTP225 */\r
1132                 txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNcs);\r
1133                 txRuntime->mode = CANTP_TX_PROCESSING;\r
1134                 txRuntime->iso15765.state = TX_WAIT_CAN_TP_TRANSMIT_CAN_TP_PROVIDE_TX_BUFFER;\r
1135 \r
1136                 res = canTpTransmitHelper(txConfig, txRuntime);\r
1137                 switch (res) {\r
1138                 case BUFREQ_OK:\r
1139                 case BUFREQ_BUSY:\r
1140                         ret = E_OK;\r
1141                         break;\r
1142                 case BUFREQ_NOT_OK:\r
1143                         ret = E_NOT_OK; /** @req CANTP072 */\r
1144                         break;\r
1145                 default:\r
1146                         ret = E_NOT_OK;\r
1147                         break;\r
1148                 }\r
1149         } else {\r
1150                 DEBUG( DEBUG_MEDIUM, "CanTp can't transmit, it is already occupied!\n", CanTpTxSduId);\r
1151                 ret = E_NOT_OK;  /** @req CANTP123 *//** @req CANTP206 */\r
1152         }\r
1153         return ret; // CAN level error code.\r
1154 }\r
1155 \r
1156 // - - - - - - - - - - - - - -\r
1157 \r
1158 #if FRTP_CANCEL_TRANSMIT_REQUEST\r
1159 Std_ReturnType FrTp_CancelTransmitRequest(PduIdType FrTpTxPduId,\r
1160                 FrTp_CancelReasonType FrTpCancelReason)\r
1161 {\r
1162         return E_NOT_OK;\r
1163 }\r
1164 #endif\r
1165 \r
1166 // - - - - - - - - - - - - - -\r
1167 \r
1168 \r
1169 void CanTp_Init(void)\r
1170 {\r
1171         CanTp_ChannelPrivateType *runtimeData;\r
1172         const CanTp_TxNSduType *txConfigParams;\r
1173         const CanTp_RxNSduType *rxConfigParams;\r
1174 \r
1175         for (int i=0; i < CANTP_NSDU_CONFIG_LIST_SIZE; i++) {\r
1176                 if ( CanTpConfig.CanTpNSduList[i].direction == IS015765_TRANSMIT ) {\r
1177                         txConfigParams = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1178                         if (txConfigParams->CanTpTxChannel < CANTP_NSDU_RUNTIME_LIST_SIZE) {\r
1179                                 runtimeData = &CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel];\r
1180                         } else {\r
1181                                 runtimeData = &CanTpRunTimeData.runtimeDataList[CANTP_NSDU_RUNTIME_LIST_SIZE-1];\r
1182                         }\r
1183                         initTx15765RuntimeData( txConfigParams, runtimeData);\r
1184                 } else {\r
1185                         rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1186                         if (rxConfigParams->CanTpRxChannel < CANTP_NSDU_RUNTIME_LIST_SIZE) {\r
1187                                 runtimeData = &CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel];\r
1188                         } else {\r
1189                                 runtimeData = &CanTpRunTimeData.runtimeDataList[CANTP_NSDU_RUNTIME_LIST_SIZE-1];\r
1190                         }\r
1191                         initRx15765RuntimeData( rxConfigParams, runtimeData);\r
1192                 }\r
1193         }\r
1194         fifoQueueInit( &CanTpRunTimeData.fifo );\r
1195         CanTpRunTimeData.internalState = CANTP_ON; /** @req CANTP170 */\r
1196 }\r
1197 \r
1198 // - - - - - - - - - - - - - -\r
1199 \r
1200 void CanTp_RxIndication(PduIdType CanTpRxPduId, /** @req CANTP078 */ /** @req CANTP035 */\r
1201                 const PduInfoType *CanTpRxPduPtr)\r
1202 {\r
1203         CanTpFifoQueueItem item;\r
1204         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1205                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_UNINIT ); /** @req CANTP238 */ /** @req CANTP031 */\r
1206 \r
1207         item.PduId = CanTpRxPduId;\r
1208         item.SduLength = CanTpRxPduPtr->SduLength;\r
1209         for (int i=0; i<item.SduLength; i++) {\r
1210                 item.SduData[i] = CanTpRxPduPtr->SduDataPtr[i];\r
1211         }\r
1212         if ( fifoQueueWrite( &CanTpRunTimeData.fifo, &item ) == FALSE ) {  /** @req CANTP077 *//** @req CANTP235 */\r
1213                 DEBUG( DEBUG_MEDIUM, "WARNING!: Frames are lost!\n");\r
1214         }\r
1215 }\r
1216 \r
1217 // - - - - - - - - - - - - - -\r
1218 \r
1219 void CanTp_RxIndication_Main(PduIdType CanTpRxPduId,\r
1220                 const PduInfoType *CanTpRxPduPtr)\r
1221 {\r
1222         const CanTp_RxNSduType *rxConfigParams; // Params reside in ROM.\r
1223         const CanTp_TxNSduType *txConfigParams;\r
1224         const CanTp_AddressingFormantType *addressingFormat; // Configured\r
1225         CanTp_ChannelPrivateType *runtimeParams; // Params reside in RAM.\r
1226         ISO15765FrameType frameType;\r
1227 \r
1228         DEBUG( DEBUG_MEDIUM, "CanTp_RxIndication: PduId=%d, [", CanTpRxPduId);\r
1229         for (int i=0; i<CanTpRxPduPtr->SduLength; i++) {\r
1230                 DEBUG( DEBUG_MEDIUM, "%x, ", CanTpRxPduPtr->SduDataPtr[i]);\r
1231         }\r
1232         DEBUG( DEBUG_MEDIUM, "]");\r
1233 \r
1234         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1235                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1236 \r
1237         if ( CanTpConfig.CanTpNSduList[CanTpRxPduId].direction == IS015765_TRANSMIT ) {\r
1238                 txConfigParams = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[CanTpRxPduId].configData;  /** @req CANTP120 */\r
1239                 addressingFormat = &txConfigParams->CanTpAddressingMode;\r
1240                 runtimeParams = &CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel]; /** @req CANTP096 *//** @req CANTP121 *//** @req CANTP122 *//** @req CANTP190 */\r
1241                 rxConfigParams = NULL;\r
1242         } else {\r
1243                 rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[CanTpRxPduId].configData;  /** @req CANTP120 */\r
1244                 addressingFormat = &rxConfigParams->CanTpAddressingFormant;\r
1245                 runtimeParams = &CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel];  /** @req CANTP096 *//** @req CANTP121 *//** @req CANTP122 *//** @req CANTP190 */\r
1246                 txConfigParams = NULL;\r
1247         }\r
1248 \r
1249         frameType = getFrameType(addressingFormat, CanTpRxPduPtr); /** @req CANTP094 *//** @req CANTP095 */\r
1250         switch (frameType) {\r
1251         case SINGLE_FRAME: {\r
1252                 if (rxConfigParams != NULL) {\r
1253                         DEBUG( DEBUG_MEDIUM, "calling handleSingleFrame!\n");\r
1254                         handleSingleFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1255                 }\r
1256                 else{\r
1257                         DEBUG( DEBUG_MEDIUM, "Single frame received on ISO15765-Tx - is ignored!\n");\r
1258                 }\r
1259                 break;\r
1260         }\r
1261         case FIRST_FRAME: {\r
1262                 if (rxConfigParams != NULL) {\r
1263                         DEBUG( DEBUG_MEDIUM, "calling handleFirstFrame!\n");\r
1264                         handleFirstFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1265                 }else{\r
1266                         DEBUG( DEBUG_MEDIUM, "First frame received on ISO15765-Tx - is ignored!\n");\r
1267                 }\r
1268                 break;\r
1269         }\r
1270         case CONSECUTIVE_FRAME: {\r
1271                 if (rxConfigParams != NULL) {\r
1272                         DEBUG( DEBUG_MEDIUM, "calling handleConsecutiveFrame!\n");\r
1273                         handleConsecutiveFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1274                 } else {\r
1275                         DEBUG( DEBUG_MEDIUM, "Consecutive frame received on ISO15765-Tx - is ignored!\n");\r
1276                 }\r
1277                 break;\r
1278         }\r
1279         case FLOW_CONTROL_CTS_FRAME: {\r
1280                 if (txConfigParams != NULL) {\r
1281                         DEBUG( DEBUG_MEDIUM, "calling handleFlowControlFrame!\n");\r
1282                         handleFlowControlFrame(txConfigParams, runtimeParams, CanTpRxPduPtr);\r
1283                 } else {\r
1284                         DEBUG( DEBUG_MEDIUM, "Flow control frame received on ISO15765-Rx - is ignored!\n");\r
1285                 }\r
1286                 break;\r
1287         }\r
1288         case INVALID_FRAME: {\r
1289                 DEBUG( DEBUG_MEDIUM, "INVALID_FRAME received - is ignored!\n!\n");\r
1290                 break;\r
1291         }\r
1292         default:\r
1293                 break;\r
1294         }\r
1295         DEBUG( DEBUG_LOW, "CanTp_RxIndication_Main exit!\n");\r
1296 }\r
1297 \r
1298 // - - - - - - - - - - - - - -\r
1299 \r
1300 void CanTp_TxConfirmation(PduIdType CanTpTxPduId) /** @req CANTP076 */\r
1301 {\r
1302         const CanTp_RxNSduType *rxConfigParams = NULL;\r
1303         const CanTp_TxNSduType *txConfigParams = NULL;\r
1304 \r
1305         DEBUG( DEBUG_MEDIUM, "CanTp_TxConfirmation called.\n" );\r
1306 \r
1307         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1308                         SERVICE_ID_CANTP_TX_CONFIRMATION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1309         VALIDATE_NO_RV( CanTpTxPduId < CANTP_NSDU_CONFIG_LIST_SIZE,\r
1310                         SERVICE_ID_CANTP_TX_CONFIRMATION, CANTP_E_INVALID_TX_ID ); /** @req CANTP158 */\r
1311 \r
1312         /** @req CANTP236 */\r
1313         if ( CanTpConfig.CanTpNSduList[CanTpTxPduId].direction == IS015765_TRANSMIT ) {\r
1314                 txConfigParams = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[CanTpTxPduId].configData;\r
1315                 CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel].iso15765.NasNarPending = FALSE;\r
1316 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
1317                 CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel].iso15765.txConfirmed = TRUE;\r
1318 #endif\r
1319         } else {\r
1320                 rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[CanTpTxPduId].configData;\r
1321                 CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel].iso15765.NasNarPending = FALSE;\r
1322         }\r
1323 }\r
1324 \r
1325 // - - - - - - - - - - - - - -\r
1326 \r
1327 void CanTp_Shutdown(void) /** @req CANTP202 *//** @req CANTP200 *//** @req CANTP010 */\r
1328 {\r
1329         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1330                         SERVICE_ID_CANTP_SHUTDOWN, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1331 \r
1332         CanTpRunTimeData.internalState = CANTP_OFF;\r
1333 }\r
1334 \r
1335 // - - - - - - - - - - - - - -\r
1336 \r
1337 \r
1338 static inline boolean checkNasNarTimeout(CanTp_ChannelPrivateType *runtimeData) {\r
1339         boolean ret = FALSE;\r
1340         if (runtimeData->iso15765.NasNarPending) {\r
1341                 TIMER_DECREMENT(runtimeData->iso15765.NasNarTimeoutCount);\r
1342                 if (runtimeData->iso15765.NasNarTimeoutCount == 0) {\r
1343                         DEBUG( DEBUG_MEDIUM, "NAS timed out.\n" );\r
1344                         runtimeData->iso15765.state = IDLE;\r
1345                         runtimeData->iso15765.NasNarPending = FALSE;\r
1346                         ret = TRUE;\r
1347                 }\r
1348         }\r
1349         return ret;\r
1350 }\r
1351 \r
1352 // - - - - - - - - - - - - - -\r
1353 \r
1354 \r
1355 void CanTp_MainFunction(void)\r
1356 {\r
1357         BufReq_ReturnType ret;\r
1358         CanTpFifoQueueItem item;\r
1359         PduLengthType bytesWrittenToSduRBuffer;\r
1360 \r
1361         CanTp_ChannelPrivateType *txRuntimeListItem = NULL;\r
1362         CanTp_ChannelPrivateType *rxRuntimeListItem = NULL;\r
1363 \r
1364         const CanTp_TxNSduType *txConfigListItem = NULL;\r
1365         const CanTp_RxNSduType *rxConfigListItem = NULL;\r
1366 \r
1367         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1368                         SERVICE_ID_CANTP_MAIN_FUNCTION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1369 \r
1370         // Dispatch the messages that resides in the FIFO to CanTp_RxIndication_Main.\r
1371         while ( fifoQueueRead( &CanTpRunTimeData.fifo, &item ) == TRUE  ) {\r
1372                 PduInfoType pduInfo;\r
1373                 pduInfo.SduDataPtr = item.SduData;\r
1374                 pduInfo.SduLength = item.SduLength;\r
1375                 CanTp_RxIndication_Main( item.PduId, &pduInfo );\r
1376         }\r
1377 \r
1378         for( int i=0; i < CANTP_NSDU_CONFIG_LIST_SIZE; i++ ) {\r
1379 #if 0   // TODO: Not tested yet\r
1380                 if (checkNasNarTimeout( txRuntimeListItem )) { /** @req CANTP075 */\r
1381                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_CanTpTxPduId, NTFRSLT_NOT_OK); /** @req CANTP074 */ /** @req CANTP204 */\r
1382                         continue;\r
1383                 }\r
1384 #endif\r
1385                 if ( CanTpConfig.CanTpNSduList[i].direction == IS015765_TRANSMIT ) {\r
1386                         txConfigListItem = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1387                         txRuntimeListItem = &CanTpRunTimeData.runtimeDataList[txConfigListItem->CanTpTxChannel];\r
1388 \r
1389                         switch (txRuntimeListItem->iso15765.state) {\r
1390                         case TX_WAIT_CAN_TP_TRANSMIT_CAN_TP_PROVIDE_TX_BUFFER:\r
1391                         {\r
1392                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount); /** @req CANTP185 */\r
1393                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0){\r
1394                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 *//** @req CANTP185 */\r
1395                                 }\r
1396                                 txRuntimeListItem->iso15765.state = IDLE;\r
1397                                 txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1398                                 break;\r
1399                         }\r
1400                         case TX_WAIT_CAN_TP_TRANSMIT_PENDING: {\r
1401                                 (void) canTpTransmitHelper(txConfigListItem, txRuntimeListItem);/** @req CANTP184 */ /** @req CANTP089 */\r
1402                                 break;\r
1403                         }\r
1404                         case TX_WAIT_SEND_CONSECUTIVE_FRAME: {\r
1405                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount); // Make sure that STmin timer has expired.\r
1406                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0) {\r
1407                                         ret = sendConsecutiveFrame(txConfigListItem, txRuntimeListItem);\r
1408                                         if ( ret == E_OK ) {\r
1409                                                 handleConsecutiveFrameSent(txConfigListItem, txRuntimeListItem);\r
1410                                         } else {\r
1411                                                 DEBUG( DEBUG_MEDIUM, "ERROR: Consecutive frame could not be sent!\n");\r
1412                                                 PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1413                                                 txRuntimeListItem->iso15765.state = IDLE;\r
1414                                                 txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1415                                         }\r
1416                                 } else {\r
1417                                         DEBUG( DEBUG_MEDIUM, "Waiting for STmin timer to expire!\n");\r
1418                                 }\r
1419                                 break;\r
1420                         }\r
1421                         case TX_WAIT_FLOW_CONTROL:\r
1422                                 //DEBUG( DEBUG_MEDIUM, "Waiting for flow control!\n");\r
1423                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount);\r
1424                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0) {\r
1425                                         DEBUG( DEBUG_MEDIUM, "State TX_WAIT_FLOW_CONTROL timed out!\n");\r
1426                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */ /** @req CANTP185 */\r
1427                                         txRuntimeListItem->iso15765.state = IDLE;\r
1428                                         txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1429                                 }\r
1430                                 break;\r
1431 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
1432                         case TX_WAIT_TX_CONFIRMATION:\r
1433                                 if      (txRuntimeListItem->iso15765.txConfirmed) {\r
1434                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_OK); /** @req CANTP074 *//** @req CANTP09 *//** @req CANTP204 */\r
1435                                         txRuntimeListItem->iso15765.state = IDLE;\r
1436                                         txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1437                                 }\r
1438                                 break;\r
1439 #endif\r
1440                         default:\r
1441                                 break;\r
1442                         }\r
1443                 } else {\r
1444                         rxConfigListItem = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1445                         rxRuntimeListItem = &CanTpRunTimeData.runtimeDataList[rxConfigListItem->CanTpRxChannel];\r
1446                         switch (rxRuntimeListItem->iso15765.state) {\r
1447                         case RX_WAIT_CONSECUTIVE_FRAME: {\r
1448                                 TIMER_DECREMENT (rxRuntimeListItem->iso15765.stateTimeoutCount);\r
1449                                 if (rxRuntimeListItem->iso15765.stateTimeoutCount == 0) {\r
1450                                         DEBUG( DEBUG_MEDIUM, "TIMEOUT!\n");\r
1451                                         PduR_CanTpRxIndication(rxConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK);\r
1452                                         rxRuntimeListItem->iso15765.state = IDLE;\r
1453                                         rxRuntimeListItem->mode = CANTP_RX_WAIT;\r
1454                                 }\r
1455                                 break;\r
1456                         }\r
1457                         case RX_WAIT_SDU_BUFFER: {\r
1458                                 TIMER_DECREMENT (rxRuntimeListItem->iso15765.stateTimeoutCount);\r
1459                                 /* We end up here if we have requested a buffer from the\r
1460                                  * PDUR but the response have been BUSY. We assume\r
1461                                  * we have data in our local buffer and we are expected\r
1462                                  * to send a flow-control clear to send (CTS).\r
1463                                  */\r
1464                                 if (rxRuntimeListItem->iso15765.stateTimeoutCount == 0) { /** @req CANTP223 */\r
1465                                         PduR_CanTpRxIndication(rxConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1466                                         rxRuntimeListItem->iso15765.state = IDLE;\r
1467                                         rxRuntimeListItem->mode = CANTP_RX_WAIT;\r
1468                                 } else { /** @req CANTP222 */\r
1469                                         PduLengthType bytesRemaining = 0;\r
1470                                         ret = copySegmentToPduRRxBuffer(rxConfigListItem, /** @req CANTP067, copies from local buffer to PDUR buffer. */\r
1471                                                                 rxRuntimeListItem,\r
1472                                                                 rxRuntimeListItem->canFrameBuffer.data,\r
1473                                                                 rxRuntimeListItem->canFrameBuffer.byteCount,\r
1474                                                                 &bytesWrittenToSduRBuffer);\r
1475                                         bytesRemaining = rxRuntimeListItem->transferTotal -\r
1476                                                         rxRuntimeListItem->transferCount;\r
1477                                         if (bytesRemaining > 0) {\r
1478                                                 sendFlowControlFrame( rxConfigListItem, rxRuntimeListItem, ret ); /** @req CANTP224 (Busy or CTS) */\r
1479                                         }\r
1480                                         if (ret == BUFREQ_OK) {\r
1481                                                 if ( bytesRemaining > 0 ) {\r
1482                                                         rxRuntimeListItem->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(rxConfigListItem->CanTpNcr);  //UH\r
1483                                                         rxRuntimeListItem->iso15765.state = RX_WAIT_CONSECUTIVE_FRAME;\r
1484                                                 } else {\r
1485                                                         PduR_CanTpRxIndication(rxConfigListItem->PduR_PduId, NTFRSLT_OK);\r
1486                                                         rxRuntimeListItem->iso15765.state = IDLE;\r
1487                                                         rxRuntimeListItem->mode = CANTP_RX_WAIT;\r
1488                                                 }\r
1489                                         } else if (ret == BUFREQ_NOT_OK ) {\r
1490                                                 PduR_CanTpRxIndication(rxConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP205 */\r
1491                                                 rxRuntimeListItem->iso15765.state = IDLE;\r
1492                                                 rxRuntimeListItem->mode = CANTP_RX_WAIT;\r
1493                                         } else if ( ret == BUFREQ_BUSY ) {\r
1494                                                 DEBUG( DEBUG_MEDIUM, "Still busy!\n");\r
1495                                         }\r
1496                                 }\r
1497                                 break;\r
1498                         }\r
1499                         default:\r
1500                                 break;\r
1501                         }\r
1502                 }\r
1503         }\r
1504 }\r
1505 \r
1506 \r