summaryrefslogtreecommitdiffstats
path: root/src/phLlcNfc_Interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/phLlcNfc_Interface.c')
-rw-r--r--src/phLlcNfc_Interface.c1010
1 files changed, 1010 insertions, 0 deletions
diff --git a/src/phLlcNfc_Interface.c b/src/phLlcNfc_Interface.c
new file mode 100644
index 0000000..92be48d
--- /dev/null
+++ b/src/phLlcNfc_Interface.c
@@ -0,0 +1,1010 @@
+/*
+ * 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_Interface.c
+* \brief Interface for both LLC and transport layer
+*
+* Project: NFC-FRI-1.1
+*
+* $Date: Tue Jun 1 14:41:26 2010 $
+* $Author: ing02260 $
+* $Revision: 1.75 $
+* $Aliases: 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_Timer.h>
+#include <phLlcNfc_Frame.h>
+#include <phLlcNfc.h>
+#include <phLlcNfc_Interface.h>
+#ifdef PH_LLCNFC_STUB
+#include <phDalNfc_Stub.h>
+#endif
+#ifdef PH_LLCNFC_DALINT
+#include <phDal4Nfc.h>
+#endif
+/*********************** End of includes ****************************/
+
+/***************************** Macros *******************************/
+#define PH_LLCNFC_APPEND_LEN (4)
+#define LLC_NS_FRAME_HEADER_MASK (0x38U)
+
+/************************ End of macros *****************************/
+
+/*********************** Local functions ****************************/
+static
+void
+phLlcNfc_WrResp_Cb(
+ void *pContext,
+ void *pHwInfo,
+ phNfc_sTransactionInfo_t *pCompInfo
+ );
+
+static
+void
+phLlcNfc_RdResp_Cb(
+ void *pContext,
+ void *pHwInfo,
+ phNfc_sTransactionInfo_t *pCompInfo
+ );
+
+/******************** End of Local functions ************************/
+
+/********************** Global variables ****************************/
+
+/******************** End of Global Variables ***********************/
+
+NFCSTATUS
+phLlcNfc_Interface_Register(
+ phLlcNfc_Context_t *psLlcCtxt,
+ phNfcLayer_sCfg_t *psIFConfig
+)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phNfcIF_sCallBack_t if_cb;
+ phNfcIF_sReference_t sreference;
+
+ if ((NULL == psLlcCtxt) || (NULL == psIFConfig))
+ {
+ result = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_INVALID_PARAMETER);
+ }
+ else
+ {
+ result = NFCSTATUS_SUCCESS;
+ if_cb.notify = NULL;
+ if_cb.receive_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_RdResp_Cb;
+ if_cb.send_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_WrResp_Cb;
+ if_cb.pif_ctxt = psLlcCtxt;
+ sreference.plower_if = &(psLlcCtxt->lower_if);
+ result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
+#ifdef PH_LLCNFC_STUB
+ result = phDalNfc_StubRegister(&sreference, if_cb, psIFConfig->layer_next);
+#endif /* #ifdef PH_LLCNFC_STUB */
+#ifdef PH_LLCNFC_DALINT
+ result = phDal4Nfc_Register(&sreference, if_cb, psIFConfig->layer_next);
+#else
+ if ((NULL != psIFConfig->layer_next) &&
+ (NULL != psIFConfig->layer_next->layer_registry))
+ {
+ result = psIFConfig->layer_next->layer_registry(
+ &sreference,
+ if_cb,
+ (void *)&psIFConfig[(psIFConfig->layer_index - 1)]);
+ }
+#endif /* #ifdef PH_LLCNFC_DALINT */
+ }
+ PH_LLCNFC_DEBUG("Llc Dal Interface Register result : 0x%x\n", result);
+ return result;
+}
+
+NFCSTATUS
+phLlcNfc_Interface_Init(
+ phLlcNfc_Context_t *psLlcCtxt
+)
+{
+ /*
+ 1. Get the pointer of the main llc context
+ */
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ if ((NULL == psLlcCtxt) ||
+ (NULL == psLlcCtxt->lower_if.init))
+ {
+ result = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_INVALID_PARAMETER);
+ }
+ else
+ {
+ /* Initialise the main context */
+ result = psLlcCtxt->lower_if.init( psLlcCtxt->lower_if.pcontext,
+ psLlcCtxt->phwinfo);
+ }
+ PH_LLCNFC_DEBUG("Llc Dal Interface Init result : 0x%x\n", result);
+ return result;
+}
+
+NFCSTATUS
+phLlcNfc_Interface_Read(
+ phLlcNfc_Context_t *psLlcCtxt,
+ uint8_t readWaitOn,
+ uint8_t *pLlcBuffer,
+ uint32_t llcBufferLength
+)
+{
+ NFCSTATUS result = NFCSTATUS_PENDING;
+ /*
+ 1. Call DAL or TL read with "phLlcNfc_LlcTl_RdResp_Cb" as
+ callback function
+ */
+ PH_LLCNFC_PRINT("Llc Dal Interface Read called\n");
+ if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) ||
+ (0 == llcBufferLength) || (NULL == psLlcCtxt->lower_if.receive) ||
+ (readWaitOn > PH_LLCNFC_READWAIT_ON))
+ {
+ result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
+ }
+ else if (PH_LLCNFC_READPEND_FLAG_OFF !=
+ psLlcCtxt->s_frameinfo.read_pending)
+ {
+ /* do nothing */
+ }
+ else
+ {
+ if (PH_LLCNFC_READWAIT_OFF == readWaitOn)
+ {
+ result = psLlcCtxt->lower_if.receive(
+ psLlcCtxt->lower_if.pcontext,
+ psLlcCtxt->phwinfo,
+ pLlcBuffer,
+ (uint8_t)llcBufferLength);
+ }
+ else
+ {
+ result = psLlcCtxt->lower_if.receive_wait(
+ psLlcCtxt->lower_if.pcontext,
+ psLlcCtxt->phwinfo,
+ pLlcBuffer,
+ (uint16_t)llcBufferLength);
+ }
+
+ if(NFCSTATUS_PENDING == result)
+ {
+ if (PH_LLCNFC_READPEND_ONE_BYTE == llcBufferLength)
+ {
+ psLlcCtxt->s_frameinfo.read_pending =
+ PH_LLCNFC_READPEND_ONE_BYTE;
+ }
+ else
+ {
+ psLlcCtxt->s_frameinfo.read_pending =
+ PH_LLCNFC_READPEND_REMAIN_BYTE;
+ }
+ }
+ }
+ PH_LLCNFC_DEBUG("Llc Dal Interface Read result : 0x%x\n", result);
+ return result;
+}
+
+NFCSTATUS
+phLlcNfc_Interface_Write(
+ phLlcNfc_Context_t *psLlcCtxt,
+ uint8_t *pLlcBuffer,
+ uint32_t llcBufferLength
+)
+{
+ NFCSTATUS result = NFCSTATUS_PENDING;
+
+ PH_LLCNFC_PRINT("Llc Dal Interface Write called\n");
+ /*
+ 1. Call DAL or TL write with "phLlcNfc_LlcTl_WrResp_Cb" as
+ callback function
+ */
+ if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) ||
+ (0 == llcBufferLength) ||
+ (NULL == psLlcCtxt->lower_if.send))
+ {
+ PH_LLCNFC_DEBUG ("psLlcCtxt : 0x%08X\n", psLlcCtxt);
+ PH_LLCNFC_DEBUG ("pLlcBuffer : 0x%08X\n", pLlcBuffer);
+ PH_LLCNFC_DEBUG ("llcBufferLength : 0x%08X\n", llcBufferLength);
+ result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER);
+ }
+ else
+ {
+ PH_LLCNFC_PRINT("Buffer to be send to Dal : \n");
+ PH_LLCNFC_PRINT_BUFFER(pLlcBuffer, llcBufferLength);
+
+ if ((TRUE == psLlcCtxt->s_frameinfo.write_pending) ||
+ (PH_LLCNFC_READPEND_REMAIN_BYTE ==
+ psLlcCtxt->s_frameinfo.read_pending))
+ {
+ result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY);
+ }
+ else
+ {
+#ifdef LLC_DATA_BYTES
+
+ PH_LLCNFC_PRINT_DATA (pLlcBuffer, llcBufferLength);
+ PH_LLCNFC_STRING (";\n");
+
+#endif /* LLC_DATA_BYTES */
+ result = psLlcCtxt->lower_if.send(psLlcCtxt->lower_if.pcontext,
+ psLlcCtxt->phwinfo,
+ pLlcBuffer,
+ (uint16_t)llcBufferLength);
+ if(NFCSTATUS_PENDING == result)
+ {
+ psLlcCtxt->s_frameinfo.write_pending = TRUE;
+ }
+ }
+ }
+ PH_LLCNFC_DEBUG("Llc Dal Interface Write result : 0x%x\n", result);
+ return result;
+}
+
+static
+void
+phLlcNfc_WrResp_Cb(
+ void *pContext,
+ void *pHwInfo,
+ phNfc_sTransactionInfo_t *pCompInfo
+)
+{
+ /*
+ 1. Check the window size, if window size = windows
+ 1. Call the send callback, which has been registered by upper
+ layer
+ */
+ 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_recv_pkt = NULL;
+ phLlcNfc_StoreIFrame_t *ps_store_frame = NULL;
+ phNfc_sCompletionInfo_t notifyinfo;
+ uint8_t count = 0;
+
+ PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB CALLED\n\n");
+
+ if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo))
+ {
+ ps_llc_ctxt->s_frameinfo.write_pending = FALSE;
+
+ PHNFC_UNUSED_VARIABLE(result);
+
+ if(NFCSTATUS_SUCCESS == pCompInfo->status)
+ {
+ ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
+ ps_recv_pkt = &(ps_frame_info->s_recvpacket);
+ ps_store_frame = &(ps_frame_info->s_send_store);
+ count = ps_frame_info->s_send_store.start_pos;
+
+ PH_LLCNFC_DEBUG("RECEIVE length : 0x%02X\n", ps_recv_pkt->llcbuf_len);
+ PH_LLCNFC_DEBUG("SENT frame type : 0x%02X\n", ps_frame_info->sent_frame_type);
+ PH_LLCNFC_DEBUG("WRITE PENDING : 0x%02X\n", ps_frame_info->write_pending);
+ PH_LLCNFC_DEBUG("WRITE PENDING status : 0x%04X\n", ps_frame_info->write_status);
+ PH_LLCNFC_DEBUG("WRITE wait frame type : 0x%02X\n", ps_frame_info->write_wait_call);
+ PH_LLCNFC_DEBUG("NS START POS : 0x%02X\n", ps_store_frame->start_pos);
+ PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_store_frame->winsize_cnt);
+
+ switch(ps_frame_info->sent_frame_type)
+ {
+ case init_u_rset_frame:
+ {
+ /* First U frame sent properly, update sent frame type
+ in the callback */
+ result = phLlcNfc_Interface_Read (ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS (ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+ break;
+ }
+
+ case init_u_a_frame:
+ {
+ /* First UA frame sent properly, update sent frame type
+ in the callback. Send the notification to the
+ upper layer */
+ ps_frame_info->sent_frame_type = write_resp_received;
+ result = phLlcNfc_Interface_Read (ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if(NULL != ps_llc_ctxt->cb_for_if.notify)
+ {
+ notifyinfo.status = NFCSTATUS_SUCCESS;
+ ps_llc_ctxt->cb_for_if.notify (
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ ps_llc_ctxt->phwinfo,
+ NFC_NOTIFY_INIT_COMPLETED,
+ &notifyinfo);
+ }
+ break;
+ }
+
+ case u_rset_frame:
+ {
+ /* Retries has failed to work, so U frame is sent */
+ ps_frame_info->sent_frame_type = write_resp_received;
+
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS (ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+ break;
+ }
+
+ case user_i_frame:
+ {
+ /* Send complete */
+ count = ps_frame_info->n_s;
+
+ ps_store_frame->s_llcpacket[count].frame_to_send =
+ ps_frame_info->sent_frame_type = write_resp_received;
+
+ /* N(S) shall be incremented now, because, this callback
+ ensures that packet is sent */
+ count =
+ ps_frame_info->n_s = ((ps_frame_info->n_s + 1) %
+ PH_LLCNFC_MOD_NS_NR);
+
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS (ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+
+
+ if ((((ps_store_frame->start_pos + ps_store_frame->winsize_cnt) %
+ PH_LLCNFC_MOD_NS_NR) == ps_frame_info->n_s) &&
+ (ps_frame_info->window_size == ps_store_frame->winsize_cnt))
+ {
+ /* Don't call the upper layer send completion callback,
+ because last sent frame is the maximum that can be
+ held by LLC due to windowing
+ store the callback info, call send completion shall
+ be sent to upper layer only after the ACK is received for the
+ I frames */
+ ps_llc_ctxt->send_cb_len = (pCompInfo->length -
+ PH_LLCNFC_APPEND_LEN);
+ }
+ else
+ {
+ /* Send completion is sent to upper layer
+ Actually, this allows the upper layer to send data, if any
+ */
+ if (NULL != ps_llc_ctxt->cb_for_if.send_complete)
+ {
+ pCompInfo->length = (pCompInfo->length -
+ PH_LLCNFC_APPEND_LEN);
+ ps_llc_ctxt->cb_for_if.send_complete (
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+ break;
+ }
+
+ case s_frame:
+ {
+#if 0
+ uint8_t i_frame_ns_value = 0;
+#endif /* #if 0 */
+ /* S frame is only sent when ever a I frame is received from
+ the PN544 in the read response callback, so the received I
+ frame is acknowledged with S frame. The write response
+ callback for sent S frame is in progress. */
+ ps_frame_info->sent_frame_type = write_resp_received;
+
+#if 0
+ i_frame_ns_value =
+ ((ps_store_frame->s_llcpacket[count].s_llcbuf.sllcpayload.llcheader
+ & LLC_NS_FRAME_HEADER_MASK) >> PH_LLCNFC_NS_START_BIT_POS);
+
+
+ PH_LLCNFC_DEBUG("Actual ns value : 0x%02X\n",
+ i_frame_ns_value);
+#endif /* #if 0 */
+
+ PH_LLCNFC_DEBUG("Window size : 0x%02X\n",
+ ps_frame_info->s_send_store.winsize_cnt);
+ PH_LLCNFC_DEBUG("frame to send : 0x%02X\n",
+ ps_store_frame->s_llcpacket[count].frame_to_send);
+
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+#ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB
+ phLlcNfc_H_SendInfo (ps_llc_ctxt);
+#endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */
+ break;
+ }
+
+#ifdef LLC_RR_INSTEAD_OF_REJ
+ case rej_rr_s_frame:
+ {
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+ break;
+ }
+#endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */
+
+ case resend_i_frame:
+ {
+ /* The code reaches here, only if stored I frame is sent
+ No changes here, but send next I frame from the stored list,
+ in the read response callback, only if proper S or I frame
+ is received from the PN544 */
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+
+ if (ps_store_frame->winsize_cnt ==
+ ps_frame_info->window_size)
+ {
+ /* Don't call the upper layer send completion callback,
+ store the callback info, call send completion after
+ ack for written frame
+ ps_llc_ctxt->send_cb_len = pCompInfo->length; */
+ }
+ else
+ {
+ if(NULL != ps_llc_ctxt->cb_for_if.send_complete)
+ {
+ pCompInfo->length = (pCompInfo->length -
+ PH_LLCNFC_APPEND_LEN);
+ ps_llc_ctxt->cb_for_if.send_complete(
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+
+ if(user_i_frame ==
+ ps_store_frame->s_llcpacket[count].frame_to_send)
+ {
+ /* Send complete */
+ ps_store_frame->s_llcpacket[count].frame_to_send =
+ resend_i_frame;
+ }
+ break;
+ }
+
+ case rejected_i_frame:
+ {
+ /* Update the sent frame type, if window size count is 0 */
+ ps_frame_info->sent_frame_type = write_resp_received;
+ /* The code enters here, whenever a I frame is resent and for
+ this resent I frame, an I frame received from PN544.
+ So the S frame is sent as the acknowledgment */
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+ break;
+ }
+
+ case resend_s_frame:
+ {
+ /* Update the sent frame type, if window size count is 0 */
+ ps_frame_info->sent_frame_type = write_resp_received;
+ /* The code enters here, whenever a I frame is resent and for
+ this resent I frame, an I frame received from PN544.
+ So the S frame is sent as the acknowledgment */
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+
+#ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB
+ phLlcNfc_H_SendInfo (ps_llc_ctxt);
+#endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */
+ break;
+ }
+
+ case reject_s_frame:
+ {
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if (NFCSTATUS_BUSY ==
+ PHNFCSTATUS(ps_frame_info->write_status))
+ {
+ ps_frame_info->write_status = NFCSTATUS_PENDING;
+ result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt);
+ }
+ break;
+ }
+
+ case u_a_frame:
+ {
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
+
+ if(ps_frame_info->s_send_store.winsize_cnt > 0)
+ {
+ result = phLlcNfc_H_SendUserIFrame (ps_llc_ctxt,
+ &(ps_frame_info->s_send_store));
+ }
+ break;
+ }
+
+ case resend_rej_s_frame:
+ {
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
+
+ if(ps_frame_info->s_send_store.winsize_cnt > 0)
+ {
+ result = phLlcNfc_H_SendTimedOutIFrame (ps_llc_ctxt,
+ &(ps_frame_info->s_send_store), 0);
+ }
+ break;
+ }
+
+ default :
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Write not successful */
+ if(NULL != ps_llc_ctxt->cb_for_if.send_complete)
+ {
+ phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
+ ps_llc_ctxt->s_timerinfo.guard_to_count);
+ PH_LLCNFC_DEBUG("Error status received : 0x%x\n", pCompInfo->status);
+ ps_llc_ctxt->cb_for_if.send_complete(
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+ }
+ PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB END\n\n");
+}
+
+static
+void
+phLlcNfc_RdResp_Cb(
+ void *pContext,
+ void *pHwInfo,
+ phNfc_sTransactionInfo_t *pCompInfo
+)
+{
+ /*
+ 1. LLC Receive has been called by the upper layer, the response
+ for this function is called by the lower layer
+ 2. Get the frame information from the receive buffer
+ 3. Depending on the received frame type, process the received
+ buffer
+ */
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
+ void *p_upperctxt = NULL;
+ uint8_t crc1 = 0,
+ crc2 = 0;
+ phLlcNfc_Frame_t *ps_frame_info = NULL;
+ phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL;
+ phLlcNfc_Payload_t *ps_llc_payload = NULL;
+ pphNfcIF_Notification_CB_t notifyul = NULL;
+ phNfc_sCompletionInfo_t notifyinfo;
+
+ PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB CALLED\n\n");
+
+ if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo)
+ && (pCompInfo->length != 0) && (NULL != pCompInfo->buffer))
+ {
+ ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
+ ps_recv_pkt = &(ps_frame_info->s_recvpacket);
+ ps_llc_payload = &(ps_recv_pkt->s_llcbuf.sllcpayload);
+
+ ps_llc_ctxt->s_frameinfo.read_pending = PH_LLCNFC_READPEND_FLAG_OFF;
+
+ if (NFCSTATUS_SUCCESS == pCompInfo->status)
+ {
+ if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) &&
+ (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < *(pCompInfo->buffer)) &&
+ (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > *(pCompInfo->buffer))))
+ {
+ PH_LLCNFC_PRINT("Buffer received : \n");
+ PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length);
+
+#if 0
+ /* Received length is 1 and receive buffer
+ contains the length field which is greater than 2,
+ so read the remaining bytes*/
+ ps_recv_pkt->s_llcbuf.llc_length_byte = pCompInfo->buffer[0];
+#endif
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)ps_llc_payload,
+ (uint32_t)(ps_recv_pkt->s_llcbuf.llc_length_byte));
+
+ if ((init_u_rset_frame == ps_frame_info->sent_frame_type) &&
+ (NFCSTATUS_PENDING != result) &&
+ (NULL != ps_llc_ctxt->cb_for_if.notify))
+ {
+ PH_LLCNFC_PRINT("Initialised error\n");
+ notifyinfo.status = result;
+ /* Copy the upper layer callback pointer and the upper
+ layer context, after that call release */
+ notifyul = ps_llc_ctxt->cb_for_if.notify;
+ p_upperctxt = ps_llc_ctxt->cb_for_if.pif_ctxt;
+ result = phLlcNfc_Release(ps_llc_ctxt, pHwInfo);
+
+ /* Wrong result, so Init failed sent */
+ notifyul(p_upperctxt, pHwInfo,
+ NFC_NOTIFY_INIT_FAILED, &notifyinfo);
+ }
+ }
+ else if (TRUE == ps_llc_ctxt->s_frameinfo.write_pending)
+ {
+ /* Ignore the bytes as write is not complete and
+ pend a read for reading 1 byte */
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(
+ ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_MIN_BUFLEN_RECVD);
+ }
+ else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) &&
+ (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) &&
+ (pCompInfo->length == ps_recv_pkt->s_llcbuf.llc_length_byte))
+ {
+ PH_LLCNFC_PRINT("Buffer received : \n");
+ PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length);
+ PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt);
+
+ /* Receive is complete, so move the state to INITIALISED */
+ if (phLlcNfc_Resend_State != ps_llc_ctxt->state)
+ {
+ result = phLlcNfc_H_ChangeState(ps_llc_ctxt,
+ phLlcNfc_Initialised_State);
+ }
+ /* Copy the received buffer and length */
+ ps_recv_pkt->llcbuf_len = (uint8_t)
+ (ps_recv_pkt->s_llcbuf.llc_length_byte + 1);
+#if 0
+ (void)memcpy(ps_llc_payload, pCompInfo->buffer,
+ pCompInfo->length);
+#endif
+
+ /*
+ Check the CRC
+ ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf :
+ consists llc length byte + llc header + data + CRC
+ (which needs to be calculated by the below function)
+ ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len :
+ Total length of the above buffer
+ ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len - 2 :
+ -2 because the CRC has to be calculated, only for the
+ bytes which has llc length byte + llc header + data.
+ But total length (llcbuf_len) consists of above mentioned
+ things with 2 byte CRC
+ ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcpayload :
+ consists only data (no length byte and no llc header)
+ (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 4) :
+ is the array index of the first CRC byte to be calculated
+ (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 3) :
+ is the array index of the second CRC byte to be calculated
+ */
+ phLlcNfc_H_ComputeCrc((uint8_t *)&(ps_recv_pkt->s_llcbuf),
+ (ps_recv_pkt->llcbuf_len - 2),
+ &crc1, &crc2);
+
+ if ((crc1 == ps_llc_payload->llcpayload[
+ (ps_recv_pkt->llcbuf_len - 4)])
+ && (crc2 == ps_llc_payload->llcpayload[
+ (ps_recv_pkt->llcbuf_len - 3)]))
+ {
+ result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt);
+ }
+#ifdef LLC_DISABLE_CRC
+ else
+ {
+ result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt);
+ }
+#else
+ else if (ps_frame_info->recv_error_count <
+ PH_LLCNFC_MAX_REJ_RETRY_COUNT)
+ {
+ PH_LLCNFC_PRINT("CRC ERROR RECVD \n");
+ PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count);
+
+ ps_frame_info->recv_error_count = (uint8_t)
+ (ps_frame_info->recv_error_count + 1);
+
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+
+#ifdef CRC_ERROR_REJ
+
+ /* Send REJ (S frame), as the CRC received has error */
+ result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt);
+
+#endif /* #ifdef CRC_ERROR_REJ */
+
+ }
+ else
+ {
+ result = phLlcNfc_Interface_Read (ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+
+ /* Raise the exception for CRC error received from the */
+ notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_BOARD_COMMUNICATION_ERROR);
+#if 0
+ phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
+#endif /* #if 0 */
+ /* Resend done, no answer from the device */
+ ps_llc_ctxt->cb_for_if.notify (
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ ps_llc_ctxt->phwinfo,
+ NFC_NOTIFY_DEVICE_ERROR,
+ &notifyinfo);
+ }
+
+#endif /* #ifdef LLC_DISABLE_CRC */
+ } /* read more than 1 byte */
+ else if (ps_frame_info->recv_error_count >=
+ PH_LLCNFC_MAX_REJ_RETRY_COUNT)
+ {
+ result = phLlcNfc_Interface_Read (ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+
+ /* Raise the exception for CRC error received from the */
+ notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_BOARD_COMMUNICATION_ERROR);
+#if 0
+ phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
+#endif /* #if 0 */
+ /* Resend done, no answer from the device */
+ ps_llc_ctxt->cb_for_if.notify (
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ ps_llc_ctxt->phwinfo,
+ NFC_NOTIFY_DEVICE_ERROR,
+ &notifyinfo);
+ }
+ else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) &&
+ (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) &&
+ (pCompInfo->length != ps_recv_pkt->s_llcbuf.llc_length_byte))
+ {
+ ps_frame_info->recv_error_count = (uint8_t)
+ (ps_frame_info->recv_error_count + 1);
+
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+
+#ifdef CRC_ERROR_REJ
+
+ /* Send REJ (S frame), as the CRC received has error */
+ result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt);
+
+#endif /* #ifdef CRC_ERROR_REJ */
+ }
+ else if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) &&
+ ((*(pCompInfo->buffer) > (PH_LLCNFC_MAX_BUFLEN_RECV_SEND - 1))
+ ||(*(pCompInfo->buffer) <= (PH_LLCNFC_MIN_BUFLEN_RECVD + 1))))
+ {
+ /* Temporary fix for the 0xFF data received
+ Solution for the read one byte, giving error in buffer
+ PH_LLCNFC_MAX_BUFLEN_RECV_SEND (0x21) is the maximum
+ bytes expected by LLC, if the buffer
+ value is greater than (0x21 - 1), then pend a read to
+ get 1 byte again
+ */
+ ps_frame_info->recv_error_count = (uint8_t)
+ (ps_frame_info->recv_error_count + 1);
+
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+ }
+ else
+ {
+ ps_frame_info->recv_error_count = (uint8_t)
+ (ps_frame_info->recv_error_count + 1);
+
+ phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
+ ps_llc_ctxt->s_timerinfo.guard_to_count);
+ pCompInfo->status = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_INVALID_FORMAT);
+ pCompInfo->buffer = NULL;
+ pCompInfo->length = 0;
+ result = phLlcNfc_Interface_Read(ps_llc_ctxt,
+ PH_LLCNFC_READWAIT_OFF,
+ (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ PH_LLCNFC_BYTES_INIT_READ);
+ if (NULL != ps_llc_ctxt->cb_for_if.receive_complete)
+ {
+ ps_llc_ctxt->cb_for_if.receive_complete(
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+ }
+ else
+ {
+ ps_frame_info->recv_error_count = (uint8_t)
+ (ps_frame_info->recv_error_count + 1);
+
+ phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER,
+ ps_llc_ctxt->s_timerinfo.guard_to_count);
+ PH_LLCNFC_DEBUG("Status Error : 0x%x\n", pCompInfo->status);
+ if (NULL != ps_llc_ctxt->cb_for_if.receive_complete)
+ {
+ ps_llc_ctxt->cb_for_if.receive_complete(
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+ }
+ else
+ {
+ if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo)
+ && (NULL != ps_llc_ctxt->cb_for_if.receive_complete))
+ {
+ ps_llc_ctxt->cb_for_if.receive_complete(
+ ps_llc_ctxt->cb_for_if.pif_ctxt,
+ pHwInfo, pCompInfo);
+ }
+ }
+
+ PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB END\n\n");
+}
+
+void
+phLlcNfc_H_SendInfo (
+ phLlcNfc_Context_t *psLlcCtxt
+ )
+{
+ phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL;
+ phLlcNfc_Frame_t *ps_frame_info = NULL;
+ phNfc_sTransactionInfo_t comp_info;
+
+ ps_frame_info = &(psLlcCtxt->s_frameinfo);
+ ps_recv_pkt = &(ps_frame_info->s_recvpacket);
+
+ if ((ps_recv_pkt->llcbuf_len > 0) &&
+ (ps_recv_pkt->llcbuf_len <= PH_LLCNFC_MAX_LLC_PAYLOAD))
+ {
+ comp_info.status = NFCSTATUS_SUCCESS;
+ /* Chop the extra Llc bytes received */
+#if 0
+ comp_info.length = (ps_recv_pkt->llcbuf_len -
+ PH_LLCNFC_LEN_APPEND);
+#else
+ comp_info.length = (uint16_t)psLlcCtxt->recvbuf_length;
+#endif /* */
+
+ if (0 != comp_info.length)
+ {
+#if 0
+ (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)(
+ ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload),
+ comp_info.length);
+#endif /* #if 0 */
+ comp_info.buffer = psLlcCtxt->precv_buf;
+ }
+ else
+ {
+ comp_info.buffer = NULL;
+ }
+ }
+ else
+ {
+ comp_info.status = PHNFCSTVAL(CID_NFC_LLC,
+ NFCSTATUS_INVALID_FORMAT);
+ comp_info.length = 0;
+ comp_info.buffer = NULL;
+ }
+
+ (void)phLlcNfc_Interface_Read(psLlcCtxt,
+ PH_LLCNFC_READWAIT_OFF,
+ &(ps_recv_pkt->s_llcbuf.llc_length_byte),
+ (uint8_t)PH_LLCNFC_BYTES_INIT_READ);
+
+ if ((NFCSTATUS_SUCCESS == comp_info.status) &&
+ (0 == comp_info.length))
+ {
+ /* May be a NULL I frame received from PN544, so dont do
+ any thing */
+ }
+ else
+ {
+ if ((NULL != psLlcCtxt->cb_for_if.receive_complete) &&
+ (TRUE == ps_frame_info->upper_recv_call))
+ {
+ ps_frame_info->upper_recv_call = FALSE;
+ psLlcCtxt->cb_for_if.receive_complete(
+ psLlcCtxt->cb_for_if.pif_ctxt,
+ psLlcCtxt->phwinfo,
+ &comp_info);
+ }
+ else
+ {
+ if (NULL != psLlcCtxt->cb_for_if.notify)
+ {
+ psLlcCtxt->cb_for_if.notify(
+ psLlcCtxt->cb_for_if.pif_ctxt,
+ psLlcCtxt->phwinfo,
+ NFC_NOTIFY_RECV_COMPLETED,
+ &comp_info);
+ }
+ }
+ }
+ return;
+}
+