• 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 <phDal4Uwb_messageQueueLib.h>
18 #include <phNxpLog.h>
19 #include <phNxpUciHal_utils.h>
20 #include <phOsalUwb_Timer.h>
21 #include <phTmlUwb.h>
22 #include <phTmlUwb_spi.h>
23 #include <phNxpUciHal.h>
24 #include <errno.h>
25 
26 extern phNxpUciHal_Control_t nxpucihal_ctrl;
27 
28 /*
29  * Duration of Timer to wait after sending an Uci packet
30  */
31 #define PHTMLUWB_MAXTIME_RETRANSMIT (200U)
32 #define MAX_WRITE_RETRY_COUNT 0x03
33 /* Value to reset variables of TML  */
34 #define PH_TMLUWB_RESET_VALUE (0x00)
35 
36 /* Indicates a Initial or offset value */
37 #define PH_TMLUWB_VALUE_ONE (0x01)
38 
39 /* Initialize Context structure pointer used to access context structure */
40 phTmlUwb_Context_t* gpphTmlUwb_Context = NULL;
41 
42 /* Local Function prototypes */
43 static tHAL_UWB_STATUS phTmlUwb_StartThread(void);
44 static void phTmlUwb_CleanUp(void);
45 static void phTmlUwb_ReadDeferredCb(void* pParams);
46 static void phTmlUwb_WriteDeferredCb(void* pParams);
47 static void* phTmlUwb_TmlReaderThread(void* pParam);
48 static void* phTmlUwb_TmlWriterThread(void* pParam);
49 
50 extern void setDeviceHandle(void* pDevHandle);
51 
52 static void phTmlUwb_WaitWriteComplete(void);
53 static void phTmlUwb_SignalWriteComplete(void);
54 static int phTmlUwb_WaitReadInit(void);
55 static int phTmlUwb_ReadAbortInit(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(pphTmlUwb_Config_t pConfig)80 tHAL_UWB_STATUS phTmlUwb_Init(pphTmlUwb_Config_t pConfig) {
81   tHAL_UWB_STATUS wInitStatus = UWBSTATUS_SUCCESS;
82 
83   /* Check if TML layer is already Initialized */
84   if (NULL != gpphTmlUwb_Context) {
85     /* TML initialization is already completed */
86     wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_ALREADY_INITIALISED);
87   }
88   /* Validate Input parameters */
89   else if ((NULL == pConfig) ||
90            (PH_TMLUWB_RESET_VALUE == pConfig->dwGetMsgThreadId)) {
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       /* Make sure that the thread runs once it is created */
105       gpphTmlUwb_Context->bThreadDone = 1;
106 
107       /* Open the device file to which data is read/written */
108       wInitStatus = phTmlUwb_spi_open_and_configure(
109           pConfig, &(gpphTmlUwb_Context->pDevHandle));
110 
111       if (UWBSTATUS_SUCCESS != wInitStatus) {
112         wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_DEVICE);
113         gpphTmlUwb_Context->pDevHandle = NULL;
114       } else {
115         gpphTmlUwb_Context->tReadInfo.bEnable = 0;
116         gpphTmlUwb_Context->tWriteInfo.bEnable = 0;
117         gpphTmlUwb_Context->tReadInfo.bThreadBusy = false;
118         gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
119 
120         setDeviceHandle(gpphTmlUwb_Context->pDevHandle);  // To set device hanlde for FW download usecase
121 
122         if (0 != sem_init(&gpphTmlUwb_Context->rxSemaphore, 0, 0)) {
123           wInitStatus = UWBSTATUS_FAILED;
124         } else if (0 != sem_init(&gpphTmlUwb_Context->txSemaphore, 0, 0)) {
125           wInitStatus = UWBSTATUS_FAILED;
126         } else if(0 != phTmlUwb_WaitReadInit()) {
127            wInitStatus = UWBSTATUS_FAILED;
128         } else if(0 != phTmlUwb_ReadAbortInit()) {
129            wInitStatus = UWBSTATUS_FAILED;
130         } else if (0 != sem_init(&gpphTmlUwb_Context->postMsgSemaphore, 0, 0)) {
131           wInitStatus = UWBSTATUS_FAILED;
132         } else {
133           sem_post(&gpphTmlUwb_Context->postMsgSemaphore);
134           /* Start TML thread (to handle write and read operations) */
135           if (UWBSTATUS_SUCCESS != phTmlUwb_StartThread()) {
136             wInitStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
137           } else {
138             /* Store the Thread Identifier to which Message is to be posted */
139             gpphTmlUwb_Context->dwCallbackThreadId =
140                   pConfig->dwGetMsgThreadId;
141             wInitStatus = UWBSTATUS_SUCCESS;
142           }
143         }
144       }
145     }
146   }
147   /* Clean up all the TML resources if any error */
148   if (UWBSTATUS_SUCCESS != wInitStatus) {
149     /* Clear all handles and memory locations initialized during init */
150     phTmlUwb_CleanUp();
151   }
152 
153   return wInitStatus;
154 }
155 
156 /*******************************************************************************
157 **
158 ** Function         phTmlUwb_StartThread
159 **
160 ** Description      Initializes comport, reader and writer threads
161 **
162 ** Parameters       None
163 **
164 ** Returns          UWB status:
165 **                  UWBSTATUS_SUCCESS - threads initialized successfully
166 **                  UWBSTATUS_FAILED - initialization failed due to system error
167 **
168 *******************************************************************************/
phTmlUwb_StartThread(void)169 static tHAL_UWB_STATUS phTmlUwb_StartThread(void) {
170   tHAL_UWB_STATUS wStartStatus = UWBSTATUS_SUCCESS;
171   void* h_threadsEvent = 0x00;
172   int pthread_create_status = 0;
173 
174   /* Create Reader and Writer threads */
175   pthread_create_status =
176       pthread_create(&gpphTmlUwb_Context->readerThread, NULL,
177                      &phTmlUwb_TmlReaderThread, (void*)h_threadsEvent);
178   if (0 != pthread_create_status) {
179     wStartStatus = UWBSTATUS_FAILED;
180   } else {
181     /*Start Writer Thread*/
182     pthread_create_status =
183         pthread_create(&gpphTmlUwb_Context->writerThread, NULL,
184                        &phTmlUwb_TmlWriterThread, (void*)h_threadsEvent);
185     if (0 != pthread_create_status) {
186       wStartStatus = UWBSTATUS_FAILED;
187     }
188   }
189 
190   return wStartStatus;
191 }
192 
193 /*******************************************************************************
194 **
195 ** Function         phTmlUwb_TmlReaderThread
196 **
197 ** Description      Read the data from the lower layer driver
198 **
199 ** Parameters       pParam  - parameters for Writer thread function
200 **
201 ** Returns          None
202 **
203 *******************************************************************************/
phTmlUwb_TmlReaderThread(void * pParam)204 static void* phTmlUwb_TmlReaderThread(void* pParam) {
205   tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
206   int32_t dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
207   uint8_t temp[UCI_MAX_DATA_LEN];
208   /* Transaction info buffer to be passed to Callback Thread */
209   static phTmlUwb_TransactInfo_t tTransactionInfo;
210   /* Structure containing Tml callback function and parameters to be invoked
211      by the callback thread */
212   static phLibUwb_DeferredCall_t tDeferredInfo;
213   /* Initialize Message structure to post message onto Callback Thread */
214   static phLibUwb_Message_t tMsg;
215   UNUSED(pParam);
216   NXPLOG_TML_D("SRxxx - Tml Reader Thread Started................\n");
217 
218   /* Writer thread loop shall be running till shutdown is invoked */
219   while (gpphTmlUwb_Context->bThreadDone) {
220     /* If Tml write is requested */
221     /* Set the variable to success initially */
222     wStatus = UWBSTATUS_SUCCESS;
223     if(sem_wait(&gpphTmlUwb_Context->rxSemaphore)!=0){
224         NXPLOG_TML_E("Failed to wait semaphore");
225     }
226     /* If Tml read is requested */
227     if (1 == gpphTmlUwb_Context->tReadInfo.bEnable) {
228       NXPLOG_TML_D("SRxxx - Read requested.....\n");
229       /* Set the variable to success initially */
230       wStatus = UWBSTATUS_SUCCESS;
231 
232       /* Variable to fetch the actual number of bytes read */
233       dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
234 
235       /* Read the data from the file onto the buffer */
236       if (NULL != gpphTmlUwb_Context->pDevHandle) {
237         NXPLOG_TML_D("SRxxx - Invoking SPI Read.....\n");
238         dwNoBytesWrRd =
239             phTmlUwb_spi_read(gpphTmlUwb_Context->pDevHandle, temp, UCI_MAX_DATA_LEN);
240         if(gpphTmlUwb_Context->bThreadDone == 0) {
241           return NULL;
242         }
243 
244         if (-1 == dwNoBytesWrRd) {
245           NXPLOG_TML_E("SRxxx - Error in SPI Read.....\n");
246           pthread_mutex_lock(&gpphTmlUwb_Context->read_abort_lock);
247           if(gpphTmlUwb_Context->is_read_abort) {
248             pthread_cond_signal(&gpphTmlUwb_Context->read_abort_condition);
249             gpphTmlUwb_Context->is_read_abort = false;
250           }
251           else {
252             sem_post(&gpphTmlUwb_Context->rxSemaphore);
253           }
254           pthread_mutex_unlock(&gpphTmlUwb_Context->read_abort_lock);
255         } else if (dwNoBytesWrRd > UCI_MAX_DATA_LEN) {
256           NXPLOG_TML_E("Numer of bytes read exceeds the limit .....\n");
257           sem_post(&gpphTmlUwb_Context->rxSemaphore);
258         } else if(0 == dwNoBytesWrRd) {
259           NXPLOG_TML_E("SRxxx - Empty packet Read, Ignore read and try new read...\n");
260           pthread_mutex_lock(&gpphTmlUwb_Context->read_abort_lock);
261           if(gpphTmlUwb_Context->is_read_abort) {
262             pthread_cond_signal(&gpphTmlUwb_Context->read_abort_condition);
263             gpphTmlUwb_Context->is_read_abort = false;
264           }
265           else {
266             sem_post(&gpphTmlUwb_Context->rxSemaphore);
267           }
268           pthread_mutex_unlock(&gpphTmlUwb_Context->read_abort_lock);
269         } else {
270           memcpy(gpphTmlUwb_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
271 
272           NXPLOG_TML_D("SRxxx - SPI Read successful.....\n");
273           gpphTmlUwb_Context->tReadInfo.bEnable = 0;
274           if (gpphTmlUwb_Context->tWriteInfo.bThreadBusy) {
275             NXPLOG_TML_D("Delay Read if write thread is busy");
276           }
277           /* Update the actual number of bytes read including header */
278           gpphTmlUwb_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
279           phNxpUciHal_print_packet("RECV",
280                                    gpphTmlUwb_Context->tReadInfo.pBuffer,
281                                    gpphTmlUwb_Context->tReadInfo.wLength);
282 
283           dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
284 
285           /* Fill the Transaction info structure to be passed to Callback
286            * Function */
287           tTransactionInfo.wStatus = wStatus;
288           tTransactionInfo.pBuff = gpphTmlUwb_Context->tReadInfo.pBuffer;
289           /* Actual number of bytes read is filled in the structure */
290           tTransactionInfo.wLength = gpphTmlUwb_Context->tReadInfo.wLength;
291 
292           /* Read operation completed successfully. Post a Message onto Callback
293            * Thread*/
294           /* Prepare the message to be posted on User thread */
295           tDeferredInfo.pCallback = &phTmlUwb_ReadDeferredCb;
296           tDeferredInfo.pParameter = &tTransactionInfo;
297           tMsg.eMsgType = PH_LIBUWB_DEFERREDCALL_MSG;
298           tMsg.pMsgData = &tDeferredInfo;
299           tMsg.Size = sizeof(tDeferredInfo);
300           NXPLOG_TML_D("SRxxx - Posting read message.....\n");
301           /* TML reader writer callback synchronization mutex lock --- START */
302           pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
303           if ((gpphTmlUwb_Context->gWriterCbflag == false) &&
304             ((gpphTmlUwb_Context->tReadInfo.pBuffer[0] & 0x60) != 0x60)) {
305             phTmlUwb_WaitWriteComplete();
306           }
307           /* TML reader writer callback synchronization mutex lock --- END */
308           pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
309           phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &tMsg);
310         }
311       } else {
312         NXPLOG_TML_D("SRxxx -gpphTmlUwb_Context->pDevHandle is NULL");
313       }
314     } else {
315       NXPLOG_TML_D("SRxxx - read request NOT enabled");
316       usleep(10 * 1000);
317     }
318   } /* End of While loop */
319 
320   return NULL;
321 }
322 
323 /*******************************************************************************
324 **
325 ** Function         phTmlUwb_TmlWriterThread
326 **
327 ** Description      Writes the requested data onto the lower layer driver
328 **
329 ** Parameters       pParam  - context provided by upper layer
330 **
331 ** Returns          None
332 **
333 *******************************************************************************/
phTmlUwb_TmlWriterThread(void * pParam)334 static void* phTmlUwb_TmlWriterThread(void* pParam) {
335   tHAL_UWB_STATUS wStatus = UWBSTATUS_SUCCESS;
336   int32_t dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
337   /* Transaction info buffer to be passed to Callback Thread */
338   static phTmlUwb_TransactInfo_t tTransactionInfo;
339   /* Structure containing Tml callback function and parameters to be invoked
340      by the callback thread */
341   static phLibUwb_DeferredCall_t tDeferredInfo;
342   /* Initialize Message structure to post message onto Callback Thread */
343   static phLibUwb_Message_t tMsg;
344   UNUSED(pParam);
345   NXPLOG_TML_D("SRxxx - Tml Writer Thread Started................\n");
346 
347   /* Writer thread loop shall be running till shutdown is invoked */
348   while (gpphTmlUwb_Context->bThreadDone) {
349     NXPLOG_TML_D("SRxxx - Tml Writer Thread Running................\n");
350     if (sem_wait(&gpphTmlUwb_Context->txSemaphore) != 0) {
351       NXPLOG_TML_E("Failed to wait semaphore ");
352     }
353     /* If Tml write is requested */
354     if (1 == gpphTmlUwb_Context->tWriteInfo.bEnable) {
355       NXPLOG_TML_D("SRxxx - Write requested.....\n");
356       /* Set the variable to success initially */
357       wStatus = UWBSTATUS_SUCCESS;
358       if (NULL != gpphTmlUwb_Context->pDevHandle) {
359         gpphTmlUwb_Context->tWriteInfo.bEnable = 0;
360         /* Variable to fetch the actual number of bytes written */
361         dwNoBytesWrRd = PH_TMLUWB_RESET_VALUE;
362         /* Write the data in the buffer onto the file */
363         NXPLOG_TML_D("SRxxx - Invoking SPI Write.....\n");
364 
365         /* TML reader writer callback synchronization mutex lock --- START
366          */
367         pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
368         gpphTmlUwb_Context->gWriterCbflag = false;
369         dwNoBytesWrRd =
370             phTmlUwb_spi_write(gpphTmlUwb_Context->pDevHandle,
371                                gpphTmlUwb_Context->tWriteInfo.pBuffer,
372                                gpphTmlUwb_Context->tWriteInfo.wLength);
373         /* TML reader writer callback synchronization mutex lock --- END */
374         pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
375 
376         /* Try SPI Write Five Times, if it fails :*/
377         if (-1 == dwNoBytesWrRd) {
378           NXPLOG_TML_E("SRxxx - Error in SPI Write.....\n");
379           wStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_FAILED);
380         } else {
381           phNxpUciHal_print_packet("SEND",
382                                    gpphTmlUwb_Context->tWriteInfo.pBuffer,
383                                    gpphTmlUwb_Context->tWriteInfo.wLength);
384         }
385         if (UWBSTATUS_SUCCESS == wStatus) {
386           NXPLOG_TML_D("SRxxx - SPI Write successful.....\n");
387           dwNoBytesWrRd = PH_TMLUWB_VALUE_ONE;
388         }
389         /* Fill the Transaction info structure to be passed to Callback Function
390          */
391         tTransactionInfo.wStatus = wStatus;
392         tTransactionInfo.pBuff = gpphTmlUwb_Context->tWriteInfo.pBuffer;
393         /* Actual number of bytes written is filled in the structure */
394         tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
395 
396         /* Prepare the message to be posted on the User thread */
397         tDeferredInfo.pCallback = &phTmlUwb_WriteDeferredCb;
398         tDeferredInfo.pParameter = &tTransactionInfo;
399         /* Write operation completed successfully. Post a Message onto Callback
400          * Thread*/
401         tMsg.eMsgType = PH_LIBUWB_DEFERREDCALL_MSG;
402         tMsg.pMsgData = &tDeferredInfo;
403         tMsg.Size = sizeof(tDeferredInfo);
404 
405 
406         NXPLOG_TML_D("SRxxx - Posting Fresh Write message.....\n");
407         phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &tMsg);
408         if (UWBSTATUS_SUCCESS == wStatus) {
409           /* TML reader writer callback synchronization mutex lock --- START
410              */
411           pthread_mutex_lock(&gpphTmlUwb_Context->wait_busy_lock);
412           gpphTmlUwb_Context->gWriterCbflag = true;
413           phTmlUwb_SignalWriteComplete();
414             /* TML reader writer callback synchronization mutex lock --- END */
415           pthread_mutex_unlock(&gpphTmlUwb_Context->wait_busy_lock);
416           }
417       } else {
418         NXPLOG_TML_D("SRxxx - gpphTmlUwb_Context->pDevHandle is NULL");
419       }
420     } else {
421       NXPLOG_TML_D("SRxxx - Write request NOT enabled");
422       usleep(10000);
423     }
424 
425   } /* End of While loop */
426 
427   return NULL;
428 }
429 
430 /*******************************************************************************
431 **
432 ** Function         phTmlUwb_CleanUp
433 **
434 ** Description      Clears all handles opened during TML initialization
435 **
436 ** Parameters       None
437 **
438 ** Returns          None
439 **
440 *******************************************************************************/
phTmlUwb_CleanUp(void)441 static void phTmlUwb_CleanUp(void) {
442   if (NULL == gpphTmlUwb_Context) {
443     return;
444   }
445   if (NULL != gpphTmlUwb_Context->pDevHandle) {
446     (void)phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_SetPower, 0);
447     gpphTmlUwb_Context->bThreadDone = 0;
448   }
449   sem_destroy(&gpphTmlUwb_Context->rxSemaphore);
450   sem_destroy(&gpphTmlUwb_Context->txSemaphore);
451   sem_destroy(&gpphTmlUwb_Context->postMsgSemaphore);
452   pthread_mutex_destroy(&gpphTmlUwb_Context->wait_busy_lock);
453   pthread_cond_destroy(&gpphTmlUwb_Context->wait_busy_condition);
454   phTmlUwb_spi_close(gpphTmlUwb_Context->pDevHandle);
455   gpphTmlUwb_Context->pDevHandle = NULL;
456   /* Clear memory allocated for storing Context variables */
457   free((void*)gpphTmlUwb_Context);
458   /* Set the pointer to NULL to indicate De-Initialization */
459   gpphTmlUwb_Context = NULL;
460 
461   return;
462 }
463 
464 /*******************************************************************************
465 **
466 ** Function         phTmlUwb_eSE_Reset
467 **
468 ** Description      Invoke this API to reset Secure Element
469 **
470 ** Parameters       None
471 **
472 ** Returns          void
473 **
474 *******************************************************************************/
phTmlUwb_eSE_Reset(void)475 void phTmlUwb_eSE_Reset(void) {
476   int status;
477   if (NULL != gpphTmlUwb_Context->pDevHandle) {
478     status = phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_EseReset, 0);
479     NXPLOG_TML_E("se reset status recieved %d",status);
480   }
481 }
482 /*******************************************************************************
483 **
484 ** Function         phTmlUwb_Shutdown
485 **
486 ** Description      Uninitializes TML layer and hardware interface
487 **
488 ** Parameters       None
489 **
490 ** Returns          UWB status:
491 **                  UWBSTATUS_SUCCESS - TML configuration released successfully
492 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
493 **                                                invalid
494 **                  UWBSTATUS_FAILED - un-initialization failed (example: unable
495 **                                     to close interface)
496 **
497 *******************************************************************************/
phTmlUwb_Shutdown(void)498 tHAL_UWB_STATUS phTmlUwb_Shutdown(void) {
499   tHAL_UWB_STATUS wShutdownStatus = UWBSTATUS_SUCCESS;
500 
501   /* Check whether TML is Initialized */
502   if (NULL != gpphTmlUwb_Context) {
503     /* Reset thread variable to terminate the thread */
504     gpphTmlUwb_Context->bThreadDone = 0;
505     /* Clear All the resources allocated during initialization */
506     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_SetPower, ABORT_READ_PENDING);
507     sem_post(&gpphTmlUwb_Context->rxSemaphore);
508     usleep(1000);
509     sem_post(&gpphTmlUwb_Context->txSemaphore);
510     usleep(1000);
511     sem_post(&gpphTmlUwb_Context->postMsgSemaphore);
512     usleep(1000);
513     if (0 != pthread_join(gpphTmlUwb_Context->readerThread, (void**)NULL)) {
514       NXPLOG_TML_E("Fail to kill reader thread!");
515     }
516     if (0 != pthread_join(gpphTmlUwb_Context->writerThread, (void**)NULL)) {
517       NXPLOG_TML_E("Fail to kill writer thread!");
518     }
519     NXPLOG_TML_D("bThreadDone == 0");
520 
521     phTmlUwb_CleanUp();
522   } else {
523     wShutdownStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
524   }
525 
526   return wShutdownStatus;
527 }
528 
529 /*******************************************************************************
530 **
531 ** Function         phTmlUwb_Write
532 **
533 ** Description      Asynchronously writes given data block to hardware
534 **                  interface/driver. Enables writer thread if there are no
535 **                  write requests pending. Returns successfully once writer
536 **                  thread completes write operation. Notifies upper layer using
537 **                  callback mechanism.
538 **
539 **                  NOTE:
540 **                  * it is important to post a message with id
541 **                    PH_TMLUWB_WRITE_MESSAGE to IntegrationThread after data
542 **                    has been written to SRxxx
543 **                  * if CRC needs to be computed, then input buffer should be
544 **                    capable to store two more bytes apart from length of
545 **                    packet
546 **
547 ** Parameters       pBuffer - data to be sent
548 **                  wLength - length of data buffer
549 **                  pTmlWriteComplete - pointer to the function to be invoked
550 **                                      upon completion
551 **                  pContext - context provided by upper layer
552 **
553 ** Returns          UWB status:
554 **                  UWBSTATUS_PENDING - command is yet to be processed
555 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
556 **                                                invalid
557 **                  UWBSTATUS_BUSY - write request is already in progress
558 **
559 *******************************************************************************/
phTmlUwb_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlUwb_TransactCompletionCb_t pTmlWriteComplete,void * pContext)560 tHAL_UWB_STATUS phTmlUwb_Write(uint8_t* pBuffer, uint16_t wLength,
561                          pphTmlUwb_TransactCompletionCb_t pTmlWriteComplete,
562                          void* pContext) {
563   tHAL_UWB_STATUS wWriteStatus;
564 
565   /* Check whether TML is Initialized */
566 
567   if (NULL != gpphTmlUwb_Context) {
568     if ((NULL != gpphTmlUwb_Context->pDevHandle) && (NULL != pBuffer) &&
569         (PH_TMLUWB_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
570       if (!gpphTmlUwb_Context->tWriteInfo.bThreadBusy) {
571         /* Setting the flag marks beginning of a Write Operation */
572         gpphTmlUwb_Context->tWriteInfo.bThreadBusy = true;
573         /* Copy the buffer, length and Callback function,
574            This shall be utilized while invoking the Callback function in thread
575            */
576         gpphTmlUwb_Context->tWriteInfo.pBuffer = pBuffer;
577         gpphTmlUwb_Context->tWriteInfo.wLength = wLength;
578         gpphTmlUwb_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
579         gpphTmlUwb_Context->tWriteInfo.pContext = pContext;
580 
581         wWriteStatus = UWBSTATUS_PENDING;
582         /* Set event to invoke Writer Thread */
583         gpphTmlUwb_Context->tWriteInfo.bEnable = 1;
584         sem_post(&gpphTmlUwb_Context->txSemaphore);
585       } else {
586         wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
587       }
588     } else {
589       wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
590     }
591   } else {
592     wWriteStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
593   }
594 
595   return wWriteStatus;
596 }
597 
598 /*******************************************************************************
599 **
600 ** Function         phTmlUwb_Read
601 **
602 ** Description      Asynchronously reads data from the driver
603 **                  Number of bytes to be read and buffer are passed by upper
604 **                  layer.
605 **                  Enables reader thread if there are no read requests pending
606 **                  Returns successfully once read operation is completed
607 **                  Notifies upper layer using callback mechanism
608 **
609 ** Parameters       pBuffer - location to send read data to the upper layer via
610 **                            callback
611 **                  wLength - length of read data buffer passed by upper layer
612 **                  pTmlReadComplete - pointer to the function to be invoked
613 **                                     upon completion of read operation
614 **                  pContext - context provided by upper layer
615 **
616 ** Returns          UWB status:
617 **                  UWBSTATUS_PENDING - command is yet to be processed
618 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
619 **                                                invalid
620 **                  UWBSTATUS_BUSY - read request is already in progress
621 **
622 *******************************************************************************/
phTmlUwb_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlUwb_TransactCompletionCb_t pTmlReadComplete,void * pContext)623 tHAL_UWB_STATUS phTmlUwb_Read(uint8_t* pBuffer, uint16_t wLength,
624                         pphTmlUwb_TransactCompletionCb_t pTmlReadComplete,
625                         void* pContext) {
626   tHAL_UWB_STATUS wReadStatus;
627 
628   /* Check whether TML is Initialized */
629   if (NULL != gpphTmlUwb_Context) {
630     if ((gpphTmlUwb_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
631         (PH_TMLUWB_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) {
632       if (!gpphTmlUwb_Context->tReadInfo.bThreadBusy) {
633         /* Setting the flag marks beginning of a Read Operation */
634         gpphTmlUwb_Context->tReadInfo.bThreadBusy = true;
635         /* Copy the buffer, length and Callback function,
636            This shall be utilized while invoking the Callback function in thread
637            */
638         gpphTmlUwb_Context->tReadInfo.pBuffer = pBuffer;
639         gpphTmlUwb_Context->tReadInfo.wLength = wLength;
640         gpphTmlUwb_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
641         gpphTmlUwb_Context->tReadInfo.pContext = pContext;
642         wReadStatus = UWBSTATUS_PENDING;
643 
644         /* Set event to invoke Reader Thread */
645         if(gpphTmlUwb_Context->is_read_abort != true) {
646           gpphTmlUwb_Context->tReadInfo.bEnable = 1; // To be enabled later
647           sem_post(&gpphTmlUwb_Context->rxSemaphore); // To be enabled later
648         }
649       } else {
650         wReadStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_BUSY);
651       }
652     } else {
653       wReadStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_INVALID_PARAMETER);
654     }
655   } else {
656     wReadStatus = PHUWBSTVAL(CID_UWB_TML, UWBSTATUS_NOT_INITIALISED);
657   }
658 
659   return wReadStatus;
660 }
661 
662 /*******************************************************************************
663 **
664 ** Function         phTmlUwb_ReadAbort
665 **
666 ** Description      Aborts pending read request (if any)
667 **
668 ** Parameters       None
669 **
670 ** Returns          UWB status:
671 **                  UWBSTATUS_SUCCESS - ongoing read operation aborted
672 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
673 **                                                invalid
674 **                  UWBSTATUS_NOT_INITIALIZED - TML layer is not initialized
675 **                  UWBSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read
676 **                                                        operation
677 **
678 *******************************************************************************/
phTmlUwb_ReadAbort(void)679 tHAL_UWB_STATUS phTmlUwb_ReadAbort(void) {
680   gpphTmlUwb_Context->tReadInfo.bEnable = 0;
681 
682   /*Reset the flag to accept another Read Request */
683   gpphTmlUwb_Context->tReadInfo.bThreadBusy = false;
684   return UWBSTATUS_SUCCESS;
685 }
686 
687 /*******************************************************************************
688 **
689 ** Function         phTmlUwb_WriteAbort
690 **
691 ** Description      Aborts pending write request (if any)
692 **
693 ** Parameters       None
694 **
695 ** Returns          UWB status:
696 **                  UWBSTATUS_SUCCESS - ongoing write operation aborted
697 **                  UWBSTATUS_INVALID_PARAMETER - at least one parameter is
698 **                                                invalid
699 **                  UWBSTATUS_NOT_INITIALIZED - TML layer is not initialized
700 **                  UWBSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write
701 **                                                        operation
702 **
703 *******************************************************************************/
phTmlUwb_WriteAbort(void)704 tHAL_UWB_STATUS phTmlUwb_WriteAbort(void) {
705 
706   gpphTmlUwb_Context->tWriteInfo.bEnable = 0;
707 
708   /* Reset the flag to accept another Write Request */
709   gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
710   return UWBSTATUS_SUCCESS;
711 }
712 
713 /*******************************************************************************
714 **
715 ** Function         phTmlUwb_DeferredCall
716 **
717 ** Description      Posts message on upper layer thread
718 **                  upon successful read or write operation
719 **
720 ** Parameters       dwThreadId  - id of the thread posting message
721 **                  ptWorkerMsg - message to be posted
722 **
723 ** Returns          None
724 **
725 *******************************************************************************/
phTmlUwb_DeferredCall(uintptr_t dwThreadId,phLibUwb_Message_t * ptWorkerMsg)726 void phTmlUwb_DeferredCall(uintptr_t dwThreadId,
727                            phLibUwb_Message_t* ptWorkerMsg) {
728   intptr_t bPostStatus;
729   UNUSED(dwThreadId);
730   /* Post message on the user thread to invoke the callback function */
731   if (sem_wait(&gpphTmlUwb_Context->postMsgSemaphore) != 0) {
732     NXPLOG_TML_E("phTmlUwb_DeferredCall: semaphore error");
733   }
734   bPostStatus =
735       phDal4Uwb_msgsnd(gpphTmlUwb_Context->dwCallbackThreadId, ptWorkerMsg, 0);
736   sem_post(&gpphTmlUwb_Context->postMsgSemaphore);
737 }
738 
739 /*******************************************************************************
740 **
741 ** Function         phTmlUwb_ReadDeferredCb
742 **
743 ** Description      Read thread call back function
744 **
745 ** Parameters       pParams - context provided by upper layer
746 **
747 ** Returns          None
748 **
749 *******************************************************************************/
phTmlUwb_ReadDeferredCb(void * pParams)750 static void phTmlUwb_ReadDeferredCb(void* pParams) {
751   /* Transaction info buffer to be passed to Callback Function */
752   phTmlUwb_TransactInfo_t* pTransactionInfo = (phTmlUwb_TransactInfo_t*)pParams;
753 
754   /* Reset the flag to accept another Read Request */
755   gpphTmlUwb_Context->tReadInfo.bThreadBusy = false;
756   gpphTmlUwb_Context->tReadInfo.pThread_Callback(
757       gpphTmlUwb_Context->tReadInfo.pContext, pTransactionInfo);
758 
759   return;
760 }
761 
762 /*******************************************************************************
763 **
764 ** Function         phTmlUwb_WriteDeferredCb
765 **
766 ** Description      Write thread call back function
767 **
768 ** Parameters       pParams - context provided by upper layer
769 **
770 ** Returns          None
771 **
772 *******************************************************************************/
phTmlUwb_WriteDeferredCb(void * pParams)773 static void phTmlUwb_WriteDeferredCb(void* pParams) {
774   /* Transaction info buffer to be passed to Callback Function */
775   phTmlUwb_TransactInfo_t* pTransactionInfo = (phTmlUwb_TransactInfo_t*)pParams;
776 
777   /* Reset the flag to accept another Write Request */
778   gpphTmlUwb_Context->tWriteInfo.bThreadBusy = false;
779   gpphTmlUwb_Context->tWriteInfo.pThread_Callback(
780       gpphTmlUwb_Context->tWriteInfo.pContext, pTransactionInfo);
781 
782   return;
783 }
784 
785 /*******************************************************************************
786 **
787 ** Function         phTmlUwb_WaitWriteComplete
788 **
789 ** Description      wait function for reader thread
790 **
791 ** Parameters       None
792 **
793 ** Returns          None
794 **
795 *******************************************************************************/
phTmlUwb_WaitWriteComplete(void)796 static void phTmlUwb_WaitWriteComplete(void) {
797   int ret;
798   struct timespec absTimeout;
799   if (clock_gettime(CLOCK_MONOTONIC, &absTimeout) == -1) {
800     NXPLOG_TML_E("Reader Thread clock_gettime failed");
801   } else {
802     absTimeout.tv_sec += 1; /*1 second timeout*/
803     gpphTmlUwb_Context->wait_busy_flag = true;
804     NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - enter");
805     ret = pthread_cond_timedwait(&gpphTmlUwb_Context->wait_busy_condition,
806                                  &gpphTmlUwb_Context->wait_busy_lock,
807                                  &absTimeout);
808     if ((ret != 0) && (ret != ETIMEDOUT)) {
809       NXPLOG_TML_E("Reader Thread wait failed");
810     }
811     NXPLOG_TML_D("phTmlUwb_WaitWriteComplete - exit");
812   }
813 }
814 
815 /*******************************************************************************
816 **
817 ** Function         phTmlUwb_SignalWriteComplete
818 **
819 ** Description      function to invoke reader thread
820 **
821 ** Parameters       None
822 **
823 ** Returns          None
824 **
825 *******************************************************************************/
phTmlUwb_SignalWriteComplete(void)826 static void phTmlUwb_SignalWriteComplete(void) {
827   int ret;
828   if (gpphTmlUwb_Context->wait_busy_flag == true) {
829     NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - enter");
830     gpphTmlUwb_Context->wait_busy_flag = false;
831     ret = pthread_cond_signal(&gpphTmlUwb_Context->wait_busy_condition);
832     if (ret) {
833       NXPLOG_TML_E(" phTmlUwb_SignalWriteComplete failed, error = 0x%X", ret);
834     }
835     NXPLOG_TML_D("phTmlUwb_SignalWriteComplete - exit");
836   }
837 }
838 
839 /*******************************************************************************
840 **
841 ** Function         phTmlUwb_WaitReadInit
842 **
843 ** Description      init function for reader thread
844 **
845 ** Parameters       None
846 **
847 ** Returns          int
848 **
849 *******************************************************************************/
phTmlUwb_WaitReadInit(void)850 static int phTmlUwb_WaitReadInit(void) {
851   int ret;
852   pthread_condattr_t attr;
853   pthread_condattr_init(&attr);
854   pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
855   memset(&gpphTmlUwb_Context->wait_busy_condition, 0,
856          sizeof(gpphTmlUwb_Context->wait_busy_condition));
857   pthread_mutex_init(&gpphTmlUwb_Context->wait_busy_lock, NULL);
858   ret = pthread_cond_init(&gpphTmlUwb_Context->wait_busy_condition, &attr);
859   if (ret) {
860     NXPLOG_TML_E(" phTmlUwb_WaitReadInit failed, error = 0x%X", ret);
861   }
862   return ret;
863 }
864 
865 /*******************************************************************************
866 **
867 ** Function         phTmlUwb_ReadAbortInit
868 **
869 ** Description      init function read abort context
870 **
871 ** Parameters       None
872 **
873 ** Returns          int
874 **
875 *******************************************************************************/
phTmlUwb_ReadAbortInit(void)876 static int phTmlUwb_ReadAbortInit(void) {
877   int ret;
878   pthread_condattr_t attr;
879   pthread_condattr_init(&attr);
880   pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
881   memset(&gpphTmlUwb_Context->read_abort_condition, 0,
882          sizeof(gpphTmlUwb_Context->read_abort_condition));
883   pthread_mutex_init(&gpphTmlUwb_Context->read_abort_lock, NULL);
884   ret = pthread_cond_init(&gpphTmlUwb_Context->read_abort_condition, &attr);
885   if (ret) {
886     NXPLOG_TML_E(" phTmlUwb_ReadAbortInit failed, error = 0x%X", ret);
887   }
888   return ret;
889 }
890 
891 /*******************************************************************************
892 **
893 ** Function         phTmlUwb_Chip_Reset
894 **
895 ** Description      Invoke this API to Chip enable/Disable
896 **
897 ** Parameters       None
898 **
899 ** Returns          void
900 **
901 *******************************************************************************/
phTmlUwb_Chip_Reset(void)902 void phTmlUwb_Chip_Reset(void){
903   if (NULL != gpphTmlUwb_Context->pDevHandle) {
904     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_SetPower, 0);
905     usleep(1000);
906     phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_SetPower, 1);
907   }
908 }
909 
910 /*******************************************************************************
911 **
912 ** Function         phTmlUwb_Spi_Reset
913 **
914 ** Description      Invoke this API to reset spi
915 **
916 ** Parameters       None
917 **
918 ** Returns          void
919 **
920 *******************************************************************************/
phTmlUwb_Spi_Reset(void)921 void phTmlUwb_Spi_Reset(void) {
922   int ret;
923   struct timespec absTimeout;
924   phTmlUwb_ReadAbort();
925   if (clock_gettime(CLOCK_MONOTONIC, &absTimeout) == -1) {
926     NXPLOG_TML_E("Reader Thread clock_gettime failed");
927   }
928   absTimeout.tv_sec += 1; /*1 second timeout*/
929   pthread_mutex_lock(&gpphTmlUwb_Context->read_abort_lock);
930   gpphTmlUwb_Context->is_read_abort = true;
931   phTmlUwb_Spi_Ioctl(gpphTmlUwb_Context->pDevHandle, phTmlUwb_SetPower, ABORT_READ_PENDING);
932   phTmlUwb_Chip_Reset();
933   ret = pthread_cond_timedwait(&gpphTmlUwb_Context->read_abort_condition,
934                                  &gpphTmlUwb_Context->read_abort_lock,
935                                  &absTimeout);
936   if ((ret != 0) && (ret != ETIMEDOUT)) {
937     NXPLOG_TML_E("Reader Thread wait failed");
938   }
939   usleep(5000);    //wait for helios bootROM mode
940   gpphTmlUwb_Context->is_read_abort = false;
941   pthread_mutex_unlock(&gpphTmlUwb_Context->read_abort_lock);
942   /*Abort the reader thread if client thread shall enable read again incase if valid packet received and notified to upper layer*/
943   phTmlUwb_ReadAbort();
944 }
945