| /* |
| * 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_Frame.c |
| * \brief To append the I or S or U frames (LLC header). |
| * |
| * Project: NFC-FRI-1.1 |
| * |
| * $Date: Tue Jun 1 14:41:26 2010 $ |
| * $Author: ing02260 $ |
| * $Revision: 1.88 $ |
| * $Aliases: NFC_FRI1.1_WK1023_R35_1 $ |
| * |
| */ |
| |
| /*************************** Includes *******************************/ |
| #include <phNfcTypes.h> |
| #include <phNfcStatus.h> |
| #include <phOsalNfc.h> |
| #include <phOsalNfc_Timer.h> |
| #include <phNfcInterface.h> |
| #include <phLlcNfc_DataTypes.h> |
| #include <phLlcNfc_Frame.h> |
| #include <phLlcNfc_Interface.h> |
| #include <phLlcNfc_Timer.h> |
| #ifdef ANDROID |
| #include <string.h> |
| #endif |
| |
| /*********************** End of includes ****************************/ |
| |
| /***************************** Macros *******************************/ |
| |
| /************************ End of macros *****************************/ |
| |
| /***************************** Global variables *******************************/ |
| |
| #ifdef LLC_RELEASE_FLAG |
| extern uint8_t g_release_flag; |
| #endif /* #ifdef LLC_RELEASE_FLAG */ |
| /************************ End of global variables *****************************/ |
| |
| /*********************** Local functions ****************************/ |
| static |
| void |
| phLlcNfc_H_UpdateCrc( |
| uint8_t crcByte, |
| uint16_t *pCrc |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>process the received U frame</b> function |
| * |
| * \copydoc page_reg This function is to process the U frame received from |
| * the device |
| * |
| * \param[in] psLlcCtxt Llc main structure information |
| * \param[in] llcPacket LLC packet information, inlcuding length information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| NFCSTATUS |
| phLlcNfc_H_ProcessUFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>process the received S frame</b> function |
| * |
| * \copydoc page_reg This function is to process the S frame received from |
| * the device |
| * |
| * \param[in] psLlcCtxt Llc main structure information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| void |
| phLlcNfc_H_ProcessSFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>Update I frame list</b> function |
| * |
| * \copydoc page_reg This function checks the nr value with the stored I frames |
| * and deletes the nodes which has been acknowledged. |
| * |
| * \param[in/out] psFrameInfo Frame structure information |
| * \param[in/out] psListInfo List information |
| * |
| * \retval number of deleted frames |
| * |
| */ |
| static |
| uint8_t |
| phLlcNfc_H_UpdateIFrameList( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_StoreIFrame_t *psListInfo |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions \b Delete list function |
| * |
| * \copydoc page_reg Delete the front node from the list |
| * |
| * \param[in] psFrameInfo Frame structure information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| void |
| phLlcNfc_H_DeleteIFrame ( |
| phLlcNfc_StoreIFrame_t *psList |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>Get the LLC header</b> function |
| * |
| * \copydoc page_reg This function checks for the correctness fo the llc header |
| * |
| * \param[in] llcHeader The byte which gives the header information |
| * |
| * \retval phLlcNfc_eU_frame U frame type. |
| * \retval phLlcNfc_eI_frame I frame type. |
| * \retval phLlcNfc_eS_frame S frame type. |
| * \retval phLlcNfc_eErr_frame Error type |
| * |
| */ |
| static |
| phLlcNfc_FrameType_t |
| phLlcNfc_H_ChkGetLlcFrameType ( |
| uint8_t llcHeader |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions \b Peek the data function |
| * |
| * \copydoc page_reg Get the packet information from the front node from the list |
| * |
| * \param[in] psListInfo The List information |
| * \param[in] packetinfo The packet information from the front node of the list |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| NFCSTATUS |
| phLlcNfc_H_IFrameList_Peek ( |
| phLlcNfc_StoreIFrame_t *psList, |
| phLlcNfc_LlcPacket_t **psPacketinfo, |
| uint8_t position |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>Update U frame information</b> function |
| * |
| * \copydoc page_reg This function updates the U frame information in the |
| * phLlcNfc_sFrame_t structure |
| * |
| * \param[in/out] psFrameInfo Frame information structure |
| * \param[in] llcPayload Llc payload information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| NFCSTATUS |
| phLlcNfc_H_Update_ReceivedRSETInfo ( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_Payload_t llcInfo |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC Reset frame information function |
| * |
| * \copydoc page_reg resets ns and nr value, when ack for U frame is received |
| * |
| * \param[in, out] psLlcCtxt Llc main structure information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| static |
| void |
| phLlcNfc_H_ResetFrameInfo ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC Reset frame sending function |
| * |
| * \copydoc page_reg Send URSET frame to PN544 |
| * |
| * \param[in, out] psLlcCtxt Llc main structure information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_BUSY Write is pended, so wait till it completes. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| NFCSTATUS |
| phLlcNfc_H_SendRSETFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ); |
| |
| /** |
| * \ingroup grp_hal_nfc_llc_helper |
| * |
| * \brief LLC helper functions <b>process the received I frame</b> function |
| * |
| * \copydoc page_reg This function is to process the I frame received from |
| * the device |
| * |
| * \param[in] psLlcCtxt Llc main structure information |
| * |
| * \retval NFCSTATUS_SUCCESS Operation successful. |
| * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. |
| * |
| */ |
| void |
| phLlcNfc_H_ProcessIFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ); |
| |
| /******************** End of Local functions ************************/ |
| |
| /********************** Global variables ****************************/ |
| |
| /******************** End of Global Variables ***********************/ |
| |
| void phLlcNfc_H_Frame_Init ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| |
| if (NULL != psLlcCtxt) |
| { |
| /* Set all the other values to 0 */ |
| (void)memset (&psLlcCtxt->s_frameinfo.s_llcpacket, 0, |
| sizeof(phLlcNfc_LlcPacket_t)); |
| |
| psLlcCtxt->s_frameinfo.window_size = |
| PH_LLCNFC_U_FRAME_MAX_WIN_SIZE; |
| /* Initialise the window size, N(S) and N(R) */ |
| #ifdef PIGGY_BACK |
| psLlcCtxt->s_frameinfo.s_recv_store.winsize_cnt = 0; |
| #endif |
| psLlcCtxt->s_frameinfo.s_send_store.winsize_cnt = 0; |
| psLlcCtxt->s_frameinfo.n_s = 0; |
| psLlcCtxt->s_frameinfo.n_r = 0; |
| psLlcCtxt->s_frameinfo.rejected_ns = DEFAULT_PACKET_INPUT; |
| } |
| } |
| |
| void |
| phLlcNfc_H_Frame_DeInit ( |
| phLlcNfc_Frame_t *psFrameInfo |
| ) |
| { |
| if (NULL != psFrameInfo) |
| { |
| /* Empty the frame information */ |
| (void)memset(&psFrameInfo->s_llcpacket, 0, |
| sizeof(phLlcNfc_LlcPacket_t)); |
| } |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_CreateUFramePayload ( |
| phLlcNfc_Context_t *psLlcCtxt, |
| phLlcNfc_LlcPacket_t *psLlcPacket, |
| uint8_t *pLlcPacketLength, |
| phLlcNfc_LlcCmd_t cmdType |
| ) |
| { |
| /* |
| U frame packet (RSET) |
| Byte 0 = Length (4 to 6 bytes) |
| Byte 1 = Header |
| Byte 2 = window size (2 >= window size <= 4) |
| Byte 3 = capabilities (SREJ option enable/disable) (optional) |
| Byte 4 = Baud rate (optional) |
| Byte 5 = CRC1 |
| Byte 6 = CRC2 |
| */ |
| NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, |
| NFCSTATUS_INVALID_PARAMETER); |
| phLlcNfc_Buffer_t *ps_llc_buf = NULL; |
| uint8_t index = 0; |
| |
| if ((NULL != psLlcCtxt) && (NULL != psLlcPacket) |
| && (NULL != pLlcPacketLength) && |
| ((phLlcNfc_e_rset == cmdType) || (phLlcNfc_e_ua == cmdType))) |
| { |
| result = NFCSTATUS_SUCCESS; |
| ps_llc_buf = &(psLlcPacket->s_llcbuf); |
| /* Get the header information */ |
| ps_llc_buf->sllcpayload.llcheader = |
| (uint8_t)PH_LLCNFC_U_HEADER_INIT; |
| if (phLlcNfc_e_rset == cmdType) |
| { |
| /* RSET command */ |
| ps_llc_buf->sllcpayload.llcheader = |
| (uint8_t)SET_BITS8( |
| ps_llc_buf->sllcpayload.llcheader, |
| PH_LLCNFC_U_FRAME_START_POS, |
| PH_LLCNFC_U_FRAME_NO_OF_POS, |
| (uint8_t)phLlcNfc_e_rset); |
| /* Default window size */ |
| ps_llc_buf->sllcpayload.llcpayload[index] = |
| PH_LLCNFC_U_FRAME_MAX_WIN_SIZE; |
| index++; |
| /* Endpoint capabilities, SREJ not supported */ |
| ps_llc_buf->sllcpayload.llcpayload[index] = |
| PH_LLCNFC_SREJ_BYTE_VALUE; |
| index++; |
| #ifdef ENABLE_BAUDRATE |
| /* baud rate 0x00 = 9600, 0x05 = 115200 */ |
| ps_llc_buf->sllcpayload.llcpayload[index] = |
| (uint8_t)phLlcNfc_e_115200; |
| index++; |
| #endif /* #ifdef ENABLE_BAUDRATE */ |
| |
| } |
| else |
| { |
| /* UA frame */ |
| ps_llc_buf->sllcpayload.llcheader = (uint8_t) |
| SET_BITS8(ps_llc_buf->sllcpayload.llcheader, |
| PH_LLCNFC_U_FRAME_START_POS, |
| PH_LLCNFC_U_FRAME_NO_OF_POS, |
| (uint8_t)phLlcNfc_e_ua); |
| } |
| /* LLC length byte updated (index + 2 CRC bytes + |
| 1 byte of header) */ |
| ps_llc_buf->llc_length_byte = (index + |
| PH_LLCNFC_NUM_OF_CRC_BYTES + 1); |
| /* Total LLC buffer size */ |
| *pLlcPacketLength = psLlcPacket->llcbuf_len = |
| (ps_llc_buf->llc_length_byte + 1); |
| /* |
| psLlcPacket->s_llcbuf : |
| consists llc length byte + llc header + data + CRC |
| (which needs to be calculated by the below function) |
| psLlcPacket->llcbuf_len : |
| Total length of the above buffer |
| psLlcPacket->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 |
| psLlcPacket->s_llcbuf.sllcpayload.llcpayload : |
| consists only data (no length byte and no llc header) |
| (psLlcPacket->llcbuf_len - 4) : |
| is the array index of the first CRC byte to be calculated |
| (psLlcPacket->llcbuf_len - 3) : |
| is the array index of the second CRC byte to be calculated |
| */ |
| index = psLlcPacket->llcbuf_len; |
| |
| phLlcNfc_H_ComputeCrc((uint8_t *)ps_llc_buf, |
| (psLlcPacket->llcbuf_len - 2), |
| &(ps_llc_buf->sllcpayload.llcpayload[(index - 4)]), |
| &(ps_llc_buf->sllcpayload.llcpayload[(index - 3)])); |
| } |
| |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_CreateSFramePayload ( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_LlcPacket_t *psLlcPacket, |
| phLlcNfc_LlcCmd_t cmdType |
| ) |
| { |
| /* |
| S frame packet (RR or RNR or REJ or SREJ). Total bytes = 4 |
| Byte 0 = Length (Length = 3 always for S frame) |
| Byte 1 = Header |
| Byte 2 = CRC1 |
| Byte 3 = CRC2 |
| */ |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_Buffer_t *ps_llc_buf = NULL; |
| uint8_t length = 0; |
| |
| ps_llc_buf = &(psLlcPacket->s_llcbuf); |
| |
| /* Initial S frame header */ |
| ps_llc_buf->sllcpayload.llcheader = PH_LLCNFC_S_HEADER_INIT; |
| /* Update the N(R) value */ |
| ps_llc_buf->sllcpayload.llcheader = (uint8_t)SET_BITS8( |
| ps_llc_buf->sllcpayload.llcheader, |
| PH_LLCNFC_NR_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS, |
| psFrameInfo->n_r); |
| |
| /* Update the type bits of S frame */ |
| ps_llc_buf->sllcpayload.llcheader = (uint8_t) |
| (ps_llc_buf->sllcpayload.llcheader | (uint8_t)cmdType); |
| |
| /* Maximum S frame length */ |
| psLlcPacket->llcbuf_len = (uint8_t)PH_LLCNFC_MAX_S_FRAME_LEN; |
| /* S frame length byte value */ |
| ps_llc_buf->llc_length_byte = (uint8_t) |
| (psLlcPacket->llcbuf_len - 1); |
| |
| /* |
| psFrameInfo->s_llcpacket.s_llcbuf : |
| consists llc length byte + llc header + data + CRC |
| (which needs to be calculated by the below function) |
| psFrameInfo->s_llcpacket.llcbuf_len : |
| Total length of the above buffer |
| psFrameInfo->s_llcpacket.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 |
| psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : |
| consists only data (no length byte and no llc header) |
| psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : |
| contains only data sent by user. |
| (psFrameInfo->s_llcpacket.llcbuf_len - 4) : |
| is the array index of the first CRC byte to be calculated |
| (psFrameInfo->s_llcpacket.llcbuf_len - 3) : |
| is the array index of the second CRC byte to be calculated |
| */ |
| length = psLlcPacket->llcbuf_len; |
| phLlcNfc_H_ComputeCrc( |
| (uint8_t *)ps_llc_buf, (length - 2), |
| &(ps_llc_buf->sllcpayload.llcpayload[(length - 4)]), |
| &(ps_llc_buf->sllcpayload.llcpayload[(length - 3)])); |
| |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_CreateIFramePayload ( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_LlcPacket_t *psLlcPacket, |
| uint8_t *pLlcBuf, |
| uint8_t llcBufLength |
| ) |
| { |
| NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, |
| NFCSTATUS_INVALID_PARAMETER); |
| phLlcNfc_Buffer_t *ps_llc_buf = NULL; |
| |
| if ((NULL != psFrameInfo) && (NULL != psLlcPacket) && |
| (NULL != pLlcBuf) && (llcBufLength > 0)) |
| { |
| result = NFCSTATUS_SUCCESS; |
| ps_llc_buf = &(psLlcPacket->s_llcbuf); |
| |
| (void)memcpy(&(ps_llc_buf->sllcpayload.llcpayload[0]), |
| pLlcBuf, llcBufLength); |
| |
| psLlcPacket->llcbuf_len = (uint8_t)llcBufLength; |
| |
| /* I frame header byte */ |
| ps_llc_buf->sllcpayload.llcheader = PH_LLCNFC_I_HEADER_INIT; |
| |
| /* Set the N(S) value */ |
| ps_llc_buf->sllcpayload.llcheader = (uint8_t) |
| SET_BITS8( |
| ps_llc_buf->sllcpayload.llcheader, |
| PH_LLCNFC_NS_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS, |
| psFrameInfo->n_s); |
| |
| /* Set the N(R) value */ |
| ps_llc_buf->sllcpayload.llcheader = (uint8_t) |
| SET_BITS8( |
| ps_llc_buf->sllcpayload.llcheader, |
| PH_LLCNFC_NR_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS, |
| psFrameInfo->n_r); |
| |
| /* Update the length byte, llc length byte value includes |
| data + CRC bytes + llc length byte */ |
| ps_llc_buf->llc_length_byte = |
| (psLlcPacket->llcbuf_len + |
| PH_LLCNFC_NUM_OF_CRC_BYTES + 1); |
| |
| /* Update total length, Total length is always equal to |
| llc length byte + 1 */ |
| psLlcPacket->llcbuf_len = |
| (ps_llc_buf->llc_length_byte + 1); |
| |
| /* |
| psFrameInfo->s_llcpacket.s_llcbuf : |
| consists llc length byte + llc header + data + CRC (which |
| needs to be calculated by the below function) |
| psFrameInfo->s_llcpacket.llcbuf_len : |
| Total length of the above buffer |
| psFrameInfo->s_llcpacket.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 |
| psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : |
| contains only data sent by user. |
| (psFrameInfo->s_llcpacket.llcbuf_len - 4) : |
| is the array index of the first CRC byte to be calculated |
| (psFrameInfo->s_llcpacket.llcbuf_len - 3) : |
| is the array index of the second CRC byte to be calculated |
| |
| */ |
| phLlcNfc_H_ComputeCrc( |
| (uint8_t*)ps_llc_buf, |
| (psLlcPacket->llcbuf_len - 2), |
| &(ps_llc_buf->sllcpayload.llcpayload |
| [(psLlcPacket->llcbuf_len - 4)]), |
| &(ps_llc_buf->sllcpayload.llcpayload |
| [(psLlcPacket->llcbuf_len - 3)])); |
| |
| |
| } |
| |
| return result; |
| } |
| |
| static |
| phLlcNfc_FrameType_t |
| phLlcNfc_H_ChkGetLlcFrameType ( |
| uint8_t llcHeader |
| ) |
| { |
| phLlcNfc_FrameType_t frame_type = phLlcNfc_eErr_frame; |
| |
| /* Mask the header byte to know the actual frame types */ |
| switch((llcHeader & PH_LLCNFC_LLC_HEADER_MASK)) |
| { |
| case PH_LLCNFC_U_HEADER_INIT: |
| { |
| frame_type = phLlcNfc_eU_frame; |
| break; |
| } |
| |
| case PH_LLCNFC_S_HEADER_INIT: |
| { |
| frame_type = phLlcNfc_eS_frame; |
| break; |
| } |
| |
| default: |
| { |
| if (PH_LLCNFC_I_HEADER_INIT == |
| (PH_LLCNFC_I_FRM_HEADER_MASK & llcHeader)) |
| { |
| frame_type = phLlcNfc_eI_frame; |
| } |
| else |
| { |
| frame_type = phLlcNfc_eErr_frame; |
| } |
| break; |
| } |
| } |
| return frame_type; |
| } |
| |
| static |
| NFCSTATUS |
| phLlcNfc_H_Update_ReceivedRSETInfo ( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_Payload_t llcInfo |
| ) |
| { |
| NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); |
| uint8_t payload_index = 0; |
| |
| if ((llcInfo.llcpayload[payload_index] >= PH_LLCNFC_U_FRAME_MIN_WIN_SIZE) && |
| (llcInfo.llcpayload[payload_index] <= PH_LLCNFC_U_FRAME_MAX_WIN_SIZE)) |
| { |
| result = NFCSTATUS_SUCCESS; |
| /* From the received buffer, get the window size from the |
| 3rd byte (recvUBufLen[3]) of the buffer */ |
| psFrameInfo->window_size = llcInfo.llcpayload[payload_index]; |
| payload_index = (uint8_t)(payload_index + 1); |
| |
| /* If 4th byte of the receive buffer (pRecvUBuf[4]) is |
| 0x01 then SREJ can come from the device*/ |
| psFrameInfo->srej_on_off = ((PH_LLCNFC_SREJ_BYTE_VALUE == |
| llcInfo.llcpayload[payload_index])? |
| PH_LLCNFC_SREJ_BYTE_VALUE:0); |
| |
| /* For present implementation, this should be always false |
| later stage remove if statement to work */ |
| if (PH_LLCNFC_SREJ_BYTE_VALUE != psFrameInfo->srej_on_off) |
| { |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); |
| } |
| else |
| { |
| payload_index = (uint8_t)(payload_index + 1); |
| |
| |
| if (llcInfo.llcpayload[payload_index] > |
| (uint8_t)phLlcNfc_e_1228000) |
| { |
| /* Error byte */ |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); |
| } |
| else |
| { |
| /* Get the baud rate from the 5th byte of the receive buffer */ |
| psFrameInfo->baud_rate = (phLlcNfc_LlcBaudRate_t) |
| (llcInfo.llcpayload[payload_index]); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| static |
| uint8_t |
| phLlcNfc_H_UpdateIFrameList( |
| phLlcNfc_Frame_t *psFrameInfo, |
| phLlcNfc_StoreIFrame_t *psListInfo |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_LlcPacket_t *pspktInfo = NULL; |
| uint8_t while_exit = FALSE; |
| uint8_t nr = 0; |
| uint8_t ns = 0; |
| uint8_t no_of_del_frames = 0; |
| |
| PHNFC_UNUSED_VARIABLE(result); |
| if(0 == psListInfo->winsize_cnt) |
| { |
| while_exit = TRUE; |
| } |
| while (FALSE == while_exit) |
| { |
| /* Get the first node from the list */ |
| result = phLlcNfc_H_IFrameList_Peek (psListInfo, &pspktInfo, |
| DEFAULT_PACKET_INPUT); |
| if (NULL != pspktInfo) |
| { |
| /* Get the N(R) value of the received packet and N(S) value of the |
| sent stored i frame */ |
| ns = (uint8_t)GET_BITS8 ( |
| pspktInfo->s_llcbuf.sllcpayload.llcheader, |
| PH_LLCNFC_NS_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS); |
| |
| nr = (uint8_t)GET_BITS8( |
| psFrameInfo->s_recvpacket.s_llcbuf.sllcpayload.llcheader, |
| PH_LLCNFC_NR_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS); |
| |
| /* Check the value of each i frame N(S) and |
| received ACKs N(R) */ |
| #if 0 |
| if(((ns <= nr) && ((nr - ns) <= psFrameInfo->window_size)) |
| || ((ns > nr) && (((PH_LLCNFC_MOD_NS_NR + nr) - ns) <= |
| PH_LLCNFC_U_FRAME_MAX_WIN_SIZE))) |
| #endif |
| if(((ns < nr) && ((nr - ns) <= psFrameInfo->window_size)) |
| || ((ns > nr) && (((PH_LLCNFC_MOD_NS_NR + nr) - ns) <= |
| PH_LLCNFC_U_FRAME_MAX_WIN_SIZE))) |
| { |
| phLlcNfc_H_DeleteIFrame (psListInfo); |
| no_of_del_frames = (uint8_t)(no_of_del_frames + 1); |
| } |
| else |
| { |
| while_exit = TRUE; |
| } |
| |
| if(0 == psListInfo->winsize_cnt) |
| { |
| while_exit = TRUE; |
| } |
| } |
| else |
| { |
| while_exit = TRUE; |
| } |
| } |
| return no_of_del_frames; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_SendUserIFrame ( |
| phLlcNfc_Context_t *psLlcCtxt, |
| phLlcNfc_StoreIFrame_t *psListInfo |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_LlcPacket_t s_create_packet; |
| phLlcNfc_LlcPacket_t *ps_get_packet = NULL; |
| phLlcNfc_Payload_t *ps_llc_payload = NULL; |
| phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
| uint8_t llc_header = 0, |
| length = 0; |
| |
| if ((NULL == psLlcCtxt) || (NULL == psListInfo)) |
| { |
| result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else if (0 == psListInfo->winsize_cnt) |
| { |
| result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); |
| } |
| else |
| { |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_store_frame = &(ps_frame_info->s_send_store); |
| |
| if ( |
| (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) |
| ) |
| { |
| /* Get the stored I frame, only if the new frame is sent |
| from the upper layer */ |
| result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, |
| ps_frame_info->n_s); |
| } |
| |
| if (NULL != ps_get_packet) |
| { |
| llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; |
| |
| /* Update n(r) value for the header */ |
| llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); |
| |
| /* Create the packet */ |
| (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, |
| sizeof (phLlcNfc_LlcPacket_t)); |
| |
| s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; |
| ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); |
| |
| /* Length of the complete llc buffer, sent to PN544 */ |
| length = s_create_packet.llcbuf_len; |
| |
| /* Compute CRC for the created packet */ |
| phLlcNfc_H_ComputeCrc ((uint8_t *)&(s_create_packet.s_llcbuf), |
| (length - 2), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); |
| |
| /* Send the i frame */ |
| result = phLlcNfc_Interface_Write (psLlcCtxt, |
| (uint8_t *)&(s_create_packet.s_llcbuf), |
| (uint32_t)s_create_packet.llcbuf_len); |
| |
| ps_frame_info->write_status = result; |
| |
| if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) |
| { |
| /* The below check is added because, write is already pended by some other |
| operation, so it has to complete, when it completes, then immediately |
| next write shall be called using the below updated variable |
| |
| The below variable is checked for the resend or rejected i frame |
| because if due to timer or reject frame from PN544, an I frame |
| has been sent (means write has been pended then the variable shall |
| not be overwritten. |
| */ |
| ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) |
| (((resend_i_frame == ps_frame_info->write_wait_call) || |
| (rejected_i_frame == ps_frame_info->write_wait_call)) ? |
| ps_frame_info->write_wait_call : user_i_frame); |
| } |
| else |
| { |
| if (NFCSTATUS_PENDING == result) |
| { |
| /* 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; |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_SendRejectedIFrame ( |
| phLlcNfc_Context_t *psLlcCtxt, |
| phLlcNfc_StoreIFrame_t *psListInfo, |
| uint8_t ns_rejected |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_LlcPacket_t s_create_packet; |
| phLlcNfc_LlcPacket_t *ps_get_packet = NULL; |
| phLlcNfc_Payload_t *ps_llc_payload = NULL; |
| phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
| uint8_t llc_header = 0; |
| uint8_t length = 0; |
| |
| if ((NULL == psLlcCtxt) || (NULL == psListInfo)) |
| { |
| result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else if (0 == psListInfo->winsize_cnt) |
| { |
| result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); |
| } |
| else |
| { |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_store_frame = &(ps_frame_info->s_send_store); |
| |
| |
| if (ns_rejected < (uint8_t)(ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos)) |
| { |
| /* To send rejected frame, first thing shall be done is |
| windows size count shall be checked. if the |
| start position |
| */ |
| if (invalid_frame != |
| ps_store_frame->s_llcpacket[ns_rejected].frame_to_send) |
| { |
| /* Above check is added to know only if */ |
| result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, |
| ns_rejected); |
| } |
| else |
| { |
| ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; |
| /* Get the stored I frame, only if the new frame is sent |
| from the upper layer */ |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, psListInfo); |
| } |
| } |
| |
| if (NULL != ps_get_packet) |
| { |
| llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; |
| |
| /* Update n(r) value for the header */ |
| llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); |
| |
| /* Create the packet */ |
| (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, |
| sizeof (phLlcNfc_LlcPacket_t)); |
| |
| s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; |
| ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); |
| |
| /* Length of the complete llc buffer, sent to PN544 */ |
| length = s_create_packet.llcbuf_len; |
| |
| /* Compute CRC for the created packet */ |
| phLlcNfc_H_ComputeCrc ((uint8_t *)&(s_create_packet.s_llcbuf), |
| (length - 2), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); |
| |
| /* Send the i frame */ |
| result = phLlcNfc_Interface_Write (psLlcCtxt, |
| (uint8_t *)&(s_create_packet.s_llcbuf), |
| (uint32_t)s_create_packet.llcbuf_len); |
| |
| ps_frame_info->write_status = result; |
| |
| if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) |
| { |
| /* Already a frame is sent and response is waited for the sent frame, |
| so update the below variable */ |
| ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) |
| (((ns_rejected != ps_store_frame->start_pos) && |
| (resend_i_frame != ps_frame_info->write_wait_call))? |
| rejected_i_frame : ps_frame_info->write_wait_call); |
| } |
| else |
| { |
| /* NFCSTATUS_PENDING means that the no other write is pending, apart |
| from the present write |
| |
| Start the timer */ |
| (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, ns_rejected); |
| |
| /* "sent_frame_type is updated" only if the data is |
| written to the lower layer. This will be used in the write |
| response callback and also indicates, what is the frame sent |
| and why |
| */ |
| ps_frame_info->sent_frame_type = rejected_i_frame; |
| |
| if ((ns_rejected + 1) < ps_frame_info->n_s) |
| { |
| ps_frame_info->rejected_ns = (uint8_t)(ns_rejected + 1); |
| |
| ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, |
| NFCSTATUS_BUSY); |
| |
| if (invalid_frame == |
| ps_store_frame->s_llcpacket[ns_rejected].frame_to_send) |
| { |
| ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; |
| ps_frame_info->write_wait_call = user_i_frame; |
| } |
| else |
| { |
| ps_frame_info->write_wait_call = rejected_i_frame; |
| } |
| } |
| else |
| { |
| ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; |
| /* This check is added to see that new frame has arrived |
| from the upper layer */ |
| if (ps_frame_info->n_s < (ps_store_frame->start_pos + |
| ps_store_frame->winsize_cnt)) |
| { |
| ps_frame_info->write_wait_call = user_i_frame; |
| } |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_SendTimedOutIFrame ( |
| phLlcNfc_Context_t *psLlcCtxt, |
| phLlcNfc_StoreIFrame_t *psListInfo, |
| uint8_t frame_to_send |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_Timerinfo_t *ps_timer_info = NULL; |
| phLlcNfc_LlcPacket_t s_create_packet; |
| phLlcNfc_LlcPacket_t *ps_get_packet = NULL; |
| phLlcNfc_Payload_t *ps_llc_payload = NULL; |
| phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
| |
| PHNFC_UNUSED_VARIABLE(frame_to_send); |
| if((NULL == psLlcCtxt) || (NULL == psListInfo)) |
| { |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else if (psListInfo->winsize_cnt == 0) |
| { |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); |
| } |
| else |
| { |
| uint8_t llc_header = 0; |
| uint8_t length = 0; |
| uint8_t timer_count = 0; |
| uint8_t timer_index = 0; |
| uint8_t ns_index = 0; |
| |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_timer_info = &(psLlcCtxt->s_timerinfo); |
| ps_store_frame = &(ps_frame_info->s_send_store); |
| |
| timer_index = ps_timer_info->index_to_send; |
| timer_count = ps_timer_info->guard_to_count; |
| ns_index = ps_timer_info->timer_ns_value[timer_index]; |
| |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL WIN SIZE CNT : 0x%02X\n", ps_store_frame->winsize_cnt); |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL START POS : 0x%02X\n", ps_store_frame->start_pos); |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL N S value : 0x%02X\n", ps_frame_info->n_s); |
| PH_LLCNFC_DEBUG("SEND TIMEOUT TIMER INDEX : 0x%02X\n", timer_index); |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL frame type : 0x%02X\n", ps_timer_info->frame_type[timer_index]); |
| |
| if (resend_i_frame == ps_timer_info->frame_type[timer_index]) |
| { |
| /* Get the stored I frame */ |
| result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, |
| ns_index); |
| } |
| |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Packet : 0x%p\n", ps_get_packet); |
| if (NULL != ps_get_packet) |
| { |
| llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; |
| |
| /* Update n(r) value for the header */ |
| llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); |
| |
| /* create the packet */ |
| (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, |
| sizeof (phLlcNfc_LlcPacket_t)); |
| |
| s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; |
| ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); |
| |
| /* Length of the complete llc buffer, sent to PN544 */ |
| length = s_create_packet.llcbuf_len; |
| |
| /* Compute CRC */ |
| phLlcNfc_H_ComputeCrc((uint8_t *)&(s_create_packet.s_llcbuf), |
| (length - 2), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), |
| (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); |
| |
| /* Send the i frame */ |
| result = phLlcNfc_Interface_Write (psLlcCtxt, |
| (uint8_t *)&(s_create_packet.s_llcbuf), |
| (uint32_t)s_create_packet.llcbuf_len); |
| |
| ps_frame_info->write_status = result; |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Write status : 0x%02X\n", result); |
| |
| if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) |
| { |
| ps_frame_info->write_wait_call = resend_i_frame; |
| } |
| else |
| { |
| /* result = NFCSTATUS_PENDING and |
| Timer is not started because the remaining timer |
| will be running */ |
| uint16_t time_out_value = 0; |
| |
| /* Each frame has the send count, so increment this |
| as soon as the frame is sent */ |
| ps_timer_info->iframe_send_count[timer_index] = (uint8_t) |
| (ps_timer_info->iframe_send_count[timer_index] + 1); |
| |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL timer index : 0x%02X\n", timer_index); |
| |
| if (timer_index > 0) |
| { |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL GUARD TO VALUE : 0x%02X\n", ps_timer_info->guard_to_value[(timer_index - 1)]); |
| /* Copy the maximum time-out value. */ |
| time_out_value = (uint16_t) |
| ((ps_timer_info->guard_to_value[(timer_index - 1)] >= |
| PH_LLCNFC_GUARD_TO_VALUE) ? |
| (ps_timer_info->guard_to_value[(timer_index - 1)] + |
| PH_LLCNFC_RESOLUTION): |
| PH_LLCNFC_GUARD_TO_VALUE); |
| } |
| else |
| { |
| /* If the timer_index is 0 means, the previous timed out |
| frame is the last frame in the list */ |
| time_out_value = (uint16_t) |
| ((ps_timer_info->guard_to_value[(timer_count - 1)] >= |
| PH_LLCNFC_GUARD_TO_VALUE) ? |
| (ps_timer_info->guard_to_value[(timer_count - 1)] + |
| PH_LLCNFC_RESOLUTION): |
| PH_LLCNFC_GUARD_TO_VALUE); |
| } |
| |
| ps_timer_info->guard_to_value[timer_index] = time_out_value; |
| |
| ps_frame_info->sent_frame_type = resend_i_frame; |
| |
| ps_timer_info->frame_type[timer_index] = invalid_frame; |
| |
| PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Next frame type : 0x%02X\n", ps_timer_info->frame_type[((timer_index + 1) % PH_LLCNFC_MAX_ACK_GUARD_TIMER)]); |
| /* Now check if next timer has expired, if yes, |
| set the index to next, on receiving the write response |
| callback for this send, then next frame can be sent */ |
| if (resend_i_frame == |
| ps_timer_info->frame_type[((timer_index + 1) % |
| PH_LLCNFC_MAX_ACK_GUARD_TIMER)]) |
| { |
| /* If next frame has to be sent, then update write wait */ |
| ps_frame_info->write_status = NFCSTATUS_BUSY; |
| ps_frame_info->write_wait_call = resend_i_frame; |
| ps_timer_info->index_to_send = (uint8_t) |
| ((timer_index + 1) % |
| PH_LLCNFC_MAX_ACK_GUARD_TIMER); |
| } |
| else |
| { |
| /* Timer is not expired, |
| Now, Check if the new frame is ready to be sent, if yes, |
| then update the variable */ |
| if ( |
| (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) |
| ) |
| { |
| ps_frame_info->write_status = PHNFCSTVAL (CID_NFC_LLC, |
| NFCSTATUS_BUSY); |
| ps_frame_info->write_wait_call = user_i_frame; |
| } |
| } |
| |
| #if 0 |
| result = phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, |
| ((llc_header >> |
| PH_LLCNFC_NS_START_BIT_POS) | |
| MAX_NS_NR_VALUE)); |
| #endif /* #if 0 */ |
| |
| } |
| } |
| else |
| { |
| if ( |
| (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) |
| ) |
| { |
| ps_frame_info->write_status = PHNFCSTVAL (CID_NFC_LLC, |
| NFCSTATUS_BUSY); |
| ps_frame_info->write_wait_call = user_i_frame; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| |
| void |
| phLlcNfc_H_ProcessIFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| uint8_t ns_index = 0; |
| #if defined (LLC_SEND_RR_ACK) |
| /* uint8_t nr_index = 0; */ |
| #endif /* #if defined (LLC_SEND_RR_ACK) */ |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
| phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; |
| phLlcNfc_LlcCmd_t cmdtype = phLlcNfc_e_error; |
| phLlcNfc_eSentFrameType_t eframe_type = invalid_frame; |
| uint8_t dont_send_s_frame = FALSE; |
| uint8_t no_of_del_frames = 0; |
| phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; |
| |
| #ifdef RECV_NR_CHECK_ENABLE |
| uint8_t recvd_nr = 0; |
| #endif /* #ifdef RECV_NR_CHECK_ENABLE */ |
| |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_store_frame = &(ps_frame_info->s_send_store); |
| ps_recv_pkt = &(ps_frame_info->s_recvpacket); |
| |
| PHNFC_UNUSED_VARIABLE(result); |
| /* Received buffer, N(S) value */ |
| ns_index = (uint8_t)GET_BITS8( |
| ps_recv_pkt->s_llcbuf.sllcpayload.llcheader, |
| PH_LLCNFC_NS_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS); |
| |
| PH_LLCNFC_DEBUG("NS START POS BEFORE DEL : 0x%02X\n", ps_store_frame->start_pos); |
| PH_LLCNFC_DEBUG("WIN SIZE BEFORE DEL : 0x%02X\n", ps_store_frame->winsize_cnt); |
| |
| /* Correct frame is received, so remove the stored i frame info */ |
| no_of_del_frames = phLlcNfc_H_UpdateIFrameList (ps_frame_info, |
| &(ps_frame_info->s_send_store)); |
| |
| PH_LLCNFC_DEBUG("NS START POS AFTER DEL : 0x%02X\n", ps_store_frame->start_pos); |
| PH_LLCNFC_DEBUG("WIN SIZE AFTER DEL : 0x%02X\n", ps_store_frame->winsize_cnt); |
| |
| #ifdef RECV_NR_CHECK_ENABLE |
| |
| recvd_nr = (uint8_t)GET_BITS8( |
| ps_recv_pkt->s_llcbuf.sllcpayload.llcheader, |
| PH_LLCNFC_NR_START_BIT_POS, |
| PH_LLCNFC_NR_NS_NO_OF_BITS); |
| |
| if (((ps_frame_info->n_s > recvd_nr) && |
| (0 == ((ps_frame_info->n_s + 1) % PH_LLCNFC_MOD_NS_NR))) |
| || (recvd_nr > ps_frame_info->n_s)) |
| |
| #else /* #ifdef RECV_NR_CHECK_ENABLE */ |
| |
| if (no_of_del_frames > 0) |
| |
| #endif /* #ifdef RECV_NR_CHECK_ENABLE */ |
| { |
| phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); |
| } |
| |
| /* Received buffer, N(S) value = N(R) of host (our |
| structure) then send RR type of s frame else send |
| REJ type of s frame */ |
| if ((ns_index == ps_frame_info->n_r) |
| #if defined (LLC_SEND_RR_ACK) |
| |
| || ((ns_index < ps_frame_info->n_r) && |
| ((ps_frame_info->n_r - ns_index) < ps_frame_info->window_size)) |
| || ((ns_index > ps_frame_info->n_r) && |
| ((ns_index - ps_frame_info->n_r) > ps_frame_info->window_size)) |
| |
| #endif /* #if defined (LLC_SEND_RR_ACK) */ |
| ) |
| { |
| PH_LLCNFC_PRINT(" Type bits of S frame to be sent is RR \n"); |
| ps_frame_info->recv_error_count = 0; |
| ps_frame_info->send_error_count = 0; |
| |
| psLlcCtxt->recvbuf_length = (ps_recv_pkt->llcbuf_len - |
| PH_LLCNFC_LEN_APPEND); |
| |
| (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)( |
| ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload), |
| psLlcCtxt->recvbuf_length); |
| |
| #if defined (LLC_SEND_RR_ACK) |
| |
| if (((ns_index < ps_frame_info->n_r) && |
| ((ps_frame_info->n_r - ns_index) < ps_frame_info->window_size)) |
| || ((ns_index > ps_frame_info->n_r) && |
| ((ns_index - ps_frame_info->n_r) > ps_frame_info->window_size))) |
| { |
| ps_frame_info->n_r = ((ns_index + 1) |
| % PH_LLCNFC_MOD_NS_NR); |
| } |
| else |
| |
| #endif /* #if defined (LLC_SEND_RR_ACK) */ |
| { |
| /* Update the N(R) value in I and S frame context */ |
| ps_frame_info->n_r = ((ps_frame_info->n_r + 1) |
| % PH_LLCNFC_MOD_NS_NR); |
| |
| #ifdef PIGGY_BACK |
| ps_frame_info->resp_recvd_count = (uint8_t) |
| (ps_frame_info->resp_recvd_count + 1); |
| #endif /* #ifdef PIGGY_BACK */ |
| |
| } |
| |
| if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status)) |
| { |
| /* Any how write cannot be done and some frame is ready to be sent |
| so this frame will act as the ACK */ |
| result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); |
| } |
| else |
| { |
| if ( |
| (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) |
| ) |
| { |
| /* If user has sent a frame and DAL write is busy, then |
| it has to be sent */ |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); |
| } |
| } |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| dont_send_s_frame = TRUE; |
| #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB |
| phLlcNfc_H_SendInfo (psLlcCtxt); |
| #endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ |
| } |
| else |
| { |
| cmdtype = phLlcNfc_e_rr; |
| /* If i frame is sent from the stored list, it got the correct |
| acknowledge i frame, so now for an i frame , s frame acknowledge |
| is sent */ |
| eframe_type = ((resend_i_frame == ps_frame_info->sent_frame_type)? |
| resend_s_frame : s_frame); |
| } |
| |
| #ifdef PIGGY_BACK |
| phLlcNfc_H_SendInfo (psLlcCtxt); |
| #endif /* #ifdef PIGGY_BACK */ |
| |
| } |
| else |
| { |
| ps_frame_info->send_error_count = (uint8_t) |
| (ps_frame_info->send_error_count + 1); |
| |
| #ifdef LLC_SEND_ERROR_COUNT |
| |
| if (ps_frame_info->send_error_count < RECV_ERROR_FRAME_COUNT) |
| |
| #endif /* #ifdef LLC_SEND_ERROR_COUNT */ |
| { |
| |
| #ifdef LLC_RR_INSTEAD_OF_REJ |
| |
| if (((ps_frame_info->n_r > 0) && (ns_index == (ps_frame_info->n_r - 1))) |
| || ((0 == ps_frame_info->n_r) && |
| (ns_index == (PH_LLCNFC_MOD_NS_NR - 1)))) |
| { |
| cmdtype = phLlcNfc_e_rr; |
| eframe_type = rej_rr_s_frame; |
| } |
| else |
| |
| #endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */ |
| { |
| cmdtype = phLlcNfc_e_rej; |
| eframe_type = ((resend_i_frame == ps_frame_info->sent_frame_type)? |
| resend_rej_s_frame : reject_s_frame); |
| } |
| } |
| |
| #ifdef LLC_SEND_ERROR_COUNT |
| else |
| { |
| #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION |
| |
| result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); |
| |
| #else /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ |
| |
| dont_send_s_frame = TRUE; |
| PH_LLCNFC_DEBUG("SEND ERROR COUNT : 0x%02X\n", ps_frame_info->send_error_count); |
| /* Error count has reached the limit, raise exception */ |
| 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 */ |
| psLlcCtxt->cb_for_if.notify ( |
| psLlcCtxt->cb_for_if.pif_ctxt, |
| psLlcCtxt->phwinfo, |
| NFC_NOTIFY_DEVICE_ERROR, |
| ¬ifyinfo); |
| |
| #endif /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ |
| } |
| #endif /* #ifdef LLC_SEND_ERROR_COUNT */ |
| } |
| |
| #ifdef LLC_RELEASE_FLAG |
| |
| if (FALSE == g_release_flag) |
| |
| #endif /* #ifdef LLC_RELEASE_FLAG */ |
| { |
| (void)phLlcNfc_Interface_Read(psLlcCtxt, |
| PH_LLCNFC_READWAIT_OFF, |
| &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| |
| #ifdef PIGGY_BACK |
| /* Check if any write call is performed or not */ |
| if (NFCSTATUS_PENDING != result) |
| { |
| /* No write is performed, So, now check */ |
| if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status)) |
| { |
| /* Any how write cannot be done and some frame is ready to be sent |
| so this frame will act as the ACK */ |
| result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); |
| } |
| } |
| |
| if (NFCSTATUS_PENDING != result) |
| { |
| if (ps_frame_info->window_size == ps_frame_info->resp_recvd_count) |
| { |
| phLlcNfc_LlcPacket_t s_packet_info; |
| /* Create S frame */ |
| (void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), cmdtype); |
| |
| result = phLlcNfc_Interface_Write(psLlcCtxt, |
| (uint8_t *)&(s_packet_info.s_llcbuf), |
| (uint32_t)(s_packet_info.llcbuf_len)); |
| |
| |
| if (0 == ps_frame_info->send_error_count) |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| } |
| ps_frame_info->sent_frame_type = eframe_type; |
| } |
| else |
| { |
| result = phLlcNfc_StartTimers (PH_LLCNFC_ACKTIMER, 0); |
| } |
| } |
| #else /* #ifdef PIGGY_BACK */ |
| |
| if ((TRUE != ps_frame_info->write_pending) && |
| (PH_LLCNFC_READPEND_REMAIN_BYTE != ps_frame_info->read_pending) && |
| (FALSE == dont_send_s_frame)) |
| { |
| phLlcNfc_LlcPacket_t s_packet_info = {0}; |
| /* Create S frame */ |
| (void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), cmdtype); |
| |
| result = phLlcNfc_Interface_Write(psLlcCtxt, |
| (uint8_t *)&(s_packet_info.s_llcbuf), |
| (uint32_t)(s_packet_info.llcbuf_len)); |
| |
| |
| if (0 == ps_frame_info->send_error_count) |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| } |
| ps_frame_info->sent_frame_type = eframe_type; |
| } |
| #endif /* #ifdef PIGGY_BACK */ |
| } |
| |
| return ; |
| } |
| |
| static |
| NFCSTATUS |
| phLlcNfc_H_ProcessUFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_LlcPacket_t *ps_uframe_pkt = NULL; |
| #ifdef LLC_URSET_NO_DELAY |
| phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; |
| #else /* #ifdef LLC_URSET_NO_DELAY */ |
| uint32_t delay_timer_id = |
| PH_OSALNFC_INVALID_TIMER_ID; |
| #endif /* #ifdef LLC_URSET_NO_DELAY */ |
| uint8_t cmdtype = phLlcNfc_e_error; |
| |
| phLlcNfc_StopTimers(PH_LLCNFC_CONNECTIONTIMER, 0); |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_uframe_pkt = &(ps_frame_info->s_recvpacket); |
| /* Check the command type */ |
| cmdtype = (ps_uframe_pkt->s_llcbuf.sllcpayload.llcheader & |
| PH_LLCNFC_U_FRAME_MODIFIER_MASK); |
| PHNFC_UNUSED_VARIABLE(result); |
| switch(cmdtype) |
| { |
| case phLlcNfc_e_rset: |
| { |
| psLlcCtxt->s_frameinfo.rset_recvd = TRUE; |
| /* command type is RSET, so update the U frame parameters */ |
| result = phLlcNfc_H_Update_ReceivedRSETInfo (ps_frame_info, |
| ps_uframe_pkt->s_llcbuf.sllcpayload); |
| /* Create a UA frame */ |
| result = phLlcNfc_H_CreateUFramePayload(psLlcCtxt, |
| ps_uframe_pkt, |
| &(ps_uframe_pkt->llcbuf_len), |
| phLlcNfc_e_ua); |
| |
| if (NFCSTATUS_SUCCESS == result) |
| { |
| /* Call DAL write */ |
| result = phLlcNfc_Interface_Write( psLlcCtxt, |
| (uint8_t*)&(ps_uframe_pkt->s_llcbuf), |
| (uint32_t)ps_uframe_pkt->llcbuf_len); |
| |
| phLlcNfc_H_ResetFrameInfo(psLlcCtxt); |
| ps_frame_info->write_status = result; |
| ps_frame_info->write_wait_call = invalid_frame; |
| if (NFCSTATUS_PENDING == result) |
| { |
| ps_frame_info->sent_frame_type = |
| ((ps_frame_info->sent_frame_type != init_u_rset_frame) ? |
| u_a_frame : init_u_a_frame); |
| } |
| else |
| { |
| if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) |
| { |
| ps_frame_info->write_wait_call = |
| ((ps_frame_info->sent_frame_type != init_u_rset_frame) ? |
| u_a_frame : init_u_a_frame); |
| result = NFCSTATUS_PENDING; |
| } |
| } |
| } |
| break; |
| } |
| case phLlcNfc_e_ua: |
| { |
| phLlcNfc_H_ResetFrameInfo (psLlcCtxt); |
| /* Add timer here, to delay the next command to the PN544 */ |
| #ifdef LLC_URSET_NO_DELAY |
| if (ps_frame_info->s_send_store.winsize_cnt > 0) |
| { |
| #if 0 |
| /* Resend I frame */ |
| result = phLlcNfc_H_SendTimedOutIFrame (psLlcCtxt, |
| &(ps_frame_info->s_send_store, 0); |
| #else |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, |
| &(ps_frame_info->s_send_store)); |
| #endif /* #if 0 */ |
| } |
| else |
| { |
| if ((init_u_rset_frame == ps_frame_info->sent_frame_type) && |
| (NULL != psLlcCtxt->cb_for_if.notify)) |
| { |
| ps_frame_info->sent_frame_type = write_resp_received; |
| notifyinfo.status = NFCSTATUS_SUCCESS; |
| /* Send the notification to the upper layer */ |
| psLlcCtxt->cb_for_if.notify( |
| psLlcCtxt->cb_for_if.pif_ctxt, |
| psLlcCtxt->phwinfo, |
| NFC_NOTIFY_INIT_COMPLETED, |
| ¬ifyinfo); |
| } |
| } |
| #else /* #ifdef LLC_URSET_NO_DELAY */ |
| delay_timer_id = phOsalNfc_Timer_Create (); |
| phOsalNfc_Timer_Start (delay_timer_id, LLC_URSET_DELAY_TIME_OUT, |
| phLlcNfc_URSET_Delay_Notify, (void*)0); |
| #endif /* #ifdef LLC_URSET_NO_DELAY */ |
| break; |
| } |
| default: |
| { |
| result = PHNFCSTVAL(CID_NFC_LLC, |
| NFCSTATUS_INVALID_FORMAT); |
| break; |
| } |
| } |
| return result; |
| } |
| |
| static |
| void |
| phLlcNfc_H_ProcessSFrame ( |
| phLlcNfc_Context_t *psLlcCtxt) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| uint8_t cmdtype = phLlcNfc_e_error; |
| #if 0 |
| prev_win_count = 0; |
| #endif /* #if 0 */ |
| phNfc_sTransactionInfo_t compinfo = {0, 0, 0, 0, 0}; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
| phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; |
| uint8_t no_of_del_frames = 0; |
| phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; |
| |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_recv_pkt = &(ps_frame_info->s_recvpacket); |
| ps_store_frame = &(ps_frame_info->s_send_store); |
| |
| cmdtype = (ps_recv_pkt->s_llcbuf.sllcpayload.llcheader & |
| PH_LLCNFC_S_FRAME_TYPE_MASK); |
| PHNFC_UNUSED_VARIABLE(result); |
| |
| PH_LLCNFC_DEBUG("NS START POS BEFORE DEL : 0x%02X\n", ps_store_frame->start_pos); |
| PH_LLCNFC_DEBUG("WIN SIZE BEFORE DEL : 0x%02X\n", ps_store_frame->winsize_cnt); |
| |
| /* Correct frame is received, so remove the |
| stored i frame info for the acknowledged frames */ |
| no_of_del_frames = phLlcNfc_H_UpdateIFrameList (ps_frame_info, |
| &(ps_frame_info->s_send_store)); |
| |
| PH_LLCNFC_DEBUG("NS START POS AFTER DEL : 0x%02X\n", ps_store_frame->start_pos); |
| PH_LLCNFC_DEBUG("WIN SIZE AFTER DEL : 0x%02X\n", ps_store_frame->winsize_cnt); |
| |
| #if 0 |
| prev_win_count = ps_frame_info->s_send_store.winsize_cnt; |
| #endif /* #if 0 */ |
| |
| /* Pend the read */ |
| result = phLlcNfc_Interface_Read (psLlcCtxt, |
| PH_LLCNFC_READWAIT_OFF, |
| &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| switch(cmdtype) |
| { |
| case phLlcNfc_e_rr: |
| case phLlcNfc_e_rej: |
| { |
| /* RR frame received */ |
| phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); |
| |
| if (phLlcNfc_e_rr == cmdtype) |
| { |
| ps_frame_info->recv_error_count = 0; |
| ps_frame_info->send_error_count = 0; |
| } |
| else |
| { |
| ps_frame_info->recv_error_count = (uint8_t) |
| (ps_frame_info->recv_error_count + 1); |
| } |
| |
| if (ps_frame_info->recv_error_count >= RECV_ERROR_FRAME_COUNT) |
| { |
| /* Do nothing */ |
| } |
| else if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status)) |
| { |
| result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); |
| } |
| else |
| { |
| if ( |
| (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + |
| ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) |
| ) |
| { |
| /* If user has sent a frame and DAL write is busy, then |
| it has to be sent */ |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); |
| } |
| } |
| |
| if ((0 != psLlcCtxt->send_cb_len) && |
| (ps_store_frame->winsize_cnt < ps_frame_info->window_size)) |
| { |
| /* Due to the window size count (i.e., count has reached |
| the limit), send completion was not sent for the previous |
| send from the upper layer. So to allow next send from the |
| upper layer, send completion is called */ |
| compinfo.length = (uint16_t)psLlcCtxt->send_cb_len; |
| compinfo.status = NFCSTATUS_SUCCESS; |
| |
| if (NULL != psLlcCtxt->cb_for_if.send_complete) |
| { |
| psLlcCtxt->send_cb_len = 0; |
| /* Call the send callback, if the window size |
| count becomes less than actual window size */ |
| psLlcCtxt->cb_for_if.send_complete ( |
| psLlcCtxt->cb_for_if.pif_ctxt, |
| psLlcCtxt->phwinfo, &compinfo); |
| } |
| } |
| break; |
| } |
| |
| #if 0 |
| case phLlcNfc_e_rej: |
| { |
| ps_frame_info->recv_error_count = (uint8_t) |
| (ps_frame_info->recv_error_count + 1); |
| /* RR frame received */ |
| phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); |
| |
| if (ps_frame_info->recv_error_count < RECV_ERROR_FRAME_COUNT) |
| { |
| /* Below check is added because if PN544 sends REJ to a frame, but |
| the next frame has already been sent from PN544, then |
| Send the user I frame */ |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); |
| } |
| break; |
| } |
| #endif /* #if 0 */ |
| |
| case phLlcNfc_e_rnr: |
| { |
| phLlcNfc_StopAllTimers (); |
| ps_frame_info->recv_error_count = (uint8_t) |
| (ps_frame_info->recv_error_count + 1); |
| break; |
| } |
| |
| case phLlcNfc_e_srej: |
| default: |
| { |
| ps_frame_info->recv_error_count = (uint8_t) |
| (ps_frame_info->recv_error_count + 1); |
| result = PHNFCSTVAL (CID_NFC_LLC, |
| NFCSTATUS_INVALID_FORMAT); |
| break; |
| } |
| } |
| |
| if (ps_frame_info->recv_error_count >= RECV_ERROR_FRAME_COUNT) |
| { |
| #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION |
| |
| result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); |
| |
| #else /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ |
| |
| PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count); |
| /* 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 */ |
| psLlcCtxt->cb_for_if.notify ( |
| psLlcCtxt->cb_for_if.pif_ctxt, |
| psLlcCtxt->phwinfo, |
| NFC_NOTIFY_DEVICE_ERROR, |
| ¬ifyinfo); |
| |
| #endif /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ |
| } |
| |
| return ; |
| } |
| |
| |
| void |
| phLlcNfc_H_ComputeCrc( |
| uint8_t *pData, |
| uint8_t length, |
| uint8_t *pCrc1, |
| uint8_t *pCrc2 |
| ) |
| { |
| uint8_t crc_byte = 0, |
| index = 0; |
| uint16_t crc = 0; |
| |
| #ifdef CRC_A |
| crc = 0x6363; /* ITU-V.41 */ |
| #else |
| crc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ |
| #endif /* #ifdef CRC_A */ |
| |
| do |
| { |
| crc_byte = pData[index]; |
| phLlcNfc_H_UpdateCrc(crc_byte, &crc); |
| index++; |
| } while (index < length); |
| |
| #ifndef INVERT_CRC |
| crc = ~crc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ |
| #endif /* #ifndef INVERT_CRC */ |
| |
| *pCrc1 = (uint8_t) (crc & 0xFF); |
| *pCrc2 = (uint8_t) ((crc >> 8) & 0xFF); |
| return; |
| } |
| |
| static |
| void |
| phLlcNfc_H_UpdateCrc( |
| uint8_t crcByte, |
| uint16_t *pCrc |
| ) |
| { |
| crcByte = (crcByte ^ (uint8_t)((*pCrc) & 0x00FF)); |
| crcByte = (crcByte ^ (uint8_t)(crcByte << 4)); |
| *pCrc = (*pCrc >> 8) ^ ((uint16_t)crcByte << 8) ^ |
| ((uint16_t)crcByte << 3) ^ |
| ((uint16_t)crcByte >> 4); |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_StoreIFrame ( |
| phLlcNfc_StoreIFrame_t *psList, |
| phLlcNfc_LlcPacket_t sPacketInfo |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| uint8_t ns_index = 0, |
| llc_header = 0; |
| |
| if ((NULL == psList) || (0 == sPacketInfo.llcbuf_len) || |
| (PH_LLCNFC_I_HEADER_INIT != |
| (sPacketInfo.s_llcbuf.sllcpayload.llcheader & |
| PH_LLCNFC_I_FRM_HEADER_MASK))) |
| { |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else |
| { |
| /* Get the index from the start index */ |
| if(psList->winsize_cnt > 0) |
| { |
| ns_index = (uint8_t)((psList->start_pos + psList->winsize_cnt) % |
| PH_LLCNFC_MOD_NS_NR); |
| } |
| else |
| { |
| ns_index = psList->start_pos; |
| } |
| |
| llc_header = (uint8_t)(PH_LLCNFC_I_HEADER_INIT | (ns_index << |
| PH_LLCNFC_NS_START_BIT_POS)); |
| sPacketInfo.s_llcbuf.sllcpayload.llcheader = llc_header; |
| |
| (void)memcpy (&(psList->s_llcpacket[ns_index]), |
| &(sPacketInfo), sizeof(phLlcNfc_LlcPacket_t)); |
| |
| /* This variable says that LLC has to send complete |
| callback for stored I frame */ |
| psList->s_llcpacket[ns_index].frame_to_send = invalid_frame; |
| |
| psList->winsize_cnt++; |
| } |
| return result; |
| } |
| |
| static |
| void |
| phLlcNfc_H_DeleteIFrame ( |
| phLlcNfc_StoreIFrame_t *psList |
| ) |
| { |
| if (NULL != psList) |
| { |
| (void)memset( &(psList->s_llcpacket[psList->start_pos]), |
| 0, sizeof(phLlcNfc_LlcPacket_t)); |
| |
| /* Go to next N(S) position */ |
| psList->start_pos = ((psList->start_pos + 1) % |
| PH_LLCNFC_MOD_NS_NR); |
| |
| if (psList->winsize_cnt > 0) |
| { |
| psList->winsize_cnt--; |
| } |
| } |
| } |
| |
| static |
| NFCSTATUS |
| phLlcNfc_H_IFrameList_Peek ( |
| phLlcNfc_StoreIFrame_t *psList, |
| phLlcNfc_LlcPacket_t **psPacketinfo, |
| uint8_t position |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| uint8_t index = 0; |
| |
| *psPacketinfo = NULL; |
| if ((NULL != psList) && (psList->winsize_cnt > 0)) |
| { |
| result = NFCSTATUS_SUCCESS; |
| if ((position < (psList->start_pos + psList->winsize_cnt)) || |
| (DEFAULT_PACKET_INPUT == position)) |
| { |
| index = (uint8_t)((DEFAULT_PACKET_INPUT == position) ? |
| psList->start_pos : position); |
| *psPacketinfo = &(psList->s_llcpacket[index]); |
| } |
| } |
| |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_ProRecvFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, |
| NFCSTATUS_INVALID_PARAMETER); |
| phLlcNfc_FrameType_t frame_type = phLlcNfc_eErr_frame; |
| #ifdef LLC_DATA_BYTES |
| uint8_t *print_buf = (uint8_t *) |
| &(psLlcCtxt->s_frameinfo.s_recvpacket.s_llcbuf); |
| uint8_t buf_len = |
| psLlcCtxt->s_frameinfo.s_recvpacket.llcbuf_len; |
| PH_LLCNFC_STRING("** Response "); |
| |
| #endif /* LLC_DATA_BYTES */ |
| if (NULL != psLlcCtxt) |
| { |
| result = NFCSTATUS_SUCCESS; |
| /* Get the received frame type */ |
| frame_type = phLlcNfc_H_ChkGetLlcFrameType( |
| psLlcCtxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcheader); |
| |
| /* Depending on the received frame type, process the |
| received buffer */ |
| switch(frame_type) |
| { |
| case phLlcNfc_eU_frame: |
| { |
| PH_LLCNFC_PRINT("U frame received \n"); |
| PH_LLCNFC_STRING("U frame "); |
| PH_LLCNFC_PRINT_DATA(print_buf, buf_len); |
| PH_LLCNFC_STRING(";\n"); |
| result = phLlcNfc_H_ProcessUFrame(psLlcCtxt); |
| break; |
| } |
| case phLlcNfc_eI_frame: |
| { |
| PH_LLCNFC_PRINT("I frame received \n"); |
| PH_LLCNFC_STRING("I frame "); |
| PH_LLCNFC_PRINT_DATA(print_buf, buf_len); |
| PH_LLCNFC_STRING(";\n"); |
| phLlcNfc_H_ProcessIFrame(psLlcCtxt); |
| break; |
| } |
| case phLlcNfc_eS_frame: |
| { |
| PH_LLCNFC_PRINT("S frame received \n"); |
| PH_LLCNFC_STRING("S frame "); |
| PH_LLCNFC_PRINT_DATA(print_buf, buf_len); |
| PH_LLCNFC_STRING(";\n"); |
| phLlcNfc_H_ProcessSFrame(psLlcCtxt); |
| break; |
| } |
| case phLlcNfc_eErr_frame: |
| default: |
| { |
| PH_LLCNFC_PRINT("Error frame received \n"); |
| result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); |
| break; |
| } |
| } |
| |
| } |
| return result; |
| } |
| |
| #ifdef CRC_ERROR_REJ |
| NFCSTATUS |
| phLlcNfc_H_SendRejectFrame( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_LlcPacket_t s_packet_info = {0}; |
| |
| result = phLlcNfc_H_CreateSFramePayload( |
| &(psLlcCtxt->s_frameinfo), |
| &(s_packet_info), |
| phLlcNfc_e_rej); |
| /* Send the "S" frame to the lower layer */ |
| result = phLlcNfc_Interface_Write(psLlcCtxt, |
| (uint8_t *)&(s_packet_info.s_llcbuf), |
| (uint32_t)(s_packet_info.llcbuf_len)); |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| /* Increment the retry count of the reject frame */ |
| psLlcCtxt->s_frameinfo.recv_error_count = |
| (psLlcCtxt->s_frameinfo.recv_error_count + 1); |
| } |
| |
| |
| return result; |
| } |
| #endif /* #ifdef CRC_ERROR_REJ */ |
| |
| static |
| void |
| phLlcNfc_H_ResetFrameInfo ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| uint8_t i = 0, |
| win_cnt = 0, |
| pos = 0, |
| while_exit = FALSE, |
| index_flag = FALSE; |
| phLlcNfc_StoreIFrame_t *ps_send_store = NULL; |
| phLlcNfc_Buffer_t *ps_buffer = NULL; |
| |
| ps_send_store = &(psLlcCtxt->s_frameinfo.s_send_store); |
| win_cnt = ps_send_store->winsize_cnt; |
| pos = ps_send_store->start_pos; |
| PH_LLCNFC_PRINT ("\n\nLLC : phLlcNfc_H_ResetFrameInfo called\n\n"); |
| PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->start_pos %08X\n", ps_send_store->start_pos); |
| PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->winsize_cnt before reset %08X\n", ps_send_store->winsize_cnt); |
| |
| |
| if (0 != pos) |
| { |
| /* If the start position of the ns = 0, then |
| no need to shift the stored llc data, |
| Else it has to be shifted to the first |
| index of the array */ |
| if(TRUE == ((pos + win_cnt) / |
| PH_LLCNFC_MAX_I_FRAME_STORE)) |
| { |
| /* 'i' is the array index, So to store data in the array, |
| windows size count shall be subtracted by 1 */ |
| i = (win_cnt - 1); |
| /* if window size > 1 and ns for 2 frames are 7 and 0, then |
| to reset the ns index to 0, the frames are copied from |
| the reverse order, so to do it a flag is declared */ |
| index_flag = TRUE; |
| pos = (((pos - 1) + win_cnt) % PH_LLCNFC_MAX_I_FRAME_STORE); |
| } |
| |
| while (FALSE == while_exit) |
| { |
| (void)memcpy ((void *)&(ps_send_store->s_llcpacket[i]), |
| (void *)&(ps_send_store->s_llcpacket[pos]), |
| sizeof (phLlcNfc_LlcPacket_t)); |
| |
| ps_send_store->s_llcpacket[i].frame_to_send = invalid_frame; |
| |
| ps_buffer = &(ps_send_store->s_llcpacket[i].s_llcbuf); |
| /* change n(s) value */ |
| ps_buffer->sllcpayload.llcheader = (uint8_t) |
| (PH_LLCNFC_I_HEADER_INIT | |
| (i << PH_LLCNFC_NS_START_BIT_POS)); |
| if(TRUE == index_flag) |
| { |
| if(0 == i) |
| { |
| while_exit = TRUE; |
| } |
| else |
| { |
| i = ((i - 1) % PH_LLCNFC_MAX_I_FRAME_STORE); |
| if (0 == pos) |
| { |
| pos = (PH_LLCNFC_MAX_I_FRAME_STORE - 1); |
| } |
| else |
| { |
| pos = ((pos - 1) % PH_LLCNFC_MAX_I_FRAME_STORE); |
| } |
| } |
| } |
| else |
| { |
| if (i >= win_cnt) |
| { |
| while_exit = TRUE; |
| } |
| else |
| { |
| i = ((i + 1) % PH_LLCNFC_MAX_I_FRAME_STORE); |
| pos = ((pos + 1) % PH_LLCNFC_MAX_I_FRAME_STORE); |
| } |
| |
| } |
| } |
| } |
| psLlcCtxt->s_timerinfo.guard_to_count = 0; |
| psLlcCtxt->s_timerinfo.timer_flag = 0; |
| ps_send_store->start_pos = 0; |
| psLlcCtxt->s_frameinfo.n_r = psLlcCtxt->s_frameinfo.n_s = 0; |
| if (ps_send_store->winsize_cnt > 0) |
| { |
| psLlcCtxt->s_frameinfo.rejected_ns = 0; |
| } |
| else |
| { |
| psLlcCtxt->s_frameinfo.rejected_ns = DEFAULT_PACKET_INPUT; |
| } |
| |
| PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->winsize_cnt after reset %08X\n", ps_send_store->winsize_cnt); |
| return; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_WriteWaitCall ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_StoreIFrame_t *ps_store_info = NULL; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| ps_store_info = &(ps_frame_info->s_send_store); |
| |
| PH_LLCNFC_PRINT ("\nLLC : phLlcNfc_H_WriteWaitCall call ..\n"); |
| PH_LLCNFC_DEBUG ("\n\nLLC : ps_frame_info->write_wait_call before call %08X\n", ps_frame_info->write_wait_call); |
| |
| ps_frame_info->write_status = NFCSTATUS_PENDING; |
| switch (ps_frame_info->write_wait_call) |
| { |
| case user_i_frame: |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_info); |
| break; |
| } |
| |
| case resend_i_frame: |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| result = phLlcNfc_H_SendTimedOutIFrame (psLlcCtxt, ps_store_info, 0); |
| break; |
| } |
| |
| case rejected_i_frame: |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| result = phLlcNfc_H_SendRejectedIFrame (psLlcCtxt, ps_store_info, |
| ps_frame_info->rejected_ns); |
| break; |
| } |
| |
| case resend_s_frame: |
| case reject_s_frame: |
| case resend_rej_s_frame: |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| break; |
| } |
| |
| case u_rset_frame: |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); |
| break; |
| } |
| |
| default : |
| { |
| ps_frame_info->write_wait_call = invalid_frame; |
| break; |
| } |
| } |
| |
| PH_LLCNFC_DEBUG ("\n\nLLC : ps_frame_info->write_wait_call after call %08X\n", ps_frame_info->write_wait_call); |
| PH_LLCNFC_PRINT ("\nLLC : phLlcNfc_H_WriteWaitCall end ..\n"); |
| return result; |
| } |
| |
| NFCSTATUS |
| phLlcNfc_H_SendRSETFrame ( |
| phLlcNfc_Context_t *psLlcCtxt |
| ) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phLlcNfc_LlcPacket_t s_packet_info; |
| phLlcNfc_Frame_t *ps_frame_info = NULL; |
| |
| ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| |
| result = phLlcNfc_H_CreateUFramePayload(psLlcCtxt, |
| &(s_packet_info), |
| &(s_packet_info.llcbuf_len), |
| phLlcNfc_e_rset); |
| |
| if (NFCSTATUS_SUCCESS == result) |
| { |
| /* Call DAL write */ |
| result = phLlcNfc_Interface_Write(psLlcCtxt, |
| (uint8_t*)&(s_packet_info.s_llcbuf), |
| (uint32_t)s_packet_info.llcbuf_len); |
| } |
| |
| ps_frame_info->write_status = result; |
| if (NFCSTATUS_PENDING == result) |
| { |
| /* Start the timer */ |
| result = phLlcNfc_StartTimers (PH_LLCNFC_CONNECTIONTIMER, 0); |
| if (NFCSTATUS_SUCCESS == result) |
| { |
| ps_frame_info->sent_frame_type = u_rset_frame; |
| result = NFCSTATUS_PENDING; |
| } |
| } |
| else |
| { |
| ps_frame_info->write_wait_call = u_rset_frame; |
| } |
| |
| return result; |
| } |
| |
| |