summaryrefslogtreecommitdiff
path: root/pn54x/tml
diff options
context:
space:
mode:
authorArian <arian.kulmer@web.de>2019-09-30 11:10:42 +0200
committerArian <arian.kulmer@web.de>2019-10-25 22:17:12 +0200
commit9224c881cf3f8575194823a6c779c0d65c42258a (patch)
treeac8a018ff4fdea5a589ca7ee3d88cd88d0d460ba /pn54x/tml
parentfbdbc276d9f25e67e49a7ca03002b838cc9c8548 (diff)
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
Diffstat (limited to 'pn54x/tml')
-rw-r--r--pn54x/tml/phDal4Nfc_messageQueueLib.c234
-rw-r--r--pn54x/tml/phDal4Nfc_messageQueueLib.h34
-rw-r--r--pn54x/tml/phOsalNfc_Timer.c444
-rw-r--r--pn54x/tml/phOsalNfc_Timer.h86
-rw-r--r--pn54x/tml/phTmlNfc.c949
-rw-r--r--pn54x/tml/phTmlNfc.h227
-rw-r--r--pn54x/tml/phTmlNfc_i2c.c315
-rw-r--r--pn54x/tml/phTmlNfc_i2c.h32
8 files changed, 2321 insertions, 0 deletions
diff --git a/pn54x/tml/phDal4Nfc_messageQueueLib.c b/pn54x/tml/phDal4Nfc_messageQueueLib.c
new file mode 100644
index 0000000..f43774d
--- /dev/null
+++ b/pn54x/tml/phDal4Nfc_messageQueueLib.c
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+/*
+ * DAL independent message queue implementation for Android (can be used under
+ * Linux too)
+ */
+
+#include <errno.h>
+#include <linux/ipc.h>
+#include <phDal4Nfc_messageQueueLib.h>
+#include <phNxpLog.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+typedef struct phDal4Nfc_message_queue_item {
+ phLibNfc_Message_t nMsg;
+ struct phDal4Nfc_message_queue_item* pPrev;
+ struct phDal4Nfc_message_queue_item* pNext;
+} phDal4Nfc_message_queue_item_t;
+
+typedef struct phDal4Nfc_message_queue {
+ phDal4Nfc_message_queue_item_t* pItems;
+ pthread_mutex_t nCriticalSectionMutex;
+ sem_t nProcessSemaphore;
+
+} phDal4Nfc_message_queue_t;
+
+/*******************************************************************************
+**
+** Function phDal4Nfc_msgget
+**
+** Description Allocates message queue
+**
+** Parameters Ignored, included only for Linux queue API compatibility
+**
+** Returns (int) value of pQueue if successful
+** -1, if failed to allocate memory or to init mutex
+**
+*******************************************************************************/
+intptr_t phDal4Nfc_msgget(key_t key, int msgflg) {
+ phDal4Nfc_message_queue_t* pQueue;
+ UNUSED(key);
+ UNUSED(msgflg);
+ pQueue =
+ (phDal4Nfc_message_queue_t*)malloc(sizeof(phDal4Nfc_message_queue_t));
+ if (pQueue == NULL) return -1;
+ memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
+ if (pthread_mutex_init(&pQueue->nCriticalSectionMutex, NULL) == -1) {
+ free(pQueue);
+ return -1;
+ }
+ if (sem_init(&pQueue->nProcessSemaphore, 0, 0) == -1) {
+ free(pQueue);
+ return -1;
+ }
+
+ return ((intptr_t)pQueue);
+}
+
+/*******************************************************************************
+**
+** Function phDal4Nfc_msgrelease
+**
+** Description Releases message queue
+**
+** Parameters msqid - message queue handle
+**
+** Returns None
+**
+*******************************************************************************/
+void phDal4Nfc_msgrelease(intptr_t msqid) {
+ phDal4Nfc_message_queue_t* pQueue = (phDal4Nfc_message_queue_t*)msqid;
+
+ if (pQueue != NULL) {
+ sem_post(&pQueue->nProcessSemaphore);
+ usleep(3000);
+ if (sem_destroy(&pQueue->nProcessSemaphore)) {
+ NXPLOG_TML_E("Failed to destroy semaphore (errno=0x%08x)", errno);
+ }
+ pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
+
+ free(pQueue);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phDal4Nfc_msgctl
+**
+** Description Destroys message queue
+**
+** Parameters msqid - message queue handle
+** cmd, buf - ignored, included only for Linux queue API
+** compatibility
+**
+** Returns 0, if successful
+** -1, if invalid handle is passed
+**
+*******************************************************************************/
+int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void* buf) {
+ phDal4Nfc_message_queue_t* pQueue;
+ phDal4Nfc_message_queue_item_t* p;
+ UNUSED(cmd);
+ UNUSED(buf);
+ if (msqid == 0) return -1;
+
+ pQueue = (phDal4Nfc_message_queue_t*)msqid;
+ pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
+ if (pQueue->pItems != NULL) {
+ p = pQueue->pItems;
+ while (p->pNext != NULL) {
+ p = p->pNext;
+ }
+ while (p->pPrev != NULL) {
+ p = p->pPrev;
+ free(p->pNext);
+ p->pNext = NULL;
+ }
+ free(p);
+ }
+ pQueue->pItems = NULL;
+ pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
+ pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
+ free(pQueue);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function phDal4Nfc_msgsnd
+**
+** Description Sends a message to the queue. The message will be added at
+** the end of the queue as appropriate for FIFO policy
+**
+** Parameters msqid - message queue handle
+** msgp - message to be sent
+** msgsz - message size
+** msgflg - ignored
+**
+** Returns 0, if successful
+** -1, if invalid parameter passed or failed to allocate memory
+**
+*******************************************************************************/
+intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t* msg, int msgflg) {
+ phDal4Nfc_message_queue_t* pQueue;
+ phDal4Nfc_message_queue_item_t* p;
+ phDal4Nfc_message_queue_item_t* pNew;
+ UNUSED(msgflg);
+ if ((msqid == 0) || (msg == NULL)) return -1;
+
+ pQueue = (phDal4Nfc_message_queue_t*)msqid;
+ pNew = (phDal4Nfc_message_queue_item_t*)malloc(
+ sizeof(phDal4Nfc_message_queue_item_t));
+ if (pNew == NULL) return -1;
+ memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
+ memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
+ pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
+
+ if (pQueue->pItems != NULL) {
+ p = pQueue->pItems;
+ while (p->pNext != NULL) {
+ p = p->pNext;
+ }
+ p->pNext = pNew;
+ pNew->pPrev = p;
+ } else {
+ pQueue->pItems = pNew;
+ }
+ pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
+
+ sem_post(&pQueue->nProcessSemaphore);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function phDal4Nfc_msgrcv
+**
+** Description Gets the oldest message from the queue.
+** If the queue is empty the function waits (blocks on a mutex)
+** until a message is posted to the queue with phDal4Nfc_msgsnd
+**
+** Parameters msqid - message queue handle
+** msgp - message to be received
+** msgsz - message size
+** msgtyp - ignored
+** msgflg - ignored
+**
+** Returns 0, if successful
+** -1, if invalid parameter passed
+**
+*******************************************************************************/
+int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t* msg, long msgtyp,
+ int msgflg) {
+ phDal4Nfc_message_queue_t* pQueue;
+ phDal4Nfc_message_queue_item_t* p;
+ UNUSED(msgflg);
+ UNUSED(msgtyp);
+ if ((msqid == 0) || (msg == NULL)) return -1;
+
+ pQueue = (phDal4Nfc_message_queue_t*)msqid;
+
+ sem_wait(&pQueue->nProcessSemaphore);
+
+ pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
+
+ if (pQueue->pItems != NULL) {
+ memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
+ p = pQueue->pItems->pNext;
+ free(pQueue->pItems);
+ pQueue->pItems = p;
+ }
+ pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
+
+ return 0;
+}
diff --git a/pn54x/tml/phDal4Nfc_messageQueueLib.h b/pn54x/tml/phDal4Nfc_messageQueueLib.h
new file mode 100644
index 0000000..1e0ede2
--- /dev/null
+++ b/pn54x/tml/phDal4Nfc_messageQueueLib.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/*
+ * DAL independent message queue implementation for Android
+ */
+
+#ifndef PHDAL4NFC_MESSAGEQUEUE_H
+#define PHDAL4NFC_MESSAGEQUEUE_H
+
+#include <linux/ipc.h>
+#include <phNfcTypes.h>
+
+intptr_t phDal4Nfc_msgget(key_t key, int msgflg);
+void phDal4Nfc_msgrelease(intptr_t msqid);
+int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void* buf);
+intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t* msg, int msgflg);
+int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t* msg, long msgtyp,
+ int msgflg);
+
+#endif /* PHDAL4NFC_MESSAGEQUEUE_H */
diff --git a/pn54x/tml/phOsalNfc_Timer.c b/pn54x/tml/phOsalNfc_Timer.c
new file mode 100644
index 0000000..3f5269d
--- /dev/null
+++ b/pn54x/tml/phOsalNfc_Timer.c
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ */
+
+/*
+ * OSAL Implementation for Timers.
+ */
+
+#include <phNfcCommon.h>
+#include <phNfcTypes.h>
+#include <phNxpLog.h>
+#include <phNxpNciHal.h>
+#include <phOsalNfc_Timer.h>
+#include <signal.h>
+
+#define PH_NFC_MAX_TIMER (5U)
+static phOsalNfc_TimerHandle_t apTimerInfo[PH_NFC_MAX_TIMER];
+
+extern phNxpNciHal_Control_t nxpncihal_ctrl;
+
+/*
+ * Defines the base address for generating timerid.
+ */
+#define PH_NFC_TIMER_BASE_ADDRESS (100U)
+
+/*
+ * Defines the value for invalid timerid returned during timeSetEvent
+ */
+#define PH_NFC_TIMER_ID_ZERO (0x00)
+
+/*
+ * Invalid timer ID type. This ID used indicate timer creation is failed */
+#define PH_NFC_TIMER_ID_INVALID (0xFFFF)
+
+/* Forward declarations */
+static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg);
+static void phOsalNfc_DeferredCall(void* pParams);
+static void phOsalNfc_Timer_Expired(union sigval sv);
+
+/*
+ *************************** Function Definitions ******************************
+ */
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Create
+**
+** Description Creates a timer which shall call back the specified function
+** when the timer expires. Fails if OSAL module is not
+** initialized or timers are already occupied
+**
+** Parameters None
+**
+** Returns TimerId
+** TimerId value of PH_OSALNFC_TIMER_ID_INVALID indicates that
+** timer is not created
+**
+*******************************************************************************/
+uint32_t phOsalNfc_Timer_Create(void) {
+ /* dwTimerId is also used as an index at which timer object can be stored */
+ uint32_t dwTimerId = PH_OSALNFC_TIMER_ID_INVALID;
+ static struct sigevent se;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ /* Timer needs to be initialized for timer usage */
+
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_notify_function = phOsalNfc_Timer_Expired;
+ se.sigev_notify_attributes = NULL;
+ dwTimerId = phUtilNfc_CheckForAvailableTimer();
+
+ /* Check whether timers are available, if yes create a timer handle structure
+ */
+ if ((PH_NFC_TIMER_ID_ZERO != dwTimerId) && (dwTimerId <= PH_NFC_MAX_TIMER)) {
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwTimerId - 1];
+ /* Build the Timer Id to be returned to Caller Function */
+ dwTimerId += PH_NFC_TIMER_BASE_ADDRESS;
+ se.sigev_value.sival_int = (int)dwTimerId;
+ /* Create POSIX timer */
+ if (timer_create(CLOCK_REALTIME, &se, &(pTimerHandle->hTimerHandle)) ==
+ -1) {
+ dwTimerId = PH_NFC_TIMER_ID_INVALID;
+ } else {
+ /* Set the state to indicate timer is ready */
+ pTimerHandle->eState = eTimerIdle;
+ /* Store the Timer Id which shall act as flag during check for timer
+ * availability */
+ pTimerHandle->TimerId = dwTimerId;
+ }
+ } else {
+ dwTimerId = PH_NFC_TIMER_ID_INVALID;
+ }
+
+ /* Timer ID invalid can be due to Uninitialized state,Non availability of
+ * Timer */
+ return dwTimerId;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Start
+**
+** Description Starts the requested, already created, timer.
+** If the timer is already running, timer stops and restarts
+** with the new timeout value and new callback function in case
+** any ??????
+** Creates a timer which shall call back the specified function
+** when the timer expires
+**
+** Parameters dwTimerId - valid timer ID obtained during timer creation
+** dwRegTimeCnt - requested timeout in milliseconds
+** pApplication_callback - application callback interface to be
+** called when timer expires
+** pContext - caller context, to be passed to the application
+** callback function
+**
+** Returns NFC status:
+** NFCSTATUS_SUCCESS - the operation was successful
+** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
+** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
+** the function
+** PH_OSALNFC_TIMER_START_ERROR - timer could not be created
+** due to system error
+**
+*******************************************************************************/
+NFCSTATUS phOsalNfc_Timer_Start(uint32_t dwTimerId, uint32_t dwRegTimeCnt,
+ pphOsalNfc_TimerCallbck_t pApplication_callback,
+ void* pContext) {
+ NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS;
+
+ struct itimerspec its;
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ /* Retrieve the index at which the timer handle structure is stored */
+ dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ /* OSAL Module needs to be initialized for timer usage */
+ /* Check whether the handle provided by user is valid */
+ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
+ (NULL != pApplication_callback)) {
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+ its.it_value.tv_sec = dwRegTimeCnt / 1000;
+ its.it_value.tv_nsec = 1000000 * (dwRegTimeCnt % 1000);
+ if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) {
+ /* This would inadvertently stop the timer*/
+ its.it_value.tv_nsec = 1;
+ }
+ pTimerHandle->Application_callback = pApplication_callback;
+ pTimerHandle->pContext = pContext;
+ pTimerHandle->eState = eTimerRunning;
+ /* Arm the timer */
+ if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
+ wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_START_ERROR);
+ }
+ } else {
+ wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+
+ return wStartStatus;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Stop
+**
+** Description Stops already started timer
+** Allows to stop running timer. In case timer is stopped,
+** timer callback will not be notified any more
+**
+** Parameters dwTimerId - valid timer ID obtained during timer creation
+**
+** Returns NFC status:
+** NFCSTATUS_SUCCESS - the operation was successful
+** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
+** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
+** the function
+** PH_OSALNFC_TIMER_STOP_ERROR - timer could not be stopped due
+** to system error
+**
+*******************************************************************************/
+NFCSTATUS phOsalNfc_Timer_Stop(uint32_t dwTimerId) {
+ NFCSTATUS wStopStatus = NFCSTATUS_SUCCESS;
+ static struct itimerspec its = {{0, 0}, {0, 0}};
+
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ /* OSAL Module and Timer needs to be initialized for timer usage */
+ /* Check whether the TimerId provided by user is valid */
+ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
+ (pTimerHandle->eState != eTimerIdle)) {
+ /* Stop the timer only if the callback has not been invoked */
+ if (pTimerHandle->eState == eTimerRunning) {
+ if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
+ wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_STOP_ERROR);
+ } else {
+ /* Change the state of timer to Stopped */
+ pTimerHandle->eState = eTimerStopped;
+ }
+ }
+ } else {
+ wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+
+ return wStopStatus;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Delete
+**
+** Description Deletes previously created timer
+** Allows to delete previously created timer. In case timer is
+** running, it is first stopped and then deleted
+**
+** Parameters dwTimerId - valid timer ID obtained during timer creation
+**
+** Returns NFC status:
+** NFCSTATUS_SUCCESS - the operation was successful
+** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
+** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
+** the function
+** PH_OSALNFC_TIMER_DELETE_ERROR - timer could not be stopped
+** due to system error
+**
+*******************************************************************************/
+NFCSTATUS phOsalNfc_Timer_Delete(uint32_t dwTimerId) {
+ NFCSTATUS wDeleteStatus = NFCSTATUS_SUCCESS;
+
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ /* OSAL Module and Timer needs to be initialized for timer usage */
+
+ /* Check whether the TimerId passed by user is valid and Deregistering of
+ * timer is successful */
+ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
+ (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
+ /* Cancel the timer before deleting */
+ if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
+ wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_DELETE_ERROR);
+ }
+ /* Clear Timer structure used to store timer related data */
+ memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
+ } else {
+ wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+ return wDeleteStatus;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Cleanup
+**
+** Description Deletes all previously created timers
+** Allows to delete previously created timers. In case timer is
+** running, it is first stopped and then deleted
+**
+** Parameters None
+**
+** Returns None
+**
+*******************************************************************************/
+void phOsalNfc_Timer_Cleanup(void) {
+ /* Delete all timers */
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ for (dwIndex = 0; dwIndex < PH_NFC_MAX_TIMER; dwIndex++) {
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ /* OSAL Module and Timer needs to be initialized for timer usage */
+
+ /* Check whether the TimerId passed by user is valid and Deregistering of
+ * timer is successful */
+ if ((0x00 != pTimerHandle->TimerId) &&
+ (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
+ /* Cancel the timer before deleting */
+ if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
+ NXPLOG_TML_E("timer %d delete error!", dwIndex);
+ }
+ /* Clear Timer structure used to store timer related data */
+ memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_DeferredCall
+**
+** Description Invokes the timer callback function after timer expiration.
+** Shall invoke the callback function registered by the timer
+** caller function
+**
+** Parameters pParams - parameters indicating the ID of the timer
+**
+** Returns None -
+**
+*******************************************************************************/
+static void phOsalNfc_DeferredCall(void* pParams) {
+ /* Retrieve the timer id from the parameter */
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+ if (NULL != pParams) {
+ /* Retrieve the index at which the timer handle structure is stored */
+ dwIndex = (uintptr_t)pParams - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ if (pTimerHandle->Application_callback != NULL) {
+ /* Invoke the callback function with osal Timer ID */
+ pTimerHandle->Application_callback((uintptr_t)pParams,
+ pTimerHandle->pContext);
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_PostTimerMsg
+**
+** Description Posts message on the user thread
+** Shall be invoked upon expiration of a timer
+** Shall post message on user thread through which timer
+** callback function shall be invoked
+**
+** Parameters pMsg - pointer to the message structure posted on user
+** thread
+**
+** Returns None
+**
+*******************************************************************************/
+static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg) {
+ (void)phDal4Nfc_msgsnd(
+ nxpncihal_ctrl.gDrvCfg
+ .nClientId /*gpphOsalNfc_Context->dwCallbackThreadID*/,
+ pMsg, 0);
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_Timer_Expired
+**
+** Description posts message upon expiration of timer
+** Shall be invoked when any one timer is expired
+** Shall post message on user thread to invoke respective
+** callback function provided by the caller of Timer function
+**
+** Returns None
+**
+*******************************************************************************/
+static void phOsalNfc_Timer_Expired(union sigval sv) {
+ uint32_t dwIndex;
+ phOsalNfc_TimerHandle_t* pTimerHandle;
+
+ dwIndex = ((uint32_t)(sv.sival_int)) - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
+ pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
+ /* Timer is stopped when callback function is invoked */
+ pTimerHandle->eState = eTimerStopped;
+
+ pTimerHandle->tDeferedCallInfo.pDeferedCall = &phOsalNfc_DeferredCall;
+ pTimerHandle->tDeferedCallInfo.pParam = (void*)((intptr_t)(sv.sival_int));
+
+ pTimerHandle->tOsalMessage.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
+ pTimerHandle->tOsalMessage.pMsgData = (void*)&pTimerHandle->tDeferedCallInfo;
+
+ /* Post a message on the queue to invoke the function */
+ phOsalNfc_PostTimerMsg((phLibNfc_Message_t*)&pTimerHandle->tOsalMessage);
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phUtilNfc_CheckForAvailableTimer
+**
+** Description Find an available timer id
+**
+** Parameters void
+**
+** Returns Available timer id
+**
+*******************************************************************************/
+uint32_t phUtilNfc_CheckForAvailableTimer(void) {
+ /* Variable used to store the index at which the object structure details
+ can be stored. Initialize it as not available. */
+ uint32_t dwIndex = 0x00;
+ uint32_t dwRetval = 0x00;
+
+ /* Check whether Timer object can be created */
+ for (dwIndex = 0x00; ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 == dwRetval));
+ dwIndex++) {
+ if (!(apTimerInfo[dwIndex].TimerId)) {
+ dwRetval = (dwIndex + 0x01);
+ }
+ }
+
+ return (dwRetval);
+}
+
+/*******************************************************************************
+**
+** Function phOsalNfc_CheckTimerPresence
+**
+** Description Checks the requested timer is present or not
+**
+** Parameters pObjectHandle - timer context
+**
+** Returns NFCSTATUS_SUCCESS if found
+** Other value if not found
+**
+*******************************************************************************/
+NFCSTATUS phOsalNfc_CheckTimerPresence(void* pObjectHandle) {
+ uint32_t dwIndex;
+ NFCSTATUS wRegisterStatus = NFCSTATUS_INVALID_PARAMETER;
+
+ for (dwIndex = 0x00;
+ ((dwIndex < PH_NFC_MAX_TIMER) && (wRegisterStatus != NFCSTATUS_SUCCESS));
+ dwIndex++) {
+ /* For Timer, check whether the requested handle is present or not */
+ if (((&apTimerInfo[dwIndex]) == (phOsalNfc_TimerHandle_t*)pObjectHandle) &&
+ (apTimerInfo[dwIndex].TimerId)) {
+ wRegisterStatus = NFCSTATUS_SUCCESS;
+ }
+ }
+ return wRegisterStatus;
+}
diff --git a/pn54x/tml/phOsalNfc_Timer.h b/pn54x/tml/phOsalNfc_Timer.h
new file mode 100644
index 0000000..5315455
--- /dev/null
+++ b/pn54x/tml/phOsalNfc_Timer.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+/*
+ * OSAL header files related to Timer functions.
+ */
+
+#ifndef PHOSALNFC_TIMER_H
+#define PHOSALNFC_TIMER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+************************* Include Files ****************************************
+*/
+
+/*
+ * Timer callback interface which will be called once registered timer
+ * time out expires.
+ * TimerId - Timer Id for which callback is called.
+ * pContext - Parameter to be passed to the callback function
+ */
+typedef void (*pphOsalNfc_TimerCallbck_t)(uint32_t TimerId, void* pContext);
+
+/*
+ * The Timer could not be created due to a
+ * system error */
+#define PH_OSALNFC_TIMER_CREATE_ERROR (0X00E0)
+
+/*
+ * The Timer could not be started due to a
+ * system error or invalid handle */
+#define PH_OSALNFC_TIMER_START_ERROR (0X00E1)
+
+/*
+ * The Timer could not be stopped due to a
+ * system error or invalid handle */
+#define PH_OSALNFC_TIMER_STOP_ERROR (0X00E2)
+
+/*
+ * The Timer could not be deleted due to a
+ * system error or invalid handle */
+#define PH_OSALNFC_TIMER_DELETE_ERROR (0X00E3)
+
+/*
+ * Invalid timer ID type.This ID used indicate timer creation is failed */
+#define PH_OSALNFC_TIMER_ID_INVALID (0xFFFF)
+
+/*
+ * OSAL timer message .This message type will be posted to
+ * calling application thread.*/
+#define PH_OSALNFC_TIMER_MSG (0x315)
+
+/*
+***************************Globals,Structure and Enumeration ******************
+*/
+
+uint32_t phOsalNfc_Timer_Create(void);
+NFCSTATUS phOsalNfc_Timer_Start(uint32_t dwTimerId, uint32_t dwRegTimeCnt,
+ pphOsalNfc_TimerCallbck_t pApplication_callback,
+ void* pContext);
+NFCSTATUS phOsalNfc_Timer_Stop(uint32_t dwTimerId);
+NFCSTATUS phOsalNfc_Timer_Delete(uint32_t dwTimerId);
+void phOsalNfc_Timer_Cleanup(void);
+uint32_t phUtilNfc_CheckForAvailableTimer(void);
+NFCSTATUS phOsalNfc_CheckTimerPresence(void* pObjectHandle);
+
+#ifdef __cplusplus
+}
+#endif /* C++ Compilation guard */
+#endif /* PHOSALNFC_TIMER_H */
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 <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;
+}
diff --git a/pn54x/tml/phTmlNfc.h b/pn54x/tml/phTmlNfc.h
new file mode 100644
index 0000000..3955354
--- /dev/null
+++ b/pn54x/tml/phTmlNfc.h
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+/*
+ * Transport Mapping Layer header files containing APIs related to initializing,
+ * reading
+ * and writing data into files provided by the driver interface.
+ *
+ * API listed here encompasses Transport Mapping Layer interfaces required to be
+ * mapped
+ * to different Interfaces and Platforms.
+ *
+ */
+
+#ifndef PHTMLNFC_H
+#define PHTMLNFC_H
+
+#include <phNfcCommon.h>
+
+/*
+ * Message posted by Reader thread upon
+ * completion of requested operation
+ */
+#define PH_TMLNFC_READ_MESSAGE (0xAA)
+
+/*
+ * Message posted by Writer thread upon
+ * completion of requested operation
+ */
+#define PH_TMLNFC_WRITE_MESSAGE (0x55)
+
+/*
+ * Value indicates to reset device
+ */
+#define PH_TMLNFC_RESETDEVICE (0x00008001)
+
+/*
+***************************Globals,Structure and Enumeration ******************
+*/
+
+/*
+ * Transaction (Tx/Rx) completion information structure of TML
+ *
+ * This structure holds the completion callback information of the
+ * transaction passed from the TML layer to the Upper layer
+ * along with the completion callback.
+ *
+ * The value of field wStatus can be interpreted as:
+ *
+ * - NFCSTATUS_SUCCESS Transaction performed
+ * successfully.
+ * - NFCSTATUS_FAILED Failed to wait on Read/Write
+ * operation.
+ * - NFCSTATUS_INSUFFICIENT_STORAGE Not enough memory to store data in
+ * case of read.
+ * - NFCSTATUS_BOARD_COMMUNICATION_ERROR Failure to Read/Write from the
+ * file or timeout.
+ */
+
+typedef struct phTmlNfc_TransactInfo {
+ NFCSTATUS wStatus; /* Status of the Transaction Completion*/
+ uint8_t* pBuff; /* Response Data of the Transaction*/
+ uint16_t wLength; /* Data size of the Transaction*/
+} phTmlNfc_TransactInfo_t; /* Instance of Transaction structure */
+
+/*
+ * TML transreceive completion callback to Upper Layer
+ *
+ * pContext - Context provided by upper layer
+ * pInfo - Transaction info. See phTmlNfc_TransactInfo
+ */
+typedef void (*pphTmlNfc_TransactCompletionCb_t)(
+ void* pContext, phTmlNfc_TransactInfo_t* pInfo);
+
+/*
+ * TML Deferred callback interface structure invoked by upper layer
+ *
+ * This could be used for read/write operations
+ *
+ * dwMsgPostedThread Message source identifier
+ * pParams Parameters for the deferred call processing
+ */
+typedef void (*pphTmlNfc_DeferFuncPointer_t)(uint32_t dwMsgPostedThread,
+ void* pParams);
+
+/*
+ * Enum definition contains supported ioctl control codes.
+ *
+ * phTmlNfc_IoCtl
+ */
+typedef enum {
+ phTmlNfc_e_Invalid = 0,
+ phTmlNfc_e_ResetDevice = PH_TMLNFC_RESETDEVICE, /* Reset the device */
+ phTmlNfc_e_EnableDownloadMode, /* Do the hardware setting to enter into
+ download mode */
+ phTmlNfc_e_EnableNormalMode /* Hardware setting for normal mode of operation
+ */
+} phTmlNfc_ControlCode_t; /* Control code for IOCTL call */
+
+/*
+ * Enable / Disable Re-Transmission of Packets
+ *
+ * phTmlNfc_ConfigNciPktReTx
+ */
+typedef enum {
+ phTmlNfc_e_EnableRetrans = 0x00, /*Enable retransmission of Nci packet */
+ phTmlNfc_e_DisableRetrans = 0x01 /*Disable retransmission of Nci packet */
+} phTmlNfc_ConfigRetrans_t; /* Configuration for Retransmission */
+
+/*
+ * Structure containing details related to read and write operations
+ *
+ */
+typedef struct phTmlNfc_ReadWriteInfo {
+ volatile uint8_t bEnable; /*This flag shall decide whether to perform
+ Write/Read operation */
+ uint8_t
+ bThreadBusy; /*Flag to indicate thread is busy on respective operation */
+ /* Transaction completion Callback function */
+ pphTmlNfc_TransactCompletionCb_t pThread_Callback;
+ void* pContext; /*Context passed while invocation of operation */
+ uint8_t* pBuffer; /*Buffer passed while invocation of operation */
+ uint16_t wLength; /*Length of data read/written */
+ NFCSTATUS wWorkStatus; /*Status of the transaction performed */
+} phTmlNfc_ReadWriteInfo_t;
+
+/*
+ *Base Context Structure containing members required for entire session
+ */
+typedef struct phTmlNfc_Context {
+ pthread_t readerThread; /*Handle to the thread which handles write and read
+ operations */
+ pthread_t writerThread;
+ volatile uint8_t
+ bThreadDone; /*Flag to decide whether to run or abort the thread */
+ phTmlNfc_ConfigRetrans_t
+ eConfig; /*Retransmission of Nci Packet during timeout */
+ uint8_t bRetryCount; /*Number of times retransmission shall happen */
+ uint8_t bWriteCbInvoked; /* Indicates whether write callback is invoked during
+ retransmission */
+ uint32_t dwTimerId; /* Timer used to retransmit nci packet */
+ phTmlNfc_ReadWriteInfo_t tReadInfo; /*Pointer to Reader Thread Structure */
+ phTmlNfc_ReadWriteInfo_t tWriteInfo; /*Pointer to Writer Thread Structure */
+ void* pDevHandle; /* Pointer to Device Handle */
+ uintptr_t dwCallbackThreadId; /* Thread ID to which message to be posted */
+ uint8_t bEnableCrc; /*Flag to validate/not CRC for input buffer */
+ sem_t rxSemaphore;
+ sem_t txSemaphore; /* Lock/Aquire txRx Semaphore */
+ sem_t postMsgSemaphore; /* Semaphore to post message atomically by Reader &
+ writer thread */
+} phTmlNfc_Context_t;
+
+/*
+ * TML Configuration exposed to upper layer.
+ */
+typedef struct phTmlNfc_Config {
+ /* Port name connected to PN54X
+ *
+ * Platform specific canonical device name to which PN54X is connected.
+ *
+ * e.g. On Linux based systems this would be /dev/PN54X
+ */
+ int8_t* pDevName;
+ /* Callback Thread ID
+ *
+ * This is the thread ID on which the Reader & Writer thread posts message. */
+ uintptr_t dwGetMsgThreadId;
+ /* Communication speed between DH and PN54X
+ *
+ * This is the baudrate of the bus for communication between DH and PN54X */
+ uint32_t dwBaudRate;
+} phTmlNfc_Config_t, *pphTmlNfc_Config_t; /* pointer to phTmlNfc_Config_t */
+
+/*
+ * TML Deferred Callback structure used to invoke Upper layer Callback function.
+ */
+typedef struct {
+ /* Deferred callback function to be invoked */
+ pphTmlNfc_DeferFuncPointer_t pDef_call;
+ /* Source identifier
+ *
+ * Identifier of the source which posted the message
+ */
+ uint32_t dwMsgPostedThread;
+ /** Actual Message
+ *
+ * This is passed as a parameter passed to the deferred callback function
+ * pDef_call. */
+ void* pParams;
+} phTmlNfc_DeferMsg_t; /* DeferMsg structure passed to User Thread */
+
+typedef enum {
+ I2C_FRAGMENATATION_DISABLED, /*i2c fragmentation_disabled */
+ I2C_FRAGMENTATION_ENABLED /*i2c_fragmentation_enabled */
+} phTmlNfc_i2cfragmentation_t;
+/* Function declarations */
+NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig);
+NFCSTATUS phTmlNfc_Shutdown(void);
+NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength,
+ pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,
+ void* pContext);
+NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength,
+ pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,
+ void* pContext);
+NFCSTATUS phTmlNfc_WriteAbort(void);
+NFCSTATUS phTmlNfc_ReadAbort(void);
+NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode);
+void phTmlNfc_DeferredCall(uintptr_t dwThreadId,
+ phLibNfc_Message_t* ptWorkerMsg);
+void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfig,
+ uint8_t bRetryCount);
+void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t enable);
+phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled();
+#endif /* PHTMLNFC_H */
diff --git a/pn54x/tml/phTmlNfc_i2c.c b/pn54x/tml/phTmlNfc_i2c.c
new file mode 100644
index 0000000..781f19b
--- /dev/null
+++ b/pn54x/tml/phTmlNfc_i2c.c
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+/*
+ * DAL I2C port implementation for linux
+ *
+ * Project: Trusted NFC Linux
+ *
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <hardware/nfc.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <phNfcStatus.h>
+#include <phNxpLog.h>
+#include <phTmlNfc_i2c.h>
+#include <string.h>
+#include "phNxpNciHal_utils.h"
+
+#define CRC_LEN 2
+#define NORMAL_MODE_HEADER_LEN 3
+#define FW_DNLD_HEADER_LEN 2
+#define FW_DNLD_LEN_OFFSET 1
+#define NORMAL_MODE_LEN_OFFSET 2
+#define FRAGMENTSIZE_MAX PHNFC_I2C_FRAGMENT_SIZE
+static bool_t bFwDnldFlag = false;
+extern phTmlNfc_i2cfragmentation_t fragmentation_enabled;
+
+/*******************************************************************************
+**
+** Function phTmlNfc_i2c_close
+**
+** Description Closes PN54X device
+**
+** Parameters pDevHandle - device handle
+**
+** Returns None
+**
+*******************************************************************************/
+void phTmlNfc_i2c_close(void* pDevHandle) {
+ if (NULL != pDevHandle) {
+ close((intptr_t)pDevHandle);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phTmlNfc_i2c_open_and_configure
+**
+** Description Open and configure PN54X device
+**
+** Parameters pConfig - hardware information
+** pLinkHandle - device handle
+**
+** Returns NFC status:
+** NFCSTATUS_SUCCESS - open_and_configure operation success
+** NFCSTATUS_INVALID_DEVICE - device open operation failure
+**
+*******************************************************************************/
+NFCSTATUS phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig,
+ void** pLinkHandle) {
+ int nHandle;
+
+ NXPLOG_TML_D("Opening port=%s\n", pConfig->pDevName);
+ /* open port */
+ nHandle = open((const char*)pConfig->pDevName, O_RDWR);
+ if (nHandle < 0) {
+ NXPLOG_TML_E("_i2c_open() Failed: retval %x", nHandle);
+ *pLinkHandle = NULL;
+ return NFCSTATUS_INVALID_DEVICE;
+ }
+
+ *pLinkHandle = (void*)((intptr_t)nHandle);
+
+ /*Reset PN54X*/
+ phTmlNfc_i2c_reset((void*)((intptr_t)nHandle), 0);
+ usleep(10 * 1000);
+ phTmlNfc_i2c_reset((void*)((intptr_t)nHandle), 1);
+
+ return NFCSTATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function phTmlNfc_i2c_read
+**
+** Description Reads requested number of bytes from PN54X device into given
+** buffer
+**
+** Parameters pDevHandle - valid device handle
+** pBuffer - buffer for read data
+** nNbBytesToRead - number of bytes requested to be read
+**
+** Returns numRead - number of successfully read bytes
+** -1 - read operation failure
+**
+*******************************************************************************/
+int phTmlNfc_i2c_read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead) {
+ int ret_Read;
+ int ret_Select;
+ int numRead = 0;
+ struct timeval tv;
+ fd_set rfds;
+ uint16_t totalBtyesToRead = 0;
+
+ int i;
+ UNUSED(nNbBytesToRead);
+ if (NULL == pDevHandle) {
+ return -1;
+ }
+
+ if (bFwDnldFlag == false) {
+ totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
+ } else {
+ totalBtyesToRead = FW_DNLD_HEADER_LEN;
+ }
+
+ /* Read with 2 second timeout, so that the read thread can be aborted
+ when the PN54X does not respond and we need to switch to FW download
+ mode. This should be done via a control socket instead. */
+ FD_ZERO(&rfds);
+ FD_SET((intptr_t)pDevHandle, &rfds);
+ tv.tv_sec = 2;
+ tv.tv_usec = 1;
+
+ ret_Select =
+ select((int)((intptr_t)pDevHandle + (int)1), &rfds, NULL, NULL, &tv);
+ if (ret_Select < 0) {
+ NXPLOG_TML_E("i2c select() errno : %x", errno);
+ return -1;
+ } else if (ret_Select == 0) {
+ NXPLOG_TML_E("i2c select() Timeout");
+ return -1;
+ } else {
+ ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead);
+ if (ret_Read > 0) {
+ numRead += ret_Read;
+ } else if (ret_Read == 0) {
+ NXPLOG_TML_E("_i2c_read() [hdr]EOF");
+ return -1;
+ } else {
+ NXPLOG_TML_E("_i2c_read() [hdr] errno : %x", errno);
+ return -1;
+ }
+
+ if (bFwDnldFlag == false) {
+ totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
+ } else {
+ totalBtyesToRead = FW_DNLD_HEADER_LEN;
+ }
+
+ if (numRead < totalBtyesToRead) {
+ ret_Read =
+ read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead);
+ if (ret_Read != totalBtyesToRead - numRead) {
+ NXPLOG_TML_E("_i2c_read() [hdr] errno : %x", errno);
+ return -1;
+ } else {
+ numRead += ret_Read;
+ }
+ }
+ if (bFwDnldFlag == true) {
+ totalBtyesToRead =
+ pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN;
+ } else {
+ totalBtyesToRead =
+ pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN;
+ }
+ if ((totalBtyesToRead - numRead) != 0) {
+ ret_Read = read((intptr_t)pDevHandle, (pBuffer + numRead),
+ totalBtyesToRead - numRead);
+ if (ret_Read > 0) {
+ numRead += ret_Read;
+ } else if (ret_Read == 0) {
+ NXPLOG_TML_E("_i2c_read() [pyld] EOF");
+ return -1;
+ } else {
+ if (bFwDnldFlag == false) {
+ NXPLOG_TML_E("_i2c_read() [hdr] received");
+ phNxpNciHal_print_packet("RECV", pBuffer, NORMAL_MODE_HEADER_LEN);
+ }
+ NXPLOG_TML_E("_i2c_read() [pyld] errno : %x", errno);
+ return -1;
+ }
+ } else {
+ NXPLOG_TML_E("_>>>>> Empty packet recieved !!");
+ }
+ }
+ return numRead;
+}
+
+/*******************************************************************************
+**
+** Function phTmlNfc_i2c_write
+**
+** Description Writes requested number of bytes from given buffer into
+** PN54X device
+**
+** Parameters pDevHandle - valid device handle
+** pBuffer - buffer for read data
+** nNbBytesToWrite - number of bytes requested to be written
+**
+** Returns numWrote - number of successfully written bytes
+** -1 - write operation failure
+**
+*******************************************************************************/
+int phTmlNfc_i2c_write(void* pDevHandle, uint8_t* pBuffer,
+ int nNbBytesToWrite) {
+ int ret;
+ int numWrote = 0;
+ int i;
+ int numBytes = nNbBytesToWrite;
+ if (NULL == pDevHandle) {
+ return -1;
+ }
+ if (fragmentation_enabled == I2C_FRAGMENATATION_DISABLED &&
+ nNbBytesToWrite > FRAGMENTSIZE_MAX) {
+ NXPLOG_TML_E(
+ "i2c_write() data larger than maximum I2C size,enable I2C "
+ "fragmentation");
+ return -1;
+ }
+ while (numWrote < nNbBytesToWrite) {
+ if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
+ nNbBytesToWrite > FRAGMENTSIZE_MAX) {
+ if (nNbBytesToWrite - numWrote > FRAGMENTSIZE_MAX) {
+ numBytes = numWrote + FRAGMENTSIZE_MAX;
+ } else {
+ numBytes = nNbBytesToWrite;
+ }
+ }
+ ret = write((intptr_t)pDevHandle, pBuffer + numWrote, numBytes - numWrote);
+ if (ret > 0) {
+ numWrote += ret;
+ if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
+ numWrote < nNbBytesToWrite) {
+ usleep(500);
+ }
+ } else if (ret == 0) {
+ NXPLOG_TML_E("_i2c_write() EOF");
+ return -1;
+ } else {
+ NXPLOG_TML_E("_i2c_write() errno : %x", errno);
+ if (errno == EINTR || errno == EAGAIN) {
+ continue;
+ }
+ return -1;
+ }
+ }
+
+ return numWrote;
+}
+
+/*******************************************************************************
+**
+** Function phTmlNfc_i2c_reset
+**
+** Description Reset PN54X device, using VEN pin
+**
+** Parameters pDevHandle - valid device handle
+** level - reset level
+**
+** Returns 0 - reset operation success
+** -1 - reset operation failure
+**
+*******************************************************************************/
+#define PN544_SET_PWR _IOW(0xe9, 0x01, unsigned int)
+int phTmlNfc_i2c_reset(void* pDevHandle, long level) {
+ int ret;
+ NXPLOG_TML_D("phTmlNfc_i2c_reset(), VEN level %ld", level);
+
+ if (NULL == pDevHandle) {
+ return -1;
+ }
+
+ ret = ioctl((intptr_t)pDevHandle, PN544_SET_PWR, level);
+ if (level == 2 && ret == 0) {
+ bFwDnldFlag = true;
+ } else {
+ bFwDnldFlag = false;
+ }
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function getDownloadFlag
+**
+** Description Returns the current mode
+**
+** Parameters none
+**
+** Returns Current mode download/NCI
+*******************************************************************************/
+bool_t getDownloadFlag(void) { return bFwDnldFlag; }
diff --git a/pn54x/tml/phTmlNfc_i2c.h b/pn54x/tml/phTmlNfc_i2c.h
new file mode 100644
index 0000000..0949a72
--- /dev/null
+++ b/pn54x/tml/phTmlNfc_i2c.h
@@ -0,0 +1,32 @@
+/*
+ * 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 I2C port implementation for linux
+ */
+
+/* Basic type definitions */
+#include <phNfcTypes.h>
+#include <phTmlNfc.h>
+
+/* Function declarations */
+void phTmlNfc_i2c_close(void* pDevHandle);
+NFCSTATUS phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig,
+ void** pLinkHandle);
+int phTmlNfc_i2c_read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead);
+int phTmlNfc_i2c_write(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToWrite);
+int phTmlNfc_i2c_reset(void* pDevHandle, long level);
+bool_t getDownloadFlag(void);