blob: 875e2957a5a3ebc2ef4b533d933b607c2030773d [file] [log] [blame]
/*
* 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 phHciNfc_Generic.c *
* \brief Generic HCI Source for the HCI Management. *
* *
* *
* Project: NFC-FRI-1.1 *
* *
* $Date: Tue Jun 8 09:31:49 2010 $ *
* $Author: ing04880 $ *
* $Revision: 1.108 $ *
* $Aliases: NFC_FRI1.1_WK1023_R35_1 $
* *
* =========================================================================== *
*/
/*
################################################################################
***************************** Header File Inclusion ****************************
################################################################################
*/
#include <phNfcCompId.h>
#include <phHciNfc_Sequence.h>
#include <phHciNfc_Pipe.h>
#include <phHciNfc_AdminMgmt.h>
#include <phHciNfc_IDMgmt.h>
#include <phHciNfc_LinkMgmt.h>
#include <phHciNfc_PollingLoop.h>
#include <phHciNfc_RFReader.h>
#include <phHciNfc_RFReaderA.h>
#include <phOsalNfc.h>
/*
################################################################################
****************************** Macro Definitions *******************************
################################################################################
*/
/* HCI timeout value */
uint32_t nxp_nfc_hci_response_timeout = NXP_NFC_HCI_TIMEOUT;
/*
################################################################################
************************ Static Variable Definitions ***************************
################################################################################
*/
#if (NXP_NFC_HCI_TIMER == 1)
#define NXP_HCI_RESPONSE_TIMEOUT (NXP_NFC_HCI_TIMEOUT)
#include <phOsalNfc_Timer.h>
/** \internal HCI Response Timer to detect the
* Stalled HCI Response */
static uint32_t hci_resp_timer_id = NXP_INVALID_TIMER_ID;
static phHciNfc_sContext_t *gpsHciContext= NULL;
#endif /* (NXP_NFC_HCI_TIMER == 1) */
/*
################################################################################
************************* Function Prototype Declaration ***********************
################################################################################
*/
#if (NXP_NFC_HCI_TIMER == 1)
static
void
phHciNfc_Response_Timeout (
uint32_t resp_timer_id, void *pContext
);
#endif /* (NXP_NFC_HCI_TIMER == 1) */
/**
* \ingroup grp_hci_nfc
*
* The phHciNfc_Send function sends the HCI Commands to the
* corresponding peripheral device, described by the HCI Context Structure.
*
* \param[in] psContext psContext is the context of
* the HCI Layer.
* \param[in] pHwRef pHwRef is the Information of
* the Device Interface Link .
* \param[in] pdata Pointer to the buffer containing
* the command to be sent.
* \param[in] length Variable that receives
* the number of bytes actually sent.
*
* \retval NFCSTATUS_PENDING Command successfully sent.
* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
* could not be interpreted properly.
* \retval Other errors Errors related to the lower layers
*
*/
static
NFCSTATUS
phHciNfc_Send(
void *psContext,
void *pHwRef,
uint8_t *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Process_HCP (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Process_Response (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Error_Response (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Process_Event (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Process_Command (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
void
phHciNfc_Reset_Pipe_MsgInfo(
phHciNfc_Pipe_Info_t *p_pipe_info
);
static
void
phHciNfc_Build_HCPMessage(
phHciNfc_HCP_Packet_t *hcp_packet,
uint8_t msg_type,
uint8_t instruction
);
static
void
phHciNfc_Build_HCPHeader(
phHciNfc_HCP_Packet_t *hcp_packet,
uint8_t chainbit,
uint8_t pipe_id
);
/**
* \ingroup grp_hci_nfc
*
* The phHciNfc_Receive_HCP function receive the HCI Host Control Packet
* Frames from the device.
*
* \param[in] psHciContext psHciContext is the context of
* the HCI Layer.
* \param[in] pHwRef pHwRef is the Information of
* the Device Interface Link .
* \param[in] pdata Pointer to the response buffer that
* receives the response read.
* \param[in] length Variable that receives
* the number of bytes read.
*
* \retval NFCSTATUS_PENDING HCP Frame receive pending.
* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
* could not be interpreted properly.
* \retval Other errors Other related errors
*
*
*/
static
NFCSTATUS
phHciNfc_Receive_HCP (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
/*
################################################################################
***************************** Function Definitions *****************************
################################################################################
*/
#if (NXP_NFC_HCI_TIMER == 1)
static
void
phHciNfc_Response_Timeout (
uint32_t resp_timer_id, void *pContext
)
{
phNfc_sCompletionInfo_t comp_info = {0,0,0};
if ( ( NULL != gpsHciContext)
&& (resp_timer_id == hci_resp_timer_id ))
{
pphNfcIF_Notification_CB_t p_upper_notify =
gpsHciContext->p_upper_notify;
void *p_upper_context =
gpsHciContext->p_upper_context;
phHal_sHwReference_t *pHwRef = gpsHciContext->p_hw_ref;
uint32_t i = 0;
HCI_DEBUG(" HCI TIMEOUT: HCI Response Timeout Occurred in %X Timer\n"
,resp_timer_id);
/* Stop the Response Timer */
phOsalNfc_Timer_Stop( hci_resp_timer_id );
comp_info.status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_BOARD_COMMUNICATION_ERROR);
/* Roll Back to the Select State */
phHciNfc_FSM_Rollback(gpsHciContext);
for(i=0;i < PHHCINFC_MAX_PIPE; i++)
{
phHciNfc_Reset_Pipe_MsgInfo(gpsHciContext->p_pipe_list[i]);
}
/* Notify the Error/Success Scenario to the upper layer */
phHciNfc_Notify( p_upper_notify, p_upper_context,
pHwRef, (uint8_t) NFC_NOTIFY_DEVICE_ERROR, &comp_info );
}
return ;
}
#endif /* (NXP_NFC_HCI_TIMER == 1) */
/*!
* \brief Allocation of the HCI Interface resources.
*
* This function releases and frees all the resources used by HCI Command and
* Response Mechanism
*/
NFCSTATUS
phHciNfc_Allocate_Resource (
void **ppBuffer,
uint16_t size
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
*ppBuffer = (void *) phOsalNfc_GetMemory(size);
if( *ppBuffer != NULL )
{
(void )memset(((void *)*ppBuffer), 0,
size);
}
else
{
*ppBuffer = NULL;
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INSUFFICIENT_RESOURCES);
}
return status;
}
/*!
* \brief Release of the HCI Interface resources.
*
* This function releases and frees all the resources used by HCI Command and
* Response Mechanism
*/
void
phHciNfc_Release_Resources (
phHciNfc_sContext_t **ppsHciContext
)
{
uint8_t i = 0;
#if (NXP_NFC_HCI_TIMER == 1)
if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id )
{
/* Stop and Un-Intialise the Response Timer */
phOsalNfc_Timer_Stop( hci_resp_timer_id );
phOsalNfc_Timer_Delete( hci_resp_timer_id );
HCI_DEBUG(" HCI : Timer %X Stopped and Released\n",
hci_resp_timer_id);
hci_resp_timer_id = NXP_INVALID_TIMER_ID;
}
gpsHciContext = NULL;
#endif /* (NXP_NFC_HCI_TIMER == 1) */
if(NULL != (*ppsHciContext)->p_admin_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_admin_info);
(*ppsHciContext)->p_admin_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_link_mgmt_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_link_mgmt_info);
(*ppsHciContext)->p_link_mgmt_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_identity_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_identity_info);
(*ppsHciContext)->p_identity_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_device_mgmt_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_device_mgmt_info);
(*ppsHciContext)->p_device_mgmt_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_reader_mgmt_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_mgmt_info);
(*ppsHciContext)->p_reader_mgmt_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_poll_loop_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_poll_loop_info);
(*ppsHciContext)->p_poll_loop_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_reader_a_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_a_info);
(*ppsHciContext)->p_reader_a_info = NULL;
}
#ifdef TYPE_B
if(NULL !=(*ppsHciContext)->p_reader_b_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_b_info);
(*ppsHciContext)->p_reader_b_info = NULL;
}
#endif
#ifdef TYPE_FELICA
if(NULL !=(*ppsHciContext)->p_felica_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_felica_info);
(*ppsHciContext)->p_felica_info = NULL;
}
#endif
#ifdef TYPE_JEWEL
if(NULL !=(*ppsHciContext)->p_jewel_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_jewel_info);
(*ppsHciContext)->p_jewel_info = NULL;
}
#endif
#ifdef TYPE_ISO15693
if(NULL !=(*ppsHciContext)->p_iso_15693_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_iso_15693_info);
(*ppsHciContext)->p_iso_15693_info = NULL;
}
#endif /* #ifdef TYPE_ISO15693 */
#ifdef ENABLE_P2P
if(NULL !=(*ppsHciContext)->p_nfcip_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_nfcip_info);
(*ppsHciContext)->p_nfcip_info = NULL;
}
#endif
if(NULL !=(*ppsHciContext)->p_emulation_mgmt_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_emulation_mgmt_info);
(*ppsHciContext)->p_emulation_mgmt_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_wi_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_wi_info);
(*ppsHciContext)->p_wi_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_swp_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_swp_info);
(*ppsHciContext)->p_swp_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_uicc_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_uicc_info);
(*ppsHciContext)->p_uicc_info = NULL;
}
#ifdef HOST_EMULATION
if(NULL !=(*ppsHciContext)->p_ce_a_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_ce_a_info);
(*ppsHciContext)->p_ce_a_info = NULL;
}
if(NULL !=(*ppsHciContext)->p_ce_b_info)
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_ce_b_info);
(*ppsHciContext)->p_ce_b_info = NULL;
}
#endif
for(i=0;i < PHHCINFC_MAX_PIPE; i++)
{
if(NULL != (*ppsHciContext)->p_pipe_list[i])
{
phOsalNfc_FreeMemory((*ppsHciContext)->p_pipe_list[i]);
}
}
phOsalNfc_FreeMemory((*ppsHciContext));
(*ppsHciContext) = NULL;
return ;
}
static
void
phHciNfc_Reset_Pipe_MsgInfo(
phHciNfc_Pipe_Info_t *p_pipe_info
)
{
if (p_pipe_info != NULL)
{
p_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESERVED;
p_pipe_info->prev_msg = MSG_INSTRUCTION_UNKNWON;
p_pipe_info->prev_status = NFCSTATUS_INVALID_HCI_INSTRUCTION;
p_pipe_info->param_info = NULL;
p_pipe_info->param_length = FALSE ;
}
return;
}
void
phHciNfc_Release_Lower(
phHciNfc_sContext_t *psHciContext,
void *pHwRef
)
{
phNfc_sLowerIF_t *plower_if =
&(psHciContext->lower_interface);
NFCSTATUS status = NFCSTATUS_SUCCESS;
PHNFC_UNUSED_VARIABLE(status);
if(NULL != plower_if->release)
{
status = plower_if->release((void *)plower_if->pcontext,
(void *)pHwRef);
(void) memset((void *)plower_if, 0, sizeof(phNfc_sLowerIF_t));
HCI_DEBUG(" HCI Releasing the Lower Layer Resources: Status = %02X\n"
,status);
}
return;
}
/*!
* \brief Sends the HCI Commands to the corresponding peripheral device.
*
* This function sends the HCI Commands to the connected NFC Pheripheral device
*/
static
NFCSTATUS
phHciNfc_Send (
void *psContext,
void *pHwRef,
uint8_t *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_sContext_t *psHciContext= (phHciNfc_sContext_t *)psContext;
NFCSTATUS status = NFCSTATUS_SUCCESS;
phNfc_sLowerIF_t *plower_if = &(psHciContext->lower_interface);
if( (NULL != plower_if)
&& (NULL != plower_if->send)
)
{
HCI_DEBUG("HCI: In Function: %s \n", __FUNCTION__);
HCI_DEBUG("HCI: Response Pending status --> %s \n",
(psHciContext->response_pending)?"TRUE":"FALSE");
HCI_PRINT_BUFFER("Send Buffer",pdata,length);
/* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_IN_PROGRESS; */
#if (NXP_NFC_HCI_TIMER == 1)
if (
(TRUE != psHciContext->tx_hcp_chaining)
&& (TRUE == psHciContext->response_pending)
&& ( NXP_INVALID_TIMER_ID != hci_resp_timer_id )
)
{
/* Start the HCI Response Timer */
phOsalNfc_Timer_Start( hci_resp_timer_id,
nxp_nfc_hci_response_timeout, phHciNfc_Response_Timeout, NULL );
HCI_DEBUG(" HCI : Timer %X Started \n", hci_resp_timer_id);
}
#endif /* (NXP_NFC_HCI_TIMER == 1) */
status = plower_if->send((void *)plower_if->pcontext,
(void *)pHwRef, pdata, length);
}
return status;
}
/*!
* \brief Receives the HCI Response from the corresponding peripheral device.
*
* This function receives the HCI Command Response to the connected NFC
* Pheripheral device.
*/
NFCSTATUS
phHciNfc_Receive(
void *psContext,
void *pHwRef,
uint8_t *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_sContext_t *psHciContext= (phHciNfc_sContext_t *)psContext;
phNfc_sLowerIF_t *plower_if = NULL ;
NFCSTATUS status = NFCSTATUS_SUCCESS;
if(NULL == psHciContext )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else
{
plower_if = &(psHciContext->lower_interface);
if( (NULL != plower_if)
&& (NULL != plower_if->receive)
)
{
/* psHciContext->hci_transact_state = NFC_TRANSACT_RECV_IN_PROGRESS; */
status = plower_if->receive((void *)plower_if->pcontext,
(void *)pHwRef, pdata, length);
}
}
return status;
}
/*!
* \brief Sends the HCP Packet to the lower link layer .
*
* This function Sends the HCI Data in the HCP packet format to the below
* Link layer.
*/
NFCSTATUS
phHciNfc_Send_HCP (
phHciNfc_sContext_t *psHciContext,
void *pHwRef
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_HCP_Packet_t *tx_data = (phHciNfc_HCP_Packet_t *)
psHciContext->send_buffer;
/* Skip the HCP Header Byte initially */
uint16_t tx_length = psHciContext->tx_total - 1 ;
uint16_t hcp_index = HCP_ZERO_LEN;
uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
static uint8_t chain_bit = HCP_CHAINBIT_DEFAULT;
pipe_id = (uint8_t) GET_BITS8( tx_data->hcp_header,
HCP_PIPEID_OFFSET, HCP_PIPEID_LEN);
/* Fragmentation of the HCP Frames */
if ( tx_length > PHHCINFC_MAX_PACKET_DATA )
{
tx_data = &psHciContext->tx_packet;
(void)memset((void *)tx_data, FALSE,
sizeof(phHciNfc_HCP_Packet_t));
if (HCP_CHAINBIT_DEFAULT == chain_bit)
{
/* HCI Chaining Needs to be Done */
psHciContext->tx_remain = tx_length;
psHciContext->tx_hcp_frgmnt_index = HCP_ZERO_LEN ;
chain_bit = HCP_CHAINBIT_BEGIN;
/* Increment the Fragment index to skip the HCP Header */
psHciContext->tx_hcp_frgmnt_index++;
psHciContext->tx_hcp_chaining = TRUE ;
tx_length = PHHCINFC_MAX_PACKET_DATA ;
}
else if ( psHciContext->tx_remain > PHHCINFC_MAX_PACKET_DATA )
{
/* Intermediate Chained HCI Frames */
tx_length = PHHCINFC_MAX_PACKET_DATA ;
}
else
{
/* End of Chaining Reached */
chain_bit = HCP_CHAINBIT_END;
tx_length = psHciContext->tx_remain ;
psHciContext->tx_hcp_chaining = FALSE ;
}
/* Build the HCP Header to have Chaining Enabled */
phHciNfc_Build_HCPHeader(tx_data, chain_bit , pipe_id );
phHciNfc_Append_HCPFrame((uint8_t *)tx_data->msg.payload, hcp_index,
(&psHciContext->send_buffer[psHciContext->tx_hcp_frgmnt_index])
, tx_length );
}
else
{
/* No Chaining Required */
chain_bit = HCP_CHAINBIT_DEFAULT;
psHciContext->tx_hcp_chaining = FALSE ;
psHciContext->tx_remain = tx_length ;
}
/* Include the Skipped HCP Header Byte */
tx_length++;
status = phHciNfc_Send ( (void *) psHciContext, pHwRef,
(uint8_t *)tx_data, tx_length );
return status;
}
/*!
* \brief Receives the HCP Packet from the lower link layer .
*
* This function receives the HCI Data in the HCP packet format from the below
* Link layer.
*/
static
NFCSTATUS
phHciNfc_Receive_HCP (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_HCP_Packet_t *packet = NULL;
uint8_t chainbit = HCP_CHAINBIT_DEFAULT;
uint16_t hcp_index = 0;
packet = (phHciNfc_HCP_Packet_t *)pdata;
chainbit = (uint8_t) GET_BITS8( packet->hcp_header,
HCP_CHAINBIT_OFFSET, HCP_CHAINBIT_LEN);
hcp_index = psHciContext->rx_hcp_frgmnt_index;
HCI_PRINT_BUFFER("Receive Buffer",((uint8_t *)pdata),length);
if (HCP_CHAINBIT_BEGIN == chainbit)
{
/* pdata = (uint8_t *)&psHciContext->rx_packet; */
/* De Fragmentation of the Received HCP Frames */
/* Subsequent Chaining Frames */
if( hcp_index > 0 )
{
/* Copy the obtained fragment and receive the next fragment */
phHciNfc_Append_HCPFrame(
psHciContext->recv_buffer, hcp_index,
(uint8_t *)&pdata[HCP_MESSAGE_LEN],
(length - HCP_MESSAGE_LEN) );
psHciContext->rx_hcp_frgmnt_index =(uint16_t)
(hcp_index + length - HCP_MESSAGE_LEN);
}
/* First Chaining Frame*/
else
{
psHciContext->rx_hcp_chaining = TRUE ;
/* Copy the obtained fragment and receive the next fragment */
phHciNfc_Append_HCPFrame(psHciContext->recv_buffer,
hcp_index, pdata, length);
psHciContext->rx_hcp_frgmnt_index = ( hcp_index + length ) ;
}
status = phHciNfc_Receive ( (void *) psHciContext, pHwRef,
pdata, length);
}
else
{
if(TRUE == psHciContext->rx_hcp_chaining)
{
/* If the chaining was done earlier */
psHciContext->rx_hcp_chaining = FALSE ;
/* Copy the Remaining buffer to the RX_BUFFER */
phHciNfc_Append_HCPFrame(
psHciContext->recv_buffer, hcp_index,
(uint8_t *)&pdata[HCP_MESSAGE_LEN],
(length - HCP_MESSAGE_LEN) );
/* If there is chaining done the return the same data */
psHciContext->rx_total =
(hcp_index + length - HCP_MESSAGE_LEN);
psHciContext->rx_hcp_frgmnt_index = FALSE ;
}
else
{
(void) memcpy( psHciContext->recv_buffer, pdata, length);
/* If there is no chaining done then return the same data */
psHciContext->rx_total = (hcp_index + length);
}
}
return status;
}
/*!
* \brief Receives the HCP Packet from the lower link layer .
*
* This function receives the HCI Data in the HCP packet format from the below
* Link layer.
*/
static
NFCSTATUS
phHciNfc_Process_HCP (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_HCP_Packet_t *packet = NULL;
phHciNfc_HCP_Message_t *message = NULL;
NFCSTATUS status = NFCSTATUS_SUCCESS;
uint8_t msg_type = 0;
if( (NULL == pdata)
|| ( length < HCP_HEADER_LEN )
)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else
{
status = phHciNfc_Receive_HCP( psHciContext, pHwRef, pdata, length );
}/* End of the Valid Data Handling */
if( NFCSTATUS_SUCCESS == status )
{
packet = (phHciNfc_HCP_Packet_t *)psHciContext->recv_buffer;
length =
#ifdef ONE_BYTE_LEN
(uint8_t)
#endif
psHciContext->rx_total ;
message = &packet->msg.message;
/* HCI_PRINT_BUFFER("Total Receive Buffer",((uint8_t *)pdata),length); */
msg_type = (uint8_t) GET_BITS8( message->msg_header,
HCP_MSG_TYPE_OFFSET, HCP_MSG_TYPE_LEN);
switch ( msg_type )
{
case HCP_MSG_TYPE_RESPONSE:
{
status = phHciNfc_Process_Response( psHciContext,
pHwRef, (void *)packet, length );
break;
}
case HCP_MSG_TYPE_EVENT:
{
status = phHciNfc_Process_Event( psHciContext,
pHwRef,(void *)packet, length );
break;
}
case HCP_MSG_TYPE_COMMAND:
{
status = phHciNfc_Process_Command( psHciContext,
pHwRef, (void *)packet, length );
break;
}
/* case HCP_MSG_TYPE_RESERVED: */
default:
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE);
break;
}
}
}/* End of Receive HCP Status */
return status;
}
static
NFCSTATUS
phHciNfc_Process_Response (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_HCP_Packet_t *packet = NULL;
phHciNfc_HCP_Message_t *message = NULL;
uint8_t instruction=0;
uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;
phHciNfc_Pipe_Info_t *p_pipe_info = NULL;
NFCSTATUS status = NFCSTATUS_SUCCESS;
packet = (phHciNfc_HCP_Packet_t *)pdata;
message = &packet->msg.message;
/* Get the instruction bits from the Message Header */
instruction = (uint8_t) GET_BITS8( message->msg_header,
HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
/* Get the Pipe ID from the HCP Header */
pipe_id = (uint8_t) GET_BITS8( packet->hcp_header,
HCP_PIPEID_OFFSET, HCP_PIPEID_LEN);
#if (NXP_NFC_HCI_TIMER == 1)
if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id )
{
/* Stop the HCI Response Timer */
HCI_DEBUG(" HCI : Timer %X Stopped \n", hci_resp_timer_id);
phOsalNfc_Timer_Stop( hci_resp_timer_id );
}
#endif /* (NXP_NFC_HCI_TIMER == 1) */
if (pipe_id >= PHHCINFC_MAX_PIPE )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);
}
else if( ((uint8_t) ANY_OK != instruction)
&& ( (pipe_id != PIPETYPE_STATIC_ADMIN )
&& ( ADM_CLEAR_ALL_PIPE != (psHciContext->p_pipe_list[pipe_id])->prev_msg ))
)
{
status = phHciNfc_Error_Response( psHciContext, pHwRef, pdata, length );
}
else
{
p_pipe_info = psHciContext->p_pipe_list[pipe_id];
if( ( NULL != p_pipe_info )
&& ( HCP_MSG_TYPE_COMMAND == p_pipe_info->sent_msg_type )
&& ( NULL != p_pipe_info->recv_resp )
)
{
status = psHciContext->p_pipe_list[pipe_id]->recv_resp( psHciContext,
pHwRef, pdata, length );
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
/* There is no Pending Response */
psHciContext->response_pending = FALSE ;
HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n",
__FUNCTION__);
if( NFCSTATUS_SUCCESS == status )
{
phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]);
status = phHciNfc_Resume_Sequence(psHciContext, pHwRef);
}/* End of Success Status validation */
else
{
HCI_DEBUG("HCI: Status --> %X \n", status );
}
} /* End of the Valid Response handling */
return status;
}
static
NFCSTATUS
phHciNfc_Error_Response (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_HCP_Packet_t *packet = (phHciNfc_HCP_Packet_t *)pdata;
phHciNfc_HCP_Message_t *message = &packet->msg.message;
NFCSTATUS status = NFCSTATUS_SUCCESS;
uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;
#if defined(HCI_TRACE) || defined (ERROR_INSTRUCTION)
uint8_t instruction = 0;
instruction = (uint8_t) GET_BITS8(message->msg_header,
HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
#endif
/* Get the Pipe ID from the HCP Header */
pipe_id = (uint8_t) GET_BITS8( packet->hcp_header,
HCP_PIPEID_OFFSET, HCP_PIPEID_LEN);
/* Process the Error Response based on the obtained instruction */
#ifdef ERROR_INSTRUCTION
switch(instruction)
{
case ANY_E_NOT_CONNECTED:
case ANY_E_CMD_PAR_UNKNOWN:
case ANY_E_NOK:
case ANY_E_PIPES_FULL:
case ANY_E_REG_PAR_UNKNOWN:
case ANY_E_PIPE_NOT_OPENED:
case ANY_E_CMD_NOT_SUPPORTED:
case ANY_E_TIMEOUT:
case ANY_E_REG_ACCESS_DENIED:
case ANY_E_PIPE_ACCESS_DENIED:
{
/* Receive Error Notification to the Upper Layer */
status = PHNFCSTVAL( CID_NFC_HCI, \
message->msg_header);
phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, length );
/* Return Success as the Error Sequence is already handled */
psHciContext->response_pending = FALSE ;
HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n",
__FUNCTION__);
status = NFCSTATUS_SUCCESS;
break;
}
/* The Statement should not reach this case */
/* case ANY_OK: */
default:
{
/* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); */
break;
}
}
#else
status = PHNFCSTVAL( CID_NFC_HCI, message->msg_header);
HCI_DEBUG("HCI Error Response(%u) from the Device \n", instruction);
psHciContext->response_pending = FALSE ;
HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n",
__FUNCTION__);
phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]);
phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t) length );
/* Return Success as the Error Sequence is already handled */
status = NFCSTATUS_SUCCESS;
#endif
return status;
}
static
NFCSTATUS
phHciNfc_Process_Event (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_HCP_Packet_t *packet = NULL;
phHciNfc_HCP_Message_t *message = NULL;
phHciNfc_Pipe_Info_t *p_pipe_info = NULL;
uint8_t instruction=0;
uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;
NFCSTATUS status = NFCSTATUS_SUCCESS;
packet = (phHciNfc_HCP_Packet_t *)pdata;
message = &packet->msg.message;
/* Get the instruction bits from the Message Header */
PHNFC_UNUSED_VARIABLE(instruction);
instruction = (uint8_t) GET_BITS8( message->msg_header,
HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
/* Get the Pipe ID from the HCP Header */
pipe_id = (uint8_t) GET_BITS8( packet->hcp_header,
HCP_PIPEID_OFFSET, HCP_PIPEID_LEN);
if (pipe_id >= PHHCINFC_MAX_PIPE )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);
}
else
{
p_pipe_info = psHciContext->p_pipe_list[pipe_id];
}
if( (p_pipe_info != NULL ) )
{
if( NULL != p_pipe_info->recv_event)
{
status = p_pipe_info->recv_event( psHciContext, pHwRef,
pdata, length );
}
else
{
HCI_DEBUG(" Event Handling Not Supported by the #%u Pipe \n",
pipe_id);
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
HCI_DEBUG("HCI: In Function: %s \n",
__FUNCTION__);
HCI_DEBUG("HCI: Response Pending status --> %s \n",
(psHciContext->response_pending)?"TRUE":"FALSE");
HCI_DEBUG("HCI: Event Pending status --> %s \n",
(psHciContext->event_pending)?"TRUE":"FALSE");
if ((TRUE == psHciContext->response_pending)
|| (TRUE == psHciContext->event_pending))
{
(void)memset(psHciContext->recv_buffer,
FALSE, PHHCINFC_MAX_BUFFERSIZE);
(void)memset((void *)&psHciContext->rx_packet,
FALSE, sizeof(phHciNfc_HCP_Packet_t));
/* Reset the Received Data Index */
psHciContext->rx_index = ZERO;
/* Reset the size of the total response data received */
psHciContext->rx_total = ZERO;
/* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_COMPLETE;*/
/* Receive the Response Packet */
status = phHciNfc_Receive( psHciContext, pHwRef,
(uint8_t *)(&psHciContext->rx_packet),
sizeof(phHciNfc_HCP_Packet_t) );
/* HCI_DEBUG("HCI Lower Layer Send Completion After Receive,\
Status = %02X\n",status); */
}
else
{
if(
/* #define EVENT_NOTIFY */
#ifndef EVENT_NOTIFY
( NFCSTATUS_SUCCESS == status )
|| ( NFCSTATUS_RF_TIMEOUT == status )
|| (( NFCSTATUS_MORE_INFORMATION == status )
#else
((FALSE == psHciContext->event_pending )
#endif
&& ( pipe_id <= PHHCINFC_MAX_PIPE ))
)
{
/* phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); */
status = phHciNfc_Resume_Sequence(psHciContext, pHwRef);
}/* End of Success Status validation */
else
{
HCI_DEBUG(" HCI: Pipe-ID --> %02X \n", pipe_id);
HCI_DEBUG(" HCI: PROCESS EVENT - Pending/Invalid Status : %X\n", status);
}
}
return status;
}
static
NFCSTATUS
phHciNfc_Process_Command (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
void *pdata,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
phHciNfc_HCP_Packet_t *packet = NULL;
phHciNfc_HCP_Message_t *message = NULL;
phHciNfc_Pipe_Info_t *p_pipe_info = NULL;
uint8_t instruction=0;
uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;
NFCSTATUS status = NFCSTATUS_SUCCESS;
packet = (phHciNfc_HCP_Packet_t *)pdata;
message = &packet->msg.message;
/* Get the instruction bits from the Message Header */
PHNFC_UNUSED_VARIABLE(instruction);
instruction = (uint8_t) GET_BITS8( message->msg_header,
HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
/* Get the Pipe ID from the HCP Header */
pipe_id = (uint8_t) GET_BITS8( packet->hcp_header,
HCP_PIPEID_OFFSET, HCP_PIPEID_LEN);
if (pipe_id >= PHHCINFC_MAX_PIPE )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);
}
else
{
p_pipe_info = psHciContext->p_pipe_list[pipe_id];
}
if( (p_pipe_info != NULL )
)
{
if( NULL != p_pipe_info->recv_cmd)
{
status = p_pipe_info->recv_cmd( psHciContext, pHwRef,
pdata, length );
}
else
{
HCI_DEBUG(" Command Handling Not Supported by the #%u Pipe \n",
pipe_id);
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
HCI_DEBUG("HCI: In Function: %s \n", __FUNCTION__);
HCI_DEBUG("HCI: Response Pending status --> %s \n",
(psHciContext->response_pending)?"TRUE":"FALSE");
if(( NFCSTATUS_SUCCESS == status )
&& (TRUE != psHciContext->response_pending)
)
{
/* Reset the Pipe Information Stored in the particular Pipe */
/* phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); */
/* Resume the Execution Sequence */
status = phHciNfc_Resume_Sequence(psHciContext, pHwRef);
}/* End of Success Status validation */
return status;
}
static
void
phHciNfc_Build_HCPMessage(
phHciNfc_HCP_Packet_t *hcp_packet,
uint8_t msg_type,
uint8_t instruction
)
{
phHciNfc_HCP_Message_t *hcp_message = NULL;
hcp_message = &(hcp_packet->msg.message);
/* Set the type to the provided message type in the HCP Message Header */
hcp_message->msg_header = (uint8_t) SET_BITS8(hcp_message->msg_header,HCP_MSG_TYPE_OFFSET,
HCP_MSG_TYPE_LEN, msg_type);
/* Set the instruction to the kind of instruction in the HCP Message Header */
hcp_message->msg_header = (uint8_t) SET_BITS8(hcp_message->msg_header,HCP_MSG_INSTRUCTION_OFFSET,
HCP_MSG_INSTRUCTION_LEN, instruction);
/* hcp_message->msg_header = hcp_message->msg_header | temp ; */
}
static
void
phHciNfc_Build_HCPHeader(
phHciNfc_HCP_Packet_t *hcp_packet,
uint8_t chainbit,
uint8_t pipe_id
)
{
/* Set the Chaining bit to the default type */
hcp_packet->hcp_header = (uint8_t) SET_BITS8(hcp_packet->hcp_header,
HCP_CHAINBIT_OFFSET, HCP_CHAINBIT_LEN, chainbit);
/* Populate the Pipe ID to the HCP Header */
hcp_packet->hcp_header = (uint8_t) SET_BITS8(hcp_packet->hcp_header,HCP_PIPEID_OFFSET,
HCP_PIPEID_LEN, pipe_id);
}
/*!
* \brief Builds the HCP Frame Packet.
*
* This function builds the HCP Frame in the HCP packet format to send to the
* connected reader device.
*/
void
phHciNfc_Build_HCPFrame (
phHciNfc_HCP_Packet_t *hcp_packet,
uint8_t chainbit,
uint8_t pipe_id,
uint8_t msg_type,
uint8_t instruction
)
{
/* Fills the HCP Header in the packet */
phHciNfc_Build_HCPHeader( hcp_packet,chainbit,pipe_id );
/* Fills the HCP Message in the packet */
phHciNfc_Build_HCPMessage( hcp_packet,msg_type,instruction );
}
/*!
* \brief Appends the HCP Frame Packet.
*
* This function Appends the HCP Frame of the HCP packet to complete the
* entire HCP Packet.
*/
void
phHciNfc_Append_HCPFrame (
/* phHciNfc_sContext_t *psHciContext, */
uint8_t *hcp_data,
uint16_t hcp_index,
uint8_t *src_data,
uint16_t src_len
)
{
uint16_t src_index = 0;
if( (NULL != src_data)
/* && (hcp_index >= 0) */
&& (src_len > 0)
)
{
for(src_index=0; src_index < src_len ; src_index++)
{
hcp_data[hcp_index + src_index] = src_data[src_index];
}
}
return;
}
/*!
* \brief Sends the Generic HCI Commands to the connected reader device.
*
* This function Sends the Generic HCI Command frames in the HCP packet format to the
* connected reader device.
*/
NFCSTATUS
phHciNfc_Send_Generic_Cmd (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t pipe_id,
uint8_t cmd
)
{
phHciNfc_HCP_Packet_t *hcp_packet = NULL;
phHciNfc_HCP_Message_t *hcp_message = NULL;
phHciNfc_Pipe_Info_t *p_pipe_info = NULL;
uint16_t length = 0;
uint16_t i=0;
NFCSTATUS status = NFCSTATUS_SUCCESS;
if((NULL == psHciContext)
|| ( pipe_id > PHHCINFC_MAX_PIPE)
||(NULL == psHciContext->p_pipe_list[pipe_id])
)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
HCI_DEBUG("%s: Invalid Arguments passed \n",
"phHciNfc_Send_Generic_Cmd");
}
else
{
p_pipe_info = (phHciNfc_Pipe_Info_t *)
psHciContext->p_pipe_list[pipe_id];
psHciContext->tx_total = 0 ;
length += HCP_HEADER_LEN ;
switch( cmd )
{
case ANY_SET_PARAMETER:
{
hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
/* Construct the HCP Frame */
phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
(uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd);
hcp_message = &(hcp_packet->msg.message);
hcp_message->payload[i++] = p_pipe_info->reg_index ;
phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload,
i, (uint8_t *)p_pipe_info->param_info,
p_pipe_info->param_length);
length =(uint16_t)(length + i + p_pipe_info->param_length);
break;
}
case ANY_GET_PARAMETER:
{
hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
/* Construct the HCP Frame */
phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
(uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd);
hcp_message = &(hcp_packet->msg.message);
hcp_message->payload[i++] = p_pipe_info->reg_index ;
length =(uint16_t)(length + i);
break;
}
case ANY_OPEN_PIPE:
case ANY_CLOSE_PIPE:
{
hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
/* Construct the HCP Frame */
phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
(uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd);
break;
}
default:
{
status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED );
HCI_DEBUG("%s: Statement Should Not Occur \n","phHciNfc_Send_Generic_Cmd");
break;
}
}
if( NFCSTATUS_SUCCESS == status )
{
p_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND;
p_pipe_info->prev_msg = cmd;
psHciContext->tx_total = length;
psHciContext->response_pending = TRUE ;
/* Send the Constructed HCP packet to the lower layer */
status = phHciNfc_Send_HCP( psHciContext, pHwRef );
p_pipe_info->prev_status = NFCSTATUS_PENDING;
}
}
return status;
}
/*!
* \brief Sets the parameter of the registers in a particular Pipe.
*
* This function configures the registers in a particular Pipe.
*/
NFCSTATUS
phHciNfc_Set_Param (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
phHciNfc_Pipe_Info_t *p_pipe_info,
uint8_t reg_index,
void *p_param,
uint16_t param_length
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS ;
if( (NULL == p_pipe_info)
|| (NULL == p_param)
|| (0 == param_length)
)
{
status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION );
}
else
{
p_pipe_info->param_info = (uint8_t *)p_param;
p_pipe_info->param_length = param_length;
p_pipe_info->reg_index = reg_index;
status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef,
(uint8_t)p_pipe_info->pipe.pipe_id,
(uint8_t)ANY_SET_PARAMETER);
p_pipe_info->prev_status = status;
}
return status;
}
#if 0
/*!
* \brief Gets the parameter of the registers in a particular Pipe.
*
* This function configures the registers in a particular Pipe.
*/
NFCSTATUS
phHciNfc_Get_Param (
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
phHciNfc_Pipe_Info_t *p_pipe_info,
uint8_t reg_index,
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS ;
return status;
}
#endif
void
phHciNfc_Send_Complete (
void *psContext,
void *pHwRef,
phNfc_sTransactionInfo_t *pInfo
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS ;
uint16_t length = 0;
HCI_PRINT("HCI Send Completion....\n");
if ( (NULL != psContext)
&& (NULL != pInfo)
&& (NULL != pHwRef)
)
{
phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext;
status = pInfo->status ;
length = pInfo->length ;
/* HCI_DEBUG("HCI Lower Layer Send Completion Before Receive,\
Status = %02X\n",status); */
if(status != NFCSTATUS_SUCCESS)
{
/* Handle the Error Scenario */
(void)memset(psHciContext->send_buffer,
FALSE, PHHCINFC_MAX_BUFFERSIZE);
/* psHciContext->hci_transact_state = NFC_TRANSACT_COMPLETE;*/
phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 );
}
else
{
HCI_DEBUG("HCI Send Completion... Length = %02X\n", length);
/* To complete the send complete with the send
* or receive with chaining.
*/
if( (TRUE == psHciContext->tx_hcp_chaining)
&&( psHciContext->tx_remain > HCP_ZERO_LEN ))
{
/* Skip the HCP Header Byte Sent */
psHciContext->tx_remain -= length - 1;
/* Skip the HCP Header Byte Sent */
psHciContext->tx_hcp_frgmnt_index += length - 1;
/* Send the Remaining HCP Data Frames */
status = phHciNfc_Send_HCP( psHciContext, pHwRef );
HCI_DEBUG("HCI (Chaining) Send Resume: Status = %02X\n", status);
if( ( NFCSTATUS_SUCCESS != status )
&& (NFCSTATUS_PENDING != status )
)
{
phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 );
}/* End of the Status check */
}
else
{
psHciContext->tx_total = HCP_ZERO_LEN ;
psHciContext->tx_remain = HCP_ZERO_LEN ;
psHciContext->tx_hcp_frgmnt_index = HCP_ZERO_LEN ;
HCI_DEBUG("HCI: %s: response_pending=%s, event_pending=%s",
__FUNCTION__,
(psHciContext->response_pending)?"TRUE":"FALSE",
(psHciContext->event_pending)?"TRUE":"FALSE"
);
if ((TRUE == psHciContext->response_pending)
|| (TRUE == psHciContext->event_pending))
{
(void) memset(psHciContext->recv_buffer,
FALSE, PHHCINFC_MAX_BUFFERSIZE);
(void) memset((void *)&psHciContext->rx_packet,
FALSE, sizeof(phHciNfc_HCP_Packet_t));
/* Reset the Received Data Index */
psHciContext->rx_index = ZERO;
/* Reset the size of the total response data received */
psHciContext->rx_total = ZERO;
/* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_COMPLETE;*/
/* Receive the Response Packet */
status = phHciNfc_Receive( psHciContext, pHwRef,
(uint8_t *)(&psHciContext->rx_packet),
sizeof(phHciNfc_HCP_Packet_t) );
/* HCI_DEBUG("HCI Lower Layer Send Completion After Receive,\
Status = %02X\n",status); */
if( ( NFCSTATUS_SUCCESS != status )
&& (NFCSTATUS_PENDING != status )
)
{
phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 );
}/* End of the Status check */
}
else
{
status = phHciNfc_Resume_Sequence(psHciContext, pHwRef );
}
}
} /* End of status != Success */
} /* End of Context != NULL */
}
void
phHciNfc_Receive_Complete (
void *psContext,
void *pHwRef,
phNfc_sTransactionInfo_t *pInfo
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS ;
void *pdata = NULL ;
uint16_t length = 0 ;
HCI_PRINT("HCI Receive Completion....\n");
if ( (NULL != psContext)
&& (NULL != pInfo)
&& (NULL != pHwRef)
)
{
phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext;
status = pInfo->status ;
pdata = pInfo->buffer ;
length = pInfo->length ;
HCI_DEBUG("HCI Lower Layer Receive Completion, Status = %02X\n",status);
if( NFCSTATUS_SUCCESS != status )
{
/* Handle the Error Scenario */
/* psHciContext->hci_transact_state = NFC_TRANSACT_COMPLETE; */
phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t)length );
}
else
{
/* Receive the remaining Response Packet */
/* psHciContext->hci_transact_state = NFC_TRANSACT_RECV_COMPLETE; */
status = phHciNfc_Process_HCP( psHciContext, pHwRef, pdata,(uint8_t) length );
if( ( NFCSTATUS_SUCCESS != status )
&& (NFCSTATUS_PENDING != status )
)
{
phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t) length );
}
}
}
}
void
phHciNfc_Notify(
pphNfcIF_Notification_CB_t p_upper_notify,
void *p_upper_context,
void *pHwRef,
uint8_t type,
void *pInfo
)
{
if( ( NULL != p_upper_notify) )
{
/* Notify the to the Upper Layer */
(p_upper_notify)(p_upper_context, pHwRef, type, pInfo);
}
}
void
phHciNfc_Tag_Notify(
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t type,
void *pInfo
)
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify;
void *pcontext = psHciContext->p_upper_context;
NFCSTATUS status = NFCSTATUS_SUCCESS;
switch( psHciContext->hci_state.next_state )
{
case hciState_Activate:
{
/* Roll Back to the Select State */
phHciNfc_FSM_Rollback(psHciContext);
break;
}
case hciState_Select:
{
status = phHciNfc_FSM_Complete(psHciContext);
break;
}
default:
{
/* Roll Back to the Select State */
phHciNfc_FSM_Rollback(psHciContext);
break;
}
}
if(NFCSTATUS_SUCCESS == status )
{
/* Notify the Tag Events to the Upper layer */
phHciNfc_Notify( p_upper_notify, pcontext , pHwRef,
type, psCompInfo);
}
else
{
phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 );
}
}
void
phHciNfc_Target_Select_Notify(
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t type,
void *pInfo
)
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify;
void *pcontext = psHciContext->p_upper_context;
NFCSTATUS status = NFCSTATUS_SUCCESS;
switch( psHciContext->hci_state.next_state )
{
case hciState_Listen:
{
/* Roll Back to the Select State */
status = phHciNfc_FSM_Complete(psHciContext);
break;
}
case hciState_Select:
{
status = phHciNfc_FSM_Complete(psHciContext);
break;
}
default:
{
/* Roll Back to the Select State */
phHciNfc_FSM_Rollback(psHciContext);
break;
}
}
if(NFCSTATUS_SUCCESS == status )
{
/* Notify the Tag Events to the Upper layer */
phHciNfc_Notify( p_upper_notify, pcontext , pHwRef,
type, psCompInfo);
}
else
{
phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 );
}
}
void
phHciNfc_Release_Notify(
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t type,
void *pInfo
)
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify;
void *pcontext = psHciContext->p_upper_context;
phHciNfc_Release_Resources( &psHciContext );
/* Notify the Failure to the Upper Layer */
phHciNfc_Notify( p_upper_notify, pcontext , pHwRef,
type, psCompInfo);
}
void
phHciNfc_Notify_Event(
void *psContext,
void *pHwRef,
uint8_t type,
void *pInfo
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
if ( (NULL != psContext)
&& (NULL != pInfo)
&& (NULL != pHwRef)
)
{
phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext;
/* Process based on the Notification type */
switch(type)
{
case NFC_NOTIFY_INIT_COMPLETED:
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
if(NFCSTATUS_SUCCESS == psCompInfo->status)
{
#if (NXP_NFC_HCI_TIMER == 1)
if ( NXP_INVALID_TIMER_ID == hci_resp_timer_id )
{
/* Create and Intialise the Response Timer */
hci_resp_timer_id = phOsalNfc_Timer_Create( );
HCI_DEBUG(" HCI : Timer %X Created \n",
hci_resp_timer_id);
}
else
{
HCI_DEBUG(" HCI : Timer Already Created, Timer ID : %X\n",
hci_resp_timer_id);
}
gpsHciContext = psHciContext;
#endif /* (NXP_NFC_HCI_TIMER == 1) */
/* Complete the Initialisation Sequence */
status = phHciNfc_Resume_Sequence(psContext ,pHwRef);
}
else
{
/* Notify the Error Scenario to the Upper Layer */
phHciNfc_Notify(psHciContext->p_upper_notify,
psHciContext->p_upper_context, pHwRef,
NFC_NOTIFY_ERROR, psCompInfo);
}
break;
}
case NFC_NOTIFY_INIT_FAILED:
{
/* Notify the Failure to the Upper Layer */
phHciNfc_Release_Notify( psContext,pHwRef,
type, pInfo );
break;
}
case NFC_NOTIFY_RECV_COMPLETED:
{
/* Receive Completed from the Lower Layer */
phHciNfc_Receive_Complete(psContext,pHwRef,pInfo);
break;
}
case NFC_NOTIFY_SEND_COMPLETED:
{
/* Receive Completed from the Lower Layer */
phHciNfc_Send_Complete(psContext,pHwRef,pInfo);
break;
}
case NFC_NOTIFY_TRANSCEIVE_COMPLETED:
{
/* TODO: TO handle Both Send and Receive Complete */
break;
}
case NFC_NOTIFY_TARGET_DISCOVERED:
{
HCI_PRINT(" PICC Discovery ! Obtain PICC Info .... \n");
/* psHciContext->hci_seq = PL_DURATION_SEQ; */
if ( hciState_Unknown == psHciContext->hci_state.next_state )
{
status = phHciNfc_FSM_Update ( psHciContext, hciState_Select );
if (NFCSTATUS_SUCCESS != status)
{
status = phHciNfc_ReaderMgmt_Deselect(
psHciContext, pHwRef, phHal_eISO14443_A_PICC, FALSE);
}
}
else
{
#ifdef SW_RELEASE_TARGET
/*status = phHciNfc_ReaderMgmt_Deselect(
psHciContext, pHwRef, phHal_eISO14443_A_PICC, FALSE); */
psHciContext->target_release = TRUE;
#else
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE);
#endif
}
break;
}
/* To Notify the Target Released Notification
* to the Above Layer */
case NFC_NOTIFY_TARGET_RELEASED:
/* To Notify the NFC Secure Element Transaction
* Information to the Above Layer */
/* case NFC_NOTIFY_TRANSACTION: */
/* To Notify the Generic Events To the Upper
* Layer */
case NFC_NOTIFY_EVENT:
/* To Notify the Data Receive Notification
* to the Above Layer */
case NFC_NOTIFY_RECV_EVENT:
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
if (((TRUE == psHciContext->event_pending) ||
(NFCSTATUS_RF_TIMEOUT == psCompInfo->status))
&& ( hciState_Transact == psHciContext->hci_state.next_state))
{
/* Rollback due to Transmission Error */
phHciNfc_FSM_Rollback(psHciContext);
}
psHciContext->event_pending = FALSE;
phHciNfc_Notify(psHciContext->p_upper_notify,
psHciContext->p_upper_context, pHwRef,
type, pInfo);
break;
}
case NFC_NOTIFY_DEVICE_ACTIVATED:
{
HCI_PRINT(" Device Activated! Obtaining Remote Reader Info .... \n");
if ( hciState_Unknown == psHciContext->hci_state.next_state )
{
switch (psHciContext->host_rf_type)
{
case phHal_eISO14443_A_PCD:
case phHal_eISO14443_B_PCD:
case phHal_eISO14443_BPrime_PCD:
case phHal_eFelica_PCD:
{
break;
}
case phHal_eNfcIP1_Initiator:
case phHal_eNfcIP1_Target:
{
break;
}
case phHal_eUnknown_DevType:
default:
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INVALID_PARAMETER);
break;
}
}
status = phHciNfc_FSM_Update ( psHciContext, hciState_Listen );
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE);
}
break;
}
case NFC_NOTIFY_DEVICE_DEACTIVATED:
{
HCI_PRINT(" Device De-Activated! \n");
if ( hciState_Unknown == psHciContext->hci_state.next_state )
{
status = phHciNfc_FSM_Update ( psHciContext, hciState_Initialise );
if(NFCSTATUS_SUCCESS == status)
{
/* Complete to the Select State */
status = phHciNfc_FSM_Complete(psHciContext);
}
else
{
HCI_PRINT(" Device Deactivated.. But Invalid State \n");
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE);
}
}
else
{
status = phHciNfc_ReaderMgmt_Update_Sequence(
psHciContext, INFO_SEQ );
if(( hciState_Listen == psHciContext->hci_state.next_state)
|| (hciState_Transact == psHciContext->hci_state.next_state))
{
psHciContext->hci_state.next_state = hciState_Initialise;
/* Roll Back to the Default State */
status = phHciNfc_FSM_Complete(psHciContext);
}
}
psHciContext->event_pending = FALSE;
phHciNfc_Notify(psHciContext->p_upper_notify,
psHciContext->p_upper_context, pHwRef,
NFC_NOTIFY_EVENT, pInfo);
break;
}
case NFC_NOTIFY_DEVICE_ERROR:
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
psCompInfo->status = ( NFCSTATUS_BOARD_COMMUNICATION_ERROR
!= PHNFCSTATUS(psCompInfo->status))?
NFCSTATUS_BOARD_COMMUNICATION_ERROR:
psCompInfo->status ;
#if (NXP_NFC_HCI_TIMER == 1)
if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id )
{
HCI_DEBUG(" HCI : Response Timer Stop, Status:%02X",
psCompInfo->status);
/* Stop and Un-Intialise the Response Timer */
phOsalNfc_Timer_Stop( hci_resp_timer_id );
}
#endif /* (NXP_NFC_HCI_TIMER == 1) */
phHciNfc_Notify(psHciContext->p_upper_notify,
psHciContext->p_upper_context, pHwRef,
(uint8_t) NFC_NOTIFY_DEVICE_ERROR, pInfo);
break;
}
case NFC_NOTIFY_ERROR:
default:
{
phNfc_sCompletionInfo_t *psCompInfo =
(phNfc_sCompletionInfo_t *)pInfo;
#if (NXP_NFC_HCI_TIMER == 1)
if (( NFCSTATUS_BOARD_COMMUNICATION_ERROR == PHNFCSTATUS(psCompInfo->status))
&& ( NXP_INVALID_TIMER_ID != hci_resp_timer_id ))
{
HCI_DEBUG(" HCI : Response Timer Stop, Status:%02X",
psCompInfo->status);
/* Stop the HCI Response Timer */
phOsalNfc_Timer_Stop( hci_resp_timer_id );
}
#endif /* (NXP_NFC_HCI_TIMER == 1) */
phHciNfc_Error_Sequence( psHciContext, pHwRef,
psCompInfo->status, NULL, 0);
break;
}
} /* End of Switch */
} /* End of Context != NULL */
}