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