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
17 #include <log/log.h>
18 #include <phNxpLog.h>
19 #include <cutils/properties.h>
20 #include <phNxpUciHal.h>
21 #include <phNxpUciHal_Adaptation.h>
22 #include <phNxpUciHal_ext.h>
23 #include <phTmlUwb_spi.h>
24 #include <sys/stat.h>
25 #include <string.h>
26 #include <array>
27 #include <map>
28 #include <vector>
29 #include "hal_nxpuwb.h"
30 #include "phNxpConfig.h"
31 #include <android-base/stringprintf.h>
32 #include "phNxpUciHal_utils.h"
33
34 #if (NXP_UWB_EXTNS == TRUE)
35 #include "phNxpUciHalProp.h"
36 #endif
37
38 using namespace std;
39 using android::base::StringPrintf;
40
41 map<uint16_t, vector<uint16_t>> input_map;
42 map<uint16_t, vector<uint16_t>> conf_map;
43
44 /*********************** Global Variables *************************************/
45 /* UCI HAL Control structure */
46 phNxpUciHal_Control_t nxpucihal_ctrl;
47 uint8_t *gpCoreDeviceInfoRsp;
48 /* TML Context */
49 extern phTmlUwb_Context_t* gpphTmlUwb_Context;
50
51 bool uwb_debug_enabled = true;
52 bool uwb_device_initialized = false;
53 bool uwb_get_platform_id = false;
54 uint32_t timeoutTimerId = 0;
55 char persistant_log_path[120];
56 static uint8_t Rx_data[UCI_MAX_DATA_LEN];
57 uint8_t deviceType = '\0';
58
59 /**************** local methods used in this file only ************************/
60 static void phNxpUciHal_open_complete(tHAL_UWB_STATUS status);
61 static void phNxpUciHal_write_complete(void* pContext,
62 phTmlUwb_TransactInfo_t* pInfo);
63 static void phNxpUciHal_close_complete(tHAL_UWB_STATUS status);
64 static void phNxpUciHal_kill_client_thread(
65 phNxpUciHal_Control_t* p_nxpucihal_ctrl);
66 static void* phNxpUciHal_client_thread(void* arg);
67 extern int phNxpUciHal_fw_download();
68 static void phNxpUciHal_print_response_status(uint8_t *p_rx_data,
69 uint16_t p_len);
70
71 /*******************************************************************************
72 * Function get_input_map
73 *
74 * Description Creates a map from the USBS CAPS Response with key as Tag and
75 * value as a vector containing Length and Values of the Tag.
76 *
77 * Returns true if the map creation successful
78 *
79 *******************************************************************************/
get_input_map(const uint8_t * i_data,uint16_t iData_len)80 bool get_input_map(const uint8_t* i_data, uint16_t iData_len) {
81 vector<uint16_t> input_vec;
82 bool ret = true;
83 uint16_t i = 0, j = 0, tag = 0, len = 0;
84 i = UCI_PKT_HDR_LEN + UCI_PKT_PAYLOAD_STATUS_LEN + UCI_PKT_NUM_CAPS_LEN;
85 if (i_data == NULL) {
86 NXPLOG_UCIHAL_D("input map creation failed, i_data is NULL" );
87 return false;
88 }
89 while (i < iData_len) {
90 if (i + 1 >= iData_len) {
91 ret = false;
92 break;
93 }
94 tag = i_data[i++];
95 // Tag IDs from 0xE0 to 0xE2 are extended tag IDs with 2 bytes length.
96 if((tag >= 0xE0) && (tag <= 0xE2)) {
97 if (i + 1 >= iData_len) {
98 ret = false;
99 break;
100 }
101 tag = (tag << 8) | i_data[i++];
102 }
103 if (i + 1 >= iData_len) {
104 ret = false;
105 break;
106 }
107 len = i_data[i++];
108 input_vec.insert(input_vec.begin(), len);
109 if (i + len > iData_len) {
110 ret = false;
111 break;
112 }
113 for (j = 1; j <= len; j++) {
114 input_vec.insert(input_vec.begin() + j, i_data[i++]);
115 }
116 input_map[tag] = input_vec;
117 input_vec.clear();
118 }
119 return ret;
120 }
121
122 /*******************************************************************************
123 * Function get_conf_map
124 *
125 * Description Creates a map from the Country code conf with key as Tag and
126 * value as a vector containing Length and Values of the Tag.
127 *
128 * Returns true if the map creation successful
129 *
130 *******************************************************************************/
get_conf_map(uint8_t * c_data,uint16_t cData_len)131 bool get_conf_map(uint8_t* c_data, uint16_t cData_len) {
132 vector<uint16_t> conf_vec;
133 bool ret = true;
134 uint16_t i = 0, j = 0, tag = 0, len = 0;
135 if (c_data == NULL) {
136 NXPLOG_UCIHAL_D("Country code conf map creation failed, c_data is NULL" );
137 return false;
138 }
139 while (i < cData_len) {
140 if (i + 1 >= cData_len) {
141 ret = false;
142 break;
143 }
144 tag = c_data[i++];
145 // Tag IDs from 0xE0 to 0xE2 are extended tag IDs with 2 bytes length.
146 if ((tag >= 0xE0) && (tag <= 0xE2)) {
147 if (i + 1 >= cData_len) {
148 ret = false;
149 break;
150 }
151 tag = (tag<<8) | c_data[i++];
152 }
153 if (i + 1 >= cData_len) {
154 ret = false;
155 break;
156 }
157 len = c_data[i++];
158 conf_vec.insert(conf_vec.begin(),len);
159 if (i + len > cData_len) {
160 ret = false;
161 break;
162 }
163 for (j = 1; j <= len; j++) {
164 conf_vec.insert(conf_vec.begin() + j, c_data[i++]);
165 }
166 conf_map[tag] = conf_vec;
167 conf_vec.clear();
168 }
169 return ret;
170 }
171
172 /******************************************************************************
173 * Function phNxpUciHal_client_thread
174 *
175 * Description This function is a thread handler which handles all TML and
176 * UCI messages.
177 *
178 * Returns void
179 *
180 ******************************************************************************/
phNxpUciHal_client_thread(void * arg)181 static void* phNxpUciHal_client_thread(void* arg) {
182 phNxpUciHal_Control_t* p_nxpucihal_ctrl = (phNxpUciHal_Control_t*)arg;
183 phLibUwb_Message_t msg;
184
185 NXPLOG_UCIHAL_D("thread started");
186
187 p_nxpucihal_ctrl->thread_running = 1;
188
189 while (p_nxpucihal_ctrl->thread_running == 1) {
190 /* Fetch next message from the UWB stack message queue */
191 if (phDal4Uwb_msgrcv(p_nxpucihal_ctrl->gDrvCfg.nClientId, &msg, 0, 0) ==
192 -1) {
193 NXPLOG_UCIHAL_E("UWB client received bad message");
194 continue;
195 }
196
197 if (p_nxpucihal_ctrl->thread_running == 0) {
198 break;
199 }
200
201 switch (msg.eMsgType) {
202 case PH_LIBUWB_DEFERREDCALL_MSG: {
203 phLibUwb_DeferredCall_t* deferCall =
204 (phLibUwb_DeferredCall_t*)(msg.pMsgData);
205
206 REENTRANCE_LOCK();
207 deferCall->pCallback(deferCall->pParameter);
208 REENTRANCE_UNLOCK();
209
210 break;
211 }
212
213 case UCI_HAL_OPEN_CPLT_MSG: {
214 REENTRANCE_LOCK();
215 if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
216 /* Send the event */
217 (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT,
218 HAL_UWB_STATUS_OK);
219 }
220 REENTRANCE_UNLOCK();
221 break;
222 }
223
224 case UCI_HAL_CLOSE_CPLT_MSG: {
225 REENTRANCE_LOCK();
226 if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
227 /* Send the event */
228 (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_CLOSE_CPLT_EVT,
229 HAL_UWB_STATUS_OK);
230 phNxpUciHal_kill_client_thread(&nxpucihal_ctrl);
231 }
232 REENTRANCE_UNLOCK();
233 break;
234 }
235
236 case UCI_HAL_INIT_CPLT_MSG: {
237 REENTRANCE_LOCK();
238 if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
239 /* Send the event */
240 (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_INIT_CPLT_EVT,
241 HAL_UWB_STATUS_OK);
242 }
243 REENTRANCE_UNLOCK();
244 break;
245 }
246
247 case UCI_HAL_ERROR_MSG: {
248 REENTRANCE_LOCK();
249 if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
250 /* Send the event */
251 (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_ERROR_EVT,
252 HAL_UWB_ERROR_EVT);
253 }
254 REENTRANCE_UNLOCK();
255 break;
256 }
257 }
258 }
259
260 NXPLOG_UCIHAL_D("NxpUciHal thread stopped");
261 pthread_exit(NULL);
262 return NULL;
263 }
264
265 /******************************************************************************
266 * Function phNxpUciHal_kill_client_thread
267 *
268 * Description This function safely kill the client thread and clean all
269 * resources.
270 *
271 * Returns void.
272 *
273 ******************************************************************************/
phNxpUciHal_kill_client_thread(phNxpUciHal_Control_t * p_nxpucihal_ctrl)274 static void phNxpUciHal_kill_client_thread(
275 phNxpUciHal_Control_t* p_nxpucihal_ctrl) {
276 NXPLOG_UCIHAL_D("Terminating phNxpUciHal client thread...");
277
278 p_nxpucihal_ctrl->p_uwb_stack_cback = NULL;
279 p_nxpucihal_ctrl->p_uwb_stack_data_cback = NULL;
280 p_nxpucihal_ctrl->thread_running = 0;
281
282 return;
283 }
284
285 /******************************************************************************
286 * Function phNxpUciHal_open
287 *
288 * Description This function is called by libuwb-uci during the
289 * initialization of the UWBC. It opens the physical connection
290 * with UWBC (SRXXX) and creates required client thread for
291 * operation.
292 * After open is complete, status is informed to libuwb-uci
293 * through callback function.
294 *
295 * Returns This function return UWBSTATUS_SUCCES (0) in case of success
296 * In case of failure returns other failure value.
297 *
298 ******************************************************************************/
phNxpUciHal_open(uwb_stack_callback_t * p_cback,uwb_stack_data_callback_t * p_data_cback)299 tHAL_UWB_STATUS phNxpUciHal_open(uwb_stack_callback_t* p_cback,
300 uwb_stack_data_callback_t* p_data_cback) {
301 phOsalUwb_Config_t tOsalConfig;
302 phTmlUwb_Config_t tTmlConfig;
303 char* uwb_dev_node = NULL;
304 const uint16_t max_len = 260;
305 tHAL_UWB_STATUS wConfigStatus = UWBSTATUS_SUCCESS;
306 pthread_attr_t attr;
307
308 if (nxpucihal_ctrl.halStatus == HAL_STATUS_OPEN) {
309 NXPLOG_UCIHAL_E("phNxpUciHal_open already open");
310 return UWBSTATUS_SUCCESS;
311 }
312
313 /* initialize trace level */
314 phNxpLog_InitializeLogLevel();
315 /*Create the timer for extns write response*/
316 timeoutTimerId = phOsalUwb_Timer_Create();
317
318 if (phNxpUciHal_init_monitor() == NULL) {
319 NXPLOG_UCIHAL_E("Init monitor failed");
320 return UWBSTATUS_FAILED;
321 }
322
323 CONCURRENCY_LOCK();
324
325 memset(&nxpucihal_ctrl, 0x00, sizeof(nxpucihal_ctrl));
326 memset(&tOsalConfig, 0x00, sizeof(tOsalConfig));
327 memset(&tTmlConfig, 0x00, sizeof(tTmlConfig));
328 uwb_dev_node = (char*)nxp_malloc(max_len * sizeof(char));
329 if (uwb_dev_node == NULL) {
330 NXPLOG_UCIHAL_E("malloc of uwb_dev_node failed ");
331 goto clean_and_return;
332 }
333
334 if (!GetNxpConfigStrValue(NAME_NXP_UWB_DEVICE_NODE, uwb_dev_node, max_len)) {
335 strcpy(uwb_dev_node, "/dev/srxxx");
336 }
337 NXPLOG_UCIHAL_E("Assigning the helios Node: %s", uwb_dev_node);
338
339 /* By default HAL status is HAL_STATUS_OPEN */
340 nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
341
342 nxpucihal_ctrl.p_uwb_stack_cback = p_cback;
343 nxpucihal_ctrl.p_uwb_stack_data_cback = p_data_cback;
344 nxpucihal_ctrl.fw_dwnld_mode = false;
345
346 #if(NXP_UWB_EXTNS == TRUE)
347 phNxpUciPropHal_initialize();
348 #endif
349
350 /* Configure hardware link */
351 nxpucihal_ctrl.gDrvCfg.nClientId = phDal4Uwb_msgget(0, 0600);
352 nxpucihal_ctrl.gDrvCfg.nLinkType = ENUM_LINK_TYPE_SPI;
353 tTmlConfig.pDevName = (int8_t*)uwb_dev_node;
354 tOsalConfig.dwCallbackThreadId = (uintptr_t)nxpucihal_ctrl.gDrvCfg.nClientId;
355 tOsalConfig.pLogFile = NULL;
356 tTmlConfig.dwGetMsgThreadId = (uintptr_t)nxpucihal_ctrl.gDrvCfg.nClientId;
357
358 /* Initialize TML layer */
359 wConfigStatus = phTmlUwb_Init(&tTmlConfig);
360 if (wConfigStatus != UWBSTATUS_SUCCESS) {
361 NXPLOG_UCIHAL_E("phTmlUwb_Init Failed");
362 goto clean_and_return;
363 } else {
364 if (uwb_dev_node != NULL) {
365 free(uwb_dev_node);
366 uwb_dev_node = NULL;
367 }
368 }
369
370 /* Create the client thread */
371 pthread_attr_init(&attr);
372 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
373 if (pthread_create(&nxpucihal_ctrl.client_thread, &attr,
374 phNxpUciHal_client_thread, &nxpucihal_ctrl) != 0) {
375 NXPLOG_UCIHAL_E("pthread_create failed");
376 wConfigStatus = phTmlUwb_Shutdown();
377 goto clean_and_return;
378 }
379
380 CONCURRENCY_UNLOCK();
381
382 #if 0
383 /* call read pending */
384 status = phTmlUwb_Read(
385 nxpucihal_ctrl.p_cmd_data, UCI_MAX_DATA_LEN,
386 (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
387 if (status != UWBSTATUS_PENDING) {
388 NXPLOG_UCIHAL_E("TML Read status error status = %x", status);
389 wConfigStatus = phTmlUwb_Shutdown();
390 wConfigStatus = UWBSTATUS_FAILED;
391 goto clean_and_return;
392 }
393 #endif
394 pthread_attr_destroy(&attr);
395 /* Call open complete */
396 phNxpUciHal_open_complete(wConfigStatus);
397 return wConfigStatus;
398
399 clean_and_return:
400 CONCURRENCY_UNLOCK();
401 if (uwb_dev_node != NULL) {
402 free(uwb_dev_node);
403 uwb_dev_node = NULL;
404 }
405
406 /* Report error status */
407 (*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT, HAL_UWB_ERROR_EVT);
408
409 nxpucihal_ctrl.p_uwb_stack_cback = NULL;
410 nxpucihal_ctrl.p_uwb_stack_data_cback = NULL;
411 phNxpUciHal_cleanup_monitor();
412 nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
413 pthread_attr_destroy(&attr);
414 return wConfigStatus;
415 }
416
417 /******************************************************************************
418 * Function phNxpUciHal_open_complete
419 *
420 * Description This function inform the status of phNxpUciHal_open
421 * function to libuwb-uci.
422 *
423 * Returns void.
424 *
425 ******************************************************************************/
phNxpUciHal_open_complete(tHAL_UWB_STATUS status)426 static void phNxpUciHal_open_complete(tHAL_UWB_STATUS status) {
427 static phLibUwb_Message_t msg;
428
429 if (status == UWBSTATUS_SUCCESS) {
430 msg.eMsgType = UCI_HAL_OPEN_CPLT_MSG;
431 nxpucihal_ctrl.hal_open_status = true;
432 nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
433 } else {
434 msg.eMsgType = UCI_HAL_ERROR_MSG;
435 }
436
437 msg.pMsgData = NULL;
438 msg.Size = 0;
439
440 phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId,
441 (phLibUwb_Message_t*)&msg);
442
443 return;
444 }
445
446 /******************************************************************************
447 * Function phNxpUciHal_write
448 *
449 * Description This function write the data to UWBC through physical
450 * interface (e.g. SPI) using the driver interface.
451 * Before sending the data to UWBC, phNxpUciHal_write_ext
452 * is called to check if there is any extension processing
453 * is required for the UCI packet being sent out.
454 *
455 * Returns It returns number of bytes successfully written to UWBC.
456 *
457 ******************************************************************************/
phNxpUciHal_write(uint16_t data_len,const uint8_t * p_data)458 tHAL_UWB_STATUS phNxpUciHal_write(uint16_t data_len, const uint8_t* p_data) {
459 if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
460 return UWBSTATUS_FAILED;
461 }
462
463 CONCURRENCY_LOCK();
464 uint16_t len = phNxpUciHal_write_unlocked(data_len, p_data);
465 CONCURRENCY_UNLOCK();
466
467 /* No data written */
468 return len;
469 }
470
471 /******************************************************************************
472 * Function phNxpUciHal_parse_get_capsInfo
473 *
474 * Description This function parses all the data passing through the HAL.
475 *
476 * Returns It returns true if the incoming command to be skipped.
477 *
478 ******************************************************************************/
phNxpUciHal_parse_get_capsInfo(uint16_t data_len,uint8_t * p_data)479 void phNxpUciHal_parse_get_capsInfo(uint16_t data_len, uint8_t* p_data) {
480 uint8_t *p = p_data;
481 uint8_t pDeviceCapsInfo[UCI_MAX_DATA_LEN];
482 uint8_t * pp = pDeviceCapsInfo;
483 uint8_t tagId=0, subTagId=0, len =0;
484 uint8_t mt = 0, gid = 0, oid = 0;
485 uint8_t capsLen = p_data[5];
486 uint8_t dataLen = p_data[3];
487 mt = (*(p_data) & UCI_MT_MASK) >> UCI_MT_SHIFT;
488 gid = p_data[0] & UCI_GID_MASK;
489 oid = p_data[1] & UCI_OID_MASK;
490 uint8_t *p_caps_value;
491 if (mt == UCI_MT_RSP) {
492 if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_GET_CAPS_INFO)) {
493 if (p_data[4] == 0) {
494 for (uint16_t index = 6; index < data_len;) {
495 tagId = p_data[index++];
496 if (tagId != 0xE0)
497 {
498 len = p_data[index++];
499 p_caps_value = (uint8_t *)(p_data + index);
500 UINT8_TO_STREAM(pp, tagId);
501 UINT8_TO_STREAM(pp, len);
502 ARRAY_TO_STREAM(pp, p_caps_value, len);
503 index = index + len;
504 } else { //ignore vendor specific data
505 subTagId = p_data[index++];
506 len = p_data[index++];
507 index = index + len;
508 capsLen--;
509 dataLen = dataLen - (len + 3);// from datalen substract tagId, subTagId, len and value of config
510 }
511 }
512 // mapping device caps according to Fira 2.0
513 // TODO: Removed once FW support available
514 uint8_t fira_2_cap_info[] = { 0xA7, 0x04, 0x00, 0x00, 0x00, 0x00,
515 0xE3, 0x01, 0x00,
516 0xE4, 0x01, 0x00,
517 0xE5, 0x01, 0x00,
518 0xE6, 0x01, 0x00,
519 0xE7, 0x01, 0x00};
520 size_t fira_2_cap_info_len = sizeof(fira_2_cap_info)/sizeof(uint8_t);
521 ARRAY_TO_STREAM(pp, fira_2_cap_info, fira_2_cap_info_len)
522 dataLen += fira_2_cap_info_len;
523
524 nxpucihal_ctrl.rx_data_len = UCI_MSG_HDR_SIZE + dataLen;
525 UCI_MSG_BLD_HDR0(p, UCI_MT_RSP, UCI_GID_CORE);
526 UCI_MSG_BLD_HDR1(p, UCI_MSG_CORE_GET_CAPS_INFO);
527 UINT8_TO_STREAM(p, 0x00);
528 UINT8_TO_STREAM(p, dataLen);
529 UINT8_TO_STREAM(p, 0x00); //status
530 UINT8_TO_STREAM(p, (capsLen + 6));
531 ARRAY_TO_STREAM(p, pDeviceCapsInfo, dataLen);
532 }
533 }
534 }
535 }
536
537 /******************************************************************************
538 * Function phNxpUciHal_parse
539 *
540 * Description This function parses all the data passing through the HAL.
541 *
542 * Returns It returns true if the incoming command to be skipped.
543 *
544 ******************************************************************************/
phNxpUciHal_parse(uint16_t data_len,const uint8_t * p_data)545 bool phNxpUciHal_parse(uint16_t data_len, const uint8_t* p_data) {
546 uint8_t mt = 0, gid = 0, oid = 0;
547 uint16_t arrLen = 0, tag = 0,idx = 0;
548 char country_code[2];
549 long retlen = 0;
550 bool ret = false;
551 static bool isCountryCodeMapCreated = false;
552 map<uint16_t, vector<uint16_t>>::iterator itr;
553 vector<uint16_t>::iterator v_itr;
554 mt = (*(p_data) & UCI_MT_MASK) >> UCI_MT_SHIFT;
555 gid = p_data[0] & UCI_GID_MASK;
556 oid = p_data[1] & UCI_OID_MASK;
557
558 if ( mt == UCI_MT_CMD) {
559 if ((gid == UCI_GID_ANDROID) && (oid == UCI_MSG_ANDROID_SET_COUNTRY_CODE)) {
560 country_code[0] = (char) p_data[4];
561 country_code[1] = (char) p_data[5];
562 if ((country_code[0] == '0') && (country_code[1] == '0')) {
563 NXPLOG_UCIHAL_D("Country code %s is Invalid!",country_code);
564 } else {
565 //Read config file based on the country code
566 if (GetNxpConfigCountryCodeByteArrayValue(NAME_NXP_COUNTRY_CODE_CONFIG, country_code, (char*)nxpucihal_ctrl.p_caps_resp,UCI_MAX_DATA_LEN, &retlen) == 1) {
567 NXPLOG_UCIHAL_D("Country code conf loaded , Country %s", country_code );
568 if (get_conf_map(nxpucihal_ctrl.p_caps_resp, retlen)) {
569 isCountryCodeMapCreated = true;
570 } else {
571 NXPLOG_UCIHAL_D("Country code conf map creation failed" );
572 }
573 } else {
574 NXPLOG_UCIHAL_D("Country code conf is empty!");
575 }
576 }
577 // send country code response to upper layer
578 nxpucihal_ctrl.rx_data_len = 5;
579 static uint8_t rsp_data[5];
580 rsp_data[0] = 0x4c;
581 rsp_data[1] = 0x01;
582 rsp_data[2] = 0x00;
583 rsp_data[3] = 0x01;
584 rsp_data[4] = 0x00; // Response Success
585 ret = true;
586 (*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len, rsp_data);
587 }
588 } else if (mt == UCI_MT_RSP) {
589 if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_GET_CAPS_INFO)) {
590 // do not modify caps if the country code is not recieved from upper layer.
591 if (isCountryCodeMapCreated == false) {
592 return false;
593 }
594 // Check UWBS Caps response status
595 if (p_data[4] == 0) {
596 if (get_input_map(p_data,data_len)) {
597 NXPLOG_UCIHAL_D("Input Map created");
598 } else {
599 NXPLOG_UCIHAL_D("Input Map creation failed");
600 return false;
601 }
602 } else {
603 return false;
604 }
605 //Compare the maps for Tags and modify input map if Values are different
606 for (itr = input_map.begin(); itr != input_map.end(); ++itr) {
607 tag = itr->first;
608 // Check for the Tag in both maps
609 if ((conf_map.count(tag)) == 1) {
610 if (tag == UWB_CHANNELS) {
611 NXPLOG_UCIHAL_D("Tag = 0x%02X , modify UWB_CHANNELS based on country conf ", tag);
612 for (int j = 0; j < (itr -> second).size(); j++) {
613 (input_map[tag])[j] = ((conf_map[tag])[j]) & ((input_map[tag])[j]);
614 }
615 }
616 } else {
617 // TAG not found do nothing
618 }
619 }
620 //convert the modified input map to p_caps_resp array
621 memset(nxpucihal_ctrl.p_caps_resp,0,UCI_MAX_DATA_LEN);
622 //Header information from Input array is updated in initial bytes
623 nxpucihal_ctrl.p_caps_resp[0] = p_data[0];
624 nxpucihal_ctrl.p_caps_resp[1] = p_data[1];
625 nxpucihal_ctrl.p_caps_resp[2] = p_data[2];
626 nxpucihal_ctrl.p_caps_resp[4] = p_data[4];
627 idx = UCI_PKT_HDR_LEN + UCI_PKT_PAYLOAD_STATUS_LEN + UCI_PKT_NUM_CAPS_LEN;
628 for (itr = input_map.begin(); itr != input_map.end(); ++itr) {
629 tag = itr->first;
630 //If Tag is 0xE0 or 0xE1 or 0xE2,Tag will be of 2 bytes
631 if (((tag >> 8) >= 0xE0) && ((tag >> 8) <= 0xE2)) {
632 nxpucihal_ctrl.p_caps_resp[idx++] = (tag & 0xFF00) >> 8;
633 nxpucihal_ctrl.p_caps_resp[idx++] = (tag & 0x00FF);
634 } else {
635 nxpucihal_ctrl.p_caps_resp[idx++] = tag;
636 }
637 for (v_itr = itr->second.begin(); v_itr != itr->second.end(); ++v_itr) {
638 nxpucihal_ctrl.p_caps_resp[idx++] = (*v_itr);
639 }
640 }
641 arrLen = idx;
642 // exclude the initial header data
643 nxpucihal_ctrl.p_caps_resp[3] = arrLen - UCI_PKT_HDR_LEN;
644 // update the number of parameter TLVs.
645 nxpucihal_ctrl.p_caps_resp[5] = input_map.size();
646 // send GET CAPS INFO response to the Upper Layer
647 (*nxpucihal_ctrl.p_uwb_stack_data_cback)(arrLen, nxpucihal_ctrl.p_caps_resp);
648 // skip the incoming packet as we have send the modified response already
649 nxpucihal_ctrl.isSkipPacket = 1;
650 ret = false;
651 }
652 } else {
653 ret = false;
654 }
655 return ret;
656 }
657
658 /******************************************************************************
659 * Function phNxpUciHal_write_unlocked
660 *
661 * Description This is the actual function which is being called by
662 * phNxpUciHal_write. This function writes the data to UWBC.
663 * It waits till write callback provide the result of write
664 * process.
665 *
666 * Returns It returns number of bytes successfully written to UWBC.
667 *
668 ******************************************************************************/
phNxpUciHal_write_unlocked(uint16_t data_len,const uint8_t * p_data)669 tHAL_UWB_STATUS phNxpUciHal_write_unlocked(uint16_t data_len, const uint8_t* p_data) {
670 tHAL_UWB_STATUS status;
671 uint8_t mt, pbf, gid, oid;
672
673 phNxpUciHal_Sem_t cb_data;
674 bool ret_ = false;
675 /* Create the local semaphore */
676 if (phNxpUciHal_init_cb_data(&cb_data, NULL) != UWBSTATUS_SUCCESS) {
677 NXPLOG_UCIHAL_D("phNxpUciHal_write_unlocked Create cb data failed");
678 data_len = 0;
679 goto clean_and_return;
680 }
681
682 if ((data_len > UCI_MAX_DATA_LEN) || (data_len < UCI_PKT_HDR_LEN)) {
683 NXPLOG_UCIHAL_E("Invalid data_len");
684 data_len = 0;
685 goto clean_and_return;
686 }
687
688 /* Create local copy of cmd_data */
689 memcpy(nxpucihal_ctrl.p_cmd_data, p_data, data_len);
690 nxpucihal_ctrl.cmd_len = data_len;
691
692 data_len = nxpucihal_ctrl.cmd_len;
693 UCI_MSG_PRS_HDR0(p_data, mt, pbf, gid);
694 UCI_MSG_PRS_HDR1(p_data, oid);
695
696 /* Vendor Specific Parsing logic */
697 ret_ = phNxpUciHal_parse(nxpucihal_ctrl.cmd_len,nxpucihal_ctrl.p_cmd_data);
698 if (ret_) {
699 goto clean_and_return;
700 }
701 status = phTmlUwb_Write(
702 (uint8_t*)nxpucihal_ctrl.p_cmd_data, (uint16_t)nxpucihal_ctrl.cmd_len,
703 (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_write_complete,
704 (void*)&cb_data);
705
706
707 if (status != UWBSTATUS_PENDING) {
708 NXPLOG_UCIHAL_E("write_unlocked status error");
709 data_len = 0;
710 goto clean_and_return;
711 }
712
713 /* Wait for callback response */
714 if (SEM_WAIT(cb_data)) {
715 NXPLOG_UCIHAL_E("write_unlocked semaphore error");
716 data_len = 0;
717 goto clean_and_return;
718 }
719
720 clean_and_return:
721 phNxpUciHal_cleanup_cb_data(&cb_data);
722 return data_len;
723 }
724
725 /******************************************************************************
726 * Function phNxpUciHal_write_complete
727 *
728 * Description This function handles write callback.
729 *
730 * Returns void.
731 *
732 ******************************************************************************/
phNxpUciHal_write_complete(void * pContext,phTmlUwb_TransactInfo_t * pInfo)733 static void phNxpUciHal_write_complete(void* pContext,
734 phTmlUwb_TransactInfo_t* pInfo) {
735 phNxpUciHal_Sem_t* p_cb_data = (phNxpUciHal_Sem_t*)pContext;
736
737 if (pInfo->wStatus == UWBSTATUS_SUCCESS) {
738 NXPLOG_UCIHAL_D("write successful status = 0x%x", pInfo->wStatus);
739 } else {
740 NXPLOG_UCIHAL_E("write error status = 0x%x", pInfo->wStatus);
741 }
742 p_cb_data->status = pInfo->wStatus;
743
744 SEM_POST(p_cb_data);
745
746 return;
747 }
748 /******************************************************************************
749 * Function phNxpUciHal_read_complete
750 *
751 * Description This function is called whenever there is an UCI packet
752 * received from UWBC. It could be RSP or NTF packet. This
753 * function provide the received UCI packet to libuwb-uci
754 * using data callback of libuwb-uci.
755 * There is a pending read called from each
756 * phNxpUciHal_read_complete so each a packet received from
757 * UWBC can be provide to libuwb-uci.
758 *
759 * Returns void.
760 *
761 ******************************************************************************/
phNxpUciHal_read_complete(void * pContext,phTmlUwb_TransactInfo_t * pInfo)762 void phNxpUciHal_read_complete(void* pContext,
763 phTmlUwb_TransactInfo_t* pInfo) {
764 tHAL_UWB_STATUS status;
765 uint8_t gid = 0, oid = 0, pbf = 0;
766 UNUSED(pContext);
767 if (nxpucihal_ctrl.read_retry_cnt == 1) {
768 nxpucihal_ctrl.read_retry_cnt = 0;
769 }
770 if (pInfo->wStatus == UWBSTATUS_SUCCESS) {
771 NXPLOG_UCIHAL_D("read successful status = 0x%x", pInfo->wStatus);
772 nxpucihal_ctrl.p_rx_data = pInfo->pBuff;
773 nxpucihal_ctrl.rx_data_len = pInfo->wLength;
774
775 gid = nxpucihal_ctrl.p_rx_data[0] & UCI_GID_MASK;
776 oid = nxpucihal_ctrl.p_rx_data[1] & UCI_OID_MASK;
777 pbf = (nxpucihal_ctrl.p_rx_data[0] & UCI_PBF_MASK) >> UCI_PBF_SHIFT;
778 nxpucihal_ctrl.isSkipPacket = 0;
779
780 phNxpUciHal_parse_get_capsInfo(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
781 phNxpUciHal_parse(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
782
783 #if(NXP_UWB_EXTNS == TRUE)
784 phNxpUciPropHal_process_response();
785 #endif
786
787 if(!uwb_device_initialized) {
788 if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_STATUS_NTF)) {
789 nxpucihal_ctrl.uwbc_device_state = nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET];
790 if(nxpucihal_ctrl.uwbc_device_state == UWB_DEVICE_INIT || nxpucihal_ctrl.uwbc_device_state == UWB_DEVICE_READY) {
791 nxpucihal_ctrl.isSkipPacket = 1;
792 SEM_POST(&(nxpucihal_ctrl.dev_status_ntf_wait));
793 }
794 }
795 }
796
797 if (nxpucihal_ctrl.hal_ext_enabled == 1){
798 if((nxpucihal_ctrl.p_rx_data[0x00] & 0xF0) == 0x40){
799 nxpucihal_ctrl.isSkipPacket = 1;
800 if(nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET] == UCI_STATUS_OK){
801 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_SUCCESS;
802 if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_INFO)) {
803 gpCoreDeviceInfoRsp = (uint8_t*)malloc(sizeof(uint8_t) * nxpucihal_ctrl.rx_data_len);
804 if(gpCoreDeviceInfoRsp != NULL) {
805 memcpy(&gpCoreDeviceInfoRsp[0], &nxpucihal_ctrl.p_rx_data[0], nxpucihal_ctrl.rx_data_len);
806 }
807 }
808 } else if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_SET_CONFIG)){
809 NXPLOG_UCIHAL_E(" status = 0x%x",nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET]);
810 /* check if any configurations are not supported then ignore the UWBSTATUS_FEATURE_NOT_SUPPORTED stastus code*/
811 nxpucihal_ctrl.ext_cb_data.status = phNxpUciHal_process_ext_rsp(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
812 } else {
813 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_FAILED;
814 NXPLOG_UCIHAL_E("command failed! status = 0x%x",nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET]);
815 }
816 usleep(1);
817 SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
818 } else if(gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GENERIC_ERROR_NTF && nxpucihal_ctrl.p_rx_data[4] == UCI_STATUS_COMMAND_RETRY){
819 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_COMMAND_RETRANSMIT;
820 SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
821 } else if (gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GENERIC_ERROR_NTF && nxpucihal_ctrl.p_rx_data[4] == UCI_STATUS_INVALID_MSG_SIZE){
822 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_INVALID_COMMAND_LENGTH;
823 SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
824 nxpucihal_ctrl.isSkipPacket = 1;
825 }
826 }
827 /* if Debug Notification, then skip sending to application */
828 if(nxpucihal_ctrl.isSkipPacket == 0) {
829 phNxpUciHal_print_response_status(nxpucihal_ctrl.p_rx_data, nxpucihal_ctrl.rx_data_len);
830 /* Read successful, send the event to higher layer */
831 if ((nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) && (nxpucihal_ctrl.rx_data_len <= UCI_MAX_PAYLOAD_LEN)) {
832 (*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len,
833 nxpucihal_ctrl.p_rx_data);
834 }
835 }
836 } else {
837 NXPLOG_UCIHAL_E("read error status = 0x%x", pInfo->wStatus);
838 }
839
840 if (nxpucihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
841 return;
842 }
843 /* Disable junk data check for each UCI packet*/
844 if(nxpucihal_ctrl.fw_dwnld_mode) {
845 if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_STATUS_NTF)){
846 nxpucihal_ctrl.fw_dwnld_mode = false;
847 }
848 }
849 /* Read again because read must be pending always.*/
850 status = phTmlUwb_Read(
851 Rx_data, UCI_MAX_DATA_LEN,
852 (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
853 if (status != UWBSTATUS_PENDING) {
854 NXPLOG_UCIHAL_E("read status error status = %x", status);
855 /* TODO: Not sure how to handle this ? */
856 }
857 return;
858 }
859
860 /******************************************************************************
861 * Function phNxpUciHal_close
862 *
863 * Description This function close the UWBC interface and free all
864 * resources.This is called by libuwb-uci on UWB service stop.
865 *
866 * Returns Always return UWBSTATUS_SUCCESS (0).
867 *
868 ******************************************************************************/
phNxpUciHal_close()869 tHAL_UWB_STATUS phNxpUciHal_close() {
870 tHAL_UWB_STATUS status;
871 if (nxpucihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
872 NXPLOG_UCIHAL_E("phNxpUciHal_close is already closed, ignoring close");
873 return UWBSTATUS_FAILED;
874 }
875
876 #if(NXP_UWB_EXTNS == TRUE)
877 phNxpUciPropHal_deinitialize();
878 #endif
879
880 uwb_device_initialized = false;
881
882 CONCURRENCY_LOCK();
883
884 nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
885
886 if (NULL != gpphTmlUwb_Context->pDevHandle) {
887 phNxpUciHal_close_complete(UWBSTATUS_SUCCESS);
888 /* Abort any pending read and write */
889 status = phTmlUwb_ReadAbort();
890 status = phTmlUwb_WriteAbort();
891
892 phOsalUwb_Timer_Cleanup();
893
894 status = phTmlUwb_Shutdown();
895
896 phDal4Uwb_msgrelease(nxpucihal_ctrl.gDrvCfg.nClientId);
897
898 memset(&nxpucihal_ctrl, 0x00, sizeof(nxpucihal_ctrl));
899
900 NXPLOG_UCIHAL_D("phNxpUciHal_close - phOsalUwb_DeInit completed");
901 }
902
903 CONCURRENCY_UNLOCK();
904
905 phNxpUciHal_cleanup_monitor();
906
907 /* Return success always */
908 return UWBSTATUS_SUCCESS;
909 }
910 /******************************************************************************
911 * Function phNxpUciHal_close_complete
912 *
913 * Description This function inform libuwb-uci about result of
914 * phNxpUciHal_close.
915 *
916 * Returns void.
917 *
918 ******************************************************************************/
phNxpUciHal_close_complete(tHAL_UWB_STATUS status)919 void phNxpUciHal_close_complete(tHAL_UWB_STATUS status) {
920 static phLibUwb_Message_t msg;
921
922 if (status == UWBSTATUS_SUCCESS) {
923 msg.eMsgType = UCI_HAL_CLOSE_CPLT_MSG;
924 } else {
925 msg.eMsgType = UCI_HAL_ERROR_MSG;
926 }
927 msg.pMsgData = NULL;
928 msg.Size = 0;
929
930 phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &msg);
931
932 return;
933 }
934
935 /******************************************************************************
936 * Function phNxpUciHal_init_complete
937 *
938 * Description This function inform libuwb-uci about result of
939 * phNxpUciHal_coreInitialization.
940 *
941 * Returns void.
942 *
943 ******************************************************************************/
phNxpUciHal_init_complete(tHAL_UWB_STATUS status)944 void phNxpUciHal_init_complete(tHAL_UWB_STATUS status) {
945 static phLibUwb_Message_t msg;
946
947 if (status == UWBSTATUS_SUCCESS) {
948 msg.eMsgType = UCI_HAL_INIT_CPLT_MSG;
949 } else {
950 msg.eMsgType = UCI_HAL_ERROR_MSG;
951 }
952 msg.pMsgData = NULL;
953 msg.Size = 0;
954
955 phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &msg);
956
957 return;
958 }
959
960 /******************************************************************************
961 * Function phNxpUciHal_parseCoreDeviceInfoRsp
962 *
963 * Description This function parse Core device Info response.
964 *
965 * Returns void.
966 *
967 ******************************************************************************/
phNxpUciHal_parseCoreDeviceInfoRsp(uint8_t * fwBootMode,uint8_t * device)968 static void phNxpUciHal_parseCoreDeviceInfoRsp(uint8_t *fwBootMode, uint8_t *device) {
969 NXPLOG_UCIHAL_D("phNxpUciHal_parseCoreDeviceInfoRsp Enter..");
970 uint8_t index = 13; // Excluding the header and Versions
971 uint8_t paramId = 0;
972 uint8_t length = 0;
973
974 if(fwBootMode == NULL || gpCoreDeviceInfoRsp == NULL){
975 return;
976 }
977
978 uint8_t len = gpCoreDeviceInfoRsp[index++];
979 while(index < len) {
980 uint8_t extParamId = gpCoreDeviceInfoRsp[index++];
981 paramId = gpCoreDeviceInfoRsp[index++];
982 length = gpCoreDeviceInfoRsp[index++];
983 if((extParamId == EXT_CONFIG_TAG_ID) && (paramId == FW_BOOT_MODE_PARAM_ID)){
984 *fwBootMode = gpCoreDeviceInfoRsp[index];
985 break;
986 }
987 if ((extParamId == EXT_CONFIG_TAG_ID) && (paramId == 0x00)) {
988 *device = gpCoreDeviceInfoRsp[index + 5];
989 NXPLOG_UCIHAL_D("phNxpUciHal_parseCoreDeviceInfoRsp DeviceType %c", *device);
990 }
991 index = index + length;
992 }
993 free(gpCoreDeviceInfoRsp);
994 return;
995 }
996
997 /******************************************************************************
998 * Function phNxpUciHal_sendGetCoreDeviceInfo
999 *
1000 * Description This function send Core device Info command.
1001 *
1002 * Returns status.
1003 *
1004 ******************************************************************************/
phNxpUciHal_sendGetCoreDeviceInfo()1005 uint8_t phNxpUciHal_sendGetCoreDeviceInfo(){
1006 std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
1007 uint8_t* vendorConfig = NULL;
1008 long retlen = 0;
1009 buffer.fill(0);
1010 const uint8_t getCoreDeviceInfoConfig[] = {0x20, 0x02, 0x00, 0x00};
1011 uint8_t fwBootMode = 0;
1012 uint8_t getCoreDeviceInfoCmdLen = 4;
1013 tHAL_UWB_STATUS status = phNxpUciHal_send_ext_cmd(getCoreDeviceInfoCmdLen, getCoreDeviceInfoConfig);
1014 if(status != UWBSTATUS_SUCCESS) {
1015 return status;
1016 } else {
1017 phNxpUciHal_parseCoreDeviceInfoRsp(&fwBootMode, &deviceType);
1018 if(fwBootMode == USER_FW_BOOT_MODE) {
1019 if (GetNxpConfigByteArrayValue(NAME_UWB_USER_FW_BOOT_MODE_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1020 if ((retlen > 0) && (retlen <= UCI_MAX_DATA_LEN)) {
1021 vendorConfig = buffer.data();
1022 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1023 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_USER_FW_BOOT_MODE_CONFIG, status);
1024 if(status != UWBSTATUS_SUCCESS) {
1025 return status;
1026 }
1027 }
1028 }
1029 }
1030 if(deviceType == SR1xxT) {
1031 if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_SR1XX_T_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1032 if (retlen > 0) {
1033 vendorConfig = buffer.data();
1034 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1035 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_SR1XX_T_CONFIG, status);
1036 if(status != UWBSTATUS_SUCCESS) {
1037 return status;
1038 }
1039 }
1040 }
1041 } else if(deviceType == SR1xxS) {
1042 if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_SR1XX_S_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1043 if (retlen > 0) {
1044 vendorConfig = buffer.data();
1045 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1046 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_SR1XX_S_CONFIG, status);
1047 if(status != UWBSTATUS_SUCCESS) {
1048 return status;
1049 }
1050 }
1051 }
1052 } else {
1053 NXPLOG_UCIHAL_D("phNxpUciHal_sendGetCoreDeviceInfo deviceType default");
1054 if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_DEFAULT_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1055 if (retlen > 0) {
1056 vendorConfig = buffer.data();
1057 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1058 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_DEFAULT_CONFIG, status);
1059 if(status != UWBSTATUS_SUCCESS) {
1060 return status;
1061 }
1062 }
1063 }
1064 }
1065 }
1066 return status;
1067 }
1068
phNxpUciHal_applyVendorConfig()1069 tHAL_UWB_STATUS phNxpUciHal_applyVendorConfig() {
1070 NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig Enter..");
1071 std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
1072 uint8_t* vendorConfig = NULL;
1073 tHAL_UWB_STATUS status;
1074 buffer.fill(0);
1075 long retlen = 0;
1076
1077 status = phNxpUciHal_sendGetCoreDeviceInfo();
1078 NXPLOG_UCIHAL_D("phNxpUciHal_sendGetCoreDeviceInfo status %d ", status);
1079 if(status != UWBSTATUS_SUCCESS) {
1080 return status;
1081 }
1082
1083 if (GetNxpConfigByteArrayValue(NAME_NXP_UWB_XTAL_38MHZ_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1084 if (retlen > 0) {
1085 vendorConfig = buffer.data();
1086 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1087 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_NXP_UWB_XTAL_38MHZ_CONFIG, status);
1088 if(status != UWBSTATUS_SUCCESS) {
1089 return status;
1090 }
1091 }
1092 }
1093 if (GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXTENDED_NTF_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
1094 if (retlen > 0) {
1095 vendorConfig = buffer.data();
1096 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1097 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_NXP_UWB_EXTENDED_NTF_CONFIG, status);
1098 if(status != UWBSTATUS_SUCCESS) {
1099 return status;
1100 }
1101 }
1102 }
1103 status = phNxpUciHal_sendGetCoreDeviceInfo();
1104 NXPLOG_UCIHAL_D(" phNxpUciHal_sendGetCoreDeviceInfo failed with status %d ", status);
1105 if(status != UWBSTATUS_SUCCESS) {
1106 return status;
1107 }
1108 for(int i = 1;i <= 10;i++) {
1109 std::string str = NAME_NXP_CORE_CONF_BLK;
1110 std::string value = std::to_string(i);
1111 std::string name = str + value;
1112 NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig :: Name of the config block is %s", name.c_str());
1113 if (GetNxpConfigByteArrayValue(name.c_str(), (char*)buffer.data(), buffer.size(), &retlen)) {
1114 if ((retlen > 0) && (retlen <= UCI_MAX_DATA_LEN)) {
1115 vendorConfig = buffer.data();
1116 status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
1117 NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", name.c_str(),status);
1118 if(status != UWBSTATUS_SUCCESS) {
1119 return status;
1120 }
1121 }
1122 }
1123 else {
1124 NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig::%s not available in the config file", name.c_str());
1125 }
1126 }
1127 return UWBSTATUS_SUCCESS;
1128 }
1129
phNxpUciHal_uwb_reset()1130 tHAL_UWB_STATUS phNxpUciHal_uwb_reset() {
1131 tHAL_UWB_STATUS status;
1132 uint8_t buffer[] = {0x20, 0x00, 0x00, 0x01, 0x00};
1133 status = phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
1134 if(status != UWBSTATUS_SUCCESS) {
1135 return status;
1136 }
1137 return UWBSTATUS_SUCCESS;
1138 }
1139
phNxpUciHal_coreInitialization()1140 tHAL_UWB_STATUS phNxpUciHal_coreInitialization() {
1141 tHAL_UWB_STATUS status;
1142 uint8_t fwd_retry_count = 0;
1143 uint8_t dev_ready_ntf[] = {0x60, 0x01, 0x00, 0x01, 0x01};
1144 nxpucihal_ctrl.isRecoveryTimerStarted = false;
1145
1146 if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
1147 NXPLOG_UCIHAL_E("HAL not initialized");
1148 return UWBSTATUS_FAILED;
1149 }
1150
1151 NXPLOG_UCIHAL_D(" Start FW download");
1152 /* Create the local semaphore */
1153 if (phNxpUciHal_init_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait, NULL) !=
1154 UWBSTATUS_SUCCESS) {
1155 NXPLOG_UCIHAL_E("Create dev_status_ntf_wait failed");
1156 return UWBSTATUS_FAILED;
1157 }
1158
1159 if (phNxpUciHal_init_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait, NULL) !=
1160 UWBSTATUS_SUCCESS) {
1161 NXPLOG_UCIHAL_E("Create uwb_binding_status_ntf_wait failed");
1162 return UWBSTATUS_FAILED;
1163 }
1164
1165 nxpucihal_ctrl.fw_dwnld_mode = true; /* system in FW download mode*/
1166 uwb_device_initialized = false;
1167
1168 fwd_retry:
1169 nxpucihal_ctrl.uwbc_device_state = UWB_DEVICE_ERROR;
1170 status = phNxpUciHal_fw_download();
1171 if(status == UWBSTATUS_SUCCESS) {
1172 status = phTmlUwb_Read( Rx_data, UCI_MAX_DATA_LEN,
1173 (pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
1174 if (status != UWBSTATUS_PENDING) {
1175 NXPLOG_UCIHAL_E("read status error status = %x", status);
1176 goto failure;
1177 }
1178 phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
1179 if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
1180 NXPLOG_UCIHAL_E("UWB_DEVICE_INIT dev_status_ntf_wait semaphore timed out");
1181 goto failure;
1182 }
1183 if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_INIT) {
1184 NXPLOG_UCIHAL_E("UWB_DEVICE_INIT not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
1185 goto failure;
1186 }
1187 status = phNxpUciHal_set_board_config();
1188 if (status != UWBSTATUS_SUCCESS) {
1189 NXPLOG_UCIHAL_E("%s: Set Board Config Failed", __func__);
1190 goto failure;
1191 }
1192 phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
1193 if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
1194 NXPLOG_UCIHAL_E("UWB_DEVICE_READY dev_status_ntf_wait semaphore timed out");
1195 goto failure;
1196 }
1197 if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_READY) {
1198 NXPLOG_UCIHAL_E("UWB_DEVICE_READY not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
1199 goto failure;
1200 }
1201 NXPLOG_UCIHAL_D("%s: Send device reset", __func__);
1202 status = phNxpUciHal_uwb_reset();
1203 if (status != UWBSTATUS_SUCCESS) {
1204 NXPLOG_UCIHAL_E("%s: device reset Failed", __func__);
1205 goto failure;
1206 }
1207 phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
1208 if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
1209 NXPLOG_UCIHAL_E("UWB_DEVICE_READY dev_status_ntf_wait semaphore timed out");
1210 goto failure;
1211 }
1212 if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_READY) {
1213 NXPLOG_UCIHAL_E("UWB_DEVICE_READY not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
1214 goto failure;
1215 }
1216 status = phNxpUciHal_applyVendorConfig();
1217 if (status != UWBSTATUS_SUCCESS) {
1218 NXPLOG_UCIHAL_E("%s: Apply vendor Config Failed", __func__);
1219 goto failure;
1220 }
1221
1222 phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
1223 if (nxpucihal_ctrl.uwb_binding_status_ntf_wait.status == UWBSTATUS_SUCCESS) {
1224 NXPLOG_UCIHAL_D("binding status notification received");
1225 } else {
1226 NXPLOG_UCIHAL_D("%s:Binding status notification timeout occured", __func__);
1227 }
1228 uwb_device_initialized = true;
1229 phNxpUciHal_init_complete(UWBSTATUS_SUCCESS);
1230 } else if(status == UWBSTATUS_FILE_NOT_FOUND) {
1231 NXPLOG_UCIHAL_E("FW download File Not found: status= %x", status);
1232 goto failure;
1233 } else {
1234 NXPLOG_UCIHAL_E("FW download is failed FW download recovery starts: status= %x", status);
1235 fwd_retry_count++;
1236 if(fwd_retry_count <= FWD_MAX_RETRY_COUNT) {
1237 phTmlUwb_Chip_Reset();
1238 usleep(5000);
1239 goto fwd_retry;
1240 } else {
1241 goto failure;
1242 }
1243 }
1244 if (nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) {
1245 (*nxpucihal_ctrl.p_uwb_stack_data_cback)((sizeof(dev_ready_ntf)/sizeof(uint8_t)),
1246 dev_ready_ntf);
1247 }
1248 phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait);
1249 phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
1250 return status;
1251 failure:
1252 phNxpUciHal_init_complete(UWBSTATUS_FAILED);
1253 phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait);
1254 phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
1255 return UWBSTATUS_FAILED;
1256 }
1257
phNxpUciHal_sessionInitialization(uint32_t sessionId)1258 tHAL_UWB_STATUS phNxpUciHal_sessionInitialization(uint32_t sessionId) {
1259 NXPLOG_UCIHAL_D(" %s: Enter", __func__);
1260 std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
1261 uint8_t vendorConfig[NXP_MAX_CONFIG_STRING_LEN] = {0x21, 0x03, 0x00};
1262 tHAL_UWB_STATUS status = UWBSTATUS_SUCCESS;
1263 buffer.fill(0);
1264 int max_config_length = NXP_MAX_CONFIG_STRING_LEN - UCI_MSG_HDR_SIZE
1265 - sizeof(sessionId);
1266 long retlen = 0, cmdlen = 0;
1267 bool appConfigStatus = false;
1268
1269 if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
1270 NXPLOG_UCIHAL_E("HAL not initialized");
1271 return UWBSTATUS_FAILED;
1272 }
1273 if(deviceType == SR1xxT) {
1274 appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_SR1XX_T_CONFIG,
1275 (char *)buffer.data(), buffer.size(),
1276 &retlen);
1277 } else if (deviceType == SR1xxS) {
1278 appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_SR1XX_S_CONFIG,
1279 (char *)buffer.data(), buffer.size(),
1280 &retlen);
1281 } else {
1282 appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_DEFAULT_CONFIG,
1283 (char *)buffer.data(), buffer.size(),
1284 &retlen);
1285 }
1286
1287 if (appConfigStatus) {
1288 if ((retlen > 0) && (retlen <= max_config_length)) {
1289 vendorConfig[3] = sizeof(sessionId) + retlen;
1290 memcpy(vendorConfig + 4, &sessionId, sizeof(sessionId));
1291 memcpy(vendorConfig + 8, buffer.data(), retlen);
1292 cmdlen = UCI_MSG_HDR_SIZE + sizeof(sessionId) + retlen;
1293 status = phNxpUciHal_send_ext_cmd(cmdlen, vendorConfig);
1294 if (status != UWBSTATUS_SUCCESS) {
1295 NXPLOG_UCIHAL_D(" %s: Apply vendor App Config Failed", __func__);
1296 return UWBSTATUS_SUCCESS;
1297 }
1298 } else {
1299 NXPLOG_UCIHAL_D(" %s: Invalid retlen", __func__);
1300 return UWBSTATUS_SUCCESS;
1301 }
1302 }
1303 return status;
1304 }
1305
phNxpUciHal_print_response_status(uint8_t * p_rx_data,uint16_t p_len)1306 static void phNxpUciHal_print_response_status(uint8_t* p_rx_data, uint16_t p_len) {
1307 uint8_t mt;
1308 int status_byte;
1309 const uint8_t response_buf[][30] = {"STATUS_OK",
1310 "STATUS_REJECTED",
1311 "STATUS_FAILED",
1312 "STATUS_SYNTAX_ERROR",
1313 "STATUS_INVALID_PARAM",
1314 "STATUS_INVALID_RANGE",
1315 "STATUS_INAVALID_MSG_SIZE",
1316 "STATUS_UNKNOWN_GID",
1317 "STATUS_UNKNOWN_OID",
1318 "STATUS_RFU",
1319 "STATUS_READ_ONLY",
1320 "STATUS_COMMAND_RETRY"};
1321 if(p_len > UCI_PKT_HDR_LEN) {
1322 mt = ((p_rx_data[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
1323 status_byte = p_rx_data[UCI_RESPONSE_STATUS_OFFSET];
1324 if((mt == UCI_MT_RSP) && (status_byte <= MAX_RESPONSE_STATUS)) {
1325 NXPLOG_UCIHAL_D(" %s: Response Status = %s", __func__ , response_buf[status_byte]);
1326 }else{
1327 NXPLOG_UCIHAL_D(" %s: Response Status = %x", __func__ , status_byte);
1328 }
1329 }
1330 }
1331
1332