Initial libnfc checkin

Source: Trusted_NFC_Device_Host_AA03.01e02_google.zip code drop (23-Sep-2010)

Change-Id: Ie47f18423f949a8d3e0815d13f55c814312add24
Signed-off-by: Nick Pelly <npelly@google.com>
diff --git a/src/phLlcNfc.c b/src/phLlcNfc.c
new file mode 100644
index 0000000..af0a3a1
--- /dev/null
+++ b/src/phLlcNfc.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+* \file  phLlcNfc.c
+* \brief Common LLC for the upper layer.
+*
+* Project: NFC-FRI-1.1
+*
+* $Date: Wed Apr 28 17:07:03 2010 $
+* $Author: ing02260 $
+* $Revision: 1.59 $
+* $Aliases: NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
+*
+*/
+
+/*************************** Includes *******************************/
+#include <phNfcTypes.h>
+#include <phNfcStatus.h>
+#include <phOsalNfc.h>
+#include <phNfcInterface.h>
+#include <phLlcNfc_DataTypes.h>
+#include <phLlcNfc.h>
+#include <phLlcNfc_Frame.h>
+#include <phLlcNfc_Interface.h>
+#include <phLlcNfc_Timer.h>
+
+/*********************** End of includes ****************************/
+
+/***************************** Macros *******************************/
+
+/************************ End of macros *****************************/
+
+/***************************** Global variables *******************************/
+
+#ifdef LLC_RELEASE_FLAG
+    uint8_t             g_release_flag;
+#endif /* #ifdef LLC_RELEASE_FLAG */
+
+/************************ End of global variables *****************************/
+
+
+
+/*********************** Local functions ****************************/
+/**
+* \ingroup grp_hal_nfc_llc
+*
+* \brief \b Init function
+*
+* \copydoc page_reg Initialise all variables of the LLC component (Asynchronous function).
+*
+* \param[in] pContext          LLC context provided by the upper layer. The LLC 
+*                              context will be given to the upper layer through the
+*                              \ref phLlcNfc_Register function
+* \param[in] pLinkInfo         Link information of the hardware 
+*
+* \retval NFCSTATUS_PENDING            If the command is yet to be processed.
+* \retval NFCSTATUS_INVALID_PARAMETER  At least one parameter of the function is invalid.
+* \retval Other errors                 Errors related to the lower layers
+*
+*/
+static 
+NFCSTATUS 
+phLlcNfc_Init (
+               void    *pContext, 
+               void    *pLinkInfo
+               );
+
+/**
+* \ingroup grp_hal_nfc_llc
+*
+* \brief \b Send function
+*
+* \copydoc page_reg This asynchronous function gets the information from the upper layer and creates the 
+*              proper LLC packet to send the information it to the hardware. The number of 
+*              bytes written is obtained from the send response callback which has been 
+*              registered in \ref phLlcNfc_Register function
+*
+* \param[in] pContext          LLC context is provided by the upper layer. The LLC 
+*                              context earlier was given to the upper layer through the
+*                              \ref phLlcNfc_Register function
+* \param[in] pLinkInfo         Link information of the hardware.
+* \param[in] pLlc_Buf          The information given by the upper layer to send it to 
+*                              the lower layer
+* \param[in] llcBufLength      the length of pLlc_Buf, that needs to be sent to the 
+*                              lower layer is given by the upper layer
+*
+* \retval NFCSTATUS_PENDING                If the command is yet to be process.
+* \retval NFCSTATUS_INVALID_PARAMETER      At least one parameter of the function is invalid.
+* \retval Other errors                     Errors related to the lower layers
+*
+*/
+static 
+NFCSTATUS 
+phLlcNfc_Send ( 
+               void            *pContext, 
+               void            *pLinkInfo, 
+               uint8_t         *pLlcBuf, 
+               uint16_t        llcBufLength
+               );
+
+/**
+* \ingroup grp_hal_nfc_llc
+*
+* \brief \b Receive function
+*
+* \copydoc page_reg This asynchronous function gets the length and the required buffer from
+*          the upper layer to receive the information from the the hardware. The 
+*          received data will be given through the receive response callback 
+*          which has been registered in the \b phLlcNfc_Register function
+*
+* \param[in] pContext          LLC context is provided by the upper layer. The LLC 
+*                              context earlier was given to the upper layer through the
+*                              \b phLlcNfc_Register function
+* \param[in] pLinkInfo         Link information of the hardware
+* \param[in] pLlc_Buf          The information given by the upper layer to receive data from
+*                              the lower layer
+* \param[in] llcBufLength      The length of pLlc_Buf given by the upper layer
+*
+* \retval NFCSTATUS_PENDING                If the command is yet to be process.
+* \retval NFCSTATUS_INVALID_PARAMETER      At least one parameter of the function is invalid.
+* \retval Other errors                     Errors related to the lower layers
+*
+*/
+static 
+NFCSTATUS 
+phLlcNfc_Receive (  
+                  void              *pContext, 
+                  void              *pLinkInfo, 
+                  uint8_t           *pLlcBuf, 
+                  uint16_t          llcBufLength
+                  );
+/******************** End of Local functions ************************/
+
+/********************** Global variables ****************************/
+
+/******************** End of Global Variables ***********************/
+
+NFCSTATUS 
+phLlcNfc_Register (
+    phNfcIF_sReference_t        *psReference,
+    phNfcIF_sCallBack_t         if_callback,
+    void                        *psIFConfig
+)
+{
+    NFCSTATUS               result = NFCSTATUS_SUCCESS;
+    phLlcNfc_Context_t      *ps_llc_ctxt = NULL;
+    phNfcLayer_sCfg_t       *psconfig = (phNfcLayer_sCfg_t *)psIFConfig;
+    
+    PH_LLCNFC_PRINT("Llc Register called\n");
+    if ((NULL == psReference) || (NULL == psIFConfig) || 
+        (NULL == psReference->plower_if) ||
+#if 0
+        (NULL == if_callback.pif_ctxt) || 
+#endif
+        (NULL == if_callback.notify) ||
+        (NULL == if_callback.receive_complete) ||  
+        (NULL == if_callback.send_complete))
+    {
+        result = PHNFCSTVAL(CID_NFC_LLC, 
+                            NFCSTATUS_INVALID_PARAMETER);
+    }
+    else
+    {        
+        /* Now LLC is in RESET state */
+        ps_llc_ctxt = (phLlcNfc_Context_t*)phOsalNfc_GetMemory(
+                                        sizeof(phLlcNfc_Context_t));
+        if (NULL == ps_llc_ctxt)
+        {
+            /* Memory allocation failed */
+            result = PHNFCSTVAL(CID_NFC_LLC, 
+                                NFCSTATUS_INSUFFICIENT_RESOURCES);
+        }
+        else 
+        {
+            result = NFCSTATUS_SUCCESS;
+
+            (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t));
+
+            /* Register the LLC functions to the upper layer */
+            psReference->plower_if->init = (pphNfcIF_Interface_t)&phLlcNfc_Init;
+            psReference->plower_if->release = (pphNfcIF_Interface_t)&phLlcNfc_Release;
+            psReference->plower_if->send = (pphNfcIF_Transact_t)&phLlcNfc_Send;
+            psReference->plower_if->receive = (pphNfcIF_Transact_t)&phLlcNfc_Receive;
+            /* Copy the LLC context to the upper layer */
+            psReference->plower_if->pcontext = ps_llc_ctxt;
+
+            /* Register the callback function from the upper layer */
+            ps_llc_ctxt->cb_for_if.receive_complete = if_callback.receive_complete;
+            ps_llc_ctxt->cb_for_if.send_complete = if_callback.send_complete;
+            ps_llc_ctxt->cb_for_if.notify = if_callback.notify;
+            /* Get the upper layer context */
+            ps_llc_ctxt->cb_for_if.pif_ctxt = if_callback.pif_ctxt;
+
+            result = phLlcNfc_Interface_Register(ps_llc_ctxt, psconfig);
+
+            if (NFCSTATUS_SUCCESS == result)
+            {
+#ifdef LLC_RELEASE_FLAG
+                g_release_flag = FALSE;
+#endif /* #ifdef LLC_RELEASE_FLAG */
+            }
+        }
+    }
+    PH_LLCNFC_DEBUG("Llc Register result : 0x%x\n", result);
+    return result;
+}
+
+static
+NFCSTATUS 
+phLlcNfc_Init (
+    void    *pContext, 
+    void    *pLinkInfo
+)
+{
+    NFCSTATUS               result = NFCSTATUS_SUCCESS;
+    phLlcNfc_Context_t      *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
+    phLlcNfc_LlcPacket_t    *ps_packet_info = NULL;
+    
+    PH_LLCNFC_PRINT("Llc Init called\n");
+    if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo))
+    {
+        result = PHNFCSTVAL(CID_NFC_LLC, 
+                            NFCSTATUS_INVALID_PARAMETER);
+    }
+    else
+    {
+        /* Initialisation */
+        ps_packet_info = &(ps_llc_ctxt->s_frameinfo.s_llcpacket);
+    
+        ps_llc_ctxt->phwinfo = pLinkInfo;
+        /* Call the internal frame initialise */
+        phLlcNfc_H_Frame_Init(ps_llc_ctxt);
+        /* Call the internal LLC TL interface initialise */
+        result = phLlcNfc_Interface_Init(ps_llc_ctxt);
+        if (NFCSTATUS_SUCCESS == result)
+        {
+            /* Call the internal LLC timer initialise */
+            result = phLlcNfc_TimerInit(ps_llc_ctxt);
+        }
+        
+        if (NFCSTATUS_SUCCESS == result)
+        {
+            /* Create the static timer */
+            phLlcNfc_CreateTimers();               
+
+            /* Create a U frame */
+            result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt, 
+                                    ps_packet_info, 
+                                    &(ps_packet_info->llcbuf_len), 
+                                    phLlcNfc_e_rset);
+        }
+        if (NFCSTATUS_SUCCESS == result)
+        {
+            /* Call DAL write */
+            result = phLlcNfc_Interface_Write(ps_llc_ctxt, 
+                                (uint8_t*)&(ps_packet_info->s_llcbuf), 
+                                (uint32_t)ps_packet_info->llcbuf_len);
+        }
+        if (NFCSTATUS_PENDING == result)
+        {
+            /* Start the timer */
+            result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0);
+            if (NFCSTATUS_SUCCESS == result)
+            {
+                ps_llc_ctxt->s_frameinfo.sent_frame_type = 
+                                                        init_u_rset_frame;
+                result = NFCSTATUS_PENDING;
+            }
+        }
+    
+        if (NFCSTATUS_PENDING != result)
+        {
+            (void)phLlcNfc_Release(ps_llc_ctxt, pLinkInfo);
+        }
+    }
+    PH_LLCNFC_DEBUG("Llc Init result : 0x%x\n", result);
+    return result;
+}
+
+NFCSTATUS 
+phLlcNfc_Release(
+    void    *pContext, 
+    void    *pLinkInfo
+)
+{
+    NFCSTATUS               result = PHNFCSTVAL(CID_NFC_LLC, 
+                                            NFCSTATUS_INVALID_PARAMETER);
+    phLlcNfc_Context_t     *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
+    /* 
+        1. Free all the memory allocated in initialise
+    */
+    PH_LLCNFC_PRINT("Llc release called\n");
+
+    if ((NULL != ps_llc_ctxt) && (NULL != pLinkInfo))
+    {
+        result = NFCSTATUS_SUCCESS;
+        ps_llc_ctxt->phwinfo = pLinkInfo;
+#ifdef INCLUDE_DALINIT_DEINIT   
+        if (NULL != ps_llc_ctxt->lower_if.release)
+        {
+            result = ps_llc_ctxt->lower_if.release(
+                            ps_llc_ctxt->lower_if.pcontext, 
+                            pLinkInfo);
+        }
+#endif
+        if (NULL != ps_llc_ctxt->lower_if.transact_abort)
+        {
+            result = ps_llc_ctxt->lower_if.transact_abort(
+                            ps_llc_ctxt->lower_if.pcontext, 
+                            pLinkInfo);
+        }
+        if (NULL != ps_llc_ctxt->lower_if.unregister)
+        {
+            result = ps_llc_ctxt->lower_if.unregister(
+                            ps_llc_ctxt->lower_if.pcontext, 
+                            pLinkInfo);
+        }
+        
+        /* Call the internal LLC timer un-initialise */
+        phLlcNfc_TimerUnInit(ps_llc_ctxt);
+        phLlcNfc_H_Frame_DeInit(&ps_llc_ctxt->s_frameinfo);
+        (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t));
+        phOsalNfc_FreeMemory(ps_llc_ctxt);
+        ps_llc_ctxt = NULL;
+
+#ifdef LLC_RELEASE_FLAG
+        g_release_flag = TRUE;
+#endif /* #ifdef LLC_RELEASE_FLAG */
+
+    }
+    PH_LLCNFC_DEBUG("Llc release result : 0x%04X\n", result);
+    return result;
+}
+
+static
+NFCSTATUS 
+phLlcNfc_Send ( 
+    void            *pContext, 
+    void            *pLinkInfo, 
+    uint8_t         *pLlcBuf, 
+    uint16_t        llcBufLength
+)
+{
+    /*
+        1. Check the function parameters for valid values
+        2. Create the I frame llc payload using the upper layer buffer
+        3. Send the updated buffer to the below layer
+        4. Store the I frame in a list, till acknowledge is received
+    */
+    NFCSTATUS               result = NFCSTATUS_SUCCESS;
+    phLlcNfc_Context_t      *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
+    phLlcNfc_Frame_t        *ps_frame_info = NULL;
+    phLlcNfc_LlcPacket_t    *ps_packet_info = NULL, 
+                            s_packet_info;
+    phLlcNfc_StoreIFrame_t  *ps_store_frame = NULL;
+#if 0
+    uint8_t                 count = 1;
+#endif /* #if 0 */
+
+    PH_LLCNFC_PRINT ("Llc Send called\n");
+    if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) ||  
+        (NULL == pLlcBuf) || (0 == llcBufLength) ||  
+        (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN))
+    {
+        /* Parameter check failed */
+        result = PHNFCSTVAL(CID_NFC_LLC, 
+                            NFCSTATUS_INVALID_PARAMETER);
+    }
+    else if (ps_llc_ctxt->s_frameinfo.s_send_store.winsize_cnt >= 
+            ps_llc_ctxt->s_frameinfo.window_size)
+    {
+        /* Window size check failed */
+        result = PHNFCSTVAL(CID_NFC_LLC, 
+                            NFCSTATUS_NOT_ALLOWED);
+    }
+    else
+    {
+        ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
+        ps_store_frame = &(ps_frame_info->s_send_store);
+
+        PH_LLCNFC_DEBUG ("Buffer length : 0x%04X\n", llcBufLength);
+        PH_LLCNFC_PRINT_BUFFER (pLlcBuf, llcBufLength);
+        
+        /* Copy the hardware information */
+        ps_llc_ctxt->phwinfo = pLinkInfo;
+
+        /* Create I frame with the user buffer  */
+        (void)phLlcNfc_H_CreateIFramePayload (
+                                &(ps_llc_ctxt->s_frameinfo), 
+                                &s_packet_info, 
+                                pLlcBuf, (uint8_t)llcBufLength);
+
+        ps_packet_info = &(ps_frame_info->s_llcpacket);
+
+        /* Store the I frame in the send list */
+        (void)phLlcNfc_H_StoreIFrame (ps_store_frame, s_packet_info);
+        result = NFCSTATUS_PENDING;
+
+#ifdef CTRL_WIN_SIZE_COUNT
+
+        /* No check required */
+        if ((TRUE != ps_frame_info->write_pending) && 
+            (PH_LLCNFC_READPEND_REMAIN_BYTE != 
+            ps_frame_info->read_pending))
+
+#else /* #ifdef CTRL_WIN_SIZE_COUNT */
+        
+        if (1 == ps_frame_info->s_send_store.winsize_cnt)
+
+#endif /* #ifdef CTRL_WIN_SIZE_COUNT */
+        {
+            (void)memcpy ((void *)ps_packet_info, (void *)&s_packet_info, 
+                        sizeof(phLlcNfc_LlcPacket_t));
+            /* Call write to the below layer, only if previous write 
+                is completed */
+            result = phLlcNfc_Interface_Write (ps_llc_ctxt, 
+                                (uint8_t *)&(ps_packet_info->s_llcbuf), 
+                                (uint32_t)ps_packet_info->llcbuf_len);
+
+            if ((NFCSTATUS_PENDING == result) || 
+                (NFCSTATUS_BUSY == PHNFCSTATUS (result)))
+            {
+                ps_frame_info->write_status = result;
+                if (NFCSTATUS_BUSY == PHNFCSTATUS(result))
+                {
+                    result = NFCSTATUS_PENDING;
+                    ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t)
+                            ((resend_i_frame == ps_frame_info->write_wait_call) ? 
+                            ps_frame_info->write_wait_call : user_i_frame);
+                }
+                else
+                {
+                    /* Start the timer */
+                    (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, 
+                                                ps_frame_info->n_s);
+                    
+                    /* "sent_frame_type is updated" only if the data is 
+                        written to the lower layer */
+                    ps_frame_info->sent_frame_type = user_i_frame;
+                }
+            }
+#if 0
+            /* Get the added frame array count */
+            count = (uint8_t)((((ps_store_frame->start_pos + 
+                            ps_store_frame->winsize_cnt) - count)) % 
+                            PH_LLCNFC_MOD_NS_NR);
+#endif /* #if 0 */
+        }
+        else
+        {
+            ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY);
+            ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t)
+                            ((resend_i_frame == ps_frame_info->write_wait_call) ? 
+                            ps_frame_info->write_wait_call : user_i_frame);
+        }
+    }
+
+    
+    PH_LLCNFC_DEBUG ("Llc Send result : 0x%04X\n", result);
+    return result;
+}
+
+static
+NFCSTATUS 
+phLlcNfc_Receive (  
+    void            *pContext, 
+    void            *pLinkInfo, 
+    uint8_t         *pLlcBuf, 
+    uint16_t        llcBufLength
+)
+{
+    NFCSTATUS               result = NFCSTATUS_SUCCESS;
+    phLlcNfc_Context_t      *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
+    phLlcNfc_LlcPacket_t    *ps_recv_pkt = NULL;
+
+    PH_LLCNFC_PRINT("Llc Receive called\n");
+    if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || 
+        (NULL == pLlcBuf) || (0 == llcBufLength) || 
+        (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN))
+    {
+        result = PHNFCSTVAL(CID_NFC_LLC, 
+                            NFCSTATUS_INVALID_PARAMETER);
+    }
+    else
+    {
+        ps_llc_ctxt->phwinfo = pLinkInfo;
+        
+        ps_recv_pkt = &(ps_llc_ctxt->s_frameinfo.s_recvpacket);
+        /* Always read the first byte to read the length, then 
+        read the entire data later using the 1 byte buffer */
+        llcBufLength = PH_LLCNFC_BYTES_INIT_READ;
+        /* Call write to the below layer */
+        result = phLlcNfc_Interface_Read(ps_llc_ctxt, 
+                                PH_LLCNFC_READWAIT_OFF, 
+                                &(ps_recv_pkt->s_llcbuf.llc_length_byte), 
+                                llcBufLength);
+
+        ps_llc_ctxt->s_frameinfo.upper_recv_call = TRUE;
+        if (NFCSTATUS_PENDING != result)
+        {
+            ps_llc_ctxt->state = phLlcNfc_Initialised_State;
+        }
+    }
+    PH_LLCNFC_DEBUG("Llc Receive result : 0x%04X\n", result);
+    return result;
+}