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