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