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