1 /* 2 * Copyright 2012-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 #ifndef _PHNXPUCIHAL_H_ 18 #define _PHNXPUCIHAL_H_ 19 20 #include <thread> 21 22 #include "hal_nxpuwb.h" 23 #include "NxpUwbChip.h" 24 #include "phNxpUciHal_Adaptation.h" 25 #include "phNxpUciHal_utils.h" 26 #include "phTmlUwb.h" 27 #include "uci_defs.h" 28 29 /********************* Definitions and structures *****************************/ 30 #define MAX_RETRY_COUNT 0x05 31 #define UCI_MAX_DATA_LEN 4200 // maximum data packet size 32 #define UCI_MAX_PAYLOAD_LEN 4200 33 #define UCI_MAX_CONFIG_PAYLOAD_LEN 0xFF 34 // #define UCI_RESPONSE_STATUS_OFFSET 0x04 35 #define UCI_PKT_HDR_LEN 0x04 36 #define UCI_PKT_PAYLOAD_STATUS_LEN 0x01 37 #define UCI_PKT_NUM_CAPS_LEN 0x01 38 #define UCI_PKT_UCI_GENERIC 0x09 39 #define UWB_CHANNELS 0x0E 40 #define CCC_UWB_CHANNELS 0xA3 41 #define COUNTRY_CODE_TAG 0x00 42 #define UWB_ENABLE_TAG 0x01 43 #define CHANNEL_5_TAG 0x02 44 #define CHANNEL_9_TAG 0x03 45 #define TX_POWER_TAG 0x05 46 #define CHANNEL_5_MASK 0xFE 47 #define CHANNEL_9_MASK 0xF7 48 #define CHANNEL_NUM_5 0x05 49 #define CHANNEL_NUM_9 0x09 50 #define CCC_CHANNEL_INFO_BIT_MASK 0x03 51 52 #define MAX_RESPONSE_STATUS 0x0C 53 54 #define UCI_MT_MASK 0xE0 55 #define UCI_PBF_MASK 0x10 56 #define UCI_GID_MASK 0x0F 57 #define UCI_OID_MASK 0x3F 58 #define UCI_OID_RANGE_DATA_NTF 0x00 59 60 #define UCI_NTF_PAYLOAD_OFFSET 0x04 61 #define NORMAL_MODE_LENGTH_OFFSET 0x03 62 #define EXTENDED_MODE_LEN_OFFSET 0x02 63 #define EXTENDED_MODE_LEN_SHIFT 0x08 64 #define EXTND_LEN_INDICATOR_OFFSET 0x01 65 #define EXTND_LEN_INDICATOR_OFFSET_MASK 0x80 66 #define UCI_SESSION_ID_OFFSET 0x04 67 #define FWD_MAX_RETRY_COUNT 0x05 68 69 #define USER_FW_BOOT_MODE 0x01 70 #define FW_VERSION_PARAM_ID 0x01 71 72 #define FW_BOOT_MODE_PARAM_ID 0x63 73 74 #define CCC_SUPPORTED_PROTOCOL_VERSIONS_ID 0xA4 75 76 /* Low power mode */ 77 #define LOW_POWER_MODE_TAG_ID 0x01 78 #define LOW_POWER_MODE_LENGTH 0x01 79 80 /* AOA support handling */ 81 #define AOA_SUPPORT_TAG_ID 0x13 82 #define ANTENNA_RX_PAIR_DEFINE_TAG_ID 0xE4 83 #define ANTENNA_RX_PAIR_DEFINE_SUB_TAG_ID 0x62 84 85 #define DEVICE_NAME_PARAM_ID 0x00 86 87 /* Mem alloc. with 8 byte alignment */ 88 #define nxp_malloc(x) malloc(((x - 1) | 7) + 1) 89 90 /* UCI Message set application config specific parameters*/ 91 #define UCI_CMD_NUM_CONFIG_PARAM_LENGTH 1 92 #define UCI_CMD_NUM_CONFIG_PARAM_BYTE 8 93 #define UCI_CMD_LENGTH_PARAM_BYTE1 3 94 #define UCI_CMD_LENGTH_PARAM_BYTE2 2 95 #define UCI_CMD_TAG_BYTE_LENGTH 1 96 #define UCI_CMD_PARAM_SIZE_BYTE_LENGTH 1 97 #define UCI_CMD_PAYLOAD_BYTE_LENGTH 1 98 99 /* FW debug and crash log path */ 100 const char debug_log_path[] = "/data/vendor/uwb/"; 101 102 /* UCI Data */ 103 #define NXP_MAX_CONFIG_STRING_LEN 2052 104 typedef struct uci_data { 105 uint16_t len; 106 uint8_t p_data[UCI_MAX_DATA_LEN]; 107 } uci_data_t; 108 109 typedef enum { 110 HAL_STATUS_CLOSE = 0, 111 HAL_STATUS_OPEN 112 } phNxpUci_HalStatus; 113 114 typedef enum { 115 UWB_DEVICE_INIT = 0, 116 UWB_DEVICE_READY, 117 UWB_DEVICE_BUSY, 118 UWB_DEVICE_STATE_UNKNOWN = 0XA0, 119 UWB_DEVICE_ERROR = 0xFF 120 }phNxpUci_UwbcState; 121 122 typedef enum { 123 UWB_DEVICE_NOT_BOUND = 0, 124 UWB_DEVICE_BOUND_UNLOCKED, 125 UWB_DEVICE_BOUND_LOCKED, 126 UWB_DEVICE_UNKNOWN 127 } phNxpUci_UwbBindingStatus; 128 129 typedef enum { 130 HAL_STATE_CLOSE = 0, 131 HAL_STATE_CORE_INIT, 132 HAL_STATE_OPEN, 133 HAL_STATE_READ_BINDING_NTF 134 } phNxpUci_HalState; 135 136 /* Macros to enable and disable extensions */ 137 #define HAL_ENABLE_EXT() (nxpucihal_ctrl.hal_ext_enabled = 1) 138 #define HAL_DISABLE_EXT() (nxpucihal_ctrl.hal_ext_enabled = 0) 139 140 typedef struct { 141 uint8_t 142 validation; /* indicates on which platform validation is done like SR100*/ 143 uint8_t android_version; /* android version */ 144 uint8_t major_version; /* major version of the MW */ 145 uint8_t minor_version; /* Minor Version of MW */ 146 uint8_t rc_version; /* RC version */ 147 uint8_t mw_drop; /* MW early drops */ 148 } phNxpUciHal_MW_Version_t; 149 150 typedef struct { 151 uint8_t major_version; /* major */ 152 uint8_t minor_version; /* minor/maintenance */ 153 uint8_t rc_version; /* patch */ 154 } phNxpUciHal_FW_Version_t; 155 156 typedef struct { 157 uint16_t restricted_channel_mask; 158 bool uwb_enable; 159 short tx_power_offset; // From UWB_COUNTRY_CODE_CAPS 160 } phNxpUciHal_Runtime_Settings_t; 161 162 // From phNxpUciHal_process_ext_cmd_rsp(), 163 // For checking CMD/RSP turn around matching. 164 class CmdRspCheck { 165 public: CmdRspCheck()166 CmdRspCheck() { } 167 StartCmd(uint8_t gid,uint8_t oid)168 void StartCmd(uint8_t gid, uint8_t oid) { 169 if (sem_ != nullptr) { 170 NXPLOG_UCIHAL_E("CMD/RSP turnaround is already ongoing!"); 171 } else { 172 sem_ = std::make_shared<UciHalSemaphore>(); 173 gid_ = gid; 174 oid_ = oid; 175 } 176 } 177 178 // CMD writer waits for the corresponding RSP Wait(long timeout_ms)179 tHAL_UWB_STATUS Wait(long timeout_ms) { 180 auto sem = GetSemaphore(); 181 if (sem == nullptr) { 182 NXPLOG_UCIHAL_E("Wait CMD/RSP for non-existed turnaround!"); 183 return UCI_STATUS_FAILED; 184 } 185 sem->wait_timeout_msec(timeout_ms); 186 auto ret = sem->getStatus(); 187 ReleaseSemaphore(); 188 return ret; 189 } 190 191 // Reset the state, this shouldn't be called while 192 // Someone is waiting from WaitRsp(). Cancel()193 void Cancel() { 194 ReleaseSemaphore(); 195 } 196 197 // Wakes up the user thread when RSP packet is matched. Wakeup(uint8_t gid,uint8_t oid)198 void Wakeup(uint8_t gid, uint8_t oid) { 199 auto sem = GetSemaphore(); 200 if (sem == nullptr) { 201 NXPLOG_UCIHAL_E("Wakeup CMD/RSP while no one is waiting for CMD/RSP!"); 202 return; 203 } 204 if (gid_ != gid || oid_ != oid) { 205 NXPLOG_UCIHAL_E( 206 "Received incorrect response of GID:%x OID:%x, expected GID:%x OID:%x", 207 gid, oid, gid_, oid_); 208 sem->post(UWBSTATUS_COMMAND_RETRANSMIT); 209 } else { 210 sem->post(UWBSTATUS_SUCCESS); 211 } 212 } 213 214 // Wakes up the user thread with error status code. WakeupError(tHAL_UWB_STATUS status)215 void WakeupError(tHAL_UWB_STATUS status) { 216 auto sem = GetSemaphore(); 217 if (sem == nullptr) { 218 NXPLOG_UCIHAL_V("Got error while no one is waiting for CMD/RSP!"); 219 return; 220 } 221 sem->post(status); 222 } 223 224 private: GetSemaphore()225 std::shared_ptr<UciHalSemaphore> GetSemaphore() { 226 return sem_; 227 } ReleaseSemaphore()228 void ReleaseSemaphore() { 229 sem_ = nullptr; 230 } 231 std::shared_ptr<UciHalSemaphore> sem_; 232 uint8_t gid_; 233 uint8_t oid_; 234 }; 235 236 /* UCI Control structure */ 237 typedef struct phNxpUciHal_Control { 238 phNxpUci_HalStatus halStatus; /* Indicate if hal is open or closed */ 239 std::thread client_thread; /* Integration thread handle */ 240 phLibUwb_sConfig_t gDrvCfg; /* Driver config data */ 241 242 std::unique_ptr<NxpUwbChip> uwb_chip; 243 244 /* libuwb-uci callbacks */ 245 uwb_stack_callback_t* p_uwb_stack_cback; 246 uwb_stack_data_callback_t* p_uwb_stack_data_cback; 247 248 /* HAL extensions */ 249 uint8_t hal_ext_enabled; 250 251 /* Waiting semaphore */ 252 CmdRspCheck cmdrsp; 253 254 /* CORE_DEVICE_INFO_RSP cache */ 255 bool isDevInfoCached; 256 uint8_t dev_info_resp[256]; 257 258 phNxpUciHal_FW_Version_t fw_version; 259 device_type_t device_type; 260 uint8_t fw_boot_mode; 261 bool_t fw_dwnld_mode; 262 263 // Per-country settings 264 phNxpUciHal_Runtime_Settings_t rt_settings; 265 266 // AOA support handling 267 int numberOfAntennaPairs; 268 269 // Extra calibration 270 // Antenna Definitions for extra calibration, b0=Antenna1, b1=Antenna2, ... 271 uint8_t cal_rx_antenna_mask; 272 uint8_t cal_tx_antenna_mask; 273 274 // Current country code 275 uint8_t country_code[2]; 276 } phNxpUciHal_Control_t; 277 278 // RX packet handler 279 struct phNxpUciHal_RxHandler; 280 281 /* Internal messages to handle callbacks */ 282 #define UCI_HAL_OPEN_CPLT_MSG 0x411 283 #define UCI_HAL_CLOSE_CPLT_MSG 0x412 284 #define UCI_HAL_INIT_CPLT_MSG 0x413 285 #define UCI_HAL_ERROR_MSG 0x415 286 287 #define UCIHAL_CMD_CODE_LEN_BYTE_OFFSET (2U) 288 #define UCIHAL_CMD_CODE_BYTE_LEN (3U) 289 290 #define NXP_CHIP_SR100 1 291 #define NXP_CHIP_SR200 2 292 #define NXP_ANDROID_VERSION (14U) /* Android version */ 293 #define UWB_NXP_MW_VERSION_MAJ (0x00) /* MW major version */ 294 #define UWB_NXP_MW_VERSION_MIN \ 295 (0x00) /* MS Nibble is MW minor version and LS Nibble is Test Object/Patch*/ 296 #define UWB_NXP_ANDROID_MW_RC_VERSION (0x02) /* Android MW RC Version */ 297 #define UWB_NXP_ANDROID_MW_DROP_VERSION (0x07) /* Android MW early drops */ 298 /******************** UCI HAL exposed functions *******************************/ 299 tHAL_UWB_STATUS phNxpUciHal_init_hw(); 300 tHAL_UWB_STATUS phNxpUciHal_write_unlocked(size_t cmd_len, const uint8_t* p_cmd); 301 void phNxpUciHal_read_complete(void* pContext, phTmlUwb_ReadTransactInfo* pInfo); 302 303 // Report UCI packet to upper layer 304 void report_uci_message(const uint8_t* buffer, size_t len); 305 306 tHAL_UWB_STATUS phNxpUciHal_uwb_reset(); 307 tHAL_UWB_STATUS phNxpUciHal_applyVendorConfig(); 308 tHAL_UWB_STATUS phNxpUciHal_process_ext_cmd_rsp(size_t cmd_len, const uint8_t *p_cmd); 309 void phNxpUciHal_send_dev_error_status_ntf(); 310 bool phNxpUciHal_parse(size_t* data_len, uint8_t *p_data); 311 312 // RX packet handler 313 // handler should returns true if the packet is handled and 314 // shouldn't report it to the upper layer. 315 316 using RxHandlerCallback = std::function<bool(size_t packet_len, const uint8_t *packet)>; 317 318 std::shared_ptr<phNxpUciHal_RxHandler> phNxpUciHal_rx_handler_add( 319 uint8_t mt, uint8_t gid, uint8_t oid, 320 bool run_once, 321 RxHandlerCallback callback); 322 void phNxpUciHal_rx_handler_del(std::shared_ptr<phNxpUciHal_RxHandler> handler); 323 324 // Helper class for rx handler with run_once=false 325 // auto-unregistered from destructor 326 327 class UciHalRxHandler { 328 public: UciHalRxHandler()329 UciHalRxHandler() { 330 } UciHalRxHandler(uint8_t mt,uint8_t gid,uint8_t oid,RxHandlerCallback callback)331 UciHalRxHandler(uint8_t mt, uint8_t gid, uint8_t oid, 332 RxHandlerCallback callback) { 333 handler_ = phNxpUciHal_rx_handler_add(mt, gid, oid, false, callback); 334 } 335 UciHalRxHandler& operator=(UciHalRxHandler &&handler) { 336 handler_ = std::move(handler.handler_); 337 return *this; 338 } ~UciHalRxHandler()339 virtual ~UciHalRxHandler() { 340 if (handler_) { 341 phNxpUciHal_rx_handler_del(handler_); 342 handler_.reset(); 343 } 344 } 345 private: 346 std::shared_ptr<phNxpUciHal_RxHandler> handler_; 347 }; 348 349 #endif /* _PHNXPUCIHAL_H_ */ 350