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