You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
949 lines
37 KiB
949 lines
37 KiB
/* |
|
* Copyright (C) 2010-2014 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. |
|
*/ |
|
|
|
/* |
|
* TML Implementation. |
|
*/ |
|
|
|
#include <phDal4Nfc_messageQueueLib.h> |
|
#include <phNxpLog.h> |
|
#include <phNxpNciHal_utils.h> |
|
#include <phOsalNfc_Timer.h> |
|
#include <phTmlNfc.h> |
|
#include <phTmlNfc_i2c.h> |
|
|
|
/* |
|
* Duration of Timer to wait after sending an Nci packet |
|
*/ |
|
#define PHTMLNFC_MAXTIME_RETRANSMIT (200U) |
|
#define MAX_WRITE_RETRY_COUNT 0x03 |
|
/* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 */ |
|
static uint8_t bCurrentRetryCount = (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; |
|
|
|
/* Value to reset variables of TML */ |
|
#define PH_TMLNFC_RESET_VALUE (0x00) |
|
|
|
/* Indicates a Initial or offset value */ |
|
#define PH_TMLNFC_VALUE_ONE (0x01) |
|
|
|
/* Initialize Context structure pointer used to access context structure */ |
|
phTmlNfc_Context_t* gpphTmlNfc_Context = NULL; |
|
phTmlNfc_i2cfragmentation_t fragmentation_enabled = I2C_FRAGMENATATION_DISABLED; |
|
/* Local Function prototypes */ |
|
static NFCSTATUS phTmlNfc_StartThread(void); |
|
static void phTmlNfc_CleanUp(void); |
|
static void phTmlNfc_ReadDeferredCb(void* pParams); |
|
static void phTmlNfc_WriteDeferredCb(void* pParams); |
|
static void phTmlNfc_TmlThread(void* pParam); |
|
static void phTmlNfc_TmlWriterThread(void* pParam); |
|
static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext); |
|
static NFCSTATUS phTmlNfc_InitiateTimer(void); |
|
|
|
/* Function definitions */ |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_Init |
|
** |
|
** Description Provides initialization of TML layer and hardware interface |
|
** Configures given hardware interface and sends handle to the |
|
** caller |
|
** |
|
** Parameters pConfig - TML configuration details as provided by the upper |
|
** layer |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - initialization successful |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_FAILED - initialization failed (for example, |
|
** unable to open hardware interface) |
|
** NFCSTATUS_INVALID_DEVICE - device has not been opened or has |
|
** been disconnected |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) { |
|
NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS; |
|
|
|
/* Check if TML layer is already Initialized */ |
|
if (NULL != gpphTmlNfc_Context) { |
|
/* TML initialization is already completed */ |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED); |
|
} |
|
/* Validate Input parameters */ |
|
else if ((NULL == pConfig) || |
|
(PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) { |
|
/*Parameters passed to TML init are wrong */ |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); |
|
} else { |
|
/* Allocate memory for TML context */ |
|
gpphTmlNfc_Context = malloc(sizeof(phTmlNfc_Context_t)); |
|
|
|
if (NULL == gpphTmlNfc_Context) { |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); |
|
} else { |
|
/* Initialise all the internal TML variables */ |
|
memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE, |
|
sizeof(phTmlNfc_Context_t)); |
|
/* Make sure that the thread runs once it is created */ |
|
gpphTmlNfc_Context->bThreadDone = 1; |
|
|
|
/* Open the device file to which data is read/written */ |
|
wInitStatus = phTmlNfc_i2c_open_and_configure( |
|
pConfig, &(gpphTmlNfc_Context->pDevHandle)); |
|
|
|
if (NFCSTATUS_SUCCESS != wInitStatus) { |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE); |
|
gpphTmlNfc_Context->pDevHandle = NULL; |
|
} else { |
|
gpphTmlNfc_Context->tReadInfo.bEnable = 0; |
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 0; |
|
gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; |
|
gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; |
|
|
|
if (0 != sem_init(&gpphTmlNfc_Context->rxSemaphore, 0, 0)) { |
|
wInitStatus = NFCSTATUS_FAILED; |
|
} else if (0 != sem_init(&gpphTmlNfc_Context->txSemaphore, 0, 0)) { |
|
wInitStatus = NFCSTATUS_FAILED; |
|
} else if (0 != sem_init(&gpphTmlNfc_Context->postMsgSemaphore, 0, 0)) { |
|
wInitStatus = NFCSTATUS_FAILED; |
|
} else { |
|
sem_post(&gpphTmlNfc_Context->postMsgSemaphore); |
|
/* Start TML thread (to handle write and read operations) */ |
|
if (NFCSTATUS_SUCCESS != phTmlNfc_StartThread()) { |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); |
|
} else { |
|
/* Create Timer used for Retransmission of NCI packets */ |
|
gpphTmlNfc_Context->dwTimerId = phOsalNfc_Timer_Create(); |
|
if (PH_OSALNFC_TIMER_ID_INVALID != gpphTmlNfc_Context->dwTimerId) { |
|
/* Store the Thread Identifier to which Message is to be posted */ |
|
gpphTmlNfc_Context->dwCallbackThreadId = |
|
pConfig->dwGetMsgThreadId; |
|
/* Enable retransmission of Nci packet & set retry count to |
|
* default */ |
|
gpphTmlNfc_Context->eConfig = phTmlNfc_e_DisableRetrans; |
|
/* Retry Count = Standby Recovery time of NFCC / Retransmission |
|
* time + 1 */ |
|
gpphTmlNfc_Context->bRetryCount = |
|
(2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; |
|
gpphTmlNfc_Context->bWriteCbInvoked = false; |
|
} else { |
|
wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
/* Clean up all the TML resources if any error */ |
|
if (NFCSTATUS_SUCCESS != wInitStatus) { |
|
/* Clear all handles and memory locations initialized during init */ |
|
phTmlNfc_CleanUp(); |
|
} |
|
|
|
return wInitStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_ConfigNciPktReTx |
|
** |
|
** Description Provides Enable/Disable Retransmission of NCI packets |
|
** Needed in case of Timeout between Transmission and Reception |
|
** of NCI packets. Retransmission can be enabled only if |
|
** standby mode is enabled |
|
** |
|
** Parameters eConfig - values from phTmlNfc_ConfigRetrans_t |
|
** bRetryCount - Number of times Nci packets shall be |
|
** retransmitted (default = 3) |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration, |
|
uint8_t bRetryCounter) { |
|
/* Enable/Disable Retransmission */ |
|
|
|
gpphTmlNfc_Context->eConfig = eConfiguration; |
|
if (phTmlNfc_e_EnableRetrans == eConfiguration) { |
|
/* Check whether Retry counter passed is valid */ |
|
if (0 != bRetryCounter) { |
|
gpphTmlNfc_Context->bRetryCount = bRetryCounter; |
|
} |
|
/* Set retry counter to its default value */ |
|
else { |
|
/* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 |
|
*/ |
|
gpphTmlNfc_Context->bRetryCount = |
|
(2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; |
|
} |
|
} |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_StartThread |
|
** |
|
** Description Initializes comport, reader and writer threads |
|
** |
|
** Parameters None |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - threads initialized successfully |
|
** NFCSTATUS_FAILED - initialization failed due to system error |
|
** |
|
*******************************************************************************/ |
|
static NFCSTATUS phTmlNfc_StartThread(void) { |
|
NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS; |
|
void* h_threadsEvent = 0x00; |
|
uint32_t dwEvent; |
|
int pthread_create_status = 0; |
|
|
|
/* Create Reader and Writer threads */ |
|
pthread_create_status = |
|
pthread_create(&gpphTmlNfc_Context->readerThread, NULL, |
|
(void*)&phTmlNfc_TmlThread, (void*)h_threadsEvent); |
|
if (0 != pthread_create_status) { |
|
wStartStatus = NFCSTATUS_FAILED; |
|
} else { |
|
/*Start Writer Thread*/ |
|
pthread_create_status = |
|
pthread_create(&gpphTmlNfc_Context->writerThread, NULL, |
|
(void*)&phTmlNfc_TmlWriterThread, (void*)h_threadsEvent); |
|
if (0 != pthread_create_status) { |
|
wStartStatus = NFCSTATUS_FAILED; |
|
} |
|
} |
|
|
|
return wStartStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_ReTxTimerCb |
|
** |
|
** Description This is the timer callback function after timer expiration. |
|
** |
|
** Parameters dwThreadId - id of the thread posting message |
|
** pContext - context provided by upper layer |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext) { |
|
if ((gpphTmlNfc_Context->dwTimerId == dwTimerId) && (NULL == pContext)) { |
|
/* If Retry Count has reached its limit,Retransmit Nci |
|
packet */ |
|
if (0 == bCurrentRetryCount) { |
|
/* Since the count has reached its limit,return from timer callback |
|
Upper layer Timeout would have happened */ |
|
} else { |
|
bCurrentRetryCount--; |
|
gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; |
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 1; |
|
} |
|
sem_post(&gpphTmlNfc_Context->txSemaphore); |
|
} |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_InitiateTimer |
|
** |
|
** Description Start a timer for Tx and Rx thread. |
|
** |
|
** Parameters void |
|
** |
|
** Returns NFC status |
|
** |
|
*******************************************************************************/ |
|
static NFCSTATUS phTmlNfc_InitiateTimer(void) { |
|
NFCSTATUS wStatus = NFCSTATUS_SUCCESS; |
|
|
|
/* Start Timer once Nci packet is sent */ |
|
wStatus = phOsalNfc_Timer_Start(gpphTmlNfc_Context->dwTimerId, |
|
(uint32_t)PHTMLNFC_MAXTIME_RETRANSMIT, |
|
phTmlNfc_ReTxTimerCb, NULL); |
|
|
|
return wStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_TmlThread |
|
** |
|
** Description Read the data from the lower layer driver |
|
** |
|
** Parameters pParam - parameters for Writer thread function |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_TmlThread(void* pParam) { |
|
NFCSTATUS wStatus = NFCSTATUS_SUCCESS; |
|
int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; |
|
uint8_t temp[260]; |
|
/* Transaction info buffer to be passed to Callback Thread */ |
|
static phTmlNfc_TransactInfo_t tTransactionInfo; |
|
/* Structure containing Tml callback function and parameters to be invoked |
|
by the callback thread */ |
|
static phLibNfc_DeferredCall_t tDeferredInfo; |
|
/* Initialize Message structure to post message onto Callback Thread */ |
|
static phLibNfc_Message_t tMsg; |
|
UNUSED(pParam); |
|
NXPLOG_TML_D("PN54X - Tml Reader Thread Started................\n"); |
|
|
|
/* Writer thread loop shall be running till shutdown is invoked */ |
|
while (gpphTmlNfc_Context->bThreadDone) { |
|
/* If Tml write is requested */ |
|
/* Set the variable to success initially */ |
|
wStatus = NFCSTATUS_SUCCESS; |
|
sem_wait(&gpphTmlNfc_Context->rxSemaphore); |
|
|
|
/* If Tml read is requested */ |
|
if (1 == gpphTmlNfc_Context->tReadInfo.bEnable) { |
|
NXPLOG_TML_D("PN54X - Read requested.....\n"); |
|
/* Set the variable to success initially */ |
|
wStatus = NFCSTATUS_SUCCESS; |
|
|
|
/* Variable to fetch the actual number of bytes read */ |
|
dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; |
|
|
|
/* Read the data from the file onto the buffer */ |
|
if (NULL != gpphTmlNfc_Context->pDevHandle) { |
|
NXPLOG_TML_D("PN54X - Invoking I2C Read.....\n"); |
|
dwNoBytesWrRd = |
|
phTmlNfc_i2c_read(gpphTmlNfc_Context->pDevHandle, temp, 260); |
|
|
|
if (-1 == dwNoBytesWrRd) { |
|
NXPLOG_TML_E("PN54X - Error in I2C Read.....\n"); |
|
sem_post(&gpphTmlNfc_Context->rxSemaphore); |
|
} else if (dwNoBytesWrRd > 260) { |
|
NXPLOG_TML_E("Numer of bytes read exceeds the limit 260.....\n"); |
|
sem_post(&gpphTmlNfc_Context->rxSemaphore); |
|
} else { |
|
memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd); |
|
|
|
NXPLOG_TML_D("PN54X - I2C Read successful.....\n"); |
|
/* This has to be reset only after a successful read */ |
|
gpphTmlNfc_Context->tReadInfo.bEnable = 0; |
|
if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && |
|
(0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) { |
|
NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n"); |
|
/* Stop Timer to prevent Retransmission */ |
|
uint32_t timerStatus = |
|
phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId); |
|
if (NFCSTATUS_SUCCESS != timerStatus) { |
|
NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n"); |
|
} else { |
|
gpphTmlNfc_Context->bWriteCbInvoked = false; |
|
} |
|
} |
|
if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { |
|
NXPLOG_TML_D("Delay Read if write thread is busy"); |
|
usleep(2000); /*2ms delay to give prio to write complete */ |
|
} |
|
/* Update the actual number of bytes read including header */ |
|
gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd); |
|
phNxpNciHal_print_packet("RECV", |
|
gpphTmlNfc_Context->tReadInfo.pBuffer, |
|
gpphTmlNfc_Context->tReadInfo.wLength); |
|
|
|
dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; |
|
|
|
/* Fill the Transaction info structure to be passed to Callback |
|
* Function */ |
|
tTransactionInfo.wStatus = wStatus; |
|
tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer; |
|
/* Actual number of bytes read is filled in the structure */ |
|
tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength; |
|
|
|
/* Read operation completed successfully. Post a Message onto Callback |
|
* Thread*/ |
|
/* Prepare the message to be posted on User thread */ |
|
tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb; |
|
tDeferredInfo.pParameter = &tTransactionInfo; |
|
tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; |
|
tMsg.pMsgData = &tDeferredInfo; |
|
tMsg.Size = sizeof(tDeferredInfo); |
|
NXPLOG_TML_D("PN54X - Posting read message.....\n"); |
|
phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); |
|
} |
|
} else { |
|
NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL"); |
|
} |
|
} else { |
|
NXPLOG_TML_D("PN54X - read request NOT enabled"); |
|
usleep(10 * 1000); |
|
} |
|
} /* End of While loop */ |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_TmlWriterThread |
|
** |
|
** Description Writes the requested data onto the lower layer driver |
|
** |
|
** Parameters pParam - context provided by upper layer |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_TmlWriterThread(void* pParam) { |
|
NFCSTATUS wStatus = NFCSTATUS_SUCCESS; |
|
int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; |
|
/* Transaction info buffer to be passed to Callback Thread */ |
|
static phTmlNfc_TransactInfo_t tTransactionInfo; |
|
/* Structure containing Tml callback function and parameters to be invoked |
|
by the callback thread */ |
|
static phLibNfc_DeferredCall_t tDeferredInfo; |
|
/* Initialize Message structure to post message onto Callback Thread */ |
|
static phLibNfc_Message_t tMsg; |
|
/* In case of I2C Write Retry */ |
|
static uint16_t retry_cnt; |
|
UNUSED(pParam); |
|
NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n"); |
|
|
|
/* Writer thread loop shall be running till shutdown is invoked */ |
|
while (gpphTmlNfc_Context->bThreadDone) { |
|
NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n"); |
|
sem_wait(&gpphTmlNfc_Context->txSemaphore); |
|
/* If Tml write is requested */ |
|
if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) { |
|
NXPLOG_TML_D("PN54X - Write requested.....\n"); |
|
/* Set the variable to success initially */ |
|
wStatus = NFCSTATUS_SUCCESS; |
|
if (NULL != gpphTmlNfc_Context->pDevHandle) { |
|
retry: |
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 0; |
|
/* Variable to fetch the actual number of bytes written */ |
|
dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; |
|
/* Write the data in the buffer onto the file */ |
|
NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n"); |
|
dwNoBytesWrRd = |
|
phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle, |
|
gpphTmlNfc_Context->tWriteInfo.pBuffer, |
|
gpphTmlNfc_Context->tWriteInfo.wLength); |
|
|
|
/* Try I2C Write Five Times, if it fails : Raju */ |
|
if (-1 == dwNoBytesWrRd) { |
|
if (getDownloadFlag() == true) { |
|
if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) { |
|
NXPLOG_NCIHAL_E("PN54X - Error in I2C Write - Retry 0x%x", |
|
retry_cnt); |
|
// Add a 10 ms delay to ensure NFCC is not still in stand by mode. |
|
usleep(10 * 1000); |
|
goto retry; |
|
} |
|
} |
|
NXPLOG_TML_E("PN54X - Error in I2C Write.....\n"); |
|
wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); |
|
} else { |
|
phNxpNciHal_print_packet("SEND", |
|
gpphTmlNfc_Context->tWriteInfo.pBuffer, |
|
gpphTmlNfc_Context->tWriteInfo.wLength); |
|
} |
|
retry_cnt = 0; |
|
if (NFCSTATUS_SUCCESS == wStatus) { |
|
NXPLOG_TML_D("PN54X - I2C Write successful.....\n"); |
|
dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE; |
|
} |
|
/* Fill the Transaction info structure to be passed to Callback Function |
|
*/ |
|
tTransactionInfo.wStatus = wStatus; |
|
tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer; |
|
/* Actual number of bytes written is filled in the structure */ |
|
tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd; |
|
|
|
/* Prepare the message to be posted on the User thread */ |
|
tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb; |
|
tDeferredInfo.pParameter = &tTransactionInfo; |
|
/* Write operation completed successfully. Post a Message onto Callback |
|
* Thread*/ |
|
tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; |
|
tMsg.pMsgData = &tDeferredInfo; |
|
tMsg.Size = sizeof(tDeferredInfo); |
|
|
|
/* Check whether Retransmission needs to be started, |
|
* If yes, Post message only if |
|
* case 1. Message is not posted && |
|
* case 11. Write status is success || |
|
* case 12. Last retry of write is also failure |
|
*/ |
|
if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && |
|
(0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { |
|
if (gpphTmlNfc_Context->bWriteCbInvoked == false) { |
|
if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) { |
|
NXPLOG_TML_D("PN54X - Posting Write message.....\n"); |
|
phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, |
|
&tMsg); |
|
gpphTmlNfc_Context->bWriteCbInvoked = true; |
|
} |
|
} |
|
} else { |
|
NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n"); |
|
phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); |
|
} |
|
} else { |
|
NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL"); |
|
} |
|
|
|
/* If Data packet is sent, then NO retransmission */ |
|
if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && |
|
(0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { |
|
NXPLOG_TML_D("PN54X - Starting timer for Retransmission case"); |
|
wStatus = phTmlNfc_InitiateTimer(); |
|
if (NFCSTATUS_SUCCESS != wStatus) { |
|
/* Reset Variables used for Retransmission */ |
|
NXPLOG_TML_D("PN54X - Retransmission timer initiate failed"); |
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 0; |
|
bCurrentRetryCount = 0; |
|
} |
|
} |
|
} else { |
|
NXPLOG_TML_D("PN54X - Write request NOT enabled"); |
|
usleep(10000); |
|
} |
|
|
|
} /* End of While loop */ |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_CleanUp |
|
** |
|
** Description Clears all handles opened during TML initialization |
|
** |
|
** Parameters None |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_CleanUp(void) { |
|
NFCSTATUS wRetval = NFCSTATUS_SUCCESS; |
|
|
|
if (NULL == gpphTmlNfc_Context) { |
|
return; |
|
} |
|
if (NULL != gpphTmlNfc_Context->pDevHandle) { |
|
(void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); |
|
gpphTmlNfc_Context->bThreadDone = 0; |
|
} |
|
sem_destroy(&gpphTmlNfc_Context->rxSemaphore); |
|
sem_destroy(&gpphTmlNfc_Context->txSemaphore); |
|
sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore); |
|
phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle); |
|
gpphTmlNfc_Context->pDevHandle = NULL; |
|
/* Clear memory allocated for storing Context variables */ |
|
free((void*)gpphTmlNfc_Context); |
|
/* Set the pointer to NULL to indicate De-Initialization */ |
|
gpphTmlNfc_Context = NULL; |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_Shutdown |
|
** |
|
** Description Uninitializes TML layer and hardware interface |
|
** |
|
** Parameters None |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - TML configuration released successfully |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_FAILED - un-initialization failed (example: unable |
|
** to close interface) |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_Shutdown(void) { |
|
NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS; |
|
|
|
/* Check whether TML is Initialized */ |
|
if (NULL != gpphTmlNfc_Context) { |
|
/* Reset thread variable to terminate the thread */ |
|
gpphTmlNfc_Context->bThreadDone = 0; |
|
usleep(1000); |
|
/* Clear All the resources allocated during initialization */ |
|
sem_post(&gpphTmlNfc_Context->rxSemaphore); |
|
usleep(1000); |
|
sem_post(&gpphTmlNfc_Context->txSemaphore); |
|
usleep(1000); |
|
sem_post(&gpphTmlNfc_Context->postMsgSemaphore); |
|
usleep(1000); |
|
sem_post(&gpphTmlNfc_Context->postMsgSemaphore); |
|
usleep(1000); |
|
if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) { |
|
NXPLOG_TML_E("Fail to kill reader thread!"); |
|
} |
|
if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) { |
|
NXPLOG_TML_E("Fail to kill writer thread!"); |
|
} |
|
NXPLOG_TML_D("bThreadDone == 0"); |
|
|
|
phTmlNfc_CleanUp(); |
|
} else { |
|
wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); |
|
} |
|
|
|
return wShutdownStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_Write |
|
** |
|
** Description Asynchronously writes given data block to hardware |
|
** interface/driver. Enables writer thread if there are no |
|
** write requests pending. Returns successfully once writer |
|
** thread completes write operation. Notifies upper layer using |
|
** callback mechanism. |
|
** |
|
** NOTE: |
|
** * it is important to post a message with id |
|
** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data |
|
** has been written to PN54X |
|
** * if CRC needs to be computed, then input buffer should be |
|
** capable to store two more bytes apart from length of |
|
** packet |
|
** |
|
** Parameters pBuffer - data to be sent |
|
** wLength - length of data buffer |
|
** pTmlWriteComplete - pointer to the function to be invoked |
|
** upon completion |
|
** pContext - context provided by upper layer |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_PENDING - command is yet to be processed |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_BUSY - write request is already in progress |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength, |
|
pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, |
|
void* pContext) { |
|
NFCSTATUS wWriteStatus; |
|
|
|
/* Check whether TML is Initialized */ |
|
|
|
if (NULL != gpphTmlNfc_Context) { |
|
if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) && |
|
(PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) { |
|
if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { |
|
/* Setting the flag marks beginning of a Write Operation */ |
|
gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; |
|
/* Copy the buffer, length and Callback function, |
|
This shall be utilized while invoking the Callback function in thread |
|
*/ |
|
gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer; |
|
gpphTmlNfc_Context->tWriteInfo.wLength = wLength; |
|
gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete; |
|
gpphTmlNfc_Context->tWriteInfo.pContext = pContext; |
|
|
|
wWriteStatus = NFCSTATUS_PENDING; |
|
// FIXME: If retry is going on. Stop the retry thread/timer |
|
if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) { |
|
/* Set retry count to default value */ |
|
// FIXME: If the timer expired there, and meanwhile we have created |
|
// a new request. The expired timer will think that retry is still |
|
// ongoing. |
|
bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount; |
|
gpphTmlNfc_Context->bWriteCbInvoked = false; |
|
} |
|
/* Set event to invoke Writer Thread */ |
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 1; |
|
sem_post(&gpphTmlNfc_Context->txSemaphore); |
|
} else { |
|
wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); |
|
} |
|
} else { |
|
wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); |
|
} |
|
} else { |
|
wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); |
|
} |
|
|
|
return wWriteStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_Read |
|
** |
|
** Description Asynchronously reads data from the driver |
|
** Number of bytes to be read and buffer are passed by upper |
|
** layer. |
|
** Enables reader thread if there are no read requests pending |
|
** Returns successfully once read operation is completed |
|
** Notifies upper layer using callback mechanism |
|
** |
|
** Parameters pBuffer - location to send read data to the upper layer via |
|
** callback |
|
** wLength - length of read data buffer passed by upper layer |
|
** pTmlReadComplete - pointer to the function to be invoked |
|
** upon completion of read operation |
|
** pContext - context provided by upper layer |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_PENDING - command is yet to be processed |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_BUSY - read request is already in progress |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength, |
|
pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, |
|
void* pContext) { |
|
NFCSTATUS wReadStatus; |
|
|
|
/* Check whether TML is Initialized */ |
|
if (NULL != gpphTmlNfc_Context) { |
|
if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) && |
|
(PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) { |
|
if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) { |
|
/* Setting the flag marks beginning of a Read Operation */ |
|
gpphTmlNfc_Context->tReadInfo.bThreadBusy = true; |
|
/* Copy the buffer, length and Callback function, |
|
This shall be utilized while invoking the Callback function in thread |
|
*/ |
|
gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer; |
|
gpphTmlNfc_Context->tReadInfo.wLength = wLength; |
|
gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; |
|
gpphTmlNfc_Context->tReadInfo.pContext = pContext; |
|
wReadStatus = NFCSTATUS_PENDING; |
|
|
|
/* Set event to invoke Reader Thread */ |
|
gpphTmlNfc_Context->tReadInfo.bEnable = 1; |
|
sem_post(&gpphTmlNfc_Context->rxSemaphore); |
|
} else { |
|
wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); |
|
} |
|
} else { |
|
wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); |
|
} |
|
} else { |
|
wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); |
|
} |
|
|
|
return wReadStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_ReadAbort |
|
** |
|
** Description Aborts pending read request (if any) |
|
** |
|
** Parameters None |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - ongoing read operation aborted |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized |
|
** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read |
|
** operation |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_ReadAbort(void) { |
|
NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; |
|
gpphTmlNfc_Context->tReadInfo.bEnable = 0; |
|
|
|
/*Reset the flag to accept another Read Request */ |
|
gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; |
|
wStatus = NFCSTATUS_SUCCESS; |
|
|
|
return wStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_WriteAbort |
|
** |
|
** Description Aborts pending write request (if any) |
|
** |
|
** Parameters None |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - ongoing write operation aborted |
|
** NFCSTATUS_INVALID_PARAMETER - at least one parameter is |
|
** invalid |
|
** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized |
|
** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write |
|
** operation |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_WriteAbort(void) { |
|
NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; |
|
|
|
gpphTmlNfc_Context->tWriteInfo.bEnable = 0; |
|
/* Stop if any retransmission is in progress */ |
|
bCurrentRetryCount = 0; |
|
|
|
/* Reset the flag to accept another Write Request */ |
|
gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; |
|
wStatus = NFCSTATUS_SUCCESS; |
|
|
|
return wStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_IoCtl |
|
** |
|
** Description Resets device when insisted by upper layer |
|
** Number of bytes to be read and buffer are passed by upper |
|
** layer |
|
** Enables reader thread if there are no read requests pending |
|
** Returns successfully once read operation is completed |
|
** Notifies upper layer using callback mechanism |
|
** |
|
** Parameters eControlCode - control code for a specific operation |
|
** |
|
** Returns NFC status: |
|
** NFCSTATUS_SUCCESS - ioctl command completed successfully |
|
** NFCSTATUS_FAILED - ioctl command request failed |
|
** |
|
*******************************************************************************/ |
|
NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) { |
|
NFCSTATUS wStatus = NFCSTATUS_SUCCESS; |
|
|
|
if (NULL == gpphTmlNfc_Context) { |
|
wStatus = NFCSTATUS_FAILED; |
|
} else { |
|
switch (eControlCode) { |
|
case phTmlNfc_e_ResetDevice: { |
|
/*Reset PN54X*/ |
|
phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); |
|
usleep(100 * 1000); |
|
phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); |
|
usleep(100 * 1000); |
|
phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); |
|
break; |
|
} |
|
case phTmlNfc_e_EnableNormalMode: { |
|
/*Reset PN54X*/ |
|
phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); |
|
usleep(10 * 1000); |
|
phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); |
|
usleep(100 * 1000); |
|
break; |
|
} |
|
case phTmlNfc_e_EnableDownloadMode: { |
|
phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0); |
|
(void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 2); |
|
usleep(100 * 1000); |
|
break; |
|
} |
|
default: { |
|
wStatus = NFCSTATUS_INVALID_PARAMETER; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
return wStatus; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_DeferredCall |
|
** |
|
** Description Posts message on upper layer thread |
|
** upon successful read or write operation |
|
** |
|
** Parameters dwThreadId - id of the thread posting message |
|
** ptWorkerMsg - message to be posted |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
void phTmlNfc_DeferredCall(uintptr_t dwThreadId, |
|
phLibNfc_Message_t* ptWorkerMsg) { |
|
intptr_t bPostStatus; |
|
UNUSED(dwThreadId); |
|
/* Post message on the user thread to invoke the callback function */ |
|
sem_wait(&gpphTmlNfc_Context->postMsgSemaphore); |
|
bPostStatus = |
|
phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0); |
|
sem_post(&gpphTmlNfc_Context->postMsgSemaphore); |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_ReadDeferredCb |
|
** |
|
** Description Read thread call back function |
|
** |
|
** Parameters pParams - context provided by upper layer |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_ReadDeferredCb(void* pParams) { |
|
/* Transaction info buffer to be passed to Callback Function */ |
|
phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; |
|
|
|
/* Reset the flag to accept another Read Request */ |
|
gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; |
|
gpphTmlNfc_Context->tReadInfo.pThread_Callback( |
|
gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo); |
|
|
|
return; |
|
} |
|
|
|
/******************************************************************************* |
|
** |
|
** Function phTmlNfc_WriteDeferredCb |
|
** |
|
** Description Write thread call back function |
|
** |
|
** Parameters pParams - context provided by upper layer |
|
** |
|
** Returns None |
|
** |
|
*******************************************************************************/ |
|
static void phTmlNfc_WriteDeferredCb(void* pParams) { |
|
/* Transaction info buffer to be passed to Callback Function */ |
|
phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; |
|
|
|
/* Reset the flag to accept another Write Request */ |
|
gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; |
|
gpphTmlNfc_Context->tWriteInfo.pThread_Callback( |
|
gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo); |
|
|
|
return; |
|
} |
|
|
|
void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) { |
|
fragmentation_enabled = result; |
|
} |
|
|
|
phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() { |
|
return fragmentation_enabled; |
|
}
|
|
|