• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012-2020 NXP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <phNxpLog.h>
18 #include <phNxpUciHal_utils.h>
19 #include <phOsalUwb_Timer.h>
20 #include <phTmlUwb.h>
21 #include <phTmlUwb_spi.h>
22 #include <phNxpUciHal.h>
23 #include <errno.h>
24 
25 extern phNxpUciHal_Control_t nxpucihal_ctrl;
26 
27 /*
28  * Duration of Timer to wait after sending an Uci packet
29  */
30 #define PHTMLUWB_MAXTIME_RETRANSMIT (200U)
31 #define MAX_WRITE_RETRY_COUNT 0x03
32 /* Value to reset variables of TML  */
33 #define PH_TMLUWB_RESET_VALUE (0x00)
34 
35 /* Indicates a Initial or offset value */
36 #define PH_TMLUWB_VALUE_ONE (0x01)
37 
38 /* Initialize Context structure pointer used to access context structure */
39 static phTmlUwb_Context_t* gpphTmlUwb_Context;
40 
41 /* Local Function prototypes */
42 static tHAL_UWB_STATUS phTmlUwb_StartWriterThread(void);
43 static void phTmlUwb_StopWriterThread(void);
44 
45 static void phTmlUwb_CleanUp(void);
46 static void phTmlUwb_ReadDeferredCb(void* pParams);
47 static void phTmlUwb_WriteDeferredCb(void* pParams);
48 static void* phTmlUwb_TmlReaderThread(void* pParam);
49 static void* phTmlUwb_TmlWriterThread(void* pParam);
50 
51 extern void setDeviceHandle(void* pDevHandle);
52 
53 static void phTmlUwb_WaitWriteComplete(void);
54 static void phTmlUwb_SignalWriteComplete(void);
55 static int phTmlUwb_WaitReadInit(void);
56 
57 /* Function definitions */
58 
59 /*******************************************************************************
60 **
61 ** Function         phTmlUwb_Init
62 **
63 ** Description      Provides initialization of TML layer and hardware interface
64 **                  Configures given hardware interface and sends handle to the
65 **                  caller
66 **
67 ** Parameters       pConfig - TML configuration details as provided by the upper
68 **                            layer
69 **
70 ** Returns          UWB status:
71 **                  UWBSTATUS_SUCCESS - initialization successful
72 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
73 **                                                invalid
74 **                  UWBSTATUS_FAILED - initialization failed (for example,
75 **                                     unable to open hardware interface)
76 **                  UWBSTATUS_INVALID_DEVICE - device has not been opened or has
77 **                                             been disconnected
78 **
79 *******************************************************************************/
phTmlUwb_Init(const char * pDevName,std::shared_ptr<MessageQueue<phLibUwb_Message>> pClientMq)80 tHAL_UWB_STATUS phTmlUwb_Init(const char* pDevName, std::shared_ptr<MessageQueue<phLibUwb_Message>> pClientMq)
81 {
82   tHAL_UWB_STATUS wInitStatus = UWBSTATUS_SUCCESS;
83 
84   /* Check if TML layer is already Initialized */
85   if (NULL != gpphTmlUwb_Context) {
86     /* TML initialization is already completed */
87     wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_ALREADY_INITIALISED);
88   }
89   /* Validate Input parameters */
90   else if (!pDevName || !pClientMq) {
91     /*Parameters passed to TML init are wrong */
92     wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
93   } else {
94     /* Allocate memory for TML context */
95     gpphTmlUwb_Context =
96         (phTmlUwb_Context_t*)malloc(sizeof(phTmlUwb_Context_t));
97 
98     if (NULL == gpphTmlUwb_Context) {
99       wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
100     } else {
101       /* Initialise all the internal TML variables */
102       memset(gpphTmlUwb_Context, PH_TMLUWB_RESET_VALUE,
103              sizeof(phTmlUwb_Context_t));
104 
105       /* Open the device file to which data is read/written */
106       wInitStatus = phTmlUwb_spi_open_and_configure(pDevName, &(gpphTmlUwb_Context->pDevHandle));
107 
108       if (UWBSTATUS_SUCCESS != wInitStatus) {
109         wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_DEVICE);
110         gpphTmlUwb_Context->pDevHandle = NULL;
111       } else {
112         gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
113         gpphTmlUwb_Context->pClientMq = pClientMq;
114 
115         setDeviceHandle(gpphTmlUwb_Context->pDevHandle);  // To set device handle for FW download usecase
116 
117         if (0 != sem_init(&gpphTmlUwb_Context->rxSemaphore, 0, 0)) {
118           wInitStatus = UWBSTATUS_FAILED;
119         } else if (0 != sem_init(&gpphTmlUwb_Context->txSemaphore, 0, 0)) {
120           wInitStatus = UWBSTATUS_FAILED;
121         } else if(0 != phTmlUwb_WaitReadInit()) {
122            wInitStatus = UWBSTATUS_FAILED;
123         } else {
124           /* Start TML thread (to handle write and read operations) */
125           if (UWBSTATUS_SUCCESS != phTmlUwb_StartWriterThread()) {
126             wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
127           } else {
128             /* Store the Thread Identifier to which Message is to be posted */
129             wInitStatus = UWBSTATUS_SUCCESS;
130           }
131         }
132       }
133     }
134   }
135   /* Clean up all the TML resources if any error */
136   if (UWBSTATUS_SUCCESS != wInitStatus) {
137     /* Clear all handles and memory locations initialized during init */
138     phTmlUwb_CleanUp();
139   }
140 
141   return wInitStatus;
142 }
143 
144 /*******************************************************************************
145 **
146 ** Function         phTmlUwb_TmlReaderThread
147 **
148 ** Description      Read the data from the lower layer driver
149 **
150 ** Parameters       pParam  - parameters for Writer thread function
151 **
152 ** Returns          None
153 **
154 *******************************************************************************/
phTmlUwb_TmlReaderThread(void * pParam)155 static void* phTmlUwb_TmlReaderThread(void* pParam)
156 {
157   UNUSED(pParam);
158 
159   /* Transaction info buffer to be passed to Callback Thread */
160   static phTmlUwb_TransactInfo_t tTransactionInfo;
161   /* Structure containing Tml callback function and parameters to be invoked
162      by the callback thread */
163   static phLibUwb_DeferredCall_t tDeferredInfo;
164 
165   gpphTmlUwb_Context->tReadInfo.bThreadRunning = true;
166   NXPLOG_TML_D("TmlReader: Thread Started");
167 
168   /* Writer thread loop shall be running till shutdown is invoked */
169   while (!gpphTmlUwb_Context->tReadInfo.bThreadShouldStop) {
170     NXPLOG_TML_V("TmlReader: Running");
171     if(sem_wait(&gpphTmlUwb_Context->rxSemaphore)) {
172       NXPLOG_TML_E("TmlReader: Failed to wait rxSemaphore err=%d", errno);
173       break;
174     }
175 
176     tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
177 
178     /* Read the data from the file onto the buffer */
179     if (!gpphTmlUwb_Context->pDevHandle) {
180       NXPLOG_TML_E("TmlRead: invalid file handle");
181       break;
182     }
183 
184     NXPLOG_TML_V("TmlReader:  Invoking SPI Read");
185 
186     uint8_t temp[UCI_MAX_DATA_LEN];
187     int32_t dwNoBytesWrRd =
188         phTmlUwb_spi_read(gpphTmlUwb_Context->pDevHandle, temp, UCI_MAX_DATA_LEN);
189 
190     if(gpphTmlUwb_Context->tReadInfo.bThreadShouldStop) {
191       break;
192     }
193 
194     if (-1 == dwNoBytesWrRd) {
195       NXPLOG_TML_E("TmlReader: Error in SPI Read");
196       sem_post(&gpphTmlUwb_Context->rxSemaphore);
197     } else if (dwNoBytesWrRd > UCI_MAX_DATA_LEN) {
198       NXPLOG_TML_E("TmlReader: Numer of bytes read exceeds the limit");
199       sem_post(&gpphTmlUwb_Context->rxSemaphore);
200     } else if(0 == dwNoBytesWrRd) {
201       NXPLOG_TML_E("TmlReader: Empty packet Read, Ignore read and try new read");
202       sem_post(&gpphTmlUwb_Context->rxSemaphore);
203     } else {
204       memcpy(gpphTmlUwb_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
205 
206       NXPLOG_TML_V("TmlReader: SPI Read successful");
207 
208       /* Update the actual number of bytes read including header */
209       gpphTmlUwb_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
210 
211       dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
212 
213       NXPLOG_TML_V("TmlReader: Posting read message");
214 
215       /* Fill the Transaction info structure to be passed to Callback
216        * Function */
217       tTransactionInfo.wStatus = wStatus;
218       tTransactionInfo.pBuff = gpphTmlUwb_Context->tReadInfo.pBuffer;
219       tTransactionInfo.wLength = gpphTmlUwb_Context->tReadInfo.wLength;
220 
221       /* Read operation completed successfully. Post a Message onto Callback
222        * Thread*/
223       /* Prepare the message to be posted on User thread */
224       tDeferredInfo.pCallback = &phTmlUwb_ReadDeferredCb;
225       tDeferredInfo.pParameter = &tTransactionInfo;
226 
227       /* TML reader writer callback synchronization mutex lock --- START */
228       pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
229       if ((gpphTmlUwb_Context->gWriterCbflag == false) &&
230         ((gpphTmlUwb_Context->tReadInfo.pBuffer[0] & 0x60) != 0x60)) {
231         phTmlUwb_WaitWriteComplete();
232       }
233       /* TML reader writer callback synchronization mutex lock --- END */
234       pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
235 
236       auto msg = std::make_shared<phLibUwb_Message>(PH_LIBUWB_DEFERREDCALL_MSG, &tDeferredInfo);
237       phTmlUwb_DeferredCall(msg);
238     }
239   } /* End of While loop */
240 
241   gpphTmlUwb_Context->tReadInfo.bThreadRunning = false;
242   NXPLOG_TML_D("Tml Reader: Thread stopped");
243 
244   return NULL;
245 }
246 
247 /*******************************************************************************
248 **
249 ** Function         phTmlUwb_TmlWriterThread
250 **
251 ** Description      Writes the requested data onto the lower layer driver
252 **
253 ** Parameters       pParam  - context provided by upper layer
254 **
255 ** Returns          None
256 **
257 *******************************************************************************/
phTmlUwb_TmlWriterThread(void * pParam)258 static void* phTmlUwb_TmlWriterThread(void* pParam)
259 {
260   UNUSED(pParam);
261 
262   /* Transaction info buffer to be passed to Callback Thread */
263   static phTmlUwb_TransactInfo_t tTransactionInfo;
264   /* Structure containing Tml callback function and parameters to be invoked
265      by the callback thread */
266   static phLibUwb_DeferredCall_t tDeferredInfo;
267 
268   gpphTmlUwb_Context->tWriteInfo.bThreadRunning = true;
269   NXPLOG_TML_D("TmlWriter: Thread Started");
270 
271   /* Writer thread loop shall be running till shutdown is invoked */
272   while (!gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop) {
273     NXPLOG_TML_V("TmlWriter: Running");
274     if (sem_wait(&gpphTmlUwb_Context->txSemaphore)) {
275       NXPLOG_TML_E("TmlWriter: Failed to wait txSemaphore, err=%d", errno);
276       break;
277     }
278 
279     tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
280 
281     if (!gpphTmlUwb_Context->pDevHandle) {
282       NXPLOG_TML_E("TmlWriter: invalid file handle");
283       break;
284     }
285 
286     NXPLOG_TML_V("TmlWriter: Invoking SPI Write");
287 
288     /* TML reader writer callback synchronization mutex lock --- START
289       */
290     pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
291     gpphTmlUwb_Context->gWriterCbflag = false;
292     int32_t dwNoBytesWrRd =
293         phTmlUwb_spi_write(gpphTmlUwb_Context->pDevHandle,
294                             gpphTmlUwb_Context->tWriteInfo.pBuffer,
295                             gpphTmlUwb_Context->tWriteInfo.wLength);
296     /* TML reader writer callback synchronization mutex lock --- END */
297     pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
298 
299     /* Try SPI Write Five Times, if it fails :*/
300     if (-1 == dwNoBytesWrRd) {
301       NXPLOG_TML_E("TmlWriter: Error in SPI Write");
302       wStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
303     } else {
304       phNxpUciHal_print_packet(NXP_TML_UCI_CMD_AP_2_UWBS,
305                                 gpphTmlUwb_Context->tWriteInfo.pBuffer,
306                                 gpphTmlUwb_Context->tWriteInfo.wLength);
307     }
308     if (UWBSTATUS_SUCCESS == wStatus) {
309       NXPLOG_TML_V("TmlWriter: SPI Write successful");
310       dwNoBytesWrRd = PH_TMLUWB_VALUE_ONE;
311     }
312 
313     NXPLOG_TML_V("TmlWriter: Posting write message");
314 
315     /* Fill the Transaction info structure to be passed to Callback Function
316      */
317     tTransactionInfo.wStatus = wStatus;
318     tTransactionInfo.pBuff = gpphTmlUwb_Context->tWriteInfo.pBuffer;
319     tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
320 
321     /* Prepare the message to be posted on the User thread */
322     tDeferredInfo.pCallback = &phTmlUwb_WriteDeferredCb;
323     tDeferredInfo.pParameter = &tTransactionInfo;
324 
325     auto msg = std::make_shared<phLibUwb_Message>(PH_LIBUWB_DEFERREDCALL_MSG, &tDeferredInfo);
326     phTmlUwb_DeferredCall(msg);
327 
328     if (UWBSTATUS_SUCCESS == wStatus) {
329       /* TML reader writer callback synchronization mutex lock --- START
330           */
331       pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
332       gpphTmlUwb_Context->gWriterCbflag = true;
333       phTmlUwb_SignalWriteComplete();
334         /* TML reader writer callback synchronization mutex lock --- END */
335       pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
336     }
337   } /* End of While loop */
338 
339   gpphTmlUwb_Context->tWriteInfo.bThreadRunning = false;
340   NXPLOG_TML_D("TmlWriter: Thread stopped");
341 
342   return NULL;
343 }
344 
345 /*******************************************************************************
346 **
347 ** Function         phTmlUwb_CleanUp
348 **
349 ** Description      Clears all handles opened during TML initialization
350 **
351 ** Parameters       None
352 **
353 ** Returns          None
354 **
355 *******************************************************************************/
phTmlUwb_CleanUp(void)356 static void phTmlUwb_CleanUp(void) {
357   if (NULL == gpphTmlUwb_Context) {
358     return;
359   }
360   if (NULL != gpphTmlUwb_Context->pDevHandle) {
361     (void)phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 0);
362   }
363 
364   sem_destroy(&gpphTmlUwb_Context->rxSemaphore);
365   sem_destroy(&gpphTmlUwb_Context->txSemaphore);
366   pthread_mutex_destroy(&gpphTmlUwb_Context->wait_busy_lock);
367   pthread_cond_destroy(&gpphTmlUwb_Context->wait_busy_condition);
368   phTmlUwb_spi_close(gpphTmlUwb_Context->pDevHandle);
369   gpphTmlUwb_Context->pDevHandle = NULL;
370 
371   /* Clear memory allocated for storing Context variables */
372   free((void*)gpphTmlUwb_Context);
373   /* Set the pointer to NULL to indicate De-Initialization */
374   gpphTmlUwb_Context = NULL;
375 
376   return;
377 }
378 
379 /*******************************************************************************
380 **
381 ** Function         phTmlUwb_Shutdown
382 **
383 ** Description      Uninitializes TML layer and hardware interface
384 **
385 ** Parameters       None
386 **
387 ** Returns          UWB status:
388 **                  UWBSTATUS_SUCCESS - TML configuration released successfully
389 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
390 **                                                invalid
391 **                  UWBSTATUS_FAILED - un-initialization failed (example: unable
392 **                                     to close interface)
393 **
394 *******************************************************************************/
phTmlUwb_Shutdown(void)395 tHAL_UWB_STATUS phTmlUwb_Shutdown(void)
396 {
397   if (!gpphTmlUwb_Context) {
398     return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
399   }
400 
401   // Abort io threads
402   phTmlUwb_StopRead();
403 
404   phTmlUwb_StopWriterThread();
405 
406   phTmlUwb_CleanUp();
407 
408   return UWBSTATUS_SUCCESS;
409 }
410 
411 /*******************************************************************************
412 **
413 ** Function         phTmlUwb_Write
414 **
415 ** Description      Asynchronously writes given data block to hardware
416 **                  interface/driver. Enables writer thread if there are no
417 **                  write requests pending. Returns successfully once writer
418 **                  thread completes write operation. Notifies upper layer using
419 **                  callback mechanism.
420 **
421 **                  NOTE:
422 **                  * it is important to post a message with id
423 **                    PH_TMLUWB_WRITE_MESSAGE to IntegrationThread after data
424 **                    has been written to SRxxx
425 **                  * if CRC needs to be computed, then input buffer should be
426 **                    capable to store two more bytes apart from length of
427 **                    packet
428 **
429 ** Parameters       pBuffer - data to be sent
430 **                  wLength - length of data buffer
431 **                  pTmlWriteComplete - pointer to the function to be invoked
432 **                                      upon completion
433 **                  pContext - context provided by upper layer
434 **
435 ** Returns          UWB status:
436 **                  UWBSTATUS_PENDING - command is yet to be processed
437 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
438 **                                                invalid
439 **                  UWBSTATUS_BUSY - write request is already in progress
440 **
441 *******************************************************************************/
phTmlUwb_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlUwb_TransactCompletionCb_t pTmlWriteComplete,void * pContext)442 tHAL_UWB_STATUS phTmlUwb_Write(uint8_t* pBuffer, uint16_t wLength,
443                          pphTmlUwb_TransactCompletionCb_t pTmlWriteComplete,
444                          void* pContext) {
445   tHAL_UWB_STATUS wWriteStatus;
446 
447   /* Check whether TML is Initialized */
448 
449   if (NULL != gpphTmlUwb_Context) {
450     if ((NULL != gpphTmlUwb_Context->pDevHandle) && (NULL != pBuffer) &&
451         (PH_TMLUWB_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
452       if (!gpphTmlUwb_Context->tWriteInfo.bThreadBusy) {
453         /* Setting the flag marks beginning of a Write Operation */
454         gpphTmlUwb_Context->tWriteInfo.bThreadBusy = true;
455         /* Copy the buffer, length and Callback function,
456            This shall be utilized while invoking the Callback function in thread
457            */
458         gpphTmlUwb_Context->tWriteInfo.pBuffer = pBuffer;
459         gpphTmlUwb_Context->tWriteInfo.wLength = wLength;
460         gpphTmlUwb_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
461         gpphTmlUwb_Context->tWriteInfo.pContext = pContext;
462 
463         wWriteStatus = UWBSTATUS_PENDING;
464         /* Set event to invoke Writer Thread */
465         sem_post(&gpphTmlUwb_Context->txSemaphore);
466       } else {
467         wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
468       }
469     } else {
470       wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
471     }
472   } else {
473     wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
474   }
475 
476   return wWriteStatus;
477 }
478 
479 /*******************************************************************************
480 **
481 ** Function         phTmlUwb_Read
482 **
483 ** Description      Asynchronously reads data from the driver
484 **                  Number of bytes to be read and buffer are passed by upper
485 **                  layer.
486 **                  Enables reader thread if there are no read requests pending
487 **                  Returns successfully once read operation is completed
488 **                  Notifies upper layer using callback mechanism
489 **
490 ** Parameters       pBuffer - location to send read data to the upper layer via
491 **                            callback
492 **                  wLength - length of read data buffer passed by upper layer
493 **                  pTmlReadComplete - pointer to the function to be invoked
494 **                                     upon completion of read operation
495 **                  pContext - context provided by upper layer
496 **
497 ** Returns          UWB status:
498 **                  UWBSTATUS_PENDING - command is yet to be processed
499 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
500 **                                                invalid
501 **                  UWBSTATUS_BUSY - read request is already in progress
502 **
503 *******************************************************************************/
phTmlUwb_StartRead(uint8_t * pBuffer,uint16_t wLength,pphTmlUwb_TransactCompletionCb_t pTmlReadComplete,void * pContext)504 tHAL_UWB_STATUS phTmlUwb_StartRead(uint8_t* pBuffer, uint16_t wLength,
505                         pphTmlUwb_TransactCompletionCb_t pTmlReadComplete,
506                         void* pContext)
507 {
508   /* Check whether TML is Initialized */
509   if (!gpphTmlUwb_Context || !gpphTmlUwb_Context->pDevHandle) {
510     return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
511   }
512 
513   if (!pBuffer || wLength < 1 || !pTmlReadComplete) {
514     return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
515   }
516 
517   if (gpphTmlUwb_Context->tReadInfo.bThreadRunning) {
518     return PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
519   }
520 
521   /* Setting the flag marks beginning of a Read Operation */
522   gpphTmlUwb_Context->tReadInfo.pBuffer = pBuffer;
523   gpphTmlUwb_Context->tReadInfo.wLength = wLength;
524   gpphTmlUwb_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
525   gpphTmlUwb_Context->tReadInfo.pContext = pContext;
526 
527   /* Set first event to invoke Reader Thread */
528   sem_post(&gpphTmlUwb_Context->rxSemaphore);
529 
530   /* Create Reader threads */
531   gpphTmlUwb_Context->tReadInfo.bThreadShouldStop = false;
532   int ret = pthread_create(&gpphTmlUwb_Context->readerThread, NULL,
533                        &phTmlUwb_TmlReaderThread, NULL);
534   if (ret) {
535     return UWBSTATUS_FAILED;
536   } else {
537     return UWBSTATUS_SUCCESS;
538   }
539 }
540 
phTmlUwb_StopRead()541 void phTmlUwb_StopRead()
542 {
543   gpphTmlUwb_Context->tReadInfo.bThreadShouldStop = true;
544 
545   if (gpphTmlUwb_Context->tReadInfo.bThreadRunning) {
546     // to wakeup from blocking read()
547     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, ABORT_READ_PENDING);
548     sem_post(&gpphTmlUwb_Context->rxSemaphore);
549 
550     pthread_join(gpphTmlUwb_Context->readerThread, NULL);
551   }
552 }
553 
554 /*******************************************************************************
555 **
556 ** Function         phTmlUwb_StartWriterThread
557 **
558 ** Description      start writer thread
559 **
560 ** Parameters       None
561 **
562 ** Returns          UWB status:
563 **                  UWBSTATUS_SUCCESS - threads initialized successfully
564 **                  UWBSTATUS_FAILED - initialization failed due to system error
565 **
566 *******************************************************************************/
phTmlUwb_StartWriterThread(void)567 static tHAL_UWB_STATUS phTmlUwb_StartWriterThread(void)
568 {
569   int ret;
570 
571   gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop = false;
572 
573   /*Start Writer Thread*/
574   ret = pthread_create(&gpphTmlUwb_Context->writerThread, NULL,
575                        &phTmlUwb_TmlWriterThread, NULL);
576   if (ret) {
577     return UWBSTATUS_FAILED;
578   } else {
579     return UWBSTATUS_SUCCESS;
580   }
581 }
582 
583 
584 /*******************************************************************************
585 **
586 ** Function         phTmlUwb_StopWriterThread
587 **
588 ** Description      Stop writer thread
589 **
590 ** Parameters       None
591 **
592 ** Returns          None
593 **
594 *******************************************************************************/
phTmlUwb_StopWriterThread(void)595 static void phTmlUwb_StopWriterThread(void)
596 {
597   gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
598   gpphTmlUwb_Context->tWriteInfo.bThreadShouldStop = true;
599 
600   if (gpphTmlUwb_Context->tWriteInfo.bThreadRunning) {
601     sem_post(&gpphTmlUwb_Context->txSemaphore);
602 
603     pthread_join(gpphTmlUwb_Context->writerThread, NULL);
604   }
605 }
606 
607 /*******************************************************************************
608 **
609 ** Function         phTmlUwb_DeferredCall
610 **
611 ** Description      Posts message on upper layer thread
612 **                  upon successful read or write operation
613 **
614 ** Parameters       msg - message to be posted
615 **
616 ** Returns          None
617 **
618 *******************************************************************************/
phTmlUwb_DeferredCall(std::shared_ptr<phLibUwb_Message> msg)619 void phTmlUwb_DeferredCall(std::shared_ptr<phLibUwb_Message> msg)
620 {
621   gpphTmlUwb_Context->pClientMq->send(msg);
622 }
623 
624 /*******************************************************************************
625 **
626 ** Function         phTmlUwb_ReadDeferredCb
627 **
628 ** Description      Read thread call back function
629 **
630 ** Parameters       pParams - context provided by upper layer
631 **
632 ** Returns          None
633 **
634 *******************************************************************************/
phTmlUwb_ReadDeferredCb(void * pParams)635 static void phTmlUwb_ReadDeferredCb(void* pParams)
636 {
637   /* Transaction info buffer to be passed to Callback Function */
638   phTmlUwb_TransactInfo_t* pTransactionInfo = (phTmlUwb_TransactInfo_t*)pParams;
639 
640   /* Reset the flag to accept another Read Request */
641   gpphTmlUwb_Context->tReadInfo.pThread_Callback(
642       gpphTmlUwb_Context->tReadInfo.pContext, pTransactionInfo);
643 
644   sem_post(&gpphTmlUwb_Context->rxSemaphore);
645 }
646 
647 /*******************************************************************************
648 **
649 ** Function         phTmlUwb_WriteDeferredCb
650 **
651 ** Description      Write thread call back function
652 **
653 ** Parameters       pParams - context provided by upper layer
654 **
655 ** Returns          None
656 **
657 *******************************************************************************/
phTmlUwb_WriteDeferredCb(void * pParams)658 static void phTmlUwb_WriteDeferredCb(void* pParams) {
659   /* Transaction info buffer to be passed to Callback Function */
660   phTmlUwb_TransactInfo_t* pTransactionInfo = (phTmlUwb_TransactInfo_t*)pParams;
661 
662   /* Reset the flag to accept another Write Request */
663   gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
664   gpphTmlUwb_Context->tWriteInfo.pThread_Callback(
665       gpphTmlUwb_Context->tWriteInfo.pContext, pTransactionInfo);
666 
667   return;
668 }
669 
670 /*******************************************************************************
671 **
672 ** Function         phTmlUwb_WaitWriteComplete
673 **
674 ** Description      wait function for reader thread
675 **
676 ** Parameters       None
677 **
678 ** Returns          None
679 **
680 *******************************************************************************/
phTmlUwb_WaitWriteComplete(void)681 static void phTmlUwb_WaitWriteComplete(void) {
682   int ret;
683   struct timespec absTimeout;
684   if (clock_gettime(CLOCK_MONOTONIC, &absTimeout) == -1) {
685     NXPLOG_TML_E("Reader Thread clock_gettime failed");
686   } else {
687     absTimeout.tv_sec += 1; /*1 second timeout*/
688     gpphTmlUwb_Context->wait_busy_flag = true;
689     NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - enter");
690     ret = pthread_cond_timedwait(&gpphTmlUwb_Context->wait_busy_condition,
691                                  &gpphTmlUwb_Context->wait_busy_lock,
692                                  &absTimeout);
693     if ((ret != 0) && (ret != ETIMEDOUT)) {
694       NXPLOG_TML_E("Reader Thread wait failed");
695     }
696     NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - exit");
697   }
698 }
699 
700 /*******************************************************************************
701 **
702 ** Function         phTmlUwb_SignalWriteComplete
703 **
704 ** Description      function to invoke reader thread
705 **
706 ** Parameters       None
707 **
708 ** Returns          None
709 **
710 *******************************************************************************/
phTmlUwb_SignalWriteComplete(void)711 static void phTmlUwb_SignalWriteComplete(void) {
712   int ret;
713   if (gpphTmlUwb_Context->wait_busy_flag == true) {
714     NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - enter");
715     gpphTmlUwb_Context->wait_busy_flag = false;
716     ret = pthread_cond_signal(&gpphTmlUwb_Context->wait_busy_condition);
717     if (ret) {
718       NXPLOG_TML_E(" phTmlUwb_SignalWriteComplete failed, error = 0x%X", ret);
719     }
720     NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - exit");
721   }
722 }
723 
724 /*******************************************************************************
725 **
726 ** Function         phTmlUwb_WaitReadInit
727 **
728 ** Description      init function for reader thread
729 **
730 ** Parameters       None
731 **
732 ** Returns          int
733 **
734 *******************************************************************************/
phTmlUwb_WaitReadInit(void)735 static int phTmlUwb_WaitReadInit(void) {
736   int ret;
737   pthread_condattr_t attr;
738   pthread_condattr_init(&attr);
739   pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
740   memset(&gpphTmlUwb_Context->wait_busy_condition, 0,
741          sizeof(gpphTmlUwb_Context->wait_busy_condition));
742   pthread_mutex_init(&gpphTmlUwb_Context->wait_busy_lock, NULL);
743   ret = pthread_cond_init(&gpphTmlUwb_Context->wait_busy_condition, &attr);
744   if (ret) {
745     NXPLOG_TML_E(" phTmlUwb_WaitReadInit failed, error = 0x%X", ret);
746   }
747   return ret;
748 }
749 
750 /*******************************************************************************
751 **
752 ** Function         phTmlUwb_Chip_Reset
753 **
754 ** Description      Invoke this API to Chip enable/Disable
755 **
756 ** Parameters       None
757 **
758 ** Returns          void
759 **
760 *******************************************************************************/
phTmlUwb_Chip_Reset(void)761 void phTmlUwb_Chip_Reset(void){
762   if (NULL != gpphTmlUwb_Context->pDevHandle) {
763     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 0);
764     usleep(1000);
765     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, 1);
766   }
767 }
768 
phTmlUwb_Suspend(void)769 void phTmlUwb_Suspend(void)
770 {
771   NXPLOG_TML_D("Suspend");
772   phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, PWR_SUSPEND);
773 
774 }
775 
phTmlUwb_Resume(void)776 void phTmlUwb_Resume(void)
777 {
778   NXPLOG_TML_D("Resume");
779   phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_ControlCode_t::SetPower, PWR_RESUME);
780 }
781