/*
* 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_CE_A.c *
* \brief HCI card emulation A management routines. *
* *
* *
* Project: NFC-FRI-1.1 *
* *
* $Date: Fri Aug 21 18:35:05 2009 $ *
* $Author: ing04880 $ *
* $Revision: 1.14 $ *
* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
* *
* =========================================================================== *
*/
/*
***************************** Header File Inclusion ****************************
*/
#include <phNfcCompId.h>
#include <phNfcHalTypes.h>
#include <phHciNfc_Pipe.h>
#include <phHciNfc_Emulation.h>
#include <phOsalNfc.h>
/*
****************************** Macro Definitions *******************************
*/
#if defined (HOST_EMULATION)
#include <phHciNfc_CE_A.h>
#define CE_A_EVT_NFC_SEND_DATA 0x10U
#define CE_A_EVT_NFC_FIELD_ON 0x11U
#define CE_A_EVT_NFC_DEACTIVATED 0x12U
#define CE_A_EVT_NFC_ACTIVATED 0x13U
#define CE_A_EVT_NFC_FIELD_OFF 0x14U
/*
*************************** Structure and Enumeration ***************************
*/
/*
*************************** Static Function Declaration **************************
*/
static
NFCSTATUS
phHciNfc_Recv_CE_A_Event(
void *psContext,
void *pHwRef,
uint8_t *pEvent,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
static
NFCSTATUS
phHciNfc_Recv_CE_A_Response(
void *psContext,
void *pHwRef,
uint8_t *pResponse,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
);
#if defined (SEND_DATA_EVENT)
static
NFCSTATUS
phHciNfc_CE_A_ProcessData(
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t *pData,
uint8_t length
);
#endif /* #if defined (SEND_DATA_EVENT) */
/*
*************************** Function Definitions ***************************
*/
NFCSTATUS
phHciNfc_CE_A_Init_Resources(
phHciNfc_sContext_t *psHciContext
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
if( NULL == psHciContext )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else
{
if(
( NULL == psHciContext->p_ce_a_info ) &&
(phHciNfc_Allocate_Resource((void **)(&ps_ce_a_info),
sizeof(phHciNfc_CE_A_Info_t))== NFCSTATUS_SUCCESS)
)
{
psHciContext->p_ce_a_info = ps_ce_a_info;
ps_ce_a_info->current_seq = HOST_CE_A_INVALID_SEQ;
ps_ce_a_info->next_seq = HOST_CE_A_INVALID_SEQ;
ps_ce_a_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES);
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Initialise(
phHciNfc_sContext_t *psHciContext,
void *pHwRef
)
{
/*
1. Open Pipe,
2. Set all parameters
*/
NFCSTATUS status = NFCSTATUS_SUCCESS;
static uint8_t sak = HOST_CE_A_SAK_DEFAULT;
static uint8_t atqa_info[] = { NXP_CE_A_ATQA_HIGH,
NXP_CE_A_ATQA_LOW};
if ((NULL == psHciContext) || (NULL == pHwRef))
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_CE_A_Info_t *ps_ce_a_info = ((phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info );
phHciNfc_Pipe_Info_t *ps_pipe_info = NULL;
ps_pipe_info = ps_ce_a_info->p_pipe_info;
if(NULL == ps_pipe_info )
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INVALID_HCI_INFORMATION);
}
else
{
switch(ps_ce_a_info->current_seq)
{
case HOST_CE_A_PIPE_OPEN:
{
status = phHciNfc_Open_Pipe( psHciContext,
pHwRef, ps_pipe_info );
if(status == NFCSTATUS_SUCCESS)
{
ps_ce_a_info->next_seq = HOST_CE_A_SAK_SEQ;
status = NFCSTATUS_PENDING;
}
break;
}
case HOST_CE_A_SAK_SEQ:
{
/* HOST Card Emulation A SAK Configuration */
ps_pipe_info->reg_index = HOST_CE_A_SAK_INDEX;
/* Configure the SAK of Host Card Emulation A */
sak = (uint8_t)HOST_CE_A_SAK_DEFAULT;
ps_pipe_info->param_info =(void*)&sak ;
ps_pipe_info->param_length = sizeof(sak) ;
status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef,
ps_pipe_info->pipe.pipe_id,
(uint8_t)ANY_SET_PARAMETER);
if(status == NFCSTATUS_PENDING)
{
ps_ce_a_info->next_seq = HOST_CE_A_ATQA_SEQ;
}
break;
}
case HOST_CE_A_ATQA_SEQ:
{
/* HOST Card Emulation A ATQA Configuration */
ps_pipe_info->reg_index = HOST_CE_A_ATQA_INDEX;
/* Configure the ATQA of Host Card Emulation A */
ps_pipe_info->param_info = (void*)atqa_info ;
ps_pipe_info->param_length = sizeof(atqa_info) ;
status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef,
ps_pipe_info->pipe.pipe_id,
(uint8_t)ANY_SET_PARAMETER);
if(status == NFCSTATUS_PENDING)
{
ps_ce_a_info->next_seq = HOST_CE_A_ENABLE_SEQ;
}
break;
}
case HOST_CE_A_ENABLE_SEQ:
{
status = phHciNfc_CE_A_Mode( psHciContext,
pHwRef, HOST_CE_MODE_ENABLE );
if(status == NFCSTATUS_PENDING)
{
ps_ce_a_info->next_seq = HOST_CE_A_DISABLE_SEQ;
status = NFCSTATUS_SUCCESS;
}
break;
}
default :
{
break;
}
}
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Release(
phHciNfc_sContext_t *psHciContext,
void *pHwRef
)
{
/*
1. Close pipe
*/
NFCSTATUS status = NFCSTATUS_SUCCESS;
if ((NULL == psHciContext) || (NULL == pHwRef))
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_CE_A_Info_t *ps_ce_a_info = ((phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info );
phHciNfc_Pipe_Info_t *ps_pipe_info = NULL;
ps_pipe_info = ps_ce_a_info->p_pipe_info;
if(NULL == ps_pipe_info )
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_NOT_ALLOWED);
}
else
{
switch(ps_ce_a_info->current_seq)
{
case HOST_CE_A_DISABLE_SEQ:
{
status = phHciNfc_CE_A_Mode( psHciContext,
pHwRef, HOST_CE_MODE_DISABLE );
if(status == NFCSTATUS_PENDING)
{
ps_ce_a_info->next_seq = HOST_CE_A_PIPE_CLOSE;
}
break;
}
case HOST_CE_A_PIPE_CLOSE:
{
/* HOST Card Emulation A pipe close sequence */
status = phHciNfc_Close_Pipe( psHciContext,
pHwRef, ps_pipe_info );
if(status == NFCSTATUS_SUCCESS)
{
ps_ce_a_info->next_seq = HOST_CE_A_PIPE_DELETE;
status = NFCSTATUS_PENDING;
}
break;
}
case HOST_CE_A_PIPE_DELETE:
{
/* HOST Card Emulation A pipe delete sequence */
status = phHciNfc_Delete_Pipe( psHciContext,
pHwRef, ps_pipe_info );
if(status == NFCSTATUS_SUCCESS)
{
#if 0
ps_ce_a_info->pipe_id = HCI_UNKNOWN_PIPE_ID;
psHciContext->p_pipe_list[ps_ce_a_info->pipe_id] = NULL;
phOsalNfc_FreeMemory((void *)ps_ce_a_info->p_pipe_info);
ps_ce_a_info->p_pipe_info = NULL;
#endif
ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN;
}
break;
}
default :
{
break;
}
}
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Update_PipeInfo(
phHciNfc_sContext_t *psHciContext,
uint8_t pipeID,
phHciNfc_Pipe_Info_t *pPipeInfo
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
if( NULL == psHciContext )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
ps_ce_a_info->current_seq = HOST_CE_A_PIPE_OPEN;
ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN;
/* Update the pipe_id of the card emulation A Gate o
btained from the HCI Response */
ps_ce_a_info->pipe_id = pipeID;
if (HCI_UNKNOWN_PIPE_ID != pipeID)
{
ps_ce_a_info->p_pipe_info = pPipeInfo;
if (NULL != pPipeInfo)
{
/* Update the Response Receive routine of the card
emulation A Gate */
pPipeInfo->recv_resp = &phHciNfc_Recv_CE_A_Response;
/* Update the event Receive routine of the card emulation A Gate */
pPipeInfo->recv_event = &phHciNfc_Recv_CE_A_Event;
}
}
else
{
ps_ce_a_info->p_pipe_info = NULL;
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Get_PipeID(
phHciNfc_sContext_t *psHciContext,
uint8_t *ppipe_id
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
if( (NULL != psHciContext)
&& ( NULL != ppipe_id )
&& ( NULL != psHciContext->p_ce_a_info )
)
{
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
*ppipe_id = ps_ce_a_info->pipe_id ;
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
return status;
}
#ifdef CE_A_SEND_EVENT
NFCSTATUS
phHciNfc_CE_A_SendData_Event(
void *psContext,
void *pHwRef,
uint8_t *pEvent,
uint8_t length
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_sContext_t *psHciContext =
(phHciNfc_sContext_t *)psContext ;
return status;
}
#endif /* #ifdef CE_A_SEND_EVENT */
static
NFCSTATUS
phHciNfc_Recv_CE_A_Response(
void *psContext,
void *pHwRef,
uint8_t *pResponse,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_sContext_t *psHciContext =
(phHciNfc_sContext_t *)psContext ;
if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse)
|| (length == 0))
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
uint8_t prev_cmd = ANY_GET_PARAMETER;
ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
if( NULL == ps_ce_a_info->p_pipe_info)
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INVALID_HCI_SEQUENCE);
}
else
{
prev_cmd = ps_ce_a_info->p_pipe_info->prev_msg ;
switch(prev_cmd)
{
case ANY_GET_PARAMETER:
{
#if 0
status = phHciNfc_CE_A_InfoUpdate(psHciContext,
ps_ce_a_info->p_pipe_info->reg_index,
&pResponse[HCP_HEADER_LEN],
(length - HCP_HEADER_LEN));
#endif /* #if 0 */
break;
}
case ANY_SET_PARAMETER:
{
HCI_PRINT("CE A Parameter Set \n");
break;
}
case ANY_OPEN_PIPE:
{
HCI_PRINT("CE A open pipe complete\n");
break;
}
case ANY_CLOSE_PIPE:
{
HCI_PRINT("CE A close pipe complete\n");
break;
}
default:
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE);
break;
}
}
if( NFCSTATUS_SUCCESS == status )
{
status = phHciNfc_CE_A_Update_Seq(psHciContext,
UPDATE_SEQ);
ps_ce_a_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS;
}
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Update_Seq(
phHciNfc_sContext_t *psHciContext,
phHciNfc_eSeqType_t seq_type
)
{
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
NFCSTATUS status = NFCSTATUS_SUCCESS;
if( NULL == psHciContext )
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if( NULL == psHciContext->p_ce_a_info )
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
switch(seq_type)
{
case RESET_SEQ:
case INIT_SEQ:
{
ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN;
ps_ce_a_info->current_seq = HOST_CE_A_PIPE_OPEN;
break;
}
case UPDATE_SEQ:
{
ps_ce_a_info->current_seq = ps_ce_a_info->next_seq;
break;
}
case INFO_SEQ:
{
break;
}
case REL_SEQ:
{
ps_ce_a_info->next_seq = HOST_CE_A_DISABLE_SEQ;
ps_ce_a_info->current_seq = HOST_CE_A_DISABLE_SEQ;
break;
}
default:
{
break;
}
}
}
return status;
}
NFCSTATUS
phHciNfc_CE_A_Mode(
void *psHciHandle,
void *pHwRef,
uint8_t enable_type
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
static uint8_t param = 0 ;
phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle);
if((NULL == psHciContext)||(NULL == pHwRef))
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_CE_A_Info_t *ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
phHciNfc_Pipe_Info_t *p_pipe_info = ps_ce_a_info->p_pipe_info;
if (NULL != p_pipe_info)
{
p_pipe_info->reg_index = HOST_CE_A_MODE_INDEX;
/* Enable/Disable Host Card Emulation A */
param = (uint8_t)enable_type;
p_pipe_info->param_info =(void*)¶m ;
p_pipe_info->param_length = sizeof(param) ;
status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef,
ps_ce_a_info->pipe_id,(uint8_t)ANY_SET_PARAMETER);
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED);
}
}
return status;
}
static
NFCSTATUS
phHciNfc_Recv_CE_A_Event(
void *psContext,
void *pHwRef,
uint8_t *pEvent,
#ifdef ONE_BYTE_LEN
uint8_t length
#else
uint16_t length
#endif
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
phHciNfc_sContext_t *psHciContext =
(phHciNfc_sContext_t *)psContext ;
if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent)
|| (length == 0))
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
}
else if(NULL == psHciContext->p_ce_a_info)
{
status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);
}
else
{
phHciNfc_HCP_Packet_t *p_packet = NULL;
phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL;
phHciNfc_HCP_Message_t *message = NULL;
static phHal_sEventInfo_t event_info;
uint8_t instruction=0;
ps_ce_a_info = (phHciNfc_CE_A_Info_t *)
psHciContext->p_ce_a_info ;
/* Variable was set but never used (ARM warning) */
PHNFC_UNUSED_VARIABLE(ps_ce_a_info);
p_packet = (phHciNfc_HCP_Packet_t *)pEvent;
message = &p_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);
psHciContext->host_rf_type = phHal_eISO14443_A_PICC;
event_info.eventHost = phHal_eHostController;
event_info.eventSource = phHal_eISO14443_A_PICC;
switch(instruction)
{
case CE_A_EVT_NFC_ACTIVATED:
{
event_info.eventType = NFC_EVT_ACTIVATED;
/* Notify to the HCI Generic layer To Update the FSM */
break;
}
case CE_A_EVT_NFC_DEACTIVATED:
{
event_info.eventType = NFC_EVT_DEACTIVATED;
HCI_PRINT("CE A Target Deactivated\n");
break;
}
case CE_A_EVT_NFC_SEND_DATA:
{
HCI_PRINT("CE A data is received from the PN544\n");
#if defined (SEND_DATA_EVENT)
if(length > HCP_HEADER_LEN)
{
status = phHciNfc_CE_A_ProcessData(
psHciContext, pHwRef,
&pEvent[HCP_HEADER_LEN],
(length - HCP_HEADER_LEN));
}
else
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INVALID_HCI_RESPONSE);
}
#endif /* #if defined (SEND_DATA_EVENT) */
break;
}
case CE_A_EVT_NFC_FIELD_ON:
{
HCI_PRINT("CE A field on\n");
event_info.eventType = NFC_EVT_FIELD_ON;
break;
}
case CE_A_EVT_NFC_FIELD_OFF:
{
HCI_PRINT("CE A field off\n");
event_info.eventType = NFC_EVT_FIELD_OFF;
break;
}
default:
{
status = PHNFCSTVAL(CID_NFC_HCI,
NFCSTATUS_INVALID_HCI_INSTRUCTION);
break;
}
}
if(NFCSTATUS_SUCCESS == status)
{
phHciNfc_Notify_Event(psHciContext, pHwRef,
NFC_NOTIFY_EVENT,
&event_info);
}
}
return status;
}
#if defined (SEND_DATA_EVENT)
static
NFCSTATUS
phHciNfc_CE_A_ProcessData(
phHciNfc_sContext_t *psHciContext,
void *pHwRef,
uint8_t *pData,
uint8_t length
)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
static uint8_t send_data[] = {0x6D, 0x80};
status = phHciNfc_CE_A_SendData_Event(
(void *)psHciContext, pHwRef,
send_data, sizeof(send_data));
return status;
}
#endif /* #if defined (SEND_DATA_EVENT) */
#endif /* #if defined (HOST_EMULATION) */