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