From 9224c881cf3f8575194823a6c779c0d65c42258a Mon Sep 17 00:00:00 2001 From: Arian Date: Mon, 30 Sep 2019 11:10:42 +0200 Subject: shinano-common: pn54x: Import from lineage-15.1 * https://github.com/LineageOS/android_system_nfc/tree/lineage-15.1/halimpl/pn54x/common * support for pn54x has been dropped in lineage-16.0 and above Change-Id: I19f2c3a6e3066bf9aaaaf4ddcd7d7ad867de0ed8 --- pn54x/tml/phTmlNfc.c | 949 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 949 insertions(+) create mode 100644 pn54x/tml/phTmlNfc.c (limited to 'pn54x/tml/phTmlNfc.c') diff --git a/pn54x/tml/phTmlNfc.c b/pn54x/tml/phTmlNfc.c new file mode 100644 index 0000000..8aad810 --- /dev/null +++ b/pn54x/tml/phTmlNfc.c @@ -0,0 +1,949 @@ +/* + * 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 +#include +#include +#include +#include +#include + +/* + * 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; +} -- cgit v1.2.3