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 ****************************/
57static
58void
59phLlcNfc_WrResp_Cb(
60                   void                        *pContext,
61                   void                        *pHwInfo,
62                   phNfc_sTransactionInfo_t    *pCompInfo
63                   );
64
65static
66void
67phLlcNfc_RdResp_Cb(
68                   void                        *pContext,
69                   void                        *pHwInfo,
70                   phNfc_sTransactionInfo_t    *pCompInfo
71                   );
72
73/******************** End of Local functions ************************/
74
75/********************** Global variables ****************************/
76int libnfc_llc_error_count = 0;
77
78/******************** End of Global Variables ***********************/
79
80NFCSTATUS
81phLlcNfc_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
124NFCSTATUS
125phLlcNfc_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
149NFCSTATUS
150phLlcNfc_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
211NFCSTATUS
212phLlcNfc_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
278static
279void
280phLlcNfc_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
644static
645void
646phLlcNfc_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                    LOGW("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                    LOGE("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                LOGE("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                LOGE("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                LOGW("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                LOGW("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            LOGW("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            LOGW("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
964void
965phLlcNfc_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