unplugged-system/hardware/nxp/uwb/halimpl/hal/phNxpUciHal.cc

1332 lines
48 KiB
C++

/*
* Copyright 2012-2019, 2022-2023 NXP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <log/log.h>
#include <phNxpLog.h>
#include <cutils/properties.h>
#include <phNxpUciHal.h>
#include <phNxpUciHal_Adaptation.h>
#include <phNxpUciHal_ext.h>
#include <phTmlUwb_spi.h>
#include <sys/stat.h>
#include <string.h>
#include <array>
#include <map>
#include <vector>
#include "hal_nxpuwb.h"
#include "phNxpConfig.h"
#include <android-base/stringprintf.h>
#include "phNxpUciHal_utils.h"
#if (NXP_UWB_EXTNS == TRUE)
#include "phNxpUciHalProp.h"
#endif
using namespace std;
using android::base::StringPrintf;
map<uint16_t, vector<uint16_t>> input_map;
map<uint16_t, vector<uint16_t>> conf_map;
/*********************** Global Variables *************************************/
/* UCI HAL Control structure */
phNxpUciHal_Control_t nxpucihal_ctrl;
uint8_t *gpCoreDeviceInfoRsp;
/* TML Context */
extern phTmlUwb_Context_t* gpphTmlUwb_Context;
bool uwb_debug_enabled = true;
bool uwb_device_initialized = false;
bool uwb_get_platform_id = false;
uint32_t timeoutTimerId = 0;
char persistant_log_path[120];
static uint8_t Rx_data[UCI_MAX_DATA_LEN];
uint8_t deviceType = '\0';
/**************** local methods used in this file only ************************/
static void phNxpUciHal_open_complete(tHAL_UWB_STATUS status);
static void phNxpUciHal_write_complete(void* pContext,
phTmlUwb_TransactInfo_t* pInfo);
static void phNxpUciHal_close_complete(tHAL_UWB_STATUS status);
static void phNxpUciHal_kill_client_thread(
phNxpUciHal_Control_t* p_nxpucihal_ctrl);
static void* phNxpUciHal_client_thread(void* arg);
extern int phNxpUciHal_fw_download();
static void phNxpUciHal_print_response_status(uint8_t *p_rx_data,
uint16_t p_len);
/*******************************************************************************
* Function get_input_map
*
* Description Creates a map from the USBS CAPS Response with key as Tag and
* value as a vector containing Length and Values of the Tag.
*
* Returns true if the map creation successful
*
*******************************************************************************/
bool get_input_map(const uint8_t* i_data, uint16_t iData_len) {
vector<uint16_t> input_vec;
bool ret = true;
uint16_t i = 0, j = 0, tag = 0, len = 0;
i = UCI_PKT_HDR_LEN + UCI_PKT_PAYLOAD_STATUS_LEN + UCI_PKT_NUM_CAPS_LEN;
if (i_data == NULL) {
NXPLOG_UCIHAL_D("input map creation failed, i_data is NULL" );
return false;
}
while (i < iData_len) {
if (i + 1 >= iData_len) {
ret = false;
break;
}
tag = i_data[i++];
// Tag IDs from 0xE0 to 0xE2 are extended tag IDs with 2 bytes length.
if((tag >= 0xE0) && (tag <= 0xE2)) {
if (i + 1 >= iData_len) {
ret = false;
break;
}
tag = (tag << 8) | i_data[i++];
}
if (i + 1 >= iData_len) {
ret = false;
break;
}
len = i_data[i++];
input_vec.insert(input_vec.begin(), len);
if (i + len > iData_len) {
ret = false;
break;
}
for (j = 1; j <= len; j++) {
input_vec.insert(input_vec.begin() + j, i_data[i++]);
}
input_map[tag] = input_vec;
input_vec.clear();
}
return ret;
}
/*******************************************************************************
* Function get_conf_map
*
* Description Creates a map from the Country code conf with key as Tag and
* value as a vector containing Length and Values of the Tag.
*
* Returns true if the map creation successful
*
*******************************************************************************/
bool get_conf_map(uint8_t* c_data, uint16_t cData_len) {
vector<uint16_t> conf_vec;
bool ret = true;
uint16_t i = 0, j = 0, tag = 0, len = 0;
if (c_data == NULL) {
NXPLOG_UCIHAL_D("Country code conf map creation failed, c_data is NULL" );
return false;
}
while (i < cData_len) {
if (i + 1 >= cData_len) {
ret = false;
break;
}
tag = c_data[i++];
// Tag IDs from 0xE0 to 0xE2 are extended tag IDs with 2 bytes length.
if ((tag >= 0xE0) && (tag <= 0xE2)) {
if (i + 1 >= cData_len) {
ret = false;
break;
}
tag = (tag<<8) | c_data[i++];
}
if (i + 1 >= cData_len) {
ret = false;
break;
}
len = c_data[i++];
conf_vec.insert(conf_vec.begin(),len);
if (i + len > cData_len) {
ret = false;
break;
}
for (j = 1; j <= len; j++) {
conf_vec.insert(conf_vec.begin() + j, c_data[i++]);
}
conf_map[tag] = conf_vec;
conf_vec.clear();
}
return ret;
}
/******************************************************************************
* Function phNxpUciHal_client_thread
*
* Description This function is a thread handler which handles all TML and
* UCI messages.
*
* Returns void
*
******************************************************************************/
static void* phNxpUciHal_client_thread(void* arg) {
phNxpUciHal_Control_t* p_nxpucihal_ctrl = (phNxpUciHal_Control_t*)arg;
phLibUwb_Message_t msg;
NXPLOG_UCIHAL_D("thread started");
p_nxpucihal_ctrl->thread_running = 1;
while (p_nxpucihal_ctrl->thread_running == 1) {
/* Fetch next message from the UWB stack message queue */
if (phDal4Uwb_msgrcv(p_nxpucihal_ctrl->gDrvCfg.nClientId, &msg, 0, 0) ==
-1) {
NXPLOG_UCIHAL_E("UWB client received bad message");
continue;
}
if (p_nxpucihal_ctrl->thread_running == 0) {
break;
}
switch (msg.eMsgType) {
case PH_LIBUWB_DEFERREDCALL_MSG: {
phLibUwb_DeferredCall_t* deferCall =
(phLibUwb_DeferredCall_t*)(msg.pMsgData);
REENTRANCE_LOCK();
deferCall->pCallback(deferCall->pParameter);
REENTRANCE_UNLOCK();
break;
}
case UCI_HAL_OPEN_CPLT_MSG: {
REENTRANCE_LOCK();
if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
/* Send the event */
(*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT,
HAL_UWB_STATUS_OK);
}
REENTRANCE_UNLOCK();
break;
}
case UCI_HAL_CLOSE_CPLT_MSG: {
REENTRANCE_LOCK();
if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
/* Send the event */
(*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_CLOSE_CPLT_EVT,
HAL_UWB_STATUS_OK);
phNxpUciHal_kill_client_thread(&nxpucihal_ctrl);
}
REENTRANCE_UNLOCK();
break;
}
case UCI_HAL_INIT_CPLT_MSG: {
REENTRANCE_LOCK();
if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
/* Send the event */
(*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_INIT_CPLT_EVT,
HAL_UWB_STATUS_OK);
}
REENTRANCE_UNLOCK();
break;
}
case UCI_HAL_ERROR_MSG: {
REENTRANCE_LOCK();
if (nxpucihal_ctrl.p_uwb_stack_cback != NULL) {
/* Send the event */
(*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_ERROR_EVT,
HAL_UWB_ERROR_EVT);
}
REENTRANCE_UNLOCK();
break;
}
}
}
NXPLOG_UCIHAL_D("NxpUciHal thread stopped");
pthread_exit(NULL);
return NULL;
}
/******************************************************************************
* Function phNxpUciHal_kill_client_thread
*
* Description This function safely kill the client thread and clean all
* resources.
*
* Returns void.
*
******************************************************************************/
static void phNxpUciHal_kill_client_thread(
phNxpUciHal_Control_t* p_nxpucihal_ctrl) {
NXPLOG_UCIHAL_D("Terminating phNxpUciHal client thread...");
p_nxpucihal_ctrl->p_uwb_stack_cback = NULL;
p_nxpucihal_ctrl->p_uwb_stack_data_cback = NULL;
p_nxpucihal_ctrl->thread_running = 0;
return;
}
/******************************************************************************
* Function phNxpUciHal_open
*
* Description This function is called by libuwb-uci during the
* initialization of the UWBC. It opens the physical connection
* with UWBC (SRXXX) and creates required client thread for
* operation.
* After open is complete, status is informed to libuwb-uci
* through callback function.
*
* Returns This function return UWBSTATUS_SUCCES (0) in case of success
* In case of failure returns other failure value.
*
******************************************************************************/
tHAL_UWB_STATUS phNxpUciHal_open(uwb_stack_callback_t* p_cback,
uwb_stack_data_callback_t* p_data_cback) {
phOsalUwb_Config_t tOsalConfig;
phTmlUwb_Config_t tTmlConfig;
char* uwb_dev_node = NULL;
const uint16_t max_len = 260;
tHAL_UWB_STATUS wConfigStatus = UWBSTATUS_SUCCESS;
pthread_attr_t attr;
if (nxpucihal_ctrl.halStatus == HAL_STATUS_OPEN) {
NXPLOG_UCIHAL_E("phNxpUciHal_open already open");
return UWBSTATUS_SUCCESS;
}
/* initialize trace level */
phNxpLog_InitializeLogLevel();
/*Create the timer for extns write response*/
timeoutTimerId = phOsalUwb_Timer_Create();
if (phNxpUciHal_init_monitor() == NULL) {
NXPLOG_UCIHAL_E("Init monitor failed");
return UWBSTATUS_FAILED;
}
CONCURRENCY_LOCK();
memset(&nxpucihal_ctrl, 0x00, sizeof(nxpucihal_ctrl));
memset(&tOsalConfig, 0x00, sizeof(tOsalConfig));
memset(&tTmlConfig, 0x00, sizeof(tTmlConfig));
uwb_dev_node = (char*)nxp_malloc(max_len * sizeof(char));
if (uwb_dev_node == NULL) {
NXPLOG_UCIHAL_E("malloc of uwb_dev_node failed ");
goto clean_and_return;
}
if (!GetNxpConfigStrValue(NAME_NXP_UWB_DEVICE_NODE, uwb_dev_node, max_len)) {
strcpy(uwb_dev_node, "/dev/srxxx");
}
NXPLOG_UCIHAL_E("Assigning the helios Node: %s", uwb_dev_node);
/* By default HAL status is HAL_STATUS_OPEN */
nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
nxpucihal_ctrl.p_uwb_stack_cback = p_cback;
nxpucihal_ctrl.p_uwb_stack_data_cback = p_data_cback;
nxpucihal_ctrl.fw_dwnld_mode = false;
#if(NXP_UWB_EXTNS == TRUE)
phNxpUciPropHal_initialize();
#endif
/* Configure hardware link */
nxpucihal_ctrl.gDrvCfg.nClientId = phDal4Uwb_msgget(0, 0600);
nxpucihal_ctrl.gDrvCfg.nLinkType = ENUM_LINK_TYPE_SPI;
tTmlConfig.pDevName = (int8_t*)uwb_dev_node;
tOsalConfig.dwCallbackThreadId = (uintptr_t)nxpucihal_ctrl.gDrvCfg.nClientId;
tOsalConfig.pLogFile = NULL;
tTmlConfig.dwGetMsgThreadId = (uintptr_t)nxpucihal_ctrl.gDrvCfg.nClientId;
/* Initialize TML layer */
wConfigStatus = phTmlUwb_Init(&tTmlConfig);
if (wConfigStatus != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("phTmlUwb_Init Failed");
goto clean_and_return;
} else {
if (uwb_dev_node != NULL) {
free(uwb_dev_node);
uwb_dev_node = NULL;
}
}
/* Create the client thread */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&nxpucihal_ctrl.client_thread, &attr,
phNxpUciHal_client_thread, &nxpucihal_ctrl) != 0) {
NXPLOG_UCIHAL_E("pthread_create failed");
wConfigStatus = phTmlUwb_Shutdown();
goto clean_and_return;
}
CONCURRENCY_UNLOCK();
#if 0
/* call read pending */
status = phTmlUwb_Read(
nxpucihal_ctrl.p_cmd_data, UCI_MAX_DATA_LEN,
(pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
if (status != UWBSTATUS_PENDING) {
NXPLOG_UCIHAL_E("TML Read status error status = %x", status);
wConfigStatus = phTmlUwb_Shutdown();
wConfigStatus = UWBSTATUS_FAILED;
goto clean_and_return;
}
#endif
pthread_attr_destroy(&attr);
/* Call open complete */
phNxpUciHal_open_complete(wConfigStatus);
return wConfigStatus;
clean_and_return:
CONCURRENCY_UNLOCK();
if (uwb_dev_node != NULL) {
free(uwb_dev_node);
uwb_dev_node = NULL;
}
/* Report error status */
(*nxpucihal_ctrl.p_uwb_stack_cback)(HAL_UWB_OPEN_CPLT_EVT, HAL_UWB_ERROR_EVT);
nxpucihal_ctrl.p_uwb_stack_cback = NULL;
nxpucihal_ctrl.p_uwb_stack_data_cback = NULL;
phNxpUciHal_cleanup_monitor();
nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
pthread_attr_destroy(&attr);
return wConfigStatus;
}
/******************************************************************************
* Function phNxpUciHal_open_complete
*
* Description This function inform the status of phNxpUciHal_open
* function to libuwb-uci.
*
* Returns void.
*
******************************************************************************/
static void phNxpUciHal_open_complete(tHAL_UWB_STATUS status) {
static phLibUwb_Message_t msg;
if (status == UWBSTATUS_SUCCESS) {
msg.eMsgType = UCI_HAL_OPEN_CPLT_MSG;
nxpucihal_ctrl.hal_open_status = true;
nxpucihal_ctrl.halStatus = HAL_STATUS_OPEN;
} else {
msg.eMsgType = UCI_HAL_ERROR_MSG;
}
msg.pMsgData = NULL;
msg.Size = 0;
phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId,
(phLibUwb_Message_t*)&msg);
return;
}
/******************************************************************************
* Function phNxpUciHal_write
*
* Description This function write the data to UWBC through physical
* interface (e.g. SPI) using the driver interface.
* Before sending the data to UWBC, phNxpUciHal_write_ext
* is called to check if there is any extension processing
* is required for the UCI packet being sent out.
*
* Returns It returns number of bytes successfully written to UWBC.
*
******************************************************************************/
tHAL_UWB_STATUS phNxpUciHal_write(uint16_t data_len, const uint8_t* p_data) {
if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
return UWBSTATUS_FAILED;
}
CONCURRENCY_LOCK();
uint16_t len = phNxpUciHal_write_unlocked(data_len, p_data);
CONCURRENCY_UNLOCK();
/* No data written */
return len;
}
/******************************************************************************
* Function phNxpUciHal_parse_get_capsInfo
*
* Description This function parses all the data passing through the HAL.
*
* Returns It returns true if the incoming command to be skipped.
*
******************************************************************************/
void phNxpUciHal_parse_get_capsInfo(uint16_t data_len, uint8_t* p_data) {
uint8_t *p = p_data;
uint8_t pDeviceCapsInfo[UCI_MAX_DATA_LEN];
uint8_t * pp = pDeviceCapsInfo;
uint8_t tagId=0, subTagId=0, len =0;
uint8_t mt = 0, gid = 0, oid = 0;
uint8_t capsLen = p_data[5];
uint8_t dataLen = p_data[3];
mt = (*(p_data) & UCI_MT_MASK) >> UCI_MT_SHIFT;
gid = p_data[0] & UCI_GID_MASK;
oid = p_data[1] & UCI_OID_MASK;
uint8_t *p_caps_value;
if (mt == UCI_MT_RSP) {
if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_GET_CAPS_INFO)) {
if (p_data[4] == 0) {
for (uint16_t index = 6; index < data_len;) {
tagId = p_data[index++];
if (tagId != 0xE0)
{
len = p_data[index++];
p_caps_value = (uint8_t *)(p_data + index);
UINT8_TO_STREAM(pp, tagId);
UINT8_TO_STREAM(pp, len);
ARRAY_TO_STREAM(pp, p_caps_value, len);
index = index + len;
} else { //ignore vendor specific data
subTagId = p_data[index++];
len = p_data[index++];
index = index + len;
capsLen--;
dataLen = dataLen - (len + 3);// from datalen substract tagId, subTagId, len and value of config
}
}
// mapping device caps according to Fira 2.0
// TODO: Removed once FW support available
uint8_t fira_2_cap_info[] = { 0xA7, 0x04, 0x00, 0x00, 0x00, 0x00,
0xE3, 0x01, 0x00,
0xE4, 0x01, 0x00,
0xE5, 0x01, 0x00,
0xE6, 0x01, 0x00,
0xE7, 0x01, 0x00};
size_t fira_2_cap_info_len = sizeof(fira_2_cap_info)/sizeof(uint8_t);
ARRAY_TO_STREAM(pp, fira_2_cap_info, fira_2_cap_info_len)
dataLen += fira_2_cap_info_len;
nxpucihal_ctrl.rx_data_len = UCI_MSG_HDR_SIZE + dataLen;
UCI_MSG_BLD_HDR0(p, UCI_MT_RSP, UCI_GID_CORE);
UCI_MSG_BLD_HDR1(p, UCI_MSG_CORE_GET_CAPS_INFO);
UINT8_TO_STREAM(p, 0x00);
UINT8_TO_STREAM(p, dataLen);
UINT8_TO_STREAM(p, 0x00); //status
UINT8_TO_STREAM(p, (capsLen + 6));
ARRAY_TO_STREAM(p, pDeviceCapsInfo, dataLen);
}
}
}
}
/******************************************************************************
* Function phNxpUciHal_parse
*
* Description This function parses all the data passing through the HAL.
*
* Returns It returns true if the incoming command to be skipped.
*
******************************************************************************/
bool phNxpUciHal_parse(uint16_t data_len, const uint8_t* p_data) {
uint8_t mt = 0, gid = 0, oid = 0;
uint16_t arrLen = 0, tag = 0,idx = 0;
char country_code[2];
long retlen = 0;
bool ret = false;
static bool isCountryCodeMapCreated = false;
map<uint16_t, vector<uint16_t>>::iterator itr;
vector<uint16_t>::iterator v_itr;
mt = (*(p_data) & UCI_MT_MASK) >> UCI_MT_SHIFT;
gid = p_data[0] & UCI_GID_MASK;
oid = p_data[1] & UCI_OID_MASK;
if ( mt == UCI_MT_CMD) {
if ((gid == UCI_GID_ANDROID) && (oid == UCI_MSG_ANDROID_SET_COUNTRY_CODE)) {
country_code[0] = (char) p_data[4];
country_code[1] = (char) p_data[5];
if ((country_code[0] == '0') && (country_code[1] == '0')) {
NXPLOG_UCIHAL_D("Country code %s is Invalid!",country_code);
} else {
//Read config file based on the country code
if (GetNxpConfigCountryCodeByteArrayValue(NAME_NXP_COUNTRY_CODE_CONFIG, country_code, (char*)nxpucihal_ctrl.p_caps_resp,UCI_MAX_DATA_LEN, &retlen) == 1) {
NXPLOG_UCIHAL_D("Country code conf loaded , Country %s", country_code );
if (get_conf_map(nxpucihal_ctrl.p_caps_resp, retlen)) {
isCountryCodeMapCreated = true;
} else {
NXPLOG_UCIHAL_D("Country code conf map creation failed" );
}
} else {
NXPLOG_UCIHAL_D("Country code conf is empty!");
}
}
// send country code response to upper layer
nxpucihal_ctrl.rx_data_len = 5;
static uint8_t rsp_data[5];
rsp_data[0] = 0x4c;
rsp_data[1] = 0x01;
rsp_data[2] = 0x00;
rsp_data[3] = 0x01;
rsp_data[4] = 0x00; // Response Success
ret = true;
(*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len, rsp_data);
}
} else if (mt == UCI_MT_RSP) {
if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_GET_CAPS_INFO)) {
// do not modify caps if the country code is not recieved from upper layer.
if (isCountryCodeMapCreated == false) {
return false;
}
// Check UWBS Caps response status
if (p_data[4] == 0) {
if (get_input_map(p_data,data_len)) {
NXPLOG_UCIHAL_D("Input Map created");
} else {
NXPLOG_UCIHAL_D("Input Map creation failed");
return false;
}
} else {
return false;
}
//Compare the maps for Tags and modify input map if Values are different
for (itr = input_map.begin(); itr != input_map.end(); ++itr) {
tag = itr->first;
// Check for the Tag in both maps
if ((conf_map.count(tag)) == 1) {
if (tag == UWB_CHANNELS) {
NXPLOG_UCIHAL_D("Tag = 0x%02X , modify UWB_CHANNELS based on country conf ", tag);
for (int j = 0; j < (itr -> second).size(); j++) {
(input_map[tag])[j] = ((conf_map[tag])[j]) & ((input_map[tag])[j]);
}
}
} else {
// TAG not found do nothing
}
}
//convert the modified input map to p_caps_resp array
memset(nxpucihal_ctrl.p_caps_resp,0,UCI_MAX_DATA_LEN);
//Header information from Input array is updated in initial bytes
nxpucihal_ctrl.p_caps_resp[0] = p_data[0];
nxpucihal_ctrl.p_caps_resp[1] = p_data[1];
nxpucihal_ctrl.p_caps_resp[2] = p_data[2];
nxpucihal_ctrl.p_caps_resp[4] = p_data[4];
idx = UCI_PKT_HDR_LEN + UCI_PKT_PAYLOAD_STATUS_LEN + UCI_PKT_NUM_CAPS_LEN;
for (itr = input_map.begin(); itr != input_map.end(); ++itr) {
tag = itr->first;
//If Tag is 0xE0 or 0xE1 or 0xE2,Tag will be of 2 bytes
if (((tag >> 8) >= 0xE0) && ((tag >> 8) <= 0xE2)) {
nxpucihal_ctrl.p_caps_resp[idx++] = (tag & 0xFF00) >> 8;
nxpucihal_ctrl.p_caps_resp[idx++] = (tag & 0x00FF);
} else {
nxpucihal_ctrl.p_caps_resp[idx++] = tag;
}
for (v_itr = itr->second.begin(); v_itr != itr->second.end(); ++v_itr) {
nxpucihal_ctrl.p_caps_resp[idx++] = (*v_itr);
}
}
arrLen = idx;
// exclude the initial header data
nxpucihal_ctrl.p_caps_resp[3] = arrLen - UCI_PKT_HDR_LEN;
// update the number of parameter TLVs.
nxpucihal_ctrl.p_caps_resp[5] = input_map.size();
// send GET CAPS INFO response to the Upper Layer
(*nxpucihal_ctrl.p_uwb_stack_data_cback)(arrLen, nxpucihal_ctrl.p_caps_resp);
// skip the incoming packet as we have send the modified response already
nxpucihal_ctrl.isSkipPacket = 1;
ret = false;
}
} else {
ret = false;
}
return ret;
}
/******************************************************************************
* Function phNxpUciHal_write_unlocked
*
* Description This is the actual function which is being called by
* phNxpUciHal_write. This function writes the data to UWBC.
* It waits till write callback provide the result of write
* process.
*
* Returns It returns number of bytes successfully written to UWBC.
*
******************************************************************************/
tHAL_UWB_STATUS phNxpUciHal_write_unlocked(uint16_t data_len, const uint8_t* p_data) {
tHAL_UWB_STATUS status;
uint8_t mt, pbf, gid, oid;
phNxpUciHal_Sem_t cb_data;
bool ret_ = false;
/* Create the local semaphore */
if (phNxpUciHal_init_cb_data(&cb_data, NULL) != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_D("phNxpUciHal_write_unlocked Create cb data failed");
data_len = 0;
goto clean_and_return;
}
if ((data_len > UCI_MAX_DATA_LEN) || (data_len < UCI_PKT_HDR_LEN)) {
NXPLOG_UCIHAL_E("Invalid data_len");
data_len = 0;
goto clean_and_return;
}
/* Create local copy of cmd_data */
memcpy(nxpucihal_ctrl.p_cmd_data, p_data, data_len);
nxpucihal_ctrl.cmd_len = data_len;
data_len = nxpucihal_ctrl.cmd_len;
UCI_MSG_PRS_HDR0(p_data, mt, pbf, gid);
UCI_MSG_PRS_HDR1(p_data, oid);
/* Vendor Specific Parsing logic */
ret_ = phNxpUciHal_parse(nxpucihal_ctrl.cmd_len,nxpucihal_ctrl.p_cmd_data);
if (ret_) {
goto clean_and_return;
}
status = phTmlUwb_Write(
(uint8_t*)nxpucihal_ctrl.p_cmd_data, (uint16_t)nxpucihal_ctrl.cmd_len,
(pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_write_complete,
(void*)&cb_data);
if (status != UWBSTATUS_PENDING) {
NXPLOG_UCIHAL_E("write_unlocked status error");
data_len = 0;
goto clean_and_return;
}
/* Wait for callback response */
if (SEM_WAIT(cb_data)) {
NXPLOG_UCIHAL_E("write_unlocked semaphore error");
data_len = 0;
goto clean_and_return;
}
clean_and_return:
phNxpUciHal_cleanup_cb_data(&cb_data);
return data_len;
}
/******************************************************************************
* Function phNxpUciHal_write_complete
*
* Description This function handles write callback.
*
* Returns void.
*
******************************************************************************/
static void phNxpUciHal_write_complete(void* pContext,
phTmlUwb_TransactInfo_t* pInfo) {
phNxpUciHal_Sem_t* p_cb_data = (phNxpUciHal_Sem_t*)pContext;
if (pInfo->wStatus == UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_D("write successful status = 0x%x", pInfo->wStatus);
} else {
NXPLOG_UCIHAL_E("write error status = 0x%x", pInfo->wStatus);
}
p_cb_data->status = pInfo->wStatus;
SEM_POST(p_cb_data);
return;
}
/******************************************************************************
* Function phNxpUciHal_read_complete
*
* Description This function is called whenever there is an UCI packet
* received from UWBC. It could be RSP or NTF packet. This
* function provide the received UCI packet to libuwb-uci
* using data callback of libuwb-uci.
* There is a pending read called from each
* phNxpUciHal_read_complete so each a packet received from
* UWBC can be provide to libuwb-uci.
*
* Returns void.
*
******************************************************************************/
void phNxpUciHal_read_complete(void* pContext,
phTmlUwb_TransactInfo_t* pInfo) {
tHAL_UWB_STATUS status;
uint8_t gid = 0, oid = 0, pbf = 0;
UNUSED(pContext);
if (nxpucihal_ctrl.read_retry_cnt == 1) {
nxpucihal_ctrl.read_retry_cnt = 0;
}
if (pInfo->wStatus == UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_D("read successful status = 0x%x", pInfo->wStatus);
nxpucihal_ctrl.p_rx_data = pInfo->pBuff;
nxpucihal_ctrl.rx_data_len = pInfo->wLength;
gid = nxpucihal_ctrl.p_rx_data[0] & UCI_GID_MASK;
oid = nxpucihal_ctrl.p_rx_data[1] & UCI_OID_MASK;
pbf = (nxpucihal_ctrl.p_rx_data[0] & UCI_PBF_MASK) >> UCI_PBF_SHIFT;
nxpucihal_ctrl.isSkipPacket = 0;
phNxpUciHal_parse_get_capsInfo(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
phNxpUciHal_parse(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
#if(NXP_UWB_EXTNS == TRUE)
phNxpUciPropHal_process_response();
#endif
if(!uwb_device_initialized) {
if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_STATUS_NTF)) {
nxpucihal_ctrl.uwbc_device_state = nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET];
if(nxpucihal_ctrl.uwbc_device_state == UWB_DEVICE_INIT || nxpucihal_ctrl.uwbc_device_state == UWB_DEVICE_READY) {
nxpucihal_ctrl.isSkipPacket = 1;
SEM_POST(&(nxpucihal_ctrl.dev_status_ntf_wait));
}
}
}
if (nxpucihal_ctrl.hal_ext_enabled == 1){
if((nxpucihal_ctrl.p_rx_data[0x00] & 0xF0) == 0x40){
nxpucihal_ctrl.isSkipPacket = 1;
if(nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET] == UCI_STATUS_OK){
nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_SUCCESS;
if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_INFO)) {
gpCoreDeviceInfoRsp = (uint8_t*)malloc(sizeof(uint8_t) * nxpucihal_ctrl.rx_data_len);
if(gpCoreDeviceInfoRsp != NULL) {
memcpy(&gpCoreDeviceInfoRsp[0], &nxpucihal_ctrl.p_rx_data[0], nxpucihal_ctrl.rx_data_len);
}
}
} else if ((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_SET_CONFIG)){
NXPLOG_UCIHAL_E(" status = 0x%x",nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET]);
/* check if any configurations are not supported then ignore the UWBSTATUS_FEATURE_NOT_SUPPORTED stastus code*/
nxpucihal_ctrl.ext_cb_data.status = phNxpUciHal_process_ext_rsp(nxpucihal_ctrl.rx_data_len, nxpucihal_ctrl.p_rx_data);
} else {
nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_FAILED;
NXPLOG_UCIHAL_E("command failed! status = 0x%x",nxpucihal_ctrl.p_rx_data[UCI_RESPONSE_STATUS_OFFSET]);
}
usleep(1);
SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
} else if(gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GENERIC_ERROR_NTF && nxpucihal_ctrl.p_rx_data[4] == UCI_STATUS_COMMAND_RETRY){
nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_COMMAND_RETRANSMIT;
SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
} else if (gid == UCI_GID_CORE && oid == UCI_MSG_CORE_GENERIC_ERROR_NTF && nxpucihal_ctrl.p_rx_data[4] == UCI_STATUS_INVALID_MSG_SIZE){
nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_INVALID_COMMAND_LENGTH;
SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
nxpucihal_ctrl.isSkipPacket = 1;
}
}
/* if Debug Notification, then skip sending to application */
if(nxpucihal_ctrl.isSkipPacket == 0) {
phNxpUciHal_print_response_status(nxpucihal_ctrl.p_rx_data, nxpucihal_ctrl.rx_data_len);
/* Read successful, send the event to higher layer */
if ((nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) && (nxpucihal_ctrl.rx_data_len <= UCI_MAX_PAYLOAD_LEN)) {
(*nxpucihal_ctrl.p_uwb_stack_data_cback)(nxpucihal_ctrl.rx_data_len,
nxpucihal_ctrl.p_rx_data);
}
}
} else {
NXPLOG_UCIHAL_E("read error status = 0x%x", pInfo->wStatus);
}
if (nxpucihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
return;
}
/* Disable junk data check for each UCI packet*/
if(nxpucihal_ctrl.fw_dwnld_mode) {
if((gid == UCI_GID_CORE) && (oid == UCI_MSG_CORE_DEVICE_STATUS_NTF)){
nxpucihal_ctrl.fw_dwnld_mode = false;
}
}
/* Read again because read must be pending always.*/
status = phTmlUwb_Read(
Rx_data, UCI_MAX_DATA_LEN,
(pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
if (status != UWBSTATUS_PENDING) {
NXPLOG_UCIHAL_E("read status error status = %x", status);
/* TODO: Not sure how to handle this ? */
}
return;
}
/******************************************************************************
* Function phNxpUciHal_close
*
* Description This function close the UWBC interface and free all
* resources.This is called by libuwb-uci on UWB service stop.
*
* Returns Always return UWBSTATUS_SUCCESS (0).
*
******************************************************************************/
tHAL_UWB_STATUS phNxpUciHal_close() {
tHAL_UWB_STATUS status;
if (nxpucihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
NXPLOG_UCIHAL_E("phNxpUciHal_close is already closed, ignoring close");
return UWBSTATUS_FAILED;
}
#if(NXP_UWB_EXTNS == TRUE)
phNxpUciPropHal_deinitialize();
#endif
uwb_device_initialized = false;
CONCURRENCY_LOCK();
nxpucihal_ctrl.halStatus = HAL_STATUS_CLOSE;
if (NULL != gpphTmlUwb_Context->pDevHandle) {
phNxpUciHal_close_complete(UWBSTATUS_SUCCESS);
/* Abort any pending read and write */
status = phTmlUwb_ReadAbort();
status = phTmlUwb_WriteAbort();
phOsalUwb_Timer_Cleanup();
status = phTmlUwb_Shutdown();
phDal4Uwb_msgrelease(nxpucihal_ctrl.gDrvCfg.nClientId);
memset(&nxpucihal_ctrl, 0x00, sizeof(nxpucihal_ctrl));
NXPLOG_UCIHAL_D("phNxpUciHal_close - phOsalUwb_DeInit completed");
}
CONCURRENCY_UNLOCK();
phNxpUciHal_cleanup_monitor();
/* Return success always */
return UWBSTATUS_SUCCESS;
}
/******************************************************************************
* Function phNxpUciHal_close_complete
*
* Description This function inform libuwb-uci about result of
* phNxpUciHal_close.
*
* Returns void.
*
******************************************************************************/
void phNxpUciHal_close_complete(tHAL_UWB_STATUS status) {
static phLibUwb_Message_t msg;
if (status == UWBSTATUS_SUCCESS) {
msg.eMsgType = UCI_HAL_CLOSE_CPLT_MSG;
} else {
msg.eMsgType = UCI_HAL_ERROR_MSG;
}
msg.pMsgData = NULL;
msg.Size = 0;
phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &msg);
return;
}
/******************************************************************************
* Function phNxpUciHal_init_complete
*
* Description This function inform libuwb-uci about result of
* phNxpUciHal_coreInitialization.
*
* Returns void.
*
******************************************************************************/
void phNxpUciHal_init_complete(tHAL_UWB_STATUS status) {
static phLibUwb_Message_t msg;
if (status == UWBSTATUS_SUCCESS) {
msg.eMsgType = UCI_HAL_INIT_CPLT_MSG;
} else {
msg.eMsgType = UCI_HAL_ERROR_MSG;
}
msg.pMsgData = NULL;
msg.Size = 0;
phTmlUwb_DeferredCall(gpphTmlUwb_Context->dwCallbackThreadId, &msg);
return;
}
/******************************************************************************
* Function phNxpUciHal_parseCoreDeviceInfoRsp
*
* Description This function parse Core device Info response.
*
* Returns void.
*
******************************************************************************/
static void phNxpUciHal_parseCoreDeviceInfoRsp(uint8_t *fwBootMode, uint8_t *device) {
NXPLOG_UCIHAL_D("phNxpUciHal_parseCoreDeviceInfoRsp Enter..");
uint8_t index = 13; // Excluding the header and Versions
uint8_t paramId = 0;
uint8_t length = 0;
if(fwBootMode == NULL || gpCoreDeviceInfoRsp == NULL){
return;
}
uint8_t len = gpCoreDeviceInfoRsp[index++];
while(index < len) {
uint8_t extParamId = gpCoreDeviceInfoRsp[index++];
paramId = gpCoreDeviceInfoRsp[index++];
length = gpCoreDeviceInfoRsp[index++];
if((extParamId == EXT_CONFIG_TAG_ID) && (paramId == FW_BOOT_MODE_PARAM_ID)){
*fwBootMode = gpCoreDeviceInfoRsp[index];
break;
}
if ((extParamId == EXT_CONFIG_TAG_ID) && (paramId == 0x00)) {
*device = gpCoreDeviceInfoRsp[index + 5];
NXPLOG_UCIHAL_D("phNxpUciHal_parseCoreDeviceInfoRsp DeviceType %c", *device);
}
index = index + length;
}
free(gpCoreDeviceInfoRsp);
return;
}
/******************************************************************************
* Function phNxpUciHal_sendGetCoreDeviceInfo
*
* Description This function send Core device Info command.
*
* Returns status.
*
******************************************************************************/
uint8_t phNxpUciHal_sendGetCoreDeviceInfo(){
std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
uint8_t* vendorConfig = NULL;
long retlen = 0;
buffer.fill(0);
const uint8_t getCoreDeviceInfoConfig[] = {0x20, 0x02, 0x00, 0x00};
uint8_t fwBootMode = 0;
uint8_t getCoreDeviceInfoCmdLen = 4;
tHAL_UWB_STATUS status = phNxpUciHal_send_ext_cmd(getCoreDeviceInfoCmdLen, getCoreDeviceInfoConfig);
if(status != UWBSTATUS_SUCCESS) {
return status;
} else {
phNxpUciHal_parseCoreDeviceInfoRsp(&fwBootMode, &deviceType);
if(fwBootMode == USER_FW_BOOT_MODE) {
if (GetNxpConfigByteArrayValue(NAME_UWB_USER_FW_BOOT_MODE_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if ((retlen > 0) && (retlen <= UCI_MAX_DATA_LEN)) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_USER_FW_BOOT_MODE_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
}
if(deviceType == SR1xxT) {
if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_SR1XX_T_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if (retlen > 0) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_SR1XX_T_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
} else if(deviceType == SR1xxS) {
if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_SR1XX_S_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if (retlen > 0) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_SR1XX_S_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
} else {
NXPLOG_UCIHAL_D("phNxpUciHal_sendGetCoreDeviceInfo deviceType default");
if (GetNxpConfigByteArrayValue(NAME_UWB_CORE_EXT_DEVICE_DEFAULT_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if (retlen > 0) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_UWB_CORE_EXT_DEVICE_DEFAULT_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
}
}
return status;
}
tHAL_UWB_STATUS phNxpUciHal_applyVendorConfig() {
NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig Enter..");
std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
uint8_t* vendorConfig = NULL;
tHAL_UWB_STATUS status;
buffer.fill(0);
long retlen = 0;
status = phNxpUciHal_sendGetCoreDeviceInfo();
NXPLOG_UCIHAL_D("phNxpUciHal_sendGetCoreDeviceInfo status %d ", status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
if (GetNxpConfigByteArrayValue(NAME_NXP_UWB_XTAL_38MHZ_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if (retlen > 0) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_NXP_UWB_XTAL_38MHZ_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
if (GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXTENDED_NTF_CONFIG, (char*)buffer.data(), buffer.size(), &retlen)) {
if (retlen > 0) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", NAME_NXP_UWB_EXTENDED_NTF_CONFIG, status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
status = phNxpUciHal_sendGetCoreDeviceInfo();
NXPLOG_UCIHAL_D(" phNxpUciHal_sendGetCoreDeviceInfo failed with status %d ", status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
for(int i = 1;i <= 10;i++) {
std::string str = NAME_NXP_CORE_CONF_BLK;
std::string value = std::to_string(i);
std::string name = str + value;
NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig :: Name of the config block is %s", name.c_str());
if (GetNxpConfigByteArrayValue(name.c_str(), (char*)buffer.data(), buffer.size(), &retlen)) {
if ((retlen > 0) && (retlen <= UCI_MAX_DATA_LEN)) {
vendorConfig = buffer.data();
status = phNxpUciHal_send_ext_cmd(retlen,vendorConfig);
NXPLOG_UCIHAL_D(" phNxpUciHal_send_ext_cmd :: status value for %s is %d ", name.c_str(),status);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
}
}
else {
NXPLOG_UCIHAL_D(" phNxpUciHal_applyVendorConfig::%s not available in the config file", name.c_str());
}
}
return UWBSTATUS_SUCCESS;
}
tHAL_UWB_STATUS phNxpUciHal_uwb_reset() {
tHAL_UWB_STATUS status;
uint8_t buffer[] = {0x20, 0x00, 0x00, 0x01, 0x00};
status = phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
if(status != UWBSTATUS_SUCCESS) {
return status;
}
return UWBSTATUS_SUCCESS;
}
tHAL_UWB_STATUS phNxpUciHal_coreInitialization() {
tHAL_UWB_STATUS status;
uint8_t fwd_retry_count = 0;
uint8_t dev_ready_ntf[] = {0x60, 0x01, 0x00, 0x01, 0x01};
nxpucihal_ctrl.isRecoveryTimerStarted = false;
if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
NXPLOG_UCIHAL_E("HAL not initialized");
return UWBSTATUS_FAILED;
}
NXPLOG_UCIHAL_D(" Start FW download");
/* Create the local semaphore */
if (phNxpUciHal_init_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait, NULL) !=
UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("Create dev_status_ntf_wait failed");
return UWBSTATUS_FAILED;
}
if (phNxpUciHal_init_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait, NULL) !=
UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("Create uwb_binding_status_ntf_wait failed");
return UWBSTATUS_FAILED;
}
nxpucihal_ctrl.fw_dwnld_mode = true; /* system in FW download mode*/
uwb_device_initialized = false;
fwd_retry:
nxpucihal_ctrl.uwbc_device_state = UWB_DEVICE_ERROR;
status = phNxpUciHal_fw_download();
if(status == UWBSTATUS_SUCCESS) {
status = phTmlUwb_Read( Rx_data, UCI_MAX_DATA_LEN,
(pphTmlUwb_TransactCompletionCb_t)&phNxpUciHal_read_complete, NULL);
if (status != UWBSTATUS_PENDING) {
NXPLOG_UCIHAL_E("read status error status = %x", status);
goto failure;
}
phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("UWB_DEVICE_INIT dev_status_ntf_wait semaphore timed out");
goto failure;
}
if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_INIT) {
NXPLOG_UCIHAL_E("UWB_DEVICE_INIT not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
goto failure;
}
status = phNxpUciHal_set_board_config();
if (status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("%s: Set Board Config Failed", __func__);
goto failure;
}
phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("UWB_DEVICE_READY dev_status_ntf_wait semaphore timed out");
goto failure;
}
if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_READY) {
NXPLOG_UCIHAL_E("UWB_DEVICE_READY not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
goto failure;
}
NXPLOG_UCIHAL_D("%s: Send device reset", __func__);
status = phNxpUciHal_uwb_reset();
if (status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("%s: device reset Failed", __func__);
goto failure;
}
phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.dev_status_ntf_wait);
if (nxpucihal_ctrl.dev_status_ntf_wait.status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("UWB_DEVICE_READY dev_status_ntf_wait semaphore timed out");
goto failure;
}
if(nxpucihal_ctrl.uwbc_device_state != UWB_DEVICE_READY) {
NXPLOG_UCIHAL_E("UWB_DEVICE_READY not received uwbc_device_state = %x",nxpucihal_ctrl.uwbc_device_state);
goto failure;
}
status = phNxpUciHal_applyVendorConfig();
if (status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_E("%s: Apply vendor Config Failed", __func__);
goto failure;
}
phNxpUciHal_sem_timed_wait(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
if (nxpucihal_ctrl.uwb_binding_status_ntf_wait.status == UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_D("binding status notification received");
} else {
NXPLOG_UCIHAL_D("%s:Binding status notification timeout occured", __func__);
}
uwb_device_initialized = true;
phNxpUciHal_init_complete(UWBSTATUS_SUCCESS);
} else if(status == UWBSTATUS_FILE_NOT_FOUND) {
NXPLOG_UCIHAL_E("FW download File Not found: status= %x", status);
goto failure;
} else {
NXPLOG_UCIHAL_E("FW download is failed FW download recovery starts: status= %x", status);
fwd_retry_count++;
if(fwd_retry_count <= FWD_MAX_RETRY_COUNT) {
phTmlUwb_Chip_Reset();
usleep(5000);
goto fwd_retry;
} else {
goto failure;
}
}
if (nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) {
(*nxpucihal_ctrl.p_uwb_stack_data_cback)((sizeof(dev_ready_ntf)/sizeof(uint8_t)),
dev_ready_ntf);
}
phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait);
phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
return status;
failure:
phNxpUciHal_init_complete(UWBSTATUS_FAILED);
phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.dev_status_ntf_wait);
phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.uwb_binding_status_ntf_wait);
return UWBSTATUS_FAILED;
}
tHAL_UWB_STATUS phNxpUciHal_sessionInitialization(uint32_t sessionId) {
NXPLOG_UCIHAL_D(" %s: Enter", __func__);
std::array<uint8_t, NXP_MAX_CONFIG_STRING_LEN> buffer;
uint8_t vendorConfig[NXP_MAX_CONFIG_STRING_LEN] = {0x21, 0x03, 0x00};
tHAL_UWB_STATUS status = UWBSTATUS_SUCCESS;
buffer.fill(0);
int max_config_length = NXP_MAX_CONFIG_STRING_LEN - UCI_MSG_HDR_SIZE
- sizeof(sessionId);
long retlen = 0, cmdlen = 0;
bool appConfigStatus = false;
if (nxpucihal_ctrl.halStatus != HAL_STATUS_OPEN) {
NXPLOG_UCIHAL_E("HAL not initialized");
return UWBSTATUS_FAILED;
}
if(deviceType == SR1xxT) {
appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_SR1XX_T_CONFIG,
(char *)buffer.data(), buffer.size(),
&retlen);
} else if (deviceType == SR1xxS) {
appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_SR1XX_S_CONFIG,
(char *)buffer.data(), buffer.size(),
&retlen);
} else {
appConfigStatus = GetNxpConfigByteArrayValue(NAME_NXP_UWB_EXT_APP_DEFAULT_CONFIG,
(char *)buffer.data(), buffer.size(),
&retlen);
}
if (appConfigStatus) {
if ((retlen > 0) && (retlen <= max_config_length)) {
vendorConfig[3] = sizeof(sessionId) + retlen;
memcpy(vendorConfig + 4, &sessionId, sizeof(sessionId));
memcpy(vendorConfig + 8, buffer.data(), retlen);
cmdlen = UCI_MSG_HDR_SIZE + sizeof(sessionId) + retlen;
status = phNxpUciHal_send_ext_cmd(cmdlen, vendorConfig);
if (status != UWBSTATUS_SUCCESS) {
NXPLOG_UCIHAL_D(" %s: Apply vendor App Config Failed", __func__);
return UWBSTATUS_SUCCESS;
}
} else {
NXPLOG_UCIHAL_D(" %s: Invalid retlen", __func__);
return UWBSTATUS_SUCCESS;
}
}
return status;
}
static void phNxpUciHal_print_response_status(uint8_t* p_rx_data, uint16_t p_len) {
uint8_t mt;
int status_byte;
const uint8_t response_buf[][30] = {"STATUS_OK",
"STATUS_REJECTED",
"STATUS_FAILED",
"STATUS_SYNTAX_ERROR",
"STATUS_INVALID_PARAM",
"STATUS_INVALID_RANGE",
"STATUS_INAVALID_MSG_SIZE",
"STATUS_UNKNOWN_GID",
"STATUS_UNKNOWN_OID",
"STATUS_RFU",
"STATUS_READ_ONLY",
"STATUS_COMMAND_RETRY"};
if(p_len > UCI_PKT_HDR_LEN) {
mt = ((p_rx_data[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
status_byte = p_rx_data[UCI_RESPONSE_STATUS_OFFSET];
if((mt == UCI_MT_RSP) && (status_byte <= MAX_RESPONSE_STATUS)) {
NXPLOG_UCIHAL_D(" %s: Response Status = %s", __func__ , response_buf[status_byte]);
}else{
NXPLOG_UCIHAL_D(" %s: Response Status = %x", __func__ , status_byte);
}
}
}