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;
+}