1 /*
2  * Copyright (C) 2010 NXP Semiconductors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*!
18 * \file  phLlcNfc_Interface.c
19 * \brief Interface for both LLC and transport layer
20 *
21 * Project: NFC-FRI-1.1
22 *
23 * $Date: Tue Jun  1 14:41:26 2010 $
24 * $Author: ing02260 $
25 * $Revision: 1.75 $
26 * $Aliases: NFC_FRI1.1_WK1023_R35_1 $
27 *
28 */
29 
30 /*************************** Includes *******************************/
31 #include <phNfcTypes.h>
32 #include <phNfcStatus.h>
33 #include <phOsalNfc.h>
34 #include <phNfcInterface.h>
35 #include <phLlcNfc_DataTypes.h>
36 #include <phLlcNfc_Timer.h>
37 #include <phLlcNfc_Frame.h>
38 #include <phLlcNfc.h>
39 #include <phLlcNfc_Interface.h>
40 #ifdef PH_LLCNFC_STUB
41 #include <phDalNfc_Stub.h>
42 #endif
43 #ifdef PH_LLCNFC_DALINT
44 #include <phDal4Nfc.h>
45 #endif
46 #define LOG_TAG "NFC-LLC"
47 
48 #include <utils/Log.h>
49 /*********************** End of includes ****************************/
50 
51 /***************************** Macros *******************************/
52 #define PH_LLCNFC_APPEND_LEN                        (4)
53 #define LLC_NS_FRAME_HEADER_MASK                    (0x38U)
54 /************************ End of macros *****************************/
55 
56 /*********************** Local functions ****************************/
57 static
58 void
59 phLlcNfc_WrResp_Cb(
60                    void                        *pContext,
61                    void                        *pHwInfo,
62                    phNfc_sTransactionInfo_t    *pCompInfo
63                    );
64 
65 static
66 void
67 phLlcNfc_RdResp_Cb(
68                    void                        *pContext,
69                    void                        *pHwInfo,
70                    phNfc_sTransactionInfo_t    *pCompInfo
71                    );
72 
73 /******************** End of Local functions ************************/
74 
75 /********************** Global variables ****************************/
76 int libnfc_llc_error_count = 0;
77 
78 /******************** End of Global Variables ***********************/
79 
80 NFCSTATUS
phLlcNfc_Interface_Register(phLlcNfc_Context_t * psLlcCtxt,phNfcLayer_sCfg_t * psIFConfig)81 phLlcNfc_Interface_Register(
82     phLlcNfc_Context_t          *psLlcCtxt,
83     phNfcLayer_sCfg_t           *psIFConfig
84 )
85 {
86     NFCSTATUS                   result = NFCSTATUS_SUCCESS;
87     phNfcIF_sCallBack_t         if_cb = {0,0,0,0};
88     phNfcIF_sReference_t        sreference = {0,0,0};
89 
90     if ((NULL == psLlcCtxt) || (NULL == psIFConfig))
91     {
92         result = PHNFCSTVAL(CID_NFC_LLC,
93                             NFCSTATUS_INVALID_PARAMETER);
94     }
95     else
96     {
97         result = NFCSTATUS_SUCCESS;
98         if_cb.notify = NULL;
99         if_cb.receive_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_RdResp_Cb;
100         if_cb.send_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_WrResp_Cb;
101         if_cb.pif_ctxt = psLlcCtxt;
102         sreference.plower_if = &(psLlcCtxt->lower_if);
103         result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
104 #ifdef PH_LLCNFC_STUB
105         result = phDalNfc_StubRegister(&sreference, if_cb, psIFConfig->layer_next);
106 #endif /* #ifdef PH_LLCNFC_STUB */
107 #ifdef PH_LLCNFC_DALINT
108         result = phDal4Nfc_Register(&sreference, if_cb, psIFConfig->layer_next);
109 #else
110         if ((NULL != psIFConfig->layer_next) &&
111             (NULL != psIFConfig->layer_next->layer_registry))
112         {
113             result = psIFConfig->layer_next->layer_registry(
114                         &sreference,
115                         if_cb,
116                         (void *)&psIFConfig[(psIFConfig->layer_index - 1)]);
117         }
118 #endif /* #ifdef PH_LLCNFC_DALINT */
119     }
120     PH_LLCNFC_DEBUG("Llc Dal Interface Register result : 0x%x\n", result);
121     return result;
122 }
123 
124 NFCSTATUS
phLlcNfc_Interface_Init(phLlcNfc_Context_t * psLlcCtxt)125 phLlcNfc_Interface_Init(
126     phLlcNfc_Context_t      *psLlcCtxt
127 )
128 {
129     /*
130         1. Get the pointer of the main llc context
131     */
132     NFCSTATUS   result = NFCSTATUS_SUCCESS;
133     if ((NULL == psLlcCtxt) ||
134         (NULL == psLlcCtxt->lower_if.init))
135     {
136         result = PHNFCSTVAL(CID_NFC_LLC,
137                             NFCSTATUS_INVALID_PARAMETER);
138     }
139     else
140     {
141         /* Initialise the main context */
142         result = psLlcCtxt->lower_if.init(  psLlcCtxt->lower_if.pcontext,
143                                             psLlcCtxt->phwinfo);
144     }
145     PH_LLCNFC_DEBUG("Llc Dal Interface Init result : 0x%x\n", result);
146     return result;
147 }
148 
149 NFCSTATUS
phLlcNfc_Interface_Read(phLlcNfc_Context_t * psLlcCtxt,uint8_t readWaitOn,uint8_t * pLlcBuffer,uint32_t llcBufferLength)150 phLlcNfc_Interface_Read(
151     phLlcNfc_Context_t      *psLlcCtxt,
152     uint8_t                 readWaitOn,
153     uint8_t                 *pLlcBuffer,
154     uint32_t                llcBufferLength
155 )
156 {
157     NFCSTATUS   result = NFCSTATUS_PENDING;
158     /*
159         1. Call DAL or TL read with "phLlcNfc_LlcTl_RdResp_Cb" as
160             callback function
161     */
162     PH_LLCNFC_PRINT("Llc Dal Interface Read called\n");
163     if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) ||
164         (0 == llcBufferLength) || (NULL == psLlcCtxt->lower_if.receive) ||
165         (readWaitOn > PH_LLCNFC_READWAIT_ON))
166     {
167         result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
168     }
169     else if (PH_LLCNFC_READPEND_FLAG_OFF !=
170             psLlcCtxt->s_frameinfo.read_pending)
171     {
172         /* do nothing */
173     }
174     else
175     {
176         if (PH_LLCNFC_READWAIT_OFF == readWaitOn)
177         {
178             result = psLlcCtxt->lower_if.receive(
179                             psLlcCtxt->lower_if.pcontext,
180                             psLlcCtxt->phwinfo,
181                             pLlcBuffer,
182                             (uint8_t)llcBufferLength);
183         }
184         else
185         {
186             result = psLlcCtxt->lower_if.receive_wait(
187                             psLlcCtxt->lower_if.pcontext,
188                             psLlcCtxt->phwinfo,
189                             pLlcBuffer,
190                             (uint16_t)llcBufferLength);
191         }
192 
193         if(NFCSTATUS_PENDING == result)
194         {
195             if (PH_LLCNFC_READPEND_ONE_BYTE == llcBufferLength)
196             {
197                 psLlcCtxt->s_frameinfo.read_pending =
198                                     PH_LLCNFC_READPEND_ONE_BYTE;
199             }
200             else
201             {
202                 psLlcCtxt->s_frameinfo.read_pending =
203                                     PH_LLCNFC_READPEND_REMAIN_BYTE;
204             }
205         }
206     }
207     PH_LLCNFC_DEBUG("Llc Dal Interface Read result : 0x%x\n", result);
208     return result;
209 }
210 
211 NFCSTATUS
phLlcNfc_Interface_Write(phLlcNfc_Context_t * psLlcCtxt,uint8_t * pLlcBuffer,uint32_t llcBufferLength)212 phLlcNfc_Interface_Write(
213     phLlcNfc_Context_t      *psLlcCtxt,
214     uint8_t             *pLlcBuffer,
215     uint32_t            llcBufferLength
216 )
217 {
218     NFCSTATUS   result = NFCSTATUS_PENDING;
219 
220     PH_LLCNFC_PRINT("Llc Dal Interface Write called\n");
221     /*
222         1. Call DAL or TL write with "phLlcNfc_LlcTl_WrResp_Cb" as
223             callback function
224     */
225     if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) ||
226         (0 == llcBufferLength) ||
227         (NULL == psLlcCtxt->lower_if.send))
228     {
229         PH_LLCNFC_DEBUG ("psLlcCtxt : 0x%p\n", psLlcCtxt);
230         PH_LLCNFC_DEBUG ("pLlcBuffer : 0x%p\n", pLlcBuffer);
231         PH_LLCNFC_DEBUG ("llcBufferLength : 0x%08X\n", llcBufferLength);
232         result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
233     }
234     else
235     {
236         PH_LLCNFC_PRINT("Buffer to be send to Dal : \n");
237         PH_LLCNFC_PRINT_BUFFER(pLlcBuffer, llcBufferLength);
238 
239         if ((TRUE == psLlcCtxt->s_frameinfo.write_pending) ||
240             (PH_LLCNFC_READPEND_REMAIN_BYTE ==
241             psLlcCtxt->s_frameinfo.read_pending))
242         {
243             result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY);
244         }
245         else
246         {
247 #ifdef LLC_DATA_BYTES
248 
249             PH_LLCNFC_PRINT_DATA (pLlcBuffer, llcBufferLength);
250             PH_LLCNFC_STRING (";\n");
251 
252 #endif /* LLC_DATA_BYTES */
253 
254             psLlcCtxt->s_frameinfo.s_llcpacket.llcbuf_len = (uint8_t)llcBufferLength;
255             (void)memcpy ((void *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf),
256                         (void *)pLlcBuffer, llcBufferLength);
257 
258             result = psLlcCtxt->lower_if.send(psLlcCtxt->lower_if.pcontext,
259                                                 psLlcCtxt->phwinfo,
260                                                 (uint8_t *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf),
261                                                 (uint16_t)llcBufferLength);
262             if(NFCSTATUS_PENDING == result)
263             {
264                 psLlcCtxt->s_frameinfo.write_pending = TRUE;
265 #ifdef PIGGY_BACK
266                 /* Stop the ACK timer, as the ACK or I frame is sent */
267                 phLlcNfc_StopTimers (PH_LLCNFC_ACKTIMER, 0);
268                 /* ACK is sent, so reset the response received count */
269                 psLlcCtxt->s_frameinfo.resp_recvd_count = 0;
270 #endif /* #ifdef PIGGY_BACK */
271             }
272         }
273     }
274     PH_LLCNFC_DEBUG("Llc Dal Interface Write result : 0x%x\n", result);
275     return result;
276 }
277 
278 static
279 void
phLlcNfc_WrResp_Cb(void * pContext,void * pHwInfo,phNfc_sTransactionInfo_t * pCompInfo)280 phLlcNfc_WrResp_Cb(
281     void                        *pContext,
282     void                        *pHwInfo,
283     phNfc_sTransactionInfo_t    *pCompInfo
284 )
285 {
286     /*
287         1. Check the window size, if window size = windows
288         1. Call the send callback, which has been registered by upper
289             layer
290     */
291     NFCSTATUS                   result = NFCSTATUS_SUCCESS;
292     phLlcNfc_Context_t          *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
293     phLlcNfc_Frame_t            *ps_frame_info = NULL;
294     phLlcNfc_LlcPacket_t        *ps_recv_pkt = NULL;
295     phLlcNfc_StoreIFrame_t      *ps_store_frame = NULL;
296     phNfc_sCompletionInfo_t     notifyinfo = {0,0,0};
297     uint8_t                     count = 0;
298 
299     PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB CALLED\n\n");
300 
301     if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo))
302     {
303         ps_llc_ctxt->s_frameinfo.write_pending = FALSE;
304 
305         PHNFC_UNUSED_VARIABLE(result);
306 
307         if(NFCSTATUS_SUCCESS == pCompInfo->status)
308         {
309             ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
310             ps_recv_pkt = &(ps_frame_info->s_recvpacket);
311             ps_store_frame = &(ps_frame_info->s_send_store);
312             count = ps_frame_info->s_send_store.start_pos;
313 
314             PH_LLCNFC_DEBUG("RECEIVE length : 0x%02X\n", ps_recv_pkt->llcbuf_len);
315             PH_LLCNFC_DEBUG("SENT frame type : 0x%02X\n", ps_frame_info->sent_frame_type);
316             PH_LLCNFC_DEBUG("WRITE PENDING : 0x%02X\n", ps_frame_info->write_pending);
317             PH_LLCNFC_DEBUG("WRITE PENDING status : 0x%04X\n", ps_frame_info->write_status);
318             PH_LLCNFC_DEBUG("WRITE wait frame type : 0x%02X\n", ps_frame_info->write_wait_call);
319             PH_LLCNFC_DEBUG("NS START POS : 0x%02X\n", ps_store_frame->start_pos);
320             PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_store_frame->winsize_cnt);
321 
322             switch(ps_frame_info->sent_frame_type)
323             {
324                 case init_u_rset_frame:
325                 {
326                     /* First U frame sent properly, update sent frame type
327                         in the callback */
328                     result = phLlcNfc_Interface_Read (ps_llc_ctxt,
329                                     PH_LLCNFC_READWAIT_OFF,
330                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
331                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
332 
333                     if (NFCSTATUS_BUSY ==
334                         PHNFCSTATUS (ps_frame_info->write_status))
335                     {
336                         ps_frame_info->write_status = NFCSTATUS_PENDING;
337                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
338                     }
339                     break;
340                 }
341 
342                 case init_u_a_frame:
343                 {
344                     /* First UA frame sent properly, update sent frame type
345                         in the callback. Send the notification to the
346                         upper layer */
347                     ps_frame_info->sent_frame_type = write_resp_received;
348                     result = phLlcNfc_Interface_Read (ps_llc_ctxt,
349                                     PH_LLCNFC_READWAIT_OFF,
350                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
351                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
352 
353                     if(NULL != ps_llc_ctxt->cb_for_if.notify)
354                     {
355                         notifyinfo.status = NFCSTATUS_SUCCESS;
356                         ps_llc_ctxt->cb_for_if.notify (
357                                         ps_llc_ctxt->cb_for_if.pif_ctxt,
358                                         ps_llc_ctxt->phwinfo,
359                                         NFC_NOTIFY_INIT_COMPLETED,
360                                         &notifyinfo);
361                     }
362                     break;
363                 }
364 
365                 case u_rset_frame:
366                 {
367                     /* Retries has failed to work, so U frame is sent */
368                     ps_frame_info->sent_frame_type = write_resp_received;
369 
370                     if (NFCSTATUS_BUSY ==
371                         PHNFCSTATUS (ps_frame_info->write_status))
372                     {
373                         ps_frame_info->write_status = NFCSTATUS_PENDING;
374                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
375                     }
376                     break;
377                 }
378 
379                 case user_i_frame:
380                 {
381                     /* Send complete */
382                     count = ps_frame_info->n_s;
383 
384                     ps_store_frame->s_llcpacket[count].frame_to_send =
385                     ps_frame_info->sent_frame_type = write_resp_received;
386 
387                     /* N(S) shall be incremented now, because, this callback
388                         ensures that packet is sent */
389                     count =
390                     ps_frame_info->n_s = ((ps_frame_info->n_s + 1) %
391                                             PH_LLCNFC_MOD_NS_NR);
392 
393                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
394                                     PH_LLCNFC_READWAIT_OFF,
395                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
396                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
397 
398                     if (NFCSTATUS_BUSY ==
399                         PHNFCSTATUS (ps_frame_info->write_status))
400                     {
401                         ps_frame_info->write_status = NFCSTATUS_PENDING;
402                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
403                     }
404 
405 
406                     if ((((ps_store_frame->start_pos + ps_store_frame->winsize_cnt) %
407                         PH_LLCNFC_MOD_NS_NR) == ps_frame_info->n_s) &&
408                         (ps_frame_info->window_size == ps_store_frame->winsize_cnt))
409                     {
410                         /* Don't call the upper layer send completion callback,
411                             because last sent frame is the maximum that can be
412                             held by LLC due to windowing
413                             store the callback info, call send completion shall
414                             be sent to upper layer only after the ACK is received for the
415                             I frames */
416                         ps_llc_ctxt->send_cb_len = (pCompInfo->length -
417                                                     PH_LLCNFC_APPEND_LEN);
418                     }
419                     else
420                     {
421                         /* Send completion is sent to upper layer
422                         Actually, this allows the upper layer to send data, if any
423                         */
424                         if (NULL != ps_llc_ctxt->cb_for_if.send_complete)
425                         {
426                             pCompInfo->length = (pCompInfo->length -
427                                                 PH_LLCNFC_APPEND_LEN);
428                             ps_llc_ctxt->cb_for_if.send_complete (
429                                         ps_llc_ctxt->cb_for_if.pif_ctxt,
430                                         pHwInfo, pCompInfo);
431                         }
432                     }
433                     break;
434                 }
435 
436                 case s_frame:
437                 {
438 #if 0
439                     uint8_t         i_frame_ns_value = 0;
440 #endif /* #if 0 */
441                     /* S frame is only sent when ever a I frame is received from
442                         the PN544 in the read response callback, so the received I
443                         frame is acknowledged with S frame. The write response
444                         callback for sent S frame is in progress. */
445                     ps_frame_info->sent_frame_type = write_resp_received;
446 
447 #if 0
448                     i_frame_ns_value =
449                         ((ps_store_frame->s_llcpacket[count].s_llcbuf.sllcpayload.llcheader
450                         & LLC_NS_FRAME_HEADER_MASK) >> PH_LLCNFC_NS_START_BIT_POS);
451 
452 
453                      PH_LLCNFC_DEBUG("Actual ns value : 0x%02X\n",
454                                                   i_frame_ns_value);
455 #endif /* #if 0 */
456 
457                      PH_LLCNFC_DEBUG("Window size : 0x%02X\n",
458                                        ps_frame_info->s_send_store.winsize_cnt);
459                      PH_LLCNFC_DEBUG("frame to send : 0x%02X\n",
460                               ps_store_frame->s_llcpacket[count].frame_to_send);
461 
462                     if (NFCSTATUS_BUSY ==
463                         PHNFCSTATUS(ps_frame_info->write_status))
464                     {
465                         ps_frame_info->write_status = NFCSTATUS_PENDING;
466                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
467                     }
468 #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB
469                     phLlcNfc_H_SendInfo (ps_llc_ctxt);
470 #endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */
471                     break;
472                 }
473 
474 #ifdef LLC_RR_INSTEAD_OF_REJ
475                 case rej_rr_s_frame:
476                 {
477                     if (NFCSTATUS_BUSY ==
478                         PHNFCSTATUS(ps_frame_info->write_status))
479                     {
480                         ps_frame_info->write_status = NFCSTATUS_PENDING;
481                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
482                     }
483                     break;
484                 }
485 #endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */
486 
487                 case resend_i_frame:
488                 {
489                     /* The code reaches here, only if stored I frame is sent
490                         No changes here, but send next I frame from the stored list,
491                         in the read response callback, only if proper S or I frame
492                         is received from the PN544 */
493                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
494                                     PH_LLCNFC_READWAIT_OFF,
495                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
496                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
497 
498                     if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status))
499                     {
500                         ps_frame_info->write_status = NFCSTATUS_PENDING;
501                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
502                     }
503 
504                     if (ps_store_frame->winsize_cnt ==
505                         ps_frame_info->window_size)
506                     {
507                         /* Don't call the upper layer send completion callback,
508                             store the callback info, call send completion after
509                             ack for written frame
510                         ps_llc_ctxt->send_cb_len = pCompInfo->length; */
511                     }
512                     else
513                     {
514                         /* ***** This notification needs to be disabled ***** */
515                         if(NULL != ps_llc_ctxt->cb_for_if.send_complete)
516                         {
517                             pCompInfo->length = (pCompInfo->length -
518                                                 PH_LLCNFC_APPEND_LEN);
519                             ps_llc_ctxt->cb_for_if.send_complete(
520                                         ps_llc_ctxt->cb_for_if.pif_ctxt,
521                                         pHwInfo, pCompInfo);
522                         }
523                     }
524 
525                     if(user_i_frame ==
526                         ps_store_frame->s_llcpacket[count].frame_to_send)
527                     {
528                         /* Send complete */
529                         ps_store_frame->s_llcpacket[count].frame_to_send =
530                                                             resend_i_frame;
531                     }
532                     break;
533                 }
534 
535                 case rejected_i_frame:
536                 {
537                     /* Update the sent frame type, if window size count is 0 */
538                     ps_frame_info->sent_frame_type = write_resp_received;
539                     /* The code enters here, whenever a I frame is resent and for
540                         this resent I frame, an I frame received from PN544.
541                         So the S frame is sent as the acknowledgment */
542                     if (NFCSTATUS_BUSY ==
543                             PHNFCSTATUS(ps_frame_info->write_status))
544                     {
545                         ps_frame_info->write_status = NFCSTATUS_PENDING;
546                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
547                     }
548                     break;
549                 }
550 
551                 case resend_s_frame:
552                 {
553                     /* Update the sent frame type, if window size count is 0 */
554                     ps_frame_info->sent_frame_type = write_resp_received;
555                     /* The code enters here, whenever a I frame is resent and for
556                         this resent I frame, an I frame received from PN544.
557                         So the S frame is sent as the acknowledgment */
558                     if (NFCSTATUS_BUSY ==
559                             PHNFCSTATUS(ps_frame_info->write_status))
560                     {
561                         ps_frame_info->write_status = NFCSTATUS_PENDING;
562                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
563                     }
564 
565 #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB
566                     phLlcNfc_H_SendInfo (ps_llc_ctxt);
567 #endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */
568                     break;
569                 }
570 
571                 case reject_s_frame:
572                 {
573                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
574                                     PH_LLCNFC_READWAIT_OFF,
575                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
576                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
577 
578                     if (NFCSTATUS_BUSY ==
579                         PHNFCSTATUS(ps_frame_info->write_status))
580                     {
581                         ps_frame_info->write_status = NFCSTATUS_PENDING;
582                         result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
583                     }
584                     break;
585                 }
586 
587                 case u_a_frame:
588                 {
589                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
590                                     PH_LLCNFC_READWAIT_OFF,
591                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
592                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
593 
594                     PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
595 
596                     if(ps_frame_info->s_send_store.winsize_cnt > 0)
597                     {
598                         result = phLlcNfc_H_SendUserIFrame (ps_llc_ctxt,
599                                             &(ps_frame_info->s_send_store));
600                     }
601                     break;
602                 }
603 
604                 case resend_rej_s_frame:
605                 {
606                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
607                                     PH_LLCNFC_READWAIT_OFF,
608                                     &(ps_recv_pkt->s_llcbuf.llc_length_byte),
609                                     (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
610 
611                     PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
612 
613                     if(ps_frame_info->s_send_store.winsize_cnt > 0)
614                     {
615                         result = phLlcNfc_H_SendTimedOutIFrame (ps_llc_ctxt,
616                                             &(ps_frame_info->s_send_store), 0);
617                     }
618                     break;
619                 }
620 
621                 default :
622                 {
623                     break;
624                 }
625             }
626         }
627         else
628         {
629             /* Write not successful */
630             if(NULL != ps_llc_ctxt->cb_for_if.send_complete)
631             {
632                 phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
633                                     ps_llc_ctxt->s_timerinfo.guard_to_count);
634                 PH_LLCNFC_DEBUG("Error status received : 0x%x\n", pCompInfo->status);
635                 ps_llc_ctxt->cb_for_if.send_complete(
636                                     ps_llc_ctxt->cb_for_if.pif_ctxt,
637                                     pHwInfo, pCompInfo);
638             }
639         }
640     }
641     PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB END\n\n");
642 }
643 
644 static
645 void
phLlcNfc_RdResp_Cb(void * pContext,void * pHwInfo,phNfc_sTransactionInfo_t * pCompInfo)646 phLlcNfc_RdResp_Cb(
647     void                        *pContext,
648     void                        *pHwInfo,
649     phNfc_sTransactionInfo_t    *pCompInfo
650 )
651 {
652     /*
653         1. LLC Receive has been called by the upper layer, the response
654             for this function is called by the lower layer
655         2. Get the frame information from the receive buffer
656         3. Depending on the received frame type, process the received
657             buffer
658     */
659     NFCSTATUS                   result = NFCSTATUS_SUCCESS;
660     phLlcNfc_Context_t          *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
661     void                        *p_upperctxt = NULL;
662     uint8_t                     crc1 = 0,
663                                 crc2 = 0;
664     phLlcNfc_Frame_t            *ps_frame_info = NULL;
665     phLlcNfc_LlcPacket_t        *ps_recv_pkt = NULL;
666     phLlcNfc_Payload_t          *ps_llc_payload = NULL;
667     pphNfcIF_Notification_CB_t  notifyul = NULL;
668     phNfc_sCompletionInfo_t     notifyinfo = {0,0,0};
669 
670     PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB CALLED\n\n");
671 
672     if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo)
673        && (NULL != pCompInfo->buffer))
674     {
675         ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
676         ps_recv_pkt = &(ps_frame_info->s_recvpacket);
677         ps_llc_payload = &(ps_recv_pkt->s_llcbuf.sllcpayload);
678 
679         ps_llc_ctxt->s_frameinfo.read_pending = PH_LLCNFC_READPEND_FLAG_OFF;
680 
681         if (NFCSTATUS_SUCCESS == pCompInfo->status)
682         {
683             if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) &&
684                 (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < *(pCompInfo->buffer)) &&
685                 (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > *(pCompInfo->buffer))))
686             {
687                 PH_LLCNFC_PRINT("Buffer received : \n");
688                 PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length);
689 
690 #if 0
691                 /* Received length is 1 and receive buffer
692                 contains the length field which is greater than 2,
693                 so read the remaining bytes*/
694                 ps_recv_pkt->s_llcbuf.llc_length_byte = pCompInfo->buffer[0];
695 #endif
696                 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
697                                 PH_LLCNFC_READWAIT_OFF,
698                                 (uint8_t *)ps_llc_payload,
699                                 (uint32_t)(ps_recv_pkt->s_llcbuf.llc_length_byte));
700 
701                 if ((init_u_rset_frame == ps_frame_info->sent_frame_type) &&
702                     (NFCSTATUS_PENDING != result) &&
703                     (NULL != ps_llc_ctxt->cb_for_if.notify))
704                 {
705                     PH_LLCNFC_PRINT("Initialised error\n");
706                     notifyinfo.status = result;
707                     /* Copy the upper layer callback pointer and the upper
708                         layer context, after that call release */
709                     notifyul = ps_llc_ctxt->cb_for_if.notify;
710                     p_upperctxt = ps_llc_ctxt->cb_for_if.pif_ctxt;
711                     result = phLlcNfc_Release(ps_llc_ctxt, pHwInfo);
712 
713                     /* Wrong result, so Init failed sent */
714                     notifyul(p_upperctxt, pHwInfo,
715                             NFC_NOTIFY_INIT_FAILED, &notifyinfo);
716                 }
717             }
718             else if (TRUE == ps_llc_ctxt->s_frameinfo.write_pending)
719             {
720                 /* Ignore the bytes as write is not complete and
721                 pend a read for reading 1 byte */
722                 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
723                                 PH_LLCNFC_READWAIT_OFF,
724                                 (uint8_t *)&(
725                                 ps_recv_pkt->s_llcbuf.llc_length_byte),
726                                 PH_LLCNFC_MIN_BUFLEN_RECVD);
727             }
728             else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) &&
729                 (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) &&
730                 (pCompInfo->length == ps_recv_pkt->s_llcbuf.llc_length_byte))
731             {
732                 PH_LLCNFC_PRINT("Buffer received : \n");
733                 PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length);
734                 PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
735 
736                 /* Receive is complete, so move the state to INITIALISED */
737                 if (phLlcNfc_Resend_State != ps_llc_ctxt->state)
738                 {
739                     result = phLlcNfc_H_ChangeState(ps_llc_ctxt,
740                                                     phLlcNfc_Initialised_State);
741                 }
742                 /* Copy the received buffer and length */
743                 ps_recv_pkt->llcbuf_len = (uint8_t)
744                                 (ps_recv_pkt->s_llcbuf.llc_length_byte + 1);
745 #if 0
746                 (void)memcpy(ps_llc_payload, pCompInfo->buffer,
747                             pCompInfo->length);
748 #endif
749 
750                 /*
751                 Check the CRC
752                 ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf :
753                         consists llc length byte + llc header + data + CRC
754                         (which needs to be calculated by the below function)
755                 ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len :
756                         Total length of the above buffer
757                 ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len - 2 :
758                         -2 because the CRC has to be calculated, only for the
759                         bytes which has llc length byte + llc header + data.
760                         But total length (llcbuf_len) consists of above mentioned
761                         things with 2 byte CRC
762                 ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcpayload :
763                         consists only data (no length byte and no llc header)
764                         (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 4) :
765                         is the array index of the first CRC byte to be calculated
766                         (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 3) :
767                         is the array index of the second CRC byte to be calculated
768                 */
769                 phLlcNfc_H_ComputeCrc((uint8_t *)&(ps_recv_pkt->s_llcbuf),
770                                     (ps_recv_pkt->llcbuf_len - 2),
771                                     &crc1, &crc2);
772 
773                 if ((crc1 == ps_llc_payload->llcpayload[
774                             (ps_recv_pkt->llcbuf_len - 4)])
775                     && (crc2 == ps_llc_payload->llcpayload[
776                             (ps_recv_pkt->llcbuf_len - 3)]))
777                 {
778                     result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt);
779                 }
780 #ifdef LLC_DISABLE_CRC
781                 else
782                 {
783                     result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt);
784                 }
785 #else
786                 else if (ps_frame_info->recv_error_count <
787                     PH_LLCNFC_MAX_REJ_RETRY_COUNT)
788                 {
789                     ALOGW("LLC bad crc");
790                     PH_LLCNFC_PRINT("CRC ERROR RECVD \n");
791                     PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count);
792 
793                     ps_frame_info->recv_error_count = (uint8_t)
794                                     (ps_frame_info->recv_error_count + 1);
795                     libnfc_llc_error_count++;
796 
797                     result = phLlcNfc_Interface_Read(ps_llc_ctxt,
798                         PH_LLCNFC_READWAIT_OFF,
799                         (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
800                         PH_LLCNFC_BYTES_INIT_READ);
801 #ifdef CRC_ERROR_REJ
802                     /* Send REJ (S frame), as the CRC received has error  */
803                     result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt);
804 
805 #endif /* #ifdef CRC_ERROR_REJ */
806 
807                 }
808                 else
809                 {
810                     ALOGE("max LLC retries exceeded, stack restart");
811                     result = phLlcNfc_Interface_Read (ps_llc_ctxt,
812                                 PH_LLCNFC_READWAIT_OFF,
813                                 (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
814                                 PH_LLCNFC_BYTES_INIT_READ);
815 
816                     /* Raise the exception for CRC error received from the  */
817                     notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC,
818                                             NFCSTATUS_BOARD_COMMUNICATION_ERROR);
819 #if 0
820                     phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
821 #endif /* #if 0 */
822                         /* Resend done, no answer from the device */
823                     ps_llc_ctxt->cb_for_if.notify (
824                                     ps_llc_ctxt->cb_for_if.pif_ctxt,
825                                     ps_llc_ctxt->phwinfo,
826                                     NFC_NOTIFY_DEVICE_ERROR,
827                                     &notifyinfo);
828                 }
829 
830 #endif /* #ifdef LLC_DISABLE_CRC */
831             } /* read more than 1 byte */
832             else if (ps_frame_info->recv_error_count >=
833                     PH_LLCNFC_MAX_REJ_RETRY_COUNT)
834             {
835                 ALOGE("max LLC retries exceeded, stack restart");
836                 result = phLlcNfc_Interface_Read (ps_llc_ctxt,
837                         PH_LLCNFC_READWAIT_OFF,
838                         (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
839                         PH_LLCNFC_BYTES_INIT_READ);
840 
841                 /* Raise the exception for CRC error received from the  */
842                 notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC,
843                                         NFCSTATUS_BOARD_COMMUNICATION_ERROR);
844 #if 0
845                 phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
846 #endif /* #if 0 */
847                     /* Resend done, no answer from the device */
848                 ps_llc_ctxt->cb_for_if.notify (
849                                 ps_llc_ctxt->cb_for_if.pif_ctxt,
850                                 ps_llc_ctxt->phwinfo,
851                                 NFC_NOTIFY_DEVICE_ERROR,
852                                 &notifyinfo);
853             }
854             else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) &&
855                 (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) &&
856                 (pCompInfo->length != ps_recv_pkt->s_llcbuf.llc_length_byte))
857             {
858                 ALOGE("bad LLC length1 %d", pCompInfo->length);
859                 ps_frame_info->recv_error_count = (uint8_t)
860                                     (ps_frame_info->recv_error_count + 1);
861                 libnfc_llc_error_count++;
862 
863                 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
864                         PH_LLCNFC_READWAIT_OFF,
865                         (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
866                         PH_LLCNFC_BYTES_INIT_READ);
867 
868 #ifdef CRC_ERROR_REJ
869 
870                 /* Send REJ (S frame), as the CRC received has error  */
871                 result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt);
872 
873 #endif /* #ifdef CRC_ERROR_REJ */
874             }
875             else if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) &&
876                 ((*(pCompInfo->buffer) > (PH_LLCNFC_MAX_BUFLEN_RECV_SEND - 1))
877                 ||(*(pCompInfo->buffer) <= (PH_LLCNFC_MIN_BUFLEN_RECVD + 1))))
878             {
879                 /* Temporary fix for the 0xFF data received
880                     Solution for the read one byte, giving error in buffer
881                     PH_LLCNFC_MAX_BUFLEN_RECV_SEND (0x21) is the maximum
882                     bytes expected by LLC, if the buffer
883                     value is greater than (0x21 - 1), then pend a read to
884                     get 1 byte again
885                 */
886                 ALOGW("bad LLC length byte %x\n", *(pCompInfo->buffer));
887                 ps_frame_info->recv_error_count = (uint8_t)
888                                     (ps_frame_info->recv_error_count + 1);
889                 libnfc_llc_error_count++;
890 
891                 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
892                         PH_LLCNFC_READWAIT_OFF,
893                         (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
894                         PH_LLCNFC_BYTES_INIT_READ);
895             }
896             else
897             {
898                 ALOGW("unknown LLC error1");
899                 ps_frame_info->recv_error_count = (uint8_t)
900                                     (ps_frame_info->recv_error_count + 1);
901                 libnfc_llc_error_count++;
902 
903                 phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
904                                     ps_llc_ctxt->s_timerinfo.guard_to_count);
905                 pCompInfo->status = PHNFCSTVAL(CID_NFC_LLC,
906                                                 NFCSTATUS_INVALID_FORMAT);
907                 pCompInfo->buffer = NULL;
908                 pCompInfo->length = 0;
909                 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
910                         PH_LLCNFC_READWAIT_OFF,
911                         (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
912                         PH_LLCNFC_BYTES_INIT_READ);
913                 if (NULL != ps_llc_ctxt->cb_for_if.receive_complete)
914                 {
915                     ps_llc_ctxt->cb_for_if.receive_complete(
916                                         ps_llc_ctxt->cb_for_if.pif_ctxt,
917                                         pHwInfo, pCompInfo);
918                 }
919             }
920         } else if (NFCSTATUS_READ_FAILED == pCompInfo->status) {
921             // partial read - try reading the length byte again
922             ALOGW("LLC length mis-match\n");
923             ps_frame_info->recv_error_count = (uint8_t)
924                                 (ps_frame_info->recv_error_count + 1);
925             libnfc_llc_error_count++;
926 
927             result = phLlcNfc_Interface_Read(ps_llc_ctxt,
928                     PH_LLCNFC_READWAIT_OFF,
929                     (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
930                     PH_LLCNFC_BYTES_INIT_READ);
931         }
932         else
933         {
934             ALOGW("unknown LLC error2");
935             ps_frame_info->recv_error_count = (uint8_t)
936                                     (ps_frame_info->recv_error_count + 1);
937             libnfc_llc_error_count++;
938 
939             phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
940                                 ps_llc_ctxt->s_timerinfo.guard_to_count);
941             PH_LLCNFC_DEBUG("Status Error : 0x%x\n", pCompInfo->status);
942             if (NULL != ps_llc_ctxt->cb_for_if.receive_complete)
943             {
944                 ps_llc_ctxt->cb_for_if.receive_complete(
945                                     ps_llc_ctxt->cb_for_if.pif_ctxt,
946                                     pHwInfo, pCompInfo);
947             }
948         }
949     }
950     else
951     {
952         if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo)
953             && (NULL != ps_llc_ctxt->cb_for_if.receive_complete))
954         {
955             ps_llc_ctxt->cb_for_if.receive_complete(
956                                     ps_llc_ctxt->cb_for_if.pif_ctxt,
957                                     pHwInfo, pCompInfo);
958         }
959     }
960 
961     PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB END\n\n");
962 }
963 
964 void
phLlcNfc_H_SendInfo(phLlcNfc_Context_t * psLlcCtxt)965 phLlcNfc_H_SendInfo (
966                     phLlcNfc_Context_t          *psLlcCtxt
967                     )
968 {
969     phLlcNfc_LlcPacket_t        *ps_recv_pkt = NULL;
970     phLlcNfc_Frame_t            *ps_frame_info = NULL;
971     phNfc_sTransactionInfo_t    comp_info = {0,0,0,0,0};
972 
973     ps_frame_info = &(psLlcCtxt->s_frameinfo);
974     ps_recv_pkt = &(ps_frame_info->s_recvpacket);
975 
976     if ((ps_recv_pkt->llcbuf_len > 0) &&
977         (ps_recv_pkt->llcbuf_len <= PH_LLCNFC_MAX_LLC_PAYLOAD))
978     {
979         comp_info.status = NFCSTATUS_SUCCESS;
980         /* Chop the extra Llc bytes received */
981 #if 0
982         comp_info.length = (ps_recv_pkt->llcbuf_len -
983                             PH_LLCNFC_LEN_APPEND);
984 #else
985         comp_info.length = (uint16_t)psLlcCtxt->recvbuf_length;
986 #endif /*  */
987 
988         if (0 != comp_info.length)
989         {
990 #if 0
991             (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)(
992                         ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload),
993                         comp_info.length);
994 #endif /* #if 0 */
995             comp_info.buffer = psLlcCtxt->precv_buf;
996         }
997         else
998         {
999             comp_info.buffer = NULL;
1000         }
1001     }
1002     else
1003     {
1004         comp_info.status = PHNFCSTVAL(CID_NFC_LLC,
1005                                     NFCSTATUS_INVALID_FORMAT);
1006         comp_info.length = 0;
1007         comp_info.buffer = NULL;
1008     }
1009 
1010     (void)phLlcNfc_Interface_Read(psLlcCtxt,
1011                         PH_LLCNFC_READWAIT_OFF,
1012                         &(ps_recv_pkt->s_llcbuf.llc_length_byte),
1013                         (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
1014 
1015     if ((NFCSTATUS_SUCCESS == comp_info.status) &&
1016         (0 == comp_info.length))
1017     {
1018         /* May be a NULL I frame received from PN544, so dont do
1019             any thing */
1020     }
1021     else
1022     {
1023         if ((NULL != psLlcCtxt->cb_for_if.receive_complete) &&
1024             (TRUE == ps_frame_info->upper_recv_call))
1025         {
1026             ps_frame_info->upper_recv_call = FALSE;
1027             psLlcCtxt->cb_for_if.receive_complete(
1028                                 psLlcCtxt->cb_for_if.pif_ctxt,
1029                                 psLlcCtxt->phwinfo,
1030                                 &comp_info);
1031         }
1032         else
1033         {
1034             if (NULL != psLlcCtxt->cb_for_if.notify)
1035             {
1036                     psLlcCtxt->cb_for_if.notify(
1037                             psLlcCtxt->cb_for_if.pif_ctxt,
1038                             psLlcCtxt->phwinfo,
1039                             NFC_NOTIFY_RECV_COMPLETED,
1040                             &comp_info);
1041             }
1042         }
1043     }
1044     return;
1045 }
1046 
1047