| /* |
| * 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); |
| } |
| } |
| } |
| |