blob: 5f27afb4c58d9cf6867f2f48556a89cb70e4fb68 [file] [log] [blame]
/*
* Copyright 2012-2020, 2024 NXP
*
* 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.
*/
#include <phNxpLog.h>
#include <phNxpUciHal_utils.h>
#include <phOsalUwb_Timer.h>
#include <phTmlUwb.h>
#include <phTmlUwb_spi.h>
#include <phNxpUciHal.h>
#include <errno.h>
extern phNxpUciHal_Control_t nxpucihal_ctrl;
/*
* Duration of Timer to wait after sending an Uci packet
*/
#define PHTMLUWB_MAXTIME_RETRANSMIT (200U)
#define MAX_WRITE_RETRY_COUNT 0x03
/* Value to reset variables of TML */
#define PH_TMLUWB_RESET_VALUE (0x00)
/* Indicates a Initial or offset value */
#define PH_TMLUWB_VALUE_ONE (0x01)
namespace {
// Structure containing details related to read and write operations
struct phTmlUwb_ReadInfo {
volatile bool bThreadShouldStop;
volatile bool bThreadRunning;
uint8_t
bThreadBusy; /*Flag to indicate thread is busy on respective operation */
/* Transaction completion Callback function */
ReadCallback* pThread_Callback;
void* pContext; /*Context passed while invocation of operation */
uint8_t* pBuffer; /*Buffer passed while invocation of operation */
size_t wLength; /*Length of data read/written */
tHAL_UWB_STATUS wWorkStatus; /*Status of the transaction performed */
};
struct phTmlUwb_WriteInfo {
volatile bool bThreadShouldStop;
volatile bool bThreadRunning;
uint8_t
bThreadBusy; /*Flag to indicate thread is busy on respective operation */
/* Transaction completion Callback function */
WriteCallback* pThread_Callback;
void* pContext; /*Context passed while invocation of operation */
const uint8_t* pBuffer; /*Buffer passed while invocation of operation */
size_t wLength; /*Length of data read/written */
tHAL_UWB_STATUS wWorkStatus; /*Status of the transaction performed */
};
// Base Context Structure containing members required for entire session
struct phTmlUwb_Context {
pthread_t readerThread;
pthread_t writerThread;
phTmlUwb_ReadInfo tReadInfo; /*Pointer to Reader Thread Structure */
phTmlUwb_WriteInfo tWriteInfo; /*Pointer to Writer Thread Structure */
void* pDevHandle; /* Pointer to Device Handle */
std::shared_ptr<MessageQueue<phLibUwb_Message>> pClientMq; /* Pointer to Client thread message queue */
sem_t rxSemaphore;
sem_t txSemaphore; /* Lock/Acquire txRx Semaphore */
pthread_cond_t wait_busy_condition; /*Condition to wait reader thread*/
pthread_mutex_t wait_busy_lock; /*Condition lock to wait reader thread*/
volatile uint8_t wait_busy_flag; /*Condition flag to wait reader thread*/
volatile uint8_t gWriterCbflag; /* flag to indicate write callback message is pushed to
queue*/
};
std::unique_ptr<phTmlUwb_Context> gpphTmlUwb_Context;
} // namespace
/* Local Function prototypes */
static tHAL_UWB_STATUS phTmlUwb_StartWriterThread(void);
static void phTmlUwb_StopWriterThread(void);
static void phTmlUwb_CleanUp(void);
static void phTmlUwb_ReadDeferredCb(void* pParams);
static void phTmlUwb_WriteDeferredCb(void* pParams);
static void* phTmlUwb_TmlReaderThread(void* pParam);
static void* phTmlUwb_TmlWriterThread(void* pParam);
extern void setDeviceHandle(void* pDevHandle);
static void phTmlUwb_WaitWriteComplete(void);
static void phTmlUwb_SignalWriteComplete(void);
static int phTmlUwb_WaitReadInit(void);
/* Function definitions */
/*******************************************************************************
**
** Function phTmlUwb_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 UWB status:
** UWBSTATUS_SUCCESS - initialization successful
** UWBSTATUS_INVALID_PARAMETER - at least one parameter is
** invalid
** UWBSTATUS_FAILED - initialization failed (for example,
** unable to open hardware interface)
** UWBSTATUS_INVALID_DEVICE - device has not been opened or has
** been disconnected
**
*******************************************************************************/
tHAL_UWB_STATUS phTmlUwb_Init(const char* pDevName,
std::shared_ptr<MessageQueue<phLibUwb_Message>> pClientMq)
{
if (gpphTmlUwb_Context != nullptr) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_ALREADY_INITIALISED);
}
if (!pDevName || !pClientMq) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
}
// Allocate memory for TML context
gpphTmlUwb_Context = std::make_unique<phTmlUwb_Context>();
if (gpphTmlUwb_Context == nullptr) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
}
// Open the device file to which data is read/written
tHAL_UWB_STATUS wInitStatus =
phTmlUwb_spi_open_and_configure(pDevName, &(gpphTmlUwb_Context->pDevHandle));
if (UWBSTATUS_SUCCESS != wInitStatus) {
gpphTmlUwb_Context->pDevHandle = NULL;
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_DEVICE);
}
gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
gpphTmlUwb_Context->pClientMq = pClientMq;
setDeviceHandle(gpphTmlUwb_Context->pDevHandle); // To set device handle for FW download usecase
if (sem_init(&gpphTmlUwb_Context->rxSemaphore, 0, 0)) {
return UWBSTATUS_FAILED;
}
if (sem_init(&gpphTmlUwb_Context->txSemaphore, 0, 0)) {
return UWBSTATUS_FAILED;
}
if(phTmlUwb_WaitReadInit()) {
return UWBSTATUS_FAILED;
}
// Start TML thread (to handle write and read operations)
if (UWBSTATUS_SUCCESS != phTmlUwb_StartWriterThread()) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
}
return UWBSTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function phTmlUwb_TmlReaderThread
**
** Description Read the data from the lower layer driver
**
** Parameters pParam - parameters for Writer thread function
**
** Returns None
**
*******************************************************************************/
static void* phTmlUwb_TmlReaderThread(void* pParam)
{
UNUSED(pParam);
/* Transaction info buffer to be passed to Callback Thread */
static phTmlUwb_ReadTransactInfo tTransactionInfo;
/* Structure containing Tml callback function and parameters to be invoked
by the callback thread */
static phLibUwb_DeferredCall_t tDeferredInfo;
gpphTmlUwb_Context->tReadInfo.bThreadRunning = true;
NXPLOG_TML_D("TmlReader: Thread Started");
/* Writer thread loop shall be running till shutdown is invoked */
while (!gpphTmlUwb_Context->tReadInfo.bThreadShouldStop) {
NXPLOG_TML_V("TmlReader: Running");
if(sem_wait(&gpphTmlUwb_Context->rxSemaphore)) {
NXPLOG_TML_E("TmlReader: Failed to wait rxSemaphore err=%d", errno);
break;
}
tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
/* Read the data from the file onto the buffer */
if (!gpphTmlUwb_Context->pDevHandle) {
NXPLOG_TML_E("TmlRead: invalid file handle");
break;
}
NXPLOG_TML_V("TmlReader: Invoking SPI Read");
uint8_t temp[UCI_MAX_DATA_LEN];
int dwNoBytesWrRd =
phTmlUwb_spi_read(gpphTmlUwb_Context->pDevHandle, temp, UCI_MAX_DATA_LEN);
if(gpphTmlUwb_Context->tReadInfo.bThreadShouldStop) {
break;
}
if (-1 == dwNoBytesWrRd) {
NXPLOG_TML_E("TmlReader: Error in SPI Read");
sem_post(&gpphTmlUwb_Context->rxSemaphore);
} else if (dwNoBytesWrRd > UCI_MAX_DATA_LEN) {
NXPLOG_TML_E("TmlReader: Numer of bytes read exceeds the limit");
sem_post(&gpphTmlUwb_Context->rxSemaphore);
} else if(0 == dwNoBytesWrRd) {
NXPLOG_TML_E("TmlReader: Empty packet Read, Ignore read and try new read");
sem_post(&gpphTmlUwb_Context->rxSemaphore);
} else {
memcpy(gpphTmlUwb_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
NXPLOG_TML_V("TmlReader: SPI Read successful");
/* Update the actual number of bytes read including header */
gpphTmlUwb_Context->tReadInfo.wLength = dwNoBytesWrRd;
dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
NXPLOG_TML_V("TmlReader: Posting read message");
/* Fill the Transaction info structure to be passed to Callback
* Function */
tTransactionInfo.wStatus = wStatus;
tTransactionInfo.pBuff = gpphTmlUwb_Context->tReadInfo.pBuffer;
tTransactionInfo.wLength = gpphTmlUwb_Context->tReadInfo.wLength;
/* Read operation completed successfully. Post a Message onto Callback
* Thread*/
/* Prepare the message to be posted on User thread */
tDeferredInfo.pCallback = &phTmlUwb_ReadDeferredCb;
tDeferredInfo.pParameter = &tTransactionInfo;
/* TML reader writer callback synchronization mutex lock --- START */
if (pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex lock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
if ((gpphTmlUwb_Context->gWriterCbflag == false) &&
((gpphTmlUwb_Context->tReadInfo.pBuffer[0] & 0x60) != 0x60)) {
phTmlUwb_WaitWriteComplete();
}
/* TML reader writer callback synchronization mutex lock --- END */
if (pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex unlock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
auto msg = std::make_shared<phLibUwb_Message>(PH_LIBUWB_DEFERREDCALL_MSG, &tDeferredInfo);
phTmlUwb_DeferredCall(msg);
}
} /* End of While loop */
gpphTmlUwb_Context->tReadInfo.bThreadRunning = false;
NXPLOG_TML_D("Tml Reader: Thread stopped");
return NULL;
}
/*******************************************************************************
**
** Function phTmlUwb_TmlWriterThread
**
** Description Writes the requested data onto the lower layer driver
**
** Parameters pParam - context provided by upper layer
**
** Returns None
**
*******************************************************************************/
static void* phTmlUwb_TmlWriterThread(void* pParam)
{
UNUSED(pParam);
/* Transaction info buffer to be passed to Callback Thread */
static phTmlUwb_WriteTransactInfo tTransactionInfo;
/* Structure containing Tml callback function and parameters to be invoked
by the callback thread */
static phLibUwb_DeferredCall_t tDeferredInfo;
gpphTmlUwb_Context->tWriteInfo.bThreadRunning = true;
NXPLOG_TML_D("TmlWriter: Thread Started");
/* Writer thread loop shall be running till shutdown is invoked */
while (!gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop) {
NXPLOG_TML_V("TmlWriter: Running");
if (sem_wait(&gpphTmlUwb_Context->txSemaphore)) {
NXPLOG_TML_E("TmlWriter: Failed to wait txSemaphore, err=%d", errno);
break;
}
if (gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop) {
break;
}
tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
if (!gpphTmlUwb_Context->pDevHandle) {
NXPLOG_TML_E("TmlWriter: invalid file handle");
break;
}
NXPLOG_TML_V("TmlWriter: Invoking SPI Write");
/* TML reader writer callback synchronization mutex lock --- START
*/
if (pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex lock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
gpphTmlUwb_Context->gWriterCbflag = false;
int32_t dwNoBytesWrRd =
phTmlUwb_spi_write(gpphTmlUwb_Context->pDevHandle,
gpphTmlUwb_Context->tWriteInfo.pBuffer,
gpphTmlUwb_Context->tWriteInfo.wLength);
/* TML reader writer callback synchronization mutex lock --- END */
if (pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex unlock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
/* Try SPI Write Five Times, if it fails :*/
if (-1 == dwNoBytesWrRd) {
NXPLOG_TML_E("TmlWriter: Error in SPI Write");
wStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
} else {
phNxpUciHal_print_packet(NXP_TML_UCI_CMD_AP_2_UWBS,
gpphTmlUwb_Context->tWriteInfo.pBuffer,
gpphTmlUwb_Context->tWriteInfo.wLength);
}
if (UWBSTATUS_SUCCESS == wStatus) {
NXPLOG_TML_V("TmlWriter: SPI Write successful");
dwNoBytesWrRd = PH_TMLUWB_VALUE_ONE;
}
NXPLOG_TML_V("TmlWriter: Posting write message");
/* Fill the Transaction info structure to be passed to Callback Function
*/
tTransactionInfo.wStatus = wStatus;
tTransactionInfo.pBuff = gpphTmlUwb_Context->tWriteInfo.pBuffer;
tTransactionInfo.wLength = dwNoBytesWrRd;
/* Prepare the message to be posted on the User thread */
tDeferredInfo.pCallback = &phTmlUwb_WriteDeferredCb;
tDeferredInfo.pParameter = &tTransactionInfo;
auto msg = std::make_shared<phLibUwb_Message>(PH_LIBUWB_DEFERREDCALL_MSG, &tDeferredInfo);
phTmlUwb_DeferredCall(msg);
if (UWBSTATUS_SUCCESS == wStatus) {
/* TML reader writer callback synchronization mutex lock --- START
*/
if (pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex lock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
gpphTmlUwb_Context->gWriterCbflag = true;
phTmlUwb_SignalWriteComplete();
/* TML reader writer callback synchronization mutex lock --- END */
if (pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Mutex unlock failed for wait_busy_lock at line: %d", __func__, __LINE__);
}
}
} /* End of While loop */
gpphTmlUwb_Context->tWriteInfo.bThreadRunning = false;
NXPLOG_TML_D("TmlWriter: Thread stopped");
return NULL;
}
/*******************************************************************************
**
** Function phTmlUwb_CleanUp
**
** Description Clears all handles opened during TML initialization
**
** Parameters None
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_CleanUp(void) {
if (gpphTmlUwb_Context == nullptr) {
return;
}
if (NULL != gpphTmlUwb_Context->pDevHandle) {
(void)phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 0);
}
sem_destroy(&gpphTmlUwb_Context->rxSemaphore);
sem_destroy(&gpphTmlUwb_Context->txSemaphore);
if (pthread_mutex_destroy(&gpphTmlUwb_Context->wait_busy_lock)) {
NXPLOG_TML_E("[%s] Failed to destroy mutex 'wait_busy_lock' at line: %d", __func__, __LINE__);
}
if (pthread_cond_destroy(&gpphTmlUwb_Context->wait_busy_condition)) {
NXPLOG_TML_E("[%s] Failed to destroy conditional variable 'wait_busy_condition' at line: %d",
__func__, __LINE__);
}
phTmlUwb_spi_close(gpphTmlUwb_Context->pDevHandle);
gpphTmlUwb_Context->pDevHandle = NULL;
gpphTmlUwb_Context.reset();
}
/*******************************************************************************
**
** Function phTmlUwb_Shutdown
**
** Description Uninitializes TML layer and hardware interface
**
** Parameters None
**
** Returns UWB status:
** UWBSTATUS_SUCCESS - TML configuration released successfully
** UWBSTATUS_INVALID_PARAMETER - at least one parameter is
** invalid
** UWBSTATUS_FAILED - un-initialization failed (example: unable
** to close interface)
**
*******************************************************************************/
tHAL_UWB_STATUS phTmlUwb_Shutdown(void)
{
if (!gpphTmlUwb_Context) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
}
// Abort io threads
phTmlUwb_StopRead();
phTmlUwb_StopWriterThread();
phTmlUwb_CleanUp();
return UWBSTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function phTmlUwb_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_TMLUWB_WRITE_MESSAGE to IntegrationThread after data
** has been written to SRxxx
** * 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 UWB status:
** UWBSTATUS_PENDING - command is yet to be processed
** UWBSTATUS_INVALID_PARAMETER - at least one parameter is
** invalid
** UWBSTATUS_BUSY - write request is already in progress
**
*******************************************************************************/
tHAL_UWB_STATUS phTmlUwb_Write(const uint8_t* pBuffer, size_t wLength,
WriteCallback pTmlWriteComplete,
void* pContext) {
tHAL_UWB_STATUS wWriteStatus;
/* Check whether TML is Initialized */
if (NULL != gpphTmlUwb_Context) {
if ((NULL != gpphTmlUwb_Context->pDevHandle) && (NULL != pBuffer) &&
(PH_TMLUWB_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
if (!gpphTmlUwb_Context->tWriteInfo.bThreadBusy) {
/* Setting the flag marks beginning of a Write Operation */
gpphTmlUwb_Context->tWriteInfo.bThreadBusy = true;
/* Copy the buffer, length and Callback function,
This shall be utilized while invoking the Callback function in thread
*/
gpphTmlUwb_Context->tWriteInfo.pBuffer = pBuffer;
gpphTmlUwb_Context->tWriteInfo.wLength = wLength;
gpphTmlUwb_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
gpphTmlUwb_Context->tWriteInfo.pContext = pContext;
wWriteStatus = UWBSTATUS_PENDING;
/* Set event to invoke Writer Thread */
sem_post(&gpphTmlUwb_Context->txSemaphore);
} else {
wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
}
} else {
wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
}
} else {
wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
}
return wWriteStatus;
}
/*******************************************************************************
**
** Function phTmlUwb_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 UWB status:
** UWBSTATUS_PENDING - command is yet to be processed
** UWBSTATUS_INVALID_PARAMETER - at least one parameter is
** invalid
** UWBSTATUS_BUSY - read request is already in progress
**
*******************************************************************************/
tHAL_UWB_STATUS phTmlUwb_StartRead(ReadCallback pTmlReadComplete, void* pContext)
{
// TODO: move this to gpphTmlUwb_Context
static uint8_t shared_rx_buffer[UCI_MAX_DATA_LEN];
/* Check whether TML is Initialized */
if (!gpphTmlUwb_Context || !gpphTmlUwb_Context->pDevHandle) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
}
if (!pTmlReadComplete) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
}
if (gpphTmlUwb_Context->tReadInfo.bThreadRunning) {
return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
}
/* Setting the flag marks beginning of a Read Operation */
gpphTmlUwb_Context->tReadInfo.pBuffer = shared_rx_buffer;
gpphTmlUwb_Context->tReadInfo.wLength = sizeof(shared_rx_buffer);
gpphTmlUwb_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
gpphTmlUwb_Context->tReadInfo.pContext = pContext;
/* Set first event to invoke Reader Thread */
sem_post(&gpphTmlUwb_Context->rxSemaphore);
/* Create Reader threads */
gpphTmlUwb_Context->tReadInfo.bThreadShouldStop = false;
int ret = pthread_create(&gpphTmlUwb_Context->readerThread, NULL,
&phTmlUwb_TmlReaderThread, NULL);
if (ret) {
return UWBSTATUS_FAILED;
} else {
return UWBSTATUS_SUCCESS;
}
}
void phTmlUwb_StopRead()
{
gpphTmlUwb_Context->tReadInfo.bThreadShouldStop = true;
if (gpphTmlUwb_Context->tReadInfo.bThreadRunning) {
// to wakeup from blocking read()
phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, ABORT_READ_PENDING);
sem_post(&gpphTmlUwb_Context->rxSemaphore);
if (pthread_join(gpphTmlUwb_Context->readerThread, NULL)) {
NXPLOG_TML_E("[%s] pthread_join failed for reader thread at line: %d ", __func__, __LINE__);
}
}
}
/*******************************************************************************
**
** Function phTmlUwb_StartWriterThread
**
** Description start writer thread
**
** Parameters None
**
** Returns UWB status:
** UWBSTATUS_SUCCESS - threads initialized successfully
** UWBSTATUS_FAILED - initialization failed due to system error
**
*******************************************************************************/
static tHAL_UWB_STATUS phTmlUwb_StartWriterThread(void)
{
int ret;
gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop = false;
/*Start Writer Thread*/
ret = pthread_create(&gpphTmlUwb_Context->writerThread, NULL,
&phTmlUwb_TmlWriterThread, NULL);
if (ret) {
return UWBSTATUS_FAILED;
} else {
return UWBSTATUS_SUCCESS;
}
}
/*******************************************************************************
**
** Function phTmlUwb_StopWriterThread
**
** Description Stop writer thread
**
** Parameters None
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_StopWriterThread(void)
{
gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop = true;
if (gpphTmlUwb_Context->tWriteInfo.bThreadRunning) {
sem_post(&gpphTmlUwb_Context->txSemaphore);
if (pthread_join(gpphTmlUwb_Context->writerThread, NULL)) {
NXPLOG_TML_E("[%s] pthread_join failed for writer thread at line: %d ", __func__, __LINE__);
}
}
}
/*******************************************************************************
**
** Function phTmlUwb_DeferredCall
**
** Description Posts message on upper layer thread
** upon successful read or write operation
**
** Parameters msg - message to be posted
**
** Returns None
**
*******************************************************************************/
void phTmlUwb_DeferredCall(std::shared_ptr<phLibUwb_Message> msg)
{
gpphTmlUwb_Context->pClientMq->send(msg);
}
/*******************************************************************************
**
** Function phTmlUwb_ReadDeferredCb
**
** Description Read thread call back function
**
** Parameters pParams - context provided by upper layer
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_ReadDeferredCb(void* pParams)
{
/* Transaction info buffer to be passed to Callback Function */
phTmlUwb_ReadTransactInfo* pTransactionInfo = (phTmlUwb_ReadTransactInfo*)pParams;
/* Reset the flag to accept another Read Request */
gpphTmlUwb_Context->tReadInfo.pThread_Callback(
gpphTmlUwb_Context->tReadInfo.pContext, pTransactionInfo);
sem_post(&gpphTmlUwb_Context->rxSemaphore);
}
/*******************************************************************************
**
** Function phTmlUwb_WriteDeferredCb
**
** Description Write thread call back function
**
** Parameters pParams - context provided by upper layer
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_WriteDeferredCb(void* pParams) {
/* Transaction info buffer to be passed to Callback Function */
phTmlUwb_WriteTransactInfo* pTransactionInfo = (phTmlUwb_WriteTransactInfo*)pParams;
/* Reset the flag to accept another Write Request */
gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
gpphTmlUwb_Context->tWriteInfo.pThread_Callback(
gpphTmlUwb_Context->tWriteInfo.pContext, pTransactionInfo);
return;
}
/*******************************************************************************
**
** Function phTmlUwb_WaitWriteComplete
**
** Description wait function for reader thread
**
** Parameters None
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_WaitWriteComplete(void) {
int ret;
struct timespec absTimeout;
if (clock_gettime(CLOCK_MONOTONIC, &absTimeout) == -1) {
NXPLOG_TML_E("Reader Thread clock_gettime failed");
} else {
absTimeout.tv_sec += 1; /*1 second timeout*/
gpphTmlUwb_Context->wait_busy_flag = true;
NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - enter");
ret = pthread_cond_timedwait(&gpphTmlUwb_Context->wait_busy_condition,
&gpphTmlUwb_Context->wait_busy_lock,
&absTimeout);
if ((ret != 0) && (ret != ETIMEDOUT)) {
NXPLOG_TML_E("Reader Thread wait failed");
}
NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - exit");
}
}
/*******************************************************************************
**
** Function phTmlUwb_SignalWriteComplete
**
** Description function to invoke reader thread
**
** Parameters None
**
** Returns None
**
*******************************************************************************/
static void phTmlUwb_SignalWriteComplete(void) {
int ret;
if (gpphTmlUwb_Context->wait_busy_flag == true) {
NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - enter");
gpphTmlUwb_Context->wait_busy_flag = false;
ret = pthread_cond_signal(&gpphTmlUwb_Context->wait_busy_condition);
if (ret) {
NXPLOG_TML_E(" phTmlUwb_SignalWriteComplete failed, error = 0x%X", ret);
}
NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - exit");
}
}
/*******************************************************************************
**
** Function phTmlUwb_WaitReadInit
**
** Description init function for reader thread
**
** Parameters None
**
** Returns int
**
*******************************************************************************/
static int phTmlUwb_WaitReadInit(void) {
int ret;
pthread_condattr_t attr;
if (pthread_condattr_init(&attr)) {
NXPLOG_TML_E(" [%s] conditional attr init failed at line: %d", __func__, __LINE__);
}
if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
NXPLOG_TML_E(" [%s] conditional attr setClock failed at line: %d", __func__, __LINE__);
}
memset(&gpphTmlUwb_Context->wait_busy_condition, 0,
sizeof(gpphTmlUwb_Context->wait_busy_condition));
if (pthread_mutex_init(&gpphTmlUwb_Context->wait_busy_lock, NULL)) {
NXPLOG_TML_E(" [%s] mutex init failed for wait busy lock at line: %d", __func__, __LINE__);
}
ret = pthread_cond_init(&gpphTmlUwb_Context->wait_busy_condition, &attr);
if (ret) {
NXPLOG_TML_E("[%s] pthread_cond_init failed for wait_busy_condition at line: %d", __func__,
__LINE__);
}
return ret;
}
/*******************************************************************************
**
** Function phTmlUwb_Chip_Reset
**
** Description Invoke this API to Chip enable/Disable
**
** Parameters None
**
** Returns void
**
*******************************************************************************/
void phTmlUwb_Chip_Reset(void){
if (NULL != gpphTmlUwb_Context->pDevHandle) {
phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 0);
usleep(1000);
phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 1);
}
}
void phTmlUwb_Suspend(void)
{
NXPLOG_TML_D("Suspend");
phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, PWR_SUSPEND);
}
void phTmlUwb_Resume(void)
{
NXPLOG_TML_D("Resume");
phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, PWR_RESUME);
}