• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012-2019, 2022-2023 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 #include <sys/stat.h>
17 
18 #include <array>
19 #include <functional>
20 #include <string.h>
21 #include <list>
22 #include <map>
23 #include <mutex>
24 #include <unordered_set>
25 #include <vector>
26 
27 #include <android-base/stringprintf.h>
28 #include <cutils/properties.h>
29 #include <log/log.h>
30 
31 #include <phNxpLog.h>
32 #include <phNxpUciHal.h>
33 #include <phNxpUciHal_Adaptation.h>
34 #include <phNxpUciHal_ext.h>
35 #include <phTmlUwb_spi.h>
36 
37 #include "hal_nxpuwb.h"
38 #include "phNxpConfig.h"
39 #include "phNxpUciHal_utils.h"
40 #include "sessionTrack.h"
41 
42 using namespace std;
43 using android::base::StringPrintf;
44 
45 /*********************** Global Variables *************************************/
46 /* UCI HAL Control structure */
47 phNxpUciHal_Control_t nxpucihal_ctrl;
48 
49 bool uwb_device_initialized = false;
50 bool uwb_get_platform_id = false;
51 uint32_t timeoutTimerId = 0;
52 char persistant_log_path[120];
53 static uint8_t Rx_data[UCI_MAX_DATA_LEN];
54 
55 /**************** local methods used in this file only ************************/
56 static void phNxpUciHal_write_complete(void* pContext,
57                                        phTmlUwb_TransactInfo_t* pInfo);
58 extern int phNxpUciHal_fw_download();
59 static void phNxpUciHal_getVersionInfo();
60 
61 /*******************************************************************************
62  * RX packet handler
63  ******************************************************************************/
64 struct phNxpUciHal_RxHandler {
65   // mt, gid, oid: packet type
66   uint8_t mt;
67   uint8_t gid;
68   uint8_t oid;
69 
70   // skip_reporting: not reports the packet to upper layer if it's true
71   bool skip_reporting;
72   bool run_once;
73 
74   std::function<void(size_t packet_len, const uint8_t *packet)> callback;
75 
phNxpUciHal_RxHandlerphNxpUciHal_RxHandler76   phNxpUciHal_RxHandler(uint8_t mt, uint8_t gid, uint8_t oid,
77     bool skip_reporting, bool run_once,
78     std::function<void(size_t packet_len, const uint8_t *packet)> callback) :
79       mt(mt), gid(gid), oid(oid),
80       skip_reporting(skip_reporting),
81       run_once(run_once),
82       callback(callback) { }
83 };
84 
85 static std::list<std::shared_ptr<phNxpUciHal_RxHandler>> rx_handlers;
86 static std::mutex rx_handlers_lock;
87 
phNxpUciHal_rx_handler_add(uint8_t mt,uint8_t gid,uint8_t oid,bool skip_reporting,bool run_once,std::function<void (size_t packet_len,const uint8_t * packet)> callback)88 std::shared_ptr<phNxpUciHal_RxHandler> phNxpUciHal_rx_handler_add(
89   uint8_t mt, uint8_t gid, uint8_t oid,
90   bool skip_reporting, bool run_once,
91   std::function<void(size_t packet_len, const uint8_t *packet)> callback)
92 {
93   auto handler = std::make_shared<phNxpUciHal_RxHandler>(mt, gid, oid,
94     skip_reporting, run_once, callback);
95   std::lock_guard<std::mutex> guard(rx_handlers_lock);
96   rx_handlers.push_back(handler);
97   return handler;
98 }
99 
phNxpUciHal_rx_handler_del(std::shared_ptr<phNxpUciHal_RxHandler> handler)100 void phNxpUciHal_rx_handler_del(std::shared_ptr<phNxpUciHal_RxHandler> handler)
101 {
102   std::lock_guard<std::mutex> guard(rx_handlers_lock);
103   rx_handlers.remove(handler);
104 }
105 
phNxpUciHal_rx_handler_check(size_t packet_len,const uint8_t * packet)106 static void phNxpUciHal_rx_handler_check(size_t packet_len, const uint8_t *packet)
107 {
108   const uint8_t mt = ((packet[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
109   const uint8_t gid = packet[0] & UCI_GID_MASK;
110   const uint8_t oid = packet[1] & UCI_OID_MASK;
111 
112   std::lock_guard<std::mutex> guard(rx_handlers_lock);
113 
114   for (auto handler : rx_handlers) {
115     if (mt == handler->mt && gid == handler->gid && oid == handler->oid) {
116       handler->callback(packet_len, packet);
117       if (handler->skip_reporting) {
118         nxpucihal_ctrl.isSkipPacket = 1;
119       }
120     }
121   }
122   rx_handlers.remove_if([mt, gid, oid](auto& handler) {
123     return mt == handler->mt && gid == handler->gid && oid == handler->oid && handler->run_once;
124   });
125 }
126 
phNxpUciHal_rx_handler_destroy(void)127 static void phNxpUciHal_rx_handler_destroy(void)
128 {
129   std::lock_guard<std::mutex> guard(rx_handlers_lock);
130   rx_handlers.clear();
131 }
132 
133 /******************************************************************************
134  * Function         phNxpUciHal_client_thread
135  *
136  * Description      This function is a thread handler which handles all TML and
137  *                  UCI messages.
138  *
139  * Returns          void
140  *
141  ******************************************************************************/
phNxpUciHal_client_thread(phNxpUciHal_Control_t * p_nxpucihal_ctrl)142 static void phNxpUciHal_client_thread(phNxpUciHal_Control_t* p_nxpucihal_ctrl)
143 {
144   NXPLOG_UCIHAL_D("thread started");
145 
146   bool thread_running = true;
147 
148   while (thread_running) {
149     /* Fetch next message from the UWB stack message queue */
150     auto msg = p_nxpucihal_ctrl->gDrvCfg.pClientMq->recv();
151 
152     if (!thread_running) {
153       break;
154     }
155 
156     switch (msg->eMsgType) {
157       case PH_LIBUWB_DEFERREDCALL_MSG: {
158         phLibUwb_DeferredCall_t* deferCall = (phLibUwb_DeferredCall_t*)(msg->pMsgData);
159 
160         REENTRANCE_LOCK();
161         deferCall->pCallback(deferCall->pParameter);
162         REENTRANCE_UNLOCK();
163 
164         break;
165       }
166 
167       case UCI_HAL_OPEN_CPLT_MSG: {
168         REENTRANCE_LOCK();
169         if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
170           /* Send the event */
171           (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT,
172                                               HAL_UWB_STATUS_OK);
173         }
174         REENTRANCE_UNLOCK();
175         break;
176       }
177 
178       case UCI_HAL_CLOSE_CPLT_MSG: {
179         REENTRANCE_LOCK();
180         if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
181           /* Send the event */
182           (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_CLOSE_CPLT_EVT,
183                                               HAL_UWB_STATUS_OK);
184         }
185         thread_running = false;
186         REENTRANCE_UNLOCK();
187         break;
188       }
189 
190       case UCI_HAL_INIT_CPLT_MSG: {
191         REENTRANCE_LOCK();
192         if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
193           /* Send the event */
194           (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_INIT_CPLT_EVT,
195                                               HAL_UWB_STATUS_OK);
196         }
197         REENTRANCE_UNLOCK();
198         break;
199       }
200 
201       case UCI_HAL_ERROR_MSG: {
202         REENTRANCE_LOCK();
203         if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
204           /* Send the event */
205           (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_ERROR_EVT,
206                                               HAL_UWB_ERROR_EVT);
207         }
208         REENTRANCE_UNLOCK();
209         break;
210       }
211     }
212   }
213 
214   NXPLOG_UCIHAL_D("NxpUciHal thread stopped");
215 }
216 
217 /******************************************************************************
218  * Function         phNxpUciHal_parse
219  *
220  * Description      This function parses all the data passing through the HAL.
221  *
222  * Returns          It returns true if the incoming command to be skipped.
223  *
224  ******************************************************************************/
phNxpUciHal_parse(uint16_t data_len,const uint8_t * p_data)225 bool phNxpUciHal_parse(uint16_t data_len, const uint8_t *p_data)
226 {
227   bool ret = false;
228 
229   if (data_len < UCI_MSG_HDR_SIZE)
230     return false;
231 
232   const uint8_t mt = (p_data[0] &UCI_MT_MASK) >> UCI_MT_SHIFT;
233   const uint8_t gid = p_data[0] & UCI_GID_MASK;
234   const uint8_t oid = p_data[1] & UCI_OID_MASK;
235 
236   if (mt == UCI_MT_CMD) {
237     if ((gid == UCI_GID_ANDROID) && (oid == UCI_MSG_ANDROID_SET_COUNTRY_CODE)) {
238       char country_code[2];
239       if (data_len == 6) {
240         country_code[0] = (char)p_data[4];
241         country_code[1] = (char)p_data[5];
242       } else {
243         NXPLOG_UCIHAL_E("Unexpected payload length for ANDROID_SET_COUNTRY_CODE, handle this with 00 country code");
244         country_code[0] = '0';
245         country_code[1] = '0';
246       }
247       phNxpUciHal_handle_set_country_code(country_code);
248       return true;
249     } else if ((gid == UCI_GID_PROPRIETARY_0x0F) && (oid == SET_VENDOR_SET_CALIBRATION)) {
250         if (p_data[UCI_MSG_HDR_SIZE + 1] ==
251             VENDOR_CALIB_PARAM_TX_POWER_PER_ANTENNA) {
252           phNxpUciHal_handle_set_calibration(p_data, data_len);
253         }
254     } else if ((gid == UCI_GID_SESSION_MANAGE) && (oid == UCI_MSG_SESSION_SET_APP_CONFIG)) {
255       return phNxpUciHal_handle_set_app_config(&nxpucihal_ctrl.cmd_len, nxpucihal_ctrl.p_cmd_data);
256     } else if ((gid == UCI_GID_SESSION_MANAGE) && (oid == UCI_MSG_SESSION_STATE_INIT)) {
257       SessionTrack_onSessionInit(nxpucihal_ctrl.cmd_len, nxpucihal_ctrl.p_cmd_data);
258     }
259   } else {
260     ret = false;
261   }
262   return ret;
263 }
264 
265 /******************************************************************************
266  * Function         phNxpUciHal_open
267  *
268  * Description      This function is called by libuwb-uci during the
269  *                  initialization of the UWBC. It opens the physical connection
270  *                  with UWBC (SRXXX) and creates required client thread for
271  *                  operation.
272  *                  After open is complete, status is informed to libuwb-uci
273  *                  through callback function.
274  *
275  * Returns          This function return UWBSTATUS_SUCCES (0) in case of success
276  *                  In case of failure returns other failure value.
277  *
278  ******************************************************************************/
phNxpUciHal_open(uwb_stack_callback_t * p_cback,uwb_stack_data_callback_t * p_data_cback)279 tHAL_UWB_STATUS phNxpUciHal_open(uwb_stack_callback_t* p_cback, uwb_stack_data_callback_t* p_data_cback)
280 {
281   static const char uwb_dev_node[256] = "/dev/srxxx";
282   tHAL_UWB_STATUS wConfigStatus = UWBSTATUS_SUCCESS;
283 
284   if (nxpucihal_ctrl.halStatus == HAL_STATUS_OPEN) {
285     NXPLOG_UCIHAL_E("phNxpUciHal_open already open");
286     return UWBSTATUS_SUCCESS;
287   }
288 
289   NxpConfig_Init();
290 
291   /* initialize trace level */
292   phNxpLog_InitializeLogLevel();
293 
294   /*Create the timer for extns write response*/
295   timeoutTimerId = phOsalUwb_Timer_Create();
296 
297   if (phNxpUciHal_init_monitor() == NULL) {
298     NXPLOG_UCIHAL_E("Init monitor failed");
299     return UWBSTATUS_FAILED;
300   }
301 
302   CONCURRENCY_LOCK();
303 
304   NXPLOG_UCIHAL_E("Assigning the default helios Node: %s", uwb_dev_node);
305   /* By default HAL status is HAL_STATUS_OPEN */
306   nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
307 
308   nxpucihal_ctrl.p_uwb_stack_cback = p_cback;
309   nxpucihal_ctrl.p_uwb_stack_data_cback = p_data_cback;
310   nxpucihal_ctrl.fw_dwnld_mode = false;
311 
312   /* Configure hardware link */
313   nxpucihal_ctrl.gDrvCfg.pClientMq = std::make_shared<MessageQueue<phLibUwb_Message>>("Client");
314   nxpucihal_ctrl.gDrvCfg.nLinkType = ENUM_LINK_TYPE_SPI;
315 
316   /* Initialize TML layer */
317   wConfigStatus = phTmlUwb_Init(uwb_dev_node, nxpucihal_ctrl.gDrvCfg.pClientMq);
318   if (wConfigStatus != UWBSTATUS_SUCCESS) {
319     NXPLOG_UCIHAL_E("phTmlUwb_Init Failed");
320     goto clean_and_return;
321   }
322 
323   /* Create the client thread */
324   nxpucihal_ctrl.client_thread =
325     std::thread{ &phNxpUciHal_client_thread, &nxpucihal_ctrl };
326 
327   nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
328 
329   CONCURRENCY_UNLOCK();
330 
331   // Per-chip (SR1XX or SR200) implementation
332   nxpucihal_ctrl.uwb_chip = GetUwbChip();
333 
334   /* Call open complete */
335   phTmlUwb_DeferredCall(std::make_shared<phLibUwb_Message>(UCI_HAL_OPEN_CPLT_MSG));
336 
337   return UWBSTATUS_SUCCESS;
338 
339 clean_and_return:
340   CONCURRENCY_UNLOCK();
341 
342   /* Report error status */
343   (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT, HAL_UWB_ERROR_EVT);
344 
345   nxpucihal_ctrl.p_uwb_stack_cback = NULL;
346   nxpucihal_ctrl.p_uwb_stack_data_cback = NULL;
347   phNxpUciHal_cleanup_monitor();
348   nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
349   return wConfigStatus;
350 }
351 
352 /******************************************************************************
353  * Function         phNxpUciHal_write
354  *
355  * Description      This function write the data to UWBC through physical
356  *                  interface (e.g. SPI) using the  driver interface.
357  *                  Before sending the data to UWBC, phNxpUciHal_write_ext
358  *                  is called to check if there is any extension processing
359  *                  is required for the UCI packet being sent out.
360  *
361  * Returns          It returns number of bytes successfully written to UWBC.
362  *
363  ******************************************************************************/
phNxpUciHal_write(uint16_t data_len,const uint8_t * p_data)364 tHAL_UWB_STATUS phNxpUciHal_write(uint16_t data_len, const uint8_t* p_data) {
365   if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
366     return UWBSTATUS_FAILED;
367   }
368   uint16_t len = 0;
369 
370   SessionTrack_keepAlive();
371 
372   CONCURRENCY_LOCK();
373   phNxpUciHal_process_ext_cmd_rsp(data_len, p_data, &len);
374   CONCURRENCY_UNLOCK();
375 
376   /* No data written */
377   return len;
378 }
379 
380 /******************************************************************************
381  * Function         phNxpUciHal_write_unlocked
382  *
383  * Description      This is the actual function which is being called by
384  *                  phNxpUciHal_write. This function writes the data to UWBC.
385  *                  It waits till write callback provide the result of write
386  *                  process.
387  *
388  * Returns          It returns number of bytes successfully written to UWBC.
389  *
390  ******************************************************************************/
phNxpUciHal_write_unlocked(uint16_t data_len,const uint8_t * p_data)391 tHAL_UWB_STATUS phNxpUciHal_write_unlocked(uint16_t data_len, const uint8_t* p_data) {
392   tHAL_UWB_STATUS status;
393   uint8_t mt, pbf, gid, oid;
394 
395   phNxpUciHal_Sem_t cb_data;
396   /* Create the local semaphore */
397   if (phNxpUciHal_init_cb_data(&cb_data, NULL) != UWBSTATUS_SUCCESS) {
398     NXPLOG_UCIHAL_D("phNxpUciHal_write_unlocked Create cb data failed");
399     data_len = 0;
400     goto clean_and_return;
401   }
402 
403   if ((data_len > UCI_MAX_DATA_LEN) || (data_len < UCI_PKT_HDR_LEN)) {
404     NXPLOG_UCIHAL_E("Invalid data_len");
405     data_len = 0;
406     goto clean_and_return;
407   }
408 
409   /* Create local copy of cmd_data */
410   memcpy(nxpucihal_ctrl.p_cmd_data, p_data, data_len);
411   nxpucihal_ctrl.cmd_len = data_len;
412 
413   data_len = nxpucihal_ctrl.cmd_len;
414   UCI_MSG_PRS_HDR0(p_data, mt, pbf, gid);
415   UCI_MSG_PRS_HDR1(p_data, oid);
416 
417   /* Vendor Specific Parsing logic */
418   nxpucihal_ctrl.hal_parse_enabled =
419       phNxpUciHal_parse(nxpucihal_ctrl.cmd_len, nxpucihal_ctrl.p_cmd_data);
420   if (nxpucihal_ctrl.hal_parse_enabled) {
421     goto clean_and_return;
422   }
423   status = phTmlUwb_Write(
424       (uint8_t*)nxpucihal_ctrl.p_cmd_data, (uint16_t)nxpucihal_ctrl.cmd_len,
425       (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_write_complete,
426       (void*)&cb_data);
427 
428 
429   if (status != UWBSTATUS_PENDING) {
430     NXPLOG_UCIHAL_E("write_unlocked status error");
431     data_len = 0;
432     goto clean_and_return;
433   }
434 
435   /* Wait for callback response */
436   if (SEM_WAIT(&cb_data)) {
437     NXPLOG_UCIHAL_E("write_unlocked semaphore error");
438     data_len = 0;
439     goto clean_and_return;
440   }
441 
442 clean_and_return:
443   phNxpUciHal_cleanup_cb_data(&cb_data);
444   return data_len;
445 }
446 
447 /******************************************************************************
448  * Function         phNxpUciHal_write_complete
449  *
450  * Description      This function handles write callback.
451  *
452  * Returns          void.
453  *
454  ******************************************************************************/
phNxpUciHal_write_complete(void * pContext,phTmlUwb_TransactInfo_t * pInfo)455 static void phNxpUciHal_write_complete(void* pContext,
456                                        phTmlUwb_TransactInfo_t* pInfo) {
457   phNxpUciHal_Sem_t* p_cb_data = (phNxpUciHal_Sem_t*)pContext;
458 
459   if (pInfo->wStatus == UWBSTATUS_SUCCESS) {
460     NXPLOG_UCIHAL_V("write successful status = 0x%x", pInfo->wStatus);
461   } else {
462     NXPLOG_UCIHAL_E("write error status = 0x%x", pInfo->wStatus);
463   }
464   p_cb_data->status = pInfo->wStatus;
465 
466   SEM_POST(p_cb_data);
467 
468   return;
469 }
470 
471 /******************************************************************************
472  * Function         phNxpUciHal_read_complete
473  *
474  * Description      This function is called whenever there is an UCI packet
475  *                  received from UWBC. It could be RSP or NTF packet. This
476  *                  function provide the received UCI packet to libuwb-uci
477  *                  using data callback of libuwb-uci.
478  *                  There is a pending read called from each
479  *                  phNxpUciHal_read_complete so each a packet received from
480  *                  UWBC can be provide to libuwb-uci.
481  *
482  * Returns          void.
483  *
484  ******************************************************************************/
phNxpUciHal_read_complete(void * pContext,phTmlUwb_TransactInfo_t * pInfo)485 void phNxpUciHal_read_complete(void* pContext, phTmlUwb_TransactInfo_t* pInfo)
486 {
487   UNUSED(pContext);
488 
489   if (pInfo->wStatus != UWBSTATUS_SUCCESS) {
490     NXPLOG_UCIHAL_E("read error status = 0x%x", pInfo->wStatus);
491     return;
492   }
493 
494   NXPLOG_UCIHAL_D("read successful status = 0x%x", pInfo->wStatus);
495 
496   for (int32_t index = 0; index < pInfo->wLength; )
497   {
498     uint8_t extBitSet = (pInfo->pBuff[index + EXTND_LEN_INDICATOR_OFFSET] & EXTND_LEN_INDICATOR_OFFSET_MASK);
499     int32_t length = pInfo->pBuff[index + NORMAL_MODE_LENGTH_OFFSET];
500     if (extBitSet || ((pInfo->pBuff[index] & UCI_MT_MASK) == 0x00)) {
501      length = (length << EXTENDED_MODE_LEN_SHIFT) | pInfo->pBuff[index + EXTENDED_MODE_LEN_OFFSET] ;
502     }
503     length += UCI_MSG_HDR_SIZE;
504     NXPLOG_UCIHAL_V("read successful length = %d", length);
505 
506     nxpucihal_ctrl.p_rx_data = &pInfo->pBuff[index];
507     nxpucihal_ctrl.rx_data_len = length;
508     phNxpUciHal_print_packet(NXP_TML_UCI_RSP_NTF_UWBS_2_AP, nxpucihal_ctrl.p_rx_data, nxpucihal_ctrl.rx_data_len);
509 
510     uint8_t mt = ((nxpucihal_ctrl.p_rx_data[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
511     uint8_t gid = nxpucihal_ctrl.p_rx_data[0] & UCI_GID_MASK;
512     uint8_t oid = nxpucihal_ctrl.p_rx_data[1] & UCI_OID_MASK;
513     uint8_t pbf = (nxpucihal_ctrl.p_rx_data[0] & UCI_PBF_MASK) >> UCI_PBF_SHIFT;
514 
515     nxpucihal_ctrl.isSkipPacket = 0;
516 
517     phNxpUciHal_rx_handler_check(pInfo->wLength, pInfo->pBuff);
518 
519     // mapping device caps according to Fira 2.0
520     if (mt == UCI_MT_RSP && gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GET_CAPS_INFO) {
521       phNxpUciHal_handle_get_caps_info(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
522     }
523 
524     // phNxpUciHal_process_ext_cmd_rsp() is waiting for the response packet
525     // set this true to wake it up for other reasons
526     bool bWakeupExtCmd = (mt == UCI_MT_RSP);
527     if (bWakeupExtCmd && nxpucihal_ctrl.ext_cb_waiting) {
528       nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_SUCCESS;
529     }
530 
531     /* DBG packets not yet supported, just ignore them silently */
532     if (!nxpucihal_ctrl.isSkipPacket) {
533       if ((mt == UCI_MT_NTF) && (gid == UCI_GID_INTERNAL) &&
534           (oid == UCI_EXT_PARAM_DBG_RFRAME_LOG_NTF)) {
535         nxpucihal_ctrl.isSkipPacket = 1;
536       }
537     }
538 
539     if (!nxpucihal_ctrl.isSkipPacket) {
540       if (!pbf && mt == UCI_MT_NTF && gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GENERIC_ERROR_NTF) {
541         uint8_t status_code = nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET];
542 
543         if (status_code == UCI_STATUS_COMMAND_RETRY) {
544           // Handle retransmissions
545           // TODO: Do not retransmit it when !nxpucihal_ctrl.hal_ext_enabled,
546           // Upper layer should take care of it.
547           nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_COMMAND_RETRANSMIT;
548           nxpucihal_ctrl.isSkipPacket = 1;
549           bWakeupExtCmd = true;
550         }
551       }
552     }
553 
554     // Check status code only for extension commands
555     if (!nxpucihal_ctrl.isSkipPacket) {
556       if (mt == UCI_MT_RSP) {
557         if (nxpucihal_ctrl.hal_ext_enabled) {
558           nxpucihal_ctrl.isSkipPacket = 1;
559 
560           if (pbf) {
561             /* XXX: fix the whole logic if this really happens */
562             NXPLOG_UCIHAL_E("FIXME: Fragmented packets received while processing internal commands!");
563           }
564 
565           uint8_t status_code = (nxpucihal_ctrl.rx_data_len > UCI_RESPONSE_STATUS_OFFSET) ?
566             nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET] : UCI_STATUS_UNKNOWN;
567 
568           if (status_code == UCI_STATUS_OK) {
569             nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_SUCCESS;
570           } else if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_SET_CONFIG)){
571             /* check if any configurations are not supported then ignore the
572               * UWBSTATUS_FEATURE_NOT_SUPPORTED status code*/
573             nxpucihal_ctrl.ext_cb_data.status = phNxpUciHal_process_ext_rsp(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
574           } else {
575             nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_FAILED;
576             NXPLOG_UCIHAL_E("Got error status code(0x%x) from internal command.", status_code);
577             usleep(1);  // XXX: not sure if it's really needed
578           }
579         }
580       }
581     }
582 
583     if (bWakeupExtCmd && nxpucihal_ctrl.ext_cb_waiting) {
584       SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
585     }
586 
587     if (!nxpucihal_ctrl.isSkipPacket) {
588       /* Read successful, send the event to higher layer */
589       if ((nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) && (nxpucihal_ctrl.rx_data_len <= UCI_MAX_PAYLOAD_LEN)) {
590         (*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
591       }
592     }
593 
594     /* Disable junk data check for each UCI packet*/
595     if(nxpucihal_ctrl.fw_dwnld_mode) {
596       if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_STATUS_NTF)){
597         nxpucihal_ctrl.fw_dwnld_mode = false;
598       }
599     }
600     index += length;
601   } //End of loop
602 }
603 
604 /******************************************************************************
605  * Function         phNxpUciHal_close
606  *
607  * Description      This function close the UWBC interface and free all
608  *                  resources.This is called by libuwb-uci on UWB service stop.
609  *
610  * Returns          Always return UWBSTATUS_SUCCESS (0).
611  *
612  ******************************************************************************/
phNxpUciHal_close()613 tHAL_UWB_STATUS phNxpUciHal_close() {
614   tHAL_UWB_STATUS status;
615   if (nxpucihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
616     NXPLOG_UCIHAL_E("phNxpUciHal_close is already closed, ignoring close");
617     return UWBSTATUS_FAILED;
618   }
619 
620   uwb_device_initialized = false;
621 
622   CONCURRENCY_LOCK();
623 
624   SessionTrack_deinit();
625 
626   NXPLOG_UCIHAL_D("Terminating phNxpUciHal client thread...");
627   phTmlUwb_DeferredCall(std::make_shared<phLibUwb_Message>(UCI_HAL_CLOSE_CPLT_MSG));
628   nxpucihal_ctrl.client_thread.join();
629 
630   status = phTmlUwb_Shutdown();
631 
632   phNxpUciHal_rx_handler_destroy();
633 
634   nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
635 
636   CONCURRENCY_UNLOCK();
637 
638   nxpucihal_ctrl.uwb_chip.reset();
639 
640   phOsalUwb_Timer_Cleanup();
641 
642   phNxpUciHal_cleanup_monitor();
643 
644   NxpConfig_Deinit();
645 
646   NXPLOG_UCIHAL_D("phNxpUciHal_close completed");
647 
648   /* Return success always */
649   return UWBSTATUS_SUCCESS;
650 }
651 
652 /******************************************************************************
653  * Function         parseAntennaConfig
654  *
655  * Description      This function parse the antenna config and update required
656  *                  params
657  *
658  * Returns          void
659  *
660  ******************************************************************************/
parseAntennaConfig(const char * configName)661 static void parseAntennaConfig(const char *configName)
662 {
663   std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
664   long retlen = 0;
665   int gotConfig = NxpConfig_GetByteArray(configName, buffer.data(), buffer.size(), &retlen);
666   if (gotConfig) {
667     if (retlen <= UCI_MSG_HDR_SIZE) {
668       NXPLOG_UCIHAL_E("parseAntennaConfig: %s is too short. Aborting.", configName);
669       return;
670     }
671   }
672   else
673   {
674     NXPLOG_UCIHAL_E("parseAntennaConfig: Failed to get '%s'. Aborting.", configName);
675     return;
676   }
677 
678   const uint16_t dataLength = retlen;
679   const uint8_t *data = buffer.data();
680 
681   uint8_t index = UCI_MSG_HDR_SIZE + 1; // Excluding the header and number of params
682   uint8_t tagId, subTagId;
683   int length;
684   while (index < dataLength) {
685     tagId = data[index++];
686     subTagId = data[index++];
687     length = data[index++];
688     if ((ANTENNA_RX_PAIR_DEFINE_TAG_ID == tagId) &&
689         (ANTENNA_RX_PAIR_DEFINE_SUB_TAG_ID == subTagId)) {
690       nxpucihal_ctrl.numberOfAntennaPairs = data[index];
691       NXPLOG_UCIHAL_D("numberOfAntennaPairs:%d", nxpucihal_ctrl.numberOfAntennaPairs);
692       break;
693     } else {
694       index = index + length;
695     }
696   }
697 }
698 
699 /******************************************************************************
700  * Function         phNxpUciHal_applyVendorConfig
701  *
702  * Description      This function applies the vendor config from config file
703  *
704  * Returns          status
705  *
706  ******************************************************************************/
phNxpUciHal_applyVendorConfig()707 tHAL_UWB_STATUS phNxpUciHal_applyVendorConfig()
708 {
709   std::vector<const char*> vendorParamNames;
710 
711   // Base parameter names
712   if (nxpucihal_ctrl.fw_boot_mode == USER_FW_BOOT_MODE) {
713     vendorParamNames.push_back(NAME_UWB_USER_FW_BOOT_MODE_CONFIG);
714   }
715   vendorParamNames.push_back(NAME_NXP_UWB_EXTENDED_NTF_CONFIG);
716 
717   // Chip parameter names
718   const char *per_chip_param = NAME_UWB_CORE_EXT_DEVICE_DEFAULT_CONFIG;
719   if (nxpucihal_ctrl.device_type == DEVICE_TYPE_SR1xxT) {
720     per_chip_param = NAME_UWB_CORE_EXT_DEVICE_SR1XX_T_CONFIG;
721   } else if (nxpucihal_ctrl.device_type == DEVICE_TYPE_SR1xxS) {
722     per_chip_param = NAME_UWB_CORE_EXT_DEVICE_SR1XX_S_CONFIG;
723   }
724   vendorParamNames.push_back(per_chip_param);
725 
726   // Parse Antenna config from chip-parameter
727   parseAntennaConfig(per_chip_param);
728 
729   // Extra parameter names, XTAL, NXP_CORE_CONF_BLK[1..10]
730   vendorParamNames.push_back(NAME_NXP_UWB_XTAL_38MHZ_CONFIG);
731   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "1");
732   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "2");
733   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "3");
734   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "4");
735   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "5");
736   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "6");
737   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "7");
738   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "8");
739   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "9");
740   vendorParamNames.push_back(NAME_NXP_CORE_CONF_BLK "10");
741 
742   // Execute
743   for (const auto paramName : vendorParamNames) {
744     std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
745     long retlen = 0;
746     if (NxpConfig_GetByteArray(paramName, buffer.data(), buffer.size(), &retlen)) {
747       if (retlen > 0 && retlen < UCI_MAX_DATA_LEN) {
748         NXPLOG_UCIHAL_D("VendorConfig: apply %s", paramName);
749         tHAL_UWB_STATUS status = phNxpUciHal_send_ext_cmd(retlen, buffer.data());
750         if (status != UWBSTATUS_SUCCESS) {
751           NXPLOG_UCIHAL_E("VendorConfig: failed to apply %s", paramName);
752           return status;
753         }
754       }
755     }
756   }
757 
758   // Low Power Mode
759   // TODO: remove this out, this can be move to Chip parameter names
760   uint8_t lowPowerMode = 0;
761   if (NxpConfig_GetNum(NAME_NXP_UWB_LOW_POWER_MODE, &lowPowerMode, sizeof(lowPowerMode))) {
762     NXPLOG_UCIHAL_D("VendorConfig: apply %s", NAME_NXP_UWB_LOW_POWER_MODE);
763 
764     // Core set config packet: GID=0x00 OID=0x04
765     const std::vector<uint8_t> packet(
766         {((UCI_MT_CMD << UCI_MT_SHIFT) | UCI_GID_CORE), UCI_MSG_CORE_SET_CONFIG,
767          0x00, 0x04, 0x01, LOW_POWER_MODE_TAG_ID, LOW_POWER_MODE_LENGTH,
768          lowPowerMode});
769 
770     if (phNxpUciHal_send_ext_cmd(packet.size(), packet.data()) != UWBSTATUS_SUCCESS) {
771       NXPLOG_UCIHAL_E("VendorConfig: failed to apply NAME_NXP_UWB_LOW_POWER_MODE");
772     }
773   }
774 
775   return UWBSTATUS_SUCCESS;
776 }
777 
778 /******************************************************************************
779  * Function         phNxpUciHal_uwb_reset
780  *
781  * Description      This function will send UWB reset command
782  *
783  * Returns          status
784  *
785  ******************************************************************************/
phNxpUciHal_uwb_reset()786 tHAL_UWB_STATUS phNxpUciHal_uwb_reset() {
787   tHAL_UWB_STATUS status;
788   uint8_t buffer[] = {0x20, 0x00, 0x00, 0x01, 0x00};
789   status = phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
790   if(status != UWBSTATUS_SUCCESS) {
791     return status;
792   }
793   return UWBSTATUS_SUCCESS;
794 }
795 
cacheDevInfoRsp()796 static bool cacheDevInfoRsp()
797 {
798   auto dev_info_cb = [](size_t packet_len, const uint8_t *packet) mutable {
799     if (packet_len < 5 || packet[UCI_RESPONSE_STATUS_OFFSET] != UWBSTATUS_SUCCESS) {
800       NXPLOG_UCIHAL_E("Failed to get valid CORE_DEVICE_INFO_RSP");
801       return;
802     }
803     if (packet_len > sizeof(nxpucihal_ctrl.dev_info_resp)) {
804       NXPLOG_UCIHAL_E("FIXME: CORE_DEVICE_INFO_RSP buffer overflow!");
805       return;
806     }
807 
808     // FIRA UCIv2.0 packet size = 14
809     // [13] = Vendor Specific Info Length
810     constexpr uint8_t firaDevInfoRspSize = 14;
811     constexpr uint8_t firaDevInfoVendorLenOffset = 13;
812 
813     if (packet_len < firaDevInfoRspSize) {
814       NXPLOG_UCIHAL_E("DEVICE_INFO_RSP packet size mismatched.");
815       return;
816     }
817 
818     const uint8_t vendorSpecificLen = packet[firaDevInfoVendorLenOffset];
819     if (packet_len != (firaDevInfoRspSize + vendorSpecificLen)) {
820       NXPLOG_UCIHAL_E("DEVICE_INFO_RSP packet size mismatched.");
821     }
822 
823     for (uint8_t i = firaDevInfoRspSize; (i + 2) <= packet_len; ) {
824       uint8_t paramId = packet[i++];
825       uint8_t length = packet[i++];
826 
827       if (i + length > packet_len)
828         break;
829 
830       if (paramId == DEVICE_NAME_PARAM_ID && length >= 6) {
831         nxpucihal_ctrl.device_type = nxpucihal_ctrl.uwb_chip->get_device_type(&packet[i], length);
832       } else if (paramId == FW_VERSION_PARAM_ID && length >= 3) {
833         nxpucihal_ctrl.fw_version.major_version = packet[i];
834         nxpucihal_ctrl.fw_version.minor_version = packet[i + 1];
835         nxpucihal_ctrl.fw_version.rc_version = packet[i + 2];
836       } else if (paramId == FW_BOOT_MODE_PARAM_ID && length >= 1) {
837         nxpucihal_ctrl.fw_boot_mode = packet[i];
838       }
839       i += length;
840     }
841     memcpy(nxpucihal_ctrl.dev_info_resp, packet, packet_len);
842     nxpucihal_ctrl.isDevInfoCached = true;
843     NXPLOG_UCIHAL_D("Device Info cached.");
844   };
845 
846   nxpucihal_ctrl.isDevInfoCached = false;
847   UciHalRxHandler devInfoRspHandler(UCI_MT_RSP, UCI_GID_CORE, UCI_MSG_CORE_DEVICE_INFO, true, dev_info_cb);
848 
849   const uint8_t CoreGetDevInfoCmd[] = {(UCI_MT_CMD << UCI_MT_SHIFT) | UCI_GID_CORE, UCI_MSG_CORE_DEVICE_INFO, 0, 0};
850   tHAL_UWB_STATUS status = phNxpUciHal_send_ext_cmd(sizeof(CoreGetDevInfoCmd), CoreGetDevInfoCmd);
851   if (status != UWBSTATUS_SUCCESS) {
852     return false;
853   }
854   return true;
855 }
856 
857 /******************************************************************************
858  * Function         phNxpUciHal_init_hw
859  *
860  * Description      Init the chip.
861  *
862  * Returns          status
863  *
864  ******************************************************************************/
phNxpUciHal_init_hw()865 tHAL_UWB_STATUS phNxpUciHal_init_hw()
866 {
867   tHAL_UWB_STATUS status;
868 
869   if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
870     NXPLOG_UCIHAL_E("HAL not initialized");
871     return UWBSTATUS_FAILED;
872   }
873 
874   uwb_device_initialized = false;
875 
876   // FW download and enter UCI operating mode
877   status = nxpucihal_ctrl.uwb_chip->chip_init();
878   if (status != UWBSTATUS_SUCCESS) {
879     return status;
880   }
881 
882   // Device Status Notification
883   UciHalSemaphore devStatusNtfWait;
884   uint8_t dev_status = UWB_DEVICE_ERROR;
885   auto dev_status_ntf_cb = [&dev_status, &devStatusNtfWait](size_t packet_len, const uint8_t *packet) mutable {
886     if (packet_len >= 5) {
887       dev_status = packet[UCI_RESPONSE_STATUS_OFFSET];
888       devStatusNtfWait.post();
889     }
890   };
891   UciHalRxHandler devStatusNtfHandler(UCI_MT_NTF, UCI_GID_CORE, UCI_MSG_CORE_DEVICE_STATUS_NTF,
892                                       true, dev_status_ntf_cb);
893 
894   // Initiate UCI packet read
895   status = phTmlUwb_StartRead( Rx_data, UCI_MAX_DATA_LEN,
896             (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
897   if (status != UWBSTATUS_SUCCESS) {
898     NXPLOG_UCIHAL_E("read status error status = %x", status);
899     return status;
900   }
901 
902   // Wait for the first Device Status Notification
903   devStatusNtfWait.wait();
904   if(dev_status != UWB_DEVICE_INIT && dev_status != UWB_DEVICE_READY) {
905     NXPLOG_UCIHAL_E("First Device Status NTF was not received or it's invalid state. 0x%x", dev_status);
906     return UWBSTATUS_FAILED;
907   }
908 
909   // Set board-config and wait for Device Status Notification
910   status = phNxpUciHal_set_board_config();
911   if (status != UWBSTATUS_SUCCESS) {
912     NXPLOG_UCIHAL_E("%s: Set Board Config Failed", __func__);
913     return status;
914   }
915   devStatusNtfWait.wait();
916   if (dev_status != UWB_DEVICE_READY) {
917     NXPLOG_UCIHAL_E("Cannot receive UWB_DEVICE_READY");
918     return UWBSTATUS_FAILED;
919   }
920 
921   // Send SW reset and wait for Device Status Notification
922   dev_status = UWB_DEVICE_ERROR;
923   status = phNxpUciHal_uwb_reset();
924   if (status != UWBSTATUS_SUCCESS) {
925     NXPLOG_UCIHAL_E("%s: device reset Failed", __func__);
926     return status;
927   }
928   devStatusNtfWait.wait();
929   if(dev_status != UWB_DEVICE_READY) {
930     NXPLOG_UCIHAL_E("UWB_DEVICE_READY not received uwbc_device_state = %x", dev_status);
931     return UWBSTATUS_FAILED;
932   }
933 
934   // Cache CORE_GET_DEVICE_INFO
935   cacheDevInfoRsp();
936 
937   status = nxpucihal_ctrl.uwb_chip->core_init();
938   if (status != UWBSTATUS_SUCCESS) {
939     return status;
940   }
941 
942   status = phNxpUciHal_applyVendorConfig();
943   if (status != UWBSTATUS_SUCCESS) {
944     NXPLOG_UCIHAL_E("%s: Apply vendor Config Failed", __func__);
945     return status;
946   }
947   phNxpUciHal_extcal_handle_coreinit();
948 
949   uwb_device_initialized = true;
950   phNxpUciHal_getVersionInfo();
951 
952   return UWBSTATUS_SUCCESS;
953 }
954 
955 /******************************************************************************
956  * Function         phNxpUciHal_coreInitialization
957  *
958  * Description      This function performs core initialization
959  *
960  * Returns          status
961  *
962  ******************************************************************************/
phNxpUciHal_coreInitialization()963 tHAL_UWB_STATUS phNxpUciHal_coreInitialization()
964 {
965   tHAL_UWB_STATUS status = phNxpUciHal_init_hw();
966   if (status != UWBSTATUS_SUCCESS) {
967     phTmlUwb_DeferredCall(std::make_shared<phLibUwb_Message>(UCI_HAL_ERROR_MSG));
968     return status;
969   }
970 
971   SessionTrack_init();
972 
973   // report to upper-layer
974   phTmlUwb_DeferredCall(std::make_shared<phLibUwb_Message>(UCI_HAL_INIT_CPLT_MSG));
975 
976   if (nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) {
977     uint8_t dev_ready_ntf[] = {0x60, 0x01, 0x00, 0x01, 0x01};
978     (*nxpucihal_ctrl.p_uwb_stack_data_cback)((sizeof(dev_ready_ntf)/sizeof(uint8_t)), dev_ready_ntf);
979   }
980 
981   return UWBSTATUS_SUCCESS;
982 }
983 
984 /******************************************************************************
985  * Function         phNxpUciHal_sessionInitialization
986  *
987  * Description      This function performs session initialization
988  *
989  * Returns          status
990  *
991  ******************************************************************************/
phNxpUciHal_sessionInitialization(uint32_t sessionId)992 tHAL_UWB_STATUS phNxpUciHal_sessionInitialization(uint32_t sessionId) {
993   NXPLOG_UCIHAL_D(" %s: Enter", __func__);
994   std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
995   uint8_t vendorConfig[NXP_MAX_CONFIG_STRING_LEN] = {0x2F, 0x00, 0x00};
996   tHAL_UWB_STATUS status = UWBSTATUS_SUCCESS;
997   buffer.fill(0);
998   int max_config_length = NXP_MAX_CONFIG_STRING_LEN - UCI_MSG_HDR_SIZE
999                             - sizeof(sessionId);
1000   long retlen = 0, cmdlen = 0;
1001   bool appConfigStatus = false;
1002 
1003   if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
1004     NXPLOG_UCIHAL_E("HAL not initialized");
1005     return UWBSTATUS_FAILED;
1006   }
1007   if(nxpucihal_ctrl.device_type == DEVICE_TYPE_SR1xxT) {
1008     appConfigStatus = NxpConfig_GetByteArray(NAME_NXP_UWB_EXT_APP_SR1XX_T_CONFIG,
1009                                    buffer.data(), buffer.size(),
1010                                    &retlen);
1011   } else if (nxpucihal_ctrl.device_type == DEVICE_TYPE_SR1xxS) {
1012     appConfigStatus = NxpConfig_GetByteArray(NAME_NXP_UWB_EXT_APP_SR1XX_S_CONFIG,
1013                                    buffer.data(), buffer.size(),
1014                                    &retlen);
1015   } else {
1016     appConfigStatus = NxpConfig_GetByteArray(NAME_NXP_UWB_EXT_APP_DEFAULT_CONFIG,
1017                                    buffer.data(), buffer.size(),
1018                                    &retlen);
1019   }
1020 
1021   if (appConfigStatus) {
1022     if ((retlen > 0) && (retlen <= max_config_length)) {
1023       vendorConfig[3] = sizeof(sessionId) + retlen;
1024       memcpy(vendorConfig + 4, &sessionId, sizeof(sessionId));
1025       memcpy(vendorConfig + 8, buffer.data(), retlen);
1026       cmdlen = UCI_MSG_HDR_SIZE + sizeof(sessionId) + retlen;
1027       status = phNxpUciHal_send_ext_cmd(cmdlen, vendorConfig);
1028       if (status != UWBSTATUS_SUCCESS) {
1029         NXPLOG_UCIHAL_D(" %s: Apply vendor App Config Failed", __func__);
1030         return UWBSTATUS_SUCCESS;
1031       }
1032     } else {
1033       NXPLOG_UCIHAL_D(" %s: Invalid retlen", __func__);
1034       return UWBSTATUS_SUCCESS;
1035     }
1036   }
1037   return status;
1038 }
1039 
1040 /******************************************************************************
1041  * Function         phNxpUciHal_GetMwVersion
1042  *
1043  * Description      This function gets the middleware version
1044  *
1045  * Returns          phNxpUciHal_MW_Version_t
1046  *
1047  ******************************************************************************/
phNxpUciHal_GetMwVersion()1048 phNxpUciHal_MW_Version_t phNxpUciHal_GetMwVersion() {
1049   phNxpUciHal_MW_Version_t mwVer;
1050   mwVer.validation = NXP_CHIP_SR100;
1051   mwVer.android_version = NXP_ANDROID_VERSION;
1052   NXPLOG_UCIHAL_D("0x%x:UWB MW Major Version:", UWB_NXP_MW_VERSION_MAJ);
1053   NXPLOG_UCIHAL_D("0x%x:UWB MW Minor Version:", UWB_NXP_MW_VERSION_MIN);
1054   mwVer.major_version = UWB_NXP_MW_VERSION_MAJ;
1055   mwVer.minor_version = UWB_NXP_MW_VERSION_MIN;
1056   mwVer.rc_version = UWB_NXP_ANDROID_MW_RC_VERSION;
1057   mwVer.mw_drop = UWB_NXP_ANDROID_MW_DROP_VERSION;
1058   return mwVer;
1059 }
1060 
1061 /******************************************************************************
1062  * Function         phNxpUciHal_getVersionInfo
1063  *
1064  * Description      This function request for version information
1065  *
1066  * Returns          void
1067  *
1068  ******************************************************************************/
phNxpUciHal_getVersionInfo()1069 void phNxpUciHal_getVersionInfo() {
1070   phNxpUciHal_MW_Version_t mwVersion = phNxpUciHal_GetMwVersion();
1071   if (mwVersion.rc_version) { /* for RC release*/
1072     ALOGI("MW Version: UWB_SW_Android_U_HKY_D%02x.%02x_RC%02x",
1073           mwVersion.major_version, mwVersion.minor_version,
1074           mwVersion.rc_version);
1075   } else if (mwVersion.mw_drop) { /* For Drops */
1076     ALOGI("MW Version: UWB_SW_Android_U_HKY_D%02x.%02x_DROP%02x",
1077           mwVersion.major_version, mwVersion.minor_version, mwVersion.mw_drop);
1078   } else { /* for Major Releases*/
1079     ALOGI("MW Version: UWB_SW_Android_U_HKY_D%02x.%02x",
1080           mwVersion.major_version, mwVersion.minor_version);
1081   }
1082 
1083   if (nxpucihal_ctrl.fw_version.rc_version) {
1084     ALOGI("FW Version: %02x.%02x_RC%02x", nxpucihal_ctrl.fw_version.major_version,
1085           nxpucihal_ctrl.fw_version.minor_version, nxpucihal_ctrl.fw_version.rc_version);
1086   } else {
1087     ALOGI("FW Version: %02x.%02x", nxpucihal_ctrl.fw_version.major_version,
1088           nxpucihal_ctrl.fw_version.minor_version);
1089   }
1090 }
1091 
1092 /*******************************************************************************
1093  * Function      phNxpUciHal_send_dev_error_status_ntf
1094  *
1095  * Description   send device status notification. Upper layer might restart
1096  *               HAL service.
1097  *
1098  * Returns       void
1099  *
1100  ******************************************* ***********************************/
phNxpUciHal_send_dev_error_status_ntf()1101 void phNxpUciHal_send_dev_error_status_ntf()
1102 {
1103  NXPLOG_UCIHAL_D("phNxpUciHal_send_dev_error_status_ntf ");
1104  nxpucihal_ctrl.rx_data_len = 5;
1105  static uint8_t rsp_data[5] = {0x60, 0x01, 0x00, 0x01, 0xFF};
1106  (*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len, rsp_data);
1107 }
1108