• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012-2019, 2022-2023 NXP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
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