]> rtime.felk.cvut.cz Git - arc.git/blob - communication/CanTp/CanTp.c
WIP: Searching for the FC TxTdu when receiving FC Pdu.
[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 static Std_ReturnType getFcIndex(const PduIdType rxId, const CanTp_AddressingFormantType *formatType,\r
1107                 const PduInfoType *CanTpRxPduPtr, CanTp_TxNSduType* txConfig ) {\r
1108         Std_ReturnType retValue = E_NOK;\r
1109         boolean bIsExtended = (*formatType == CANTP_EXTENDED);\r
1110         uint8 txId = START_OF_TX_CONFIG;\r
1111 \r
1112         /* TODO: John - Manage if there are no Tx configs */\r
1113         do {\r
1114                 txConfig = &CanTpConfig.CanTpNSduList[txId].configData;\r
1115                 if( txConfig->CanTp_FcPduId == rxId ) {\r
1116                         if( !(CANTP_EXTENDED == *formatType) &&\r
1117                                         CANTP_EXTENDED != txConfig->CanTpAddressingFormant ) {\r
1118                                 retValue = E_OK;\r
1119                                 break;\r
1120                         } else {\r
1121 \r
1122                                 if( CANTP_EXTENDED == txConfig->CanTpAddressingFormant &&\r
1123                                                 CanTpRxPduPtr->SduDataPtr[0] == txConfig->CanTp_NSaType->CanTpNSa ) {\r
1124                                         /* TA in received frame matches SA in the tx channel */\r
1125                                         retValue = E_OK;\r
1126                                         break;\r
1127                                 }\r
1128                         }\r
1129                 }\r
1130         } while( &CanTpConfig.CanTpNSduList[txId].listItemType != CANTP_END_OF_LIST );\r
1131 \r
1132         return retValue;\r
1133 }\r
1134 // - - - - - - - - - - - - - -\r
1135 \r
1136 \r
1137 Std_ReturnType CanTp_Transmit(PduIdType CanTpTxSduId,\r
1138                 const PduInfoType *CanTpTxInfoPtr)  /** @req CANTP176 */\r
1139 {\r
1140         const CanTp_TxNSduType *txConfig = NULL;\r
1141         CanTp_ChannelPrivateType *txRuntime = NULL;\r
1142         BufReq_ReturnType res = BUFREQ_NOT_OK;\r
1143         Std_ReturnType ret = 0;\r
1144 \r
1145         DEBUG( DEBUG_MEDIUM, "CanTp_Transmit called in polite index: %d!\n", CanTpTxSduId);\r
1146 \r
1147         VALIDATE( CanTpTxInfoPtr != NULL,\r
1148                         SERVICE_ID_CANTP_TRANSMIT, CANTP_E_PARAM_ADDRESS ); /** @req CANTP031 */\r
1149         VALIDATE( CanTpRunTimeData.internalState == CANTP_ON, /** @req CANTP238 */\r
1150                         SERVICE_ID_CANTP_TRANSMIT, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1151         VALIDATE( CanTpTxSduId < CANTP_NSDU_CONFIG_LIST_SIZE, SERVICE_ID_CANTP_TRANSMIT, CANTP_E_INVALID_TX_ID );\r
1152 \r
1153         txConfig =&CanTpConfig.CanTpNSduList[CanTpTxSduId].configData.CanTpTxNSdu;\r
1154 \r
1155         txRuntime = &CanTpRunTimeData.runtimeDataList[txConfig->CanTpTxChannel]; // Runtime data.\r
1156         if (txRuntime->iso15765.state == IDLE) {\r
1157                 txRuntime->pdurBufferCount = 0;\r
1158                 txRuntime->pdurBufferCount = 0;\r
1159                 txRuntime->transferCount = 0;\r
1160                 txRuntime->iso15765.framesHandledCount = 0;\r
1161                 txRuntime->transferTotal = CanTpTxInfoPtr->SduLength; /** @req CANTP225 */\r
1162                 txRuntime->iso15765.stateTimeoutCount = CANTP_CONVERT_MS_TO_MAIN_CYCLES(txConfig->CanTpNcs);\r
1163                 txRuntime->mode = CANTP_TX_PROCESSING;\r
1164                 txRuntime->iso15765.state = TX_WAIT_CAN_TP_TRANSMIT_CAN_TP_PROVIDE_TX_BUFFER;\r
1165 \r
1166                 res = canTpTransmitHelper(txConfig, txRuntime);\r
1167                 switch (res) {\r
1168                 case BUFREQ_OK:\r
1169                 case BUFREQ_BUSY:\r
1170                         ret = E_OK;\r
1171                         break;\r
1172                 case BUFREQ_NOT_OK:\r
1173                         ret = E_NOT_OK; /** @req CANTP072 */\r
1174                         break;\r
1175                 default:\r
1176                         ret = E_NOT_OK;\r
1177                         break;\r
1178                 }\r
1179         } else {\r
1180                 DEBUG( DEBUG_MEDIUM, "CanTp can't transmit, it is already occupied!\n", CanTpTxSduId);\r
1181                 ret = E_NOT_OK;  /** @req CANTP123 *//** @req CANTP206 */\r
1182         }\r
1183         return ret; // CAN level error code.\r
1184 }\r
1185 \r
1186 // - - - - - - - - - - - - - -\r
1187 \r
1188 #if FRTP_CANCEL_TRANSMIT_REQUEST\r
1189 Std_ReturnType FrTp_CancelTransmitRequest(PduIdType FrTpTxPduId,\r
1190                 FrTp_CancelReasonType FrTpCancelReason)\r
1191 {\r
1192         return E_NOT_OK;\r
1193 }\r
1194 #endif\r
1195 \r
1196 // - - - - - - - - - - - - - -\r
1197 \r
1198 \r
1199 void CanTp_Init(void)\r
1200 {\r
1201         CanTp_ChannelPrivateType *runtimeData;\r
1202         const CanTp_TxNSduType *txConfigParams;\r
1203         const CanTp_RxNSduType *rxConfigParams;\r
1204 \r
1205         for (int i=0; i < CANTP_NSDU_CONFIG_LIST_SIZE; i++) {\r
1206                 if ( CanTpConfig.CanTpNSduList[i].direction == IS015765_TRANSMIT ) {\r
1207                         txConfigParams = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1208                         if (txConfigParams->CanTpTxChannel < CANTP_NSDU_RUNTIME_LIST_SIZE) {\r
1209                                 runtimeData = &CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel];\r
1210                         } else {\r
1211                                 runtimeData = &CanTpRunTimeData.runtimeDataList[CANTP_NSDU_RUNTIME_LIST_SIZE-1];\r
1212                         }\r
1213                         initTx15765RuntimeData( txConfigParams, runtimeData);\r
1214                 } else {\r
1215                         rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1216                         if (rxConfigParams->CanTpRxChannel < CANTP_NSDU_RUNTIME_LIST_SIZE) {\r
1217                                 runtimeData = &CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel];\r
1218                         } else {\r
1219                                 runtimeData = &CanTpRunTimeData.runtimeDataList[CANTP_NSDU_RUNTIME_LIST_SIZE-1];\r
1220                         }\r
1221                         initRx15765RuntimeData( rxConfigParams, runtimeData);\r
1222                 }\r
1223         }\r
1224         fifoQueueInit( &CanTpRunTimeData.fifo );\r
1225         CanTpRunTimeData.internalState = CANTP_ON; /** @req CANTP170 */\r
1226 }\r
1227 \r
1228 // - - - - - - - - - - - - - -\r
1229 \r
1230 void CanTp_RxIndication(PduIdType CanTpRxPduId, /** @req CANTP078 */ /** @req CANTP035 */\r
1231                 const PduInfoType *CanTpRxPduPtr)\r
1232 {\r
1233         CanTpFifoQueueItem item;\r
1234         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1235                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_UNINIT ); /** @req CANTP238 */ /** @req CANTP031 */\r
1236 \r
1237         item.PduId = CanTpRxPduId;\r
1238         item.SduLength = CanTpRxPduPtr->SduLength;\r
1239         for (int i=0; i<item.SduLength; i++) {\r
1240                 item.SduData[i] = CanTpRxPduPtr->SduDataPtr[i];\r
1241         }\r
1242         if ( fifoQueueWrite( &CanTpRunTimeData.fifo, &item ) == FALSE ) {  /** @req CANTP077 *//** @req CANTP235 */\r
1243                 DEBUG( DEBUG_MEDIUM, "WARNING!: Frames are lost!\n");\r
1244         }\r
1245 }\r
1246 \r
1247 // - - - - - - - - - - - - - -\r
1248 \r
1249 void CanTp_RxIndication_Main(PduIdType CanTpRxPduId,\r
1250                 const PduInfoType *CanTpRxPduPtr)\r
1251 {\r
1252         const CanTp_RxNSduType *rxConfigParams; // Params reside in ROM.\r
1253         const CanTp_TxNSduType *txConfigParams;\r
1254         const CanTp_AddressingFormantType *addressingFormat; // Configured\r
1255         CanTp_ChannelPrivateType *runtimeParams; // Params reside in RAM.\r
1256         ISO15765FrameType frameType;\r
1257 \r
1258         DEBUG( DEBUG_MEDIUM, "CanTp_RxIndication: PduId=%d, [", CanTpRxPduId);\r
1259         for (int i=0; i<CanTpRxPduPtr->SduLength; i++) {\r
1260                 DEBUG( DEBUG_MEDIUM, "%x, ", CanTpRxPduPtr->SduDataPtr[i]);\r
1261         }\r
1262         DEBUG( DEBUG_MEDIUM, "]");\r
1263 \r
1264         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1265                         SERVICE_ID_CANTP_RX_INDICATION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1266 \r
1267         if ( CanTpConfig.CanTpNSduList[CanTpRxPduId].direction == IS015765_TRANSMIT ) {\r
1268                 DEBUG( DEBUG_MEDIUM, "Received pduId which is not RECEIVE - ignoring!\n");\r
1269         } else {\r
1270                 rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[CanTpRxPduId].configData;  /** @req CANTP120 */\r
1271                 addressingFormat = &rxConfigParams->CanTpAddressingFormant;\r
1272                 runtimeParams = &CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel];  /** @req CANTP096 *//** @req CANTP121 *//** @req CANTP122 *//** @req CANTP190 */\r
1273                 txConfigParams = NULL;\r
1274         }\r
1275 \r
1276         /* TODO: John - Note that the addressing format is taken from the rxConfig\r
1277          * (since we don't know if there is a tx config yet */\r
1278         frameType = getFrameType(addressingFormat, CanTpRxPduPtr); /** @req CANTP094 *//** @req CANTP095 */\r
1279 \r
1280         if( frameType == FLOW_CONTROL_CTS_FRAME ) {\r
1281                 Std_ReturnType ret = getFcIndex(CanTpRxPduId, addressingFormat, CanTpRxPduPtr, &rxConfigParams->CanTpNSa, &txConfigParams );\r
1282                 if( ret != E_OK ) {\r
1283                         /* No Tx channel found - set to NULL in order to ignore */\r
1284                         txConfigParams = NULL;\r
1285                 }\r
1286                 runtimeParams = &CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpRxChannel];  /** @req CANTP096 *//** @req CANTP121 *//** @req CANTP122 *//** @req CANTP190 */\r
1287                 rxConfigParams = NULL;\r
1288         }\r
1289 \r
1290         switch (frameType) {\r
1291         case SINGLE_FRAME: {\r
1292                 if (rxConfigParams != NULL) {\r
1293                         DEBUG( DEBUG_MEDIUM, "calling handleSingleFrame!\n");\r
1294                         handleSingleFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1295                 }\r
1296                 else{\r
1297                         DEBUG( DEBUG_MEDIUM, "Single frame received on ISO15765-Tx - is ignored!\n");\r
1298                 }\r
1299                 break;\r
1300         }\r
1301         case FIRST_FRAME: {\r
1302                 if (rxConfigParams != NULL) {\r
1303                         DEBUG( DEBUG_MEDIUM, "calling handleFirstFrame!\n");\r
1304                         handleFirstFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1305                 }else{\r
1306                         DEBUG( DEBUG_MEDIUM, "First frame received on ISO15765-Tx - is ignored!\n");\r
1307                 }\r
1308                 break;\r
1309         }\r
1310         case CONSECUTIVE_FRAME: {\r
1311                 if (rxConfigParams != NULL) {\r
1312                         DEBUG( DEBUG_MEDIUM, "calling handleConsecutiveFrame!\n");\r
1313                         handleConsecutiveFrame(rxConfigParams, runtimeParams, CanTpRxPduPtr);\r
1314                 } else {\r
1315                         DEBUG( DEBUG_MEDIUM, "Consecutive frame received on ISO15765-Tx - is ignored!\n");\r
1316                 }\r
1317                 break;\r
1318         }\r
1319         case FLOW_CONTROL_CTS_FRAME: {\r
1320                 if (txConfigParams != NULL) {\r
1321                         DEBUG( DEBUG_MEDIUM, "calling handleFlowControlFrame!\n");\r
1322                         handleFlowControlFrame(txConfigParams, runtimeParams, CanTpRxPduPtr);\r
1323                 } else {\r
1324                         DEBUG( DEBUG_MEDIUM, "Flow control frame received on ISO15765-Rx - is ignored!\n");\r
1325                 }\r
1326                 break;\r
1327         }\r
1328         case INVALID_FRAME: {\r
1329                 DEBUG( DEBUG_MEDIUM, "INVALID_FRAME received - is ignored!\n!\n");\r
1330                 break;\r
1331         }\r
1332         default:\r
1333                 break;\r
1334         }\r
1335         DEBUG( DEBUG_LOW, "CanTp_RxIndication_Main exit!\n");\r
1336 }\r
1337 \r
1338 // - - - - - - - - - - - - - -\r
1339 \r
1340 void CanTp_TxConfirmation(PduIdType CanTpTxPduId) /** @req CANTP076 */\r
1341 {\r
1342         const CanTp_RxNSduType *rxConfigParams = NULL;\r
1343         const CanTp_TxNSduType *txConfigParams = NULL;\r
1344 \r
1345         DEBUG( DEBUG_MEDIUM, "CanTp_TxConfirmation called.\n" );\r
1346 \r
1347         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1348                         SERVICE_ID_CANTP_TX_CONFIRMATION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1349         VALIDATE_NO_RV( CanTpTxPduId < CANTP_NSDU_CONFIG_LIST_SIZE,\r
1350                         SERVICE_ID_CANTP_TX_CONFIRMATION, CANTP_E_INVALID_TX_ID ); /** @req CANTP158 */\r
1351 \r
1352         /** @req CANTP236 */\r
1353         if ( CanTpConfig.CanTpNSduList[CanTpTxPduId].direction == IS015765_TRANSMIT ) {\r
1354                 txConfigParams = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[CanTpTxPduId].configData;\r
1355                 CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel].iso15765.NasNarPending = FALSE;\r
1356 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
1357                 CanTpRunTimeData.runtimeDataList[txConfigParams->CanTpTxChannel].iso15765.txConfirmed = TRUE;\r
1358 #endif\r
1359         } else {\r
1360                 rxConfigParams = (CanTp_RxNSduType*)&CanTpConfig.CanTpNSduList[CanTpTxPduId].configData;\r
1361                 CanTpRunTimeData.runtimeDataList[rxConfigParams->CanTpRxChannel].iso15765.NasNarPending = FALSE;\r
1362         }\r
1363 }\r
1364 \r
1365 // - - - - - - - - - - - - - -\r
1366 \r
1367 void CanTp_Shutdown(void) /** @req CANTP202 *//** @req CANTP200 *//** @req CANTP010 */\r
1368 {\r
1369         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1370                         SERVICE_ID_CANTP_SHUTDOWN, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1371 \r
1372         CanTpRunTimeData.internalState = CANTP_OFF;\r
1373 }\r
1374 \r
1375 // - - - - - - - - - - - - - -\r
1376 \r
1377 \r
1378 static inline boolean checkNasNarTimeout(CanTp_ChannelPrivateType *runtimeData) {\r
1379         boolean ret = FALSE;\r
1380         if (runtimeData->iso15765.NasNarPending) {\r
1381                 TIMER_DECREMENT(runtimeData->iso15765.NasNarTimeoutCount);\r
1382                 if (runtimeData->iso15765.NasNarTimeoutCount == 0) {\r
1383                         DEBUG( DEBUG_MEDIUM, "NAS timed out.\n" );\r
1384                         runtimeData->iso15765.state = IDLE;\r
1385                         runtimeData->iso15765.NasNarPending = FALSE;\r
1386                         ret = TRUE;\r
1387                 }\r
1388         }\r
1389         return ret;\r
1390 }\r
1391 \r
1392 // - - - - - - - - - - - - - -\r
1393 \r
1394 \r
1395 void CanTp_MainFunction(void)\r
1396 {\r
1397         BufReq_ReturnType ret;\r
1398         CanTpFifoQueueItem item;\r
1399         PduLengthType bytesWrittenToSduRBuffer;\r
1400 \r
1401         CanTp_ChannelPrivateType *txRuntimeListItem = NULL;\r
1402         CanTp_ChannelPrivateType *rxRuntimeListItem = NULL;\r
1403 \r
1404         const CanTp_TxNSduType *txConfigListItem = NULL;\r
1405         const CanTp_RxNSduType *rxConfigListItem = NULL;\r
1406 \r
1407         VALIDATE_NO_RV( CanTpRunTimeData.internalState == CANTP_ON,\r
1408                         SERVICE_ID_CANTP_MAIN_FUNCTION, CANTP_E_UNINIT ); /** @req CANTP031 */\r
1409 \r
1410         // Dispatch the messages that resides in the FIFO to CanTp_RxIndication_Main.\r
1411         while ( fifoQueueRead( &CanTpRunTimeData.fifo, &item ) == TRUE  ) {\r
1412                 PduInfoType pduInfo;\r
1413                 pduInfo.SduDataPtr = item.SduData;\r
1414                 pduInfo.SduLength = item.SduLength;\r
1415                 CanTp_RxIndication_Main( item.PduId, &pduInfo );\r
1416         }\r
1417 \r
1418         for( int i=0; i < CANTP_NSDU_CONFIG_LIST_SIZE; i++ ) {\r
1419 #if 0   // TODO: Not tested yet\r
1420                 if (checkNasNarTimeout( txRuntimeListItem )) { /** @req CANTP075 */\r
1421                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_CanTpTxPduId, NTFRSLT_NOT_OK); /** @req CANTP074 */ /** @req CANTP204 */\r
1422                         continue;\r
1423                 }\r
1424 #endif\r
1425                 if ( CanTpConfig.CanTpNSduList[i].direction == IS015765_TRANSMIT ) {\r
1426                         txConfigListItem = (CanTp_TxNSduType*)&CanTpConfig.CanTpNSduList[i].configData;\r
1427                         txRuntimeListItem = &CanTpRunTimeData.runtimeDataList[txConfigListItem->CanTpTxChannel];\r
1428 \r
1429                         switch (txRuntimeListItem->iso15765.state) {\r
1430                         case TX_WAIT_CAN_TP_TRANSMIT_CAN_TP_PROVIDE_TX_BUFFER:\r
1431                         {\r
1432                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount); /** @req CANTP185 */\r
1433                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0){\r
1434                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 *//** @req CANTP185 */\r
1435                                 }\r
1436                                 txRuntimeListItem->iso15765.state = IDLE;\r
1437                                 txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1438                                 break;\r
1439                         }\r
1440                         case TX_WAIT_CAN_TP_TRANSMIT_PENDING: {\r
1441                                 (void) canTpTransmitHelper(txConfigListItem, txRuntimeListItem);/** @req CANTP184 */ /** @req CANTP089 */\r
1442                                 break;\r
1443                         }\r
1444                         case TX_WAIT_SEND_CONSECUTIVE_FRAME: {\r
1445                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount); // Make sure that STmin timer has expired.\r
1446                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0) {\r
1447                                         ret = sendConsecutiveFrame(txConfigListItem, txRuntimeListItem);\r
1448                                         if ( ret == E_OK ) {\r
1449                                                 handleConsecutiveFrameSent(txConfigListItem, txRuntimeListItem);\r
1450                                         } else {\r
1451                                                 DEBUG( DEBUG_MEDIUM, "ERROR: Consecutive frame could not be sent!\n");\r
1452                                                 PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */\r
1453                                                 txRuntimeListItem->iso15765.state = IDLE;\r
1454                                                 txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1455                                         }\r
1456                                 } else {\r
1457                                         DEBUG( DEBUG_MEDIUM, "Waiting for STmin timer to expire!\n");\r
1458                                 }\r
1459                                 break;\r
1460                         }\r
1461                         case TX_WAIT_FLOW_CONTROL:\r
1462                                 //DEBUG( DEBUG_MEDIUM, "Waiting for flow control!\n");\r
1463                                 TIMER_DECREMENT(txRuntimeListItem->iso15765.stateTimeoutCount);\r
1464                                 if (txRuntimeListItem->iso15765.stateTimeoutCount == 0) {\r
1465                                         DEBUG( DEBUG_MEDIUM, "State TX_WAIT_FLOW_CONTROL timed out!\n");\r
1466                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_E_NOT_OK); /** @req CANTP204 */ /** @req CANTP185 */\r
1467                                         txRuntimeListItem->iso15765.state = IDLE;\r
1468                                         txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1469                                 }\r
1470                                 break;\r
1471 #if (CANTP_IMMEDIATE_TX_CONFIRMATION == STD_OFF)\r
1472                         case TX_WAIT_TX_CONFIRMATION:\r
1473                                 if      (txRuntimeListItem->iso15765.txConfirmed) {\r
1474                                         PduR_CanTpTxConfirmation(txConfigListItem->PduR_PduId, NTFRSLT_OK); /** @req CANTP074 *//** @req CANTP09 *//** @req CANTP204 */\r
1475                                         txRuntimeListItem->iso15765.state = IDLE;\r
1476                                         txRuntimeListItem->mode = CANTP_TX_WAIT;\r
1477                                 }\r
1478                                 break;\r
1479 #endif\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