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 inline constexpr const char debug_log_path[] = "/data/vendor/uwb/"; 101 102 // Device file 103 inline constexpr const char uwb_dev_node[] = "/dev/srxxx"; 104 105 /* UCI Data */ 106 #define NXP_MAX_CONFIG_STRING_LEN 2052 107 typedef struct uci_data { 108 uint16_t len; 109 uint8_t p_data[UCI_MAX_DATA_LEN]; 110 } uci_data_t; 111 112 typedef enum { 113 HAL_STATUS_CLOSE = 0, 114 HAL_STATUS_OPEN 115 } phNxpUci_HalStatus; 116 117 typedef enum { 118 UWB_DEVICE_INIT = 0, 119 UWB_DEVICE_READY, 120 UWB_DEVICE_BUSY, 121 UWB_DEVICE_STATE_UNKNOWN = 0XA0, 122 UWB_DEVICE_ERROR = 0xFF 123 }phNxpUci_UwbcState; 124 125 typedef enum { 126 UWB_DEVICE_NOT_BOUND = 0, 127 UWB_DEVICE_BOUND_UNLOCKED, 128 UWB_DEVICE_BOUND_LOCKED, 129 UWB_DEVICE_UNKNOWN 130 } phNxpUci_UwbBindingStatus; 131 132 typedef enum { 133 HAL_STATE_CLOSE = 0, 134 HAL_STATE_CORE_INIT, 135 HAL_STATE_OPEN, 136 HAL_STATE_READ_BINDING_NTF 137 } phNxpUci_HalState; 138 139 /* Macros to enable and disable extensions */ 140 #define HAL_ENABLE_EXT() (nxpucihal_ctrl.hal_ext_enabled = 1) 141 #define HAL_DISABLE_EXT() (nxpucihal_ctrl.hal_ext_enabled = 0) 142 143 typedef struct { 144 uint8_t 145 validation; /* indicates on which platform validation is done like SR100*/ 146 uint8_t android_version; /* android version */ 147 uint8_t major_version; /* major version of the MW */ 148 uint8_t minor_version; /* Minor Version of MW */ 149 uint8_t rc_version; /* RC version */ 150 uint8_t mw_drop; /* MW early drops */ 151 } phNxpUciHal_MW_Version_t; 152 153 typedef struct { 154 uint8_t major_version; /* major */ 155 uint8_t minor_version; /* minor/maintenance */ 156 uint8_t rc_version; /* patch */ 157 } phNxpUciHal_FW_Version_t; 158 159 typedef struct { 160 uint16_t restricted_channel_mask; 161 bool uwb_enable; 162 short tx_power_offset; // From UWB_COUNTRY_CODE_CAPS 163 } phNxpUciHal_Runtime_Settings_t; 164 165 // From phNxpUciHal_process_ext_cmd_rsp(), 166 // For checking CMD/RSP turn around matching. 167 class CmdRspCheck { 168 public: CmdRspCheck()169 CmdRspCheck() { } 170 StartCmd(uint8_t gid,uint8_t oid)171 void StartCmd(uint8_t gid, uint8_t oid) { 172 if (sem_ != nullptr) { 173 NXPLOG_UCIHAL_E("CMD/RSP turnaround is already ongoing!"); 174 } else { 175 sem_ = std::make_shared<UciHalSemaphore>(); 176 gid_ = gid; 177 oid_ = oid; 178 } 179 } 180 181 // CMD writer waits for the corresponding RSP Wait(long timeout_ms)182 tHAL_UWB_STATUS Wait(long timeout_ms) { 183 auto sem = GetSemaphore(); 184 if (sem == nullptr) { 185 NXPLOG_UCIHAL_E("Wait CMD/RSP for non-existed turnaround!"); 186 return UCI_STATUS_FAILED; 187 } 188 sem->wait_timeout_msec(timeout_ms); 189 auto ret = sem->getStatus(); 190 ReleaseSemaphore(); 191 return ret; 192 } 193 194 // Reset the state, this shouldn't be called while 195 // Someone is waiting from WaitRsp(). Cancel()196 void Cancel() { 197 ReleaseSemaphore(); 198 } 199 200 // Wakes up the user thread when RSP packet is matched. Wakeup(uint8_t gid,uint8_t oid)201 void Wakeup(uint8_t gid, uint8_t oid) { 202 auto sem = GetSemaphore(); 203 if (sem == nullptr) { 204 NXPLOG_UCIHAL_E("Wakeup CMD/RSP while no one is waiting for CMD/RSP!"); 205 return; 206 } 207 if (gid_ != gid || oid_ != oid) { 208 NXPLOG_UCIHAL_E( 209 "Received incorrect response of GID:%x OID:%x, expected GID:%x OID:%x", 210 gid, oid, gid_, oid_); 211 sem->post(UWBSTATUS_COMMAND_RETRANSMIT); 212 } else { 213 sem->post(UWBSTATUS_SUCCESS); 214 } 215 } 216 217 // Wakes up the user thread with error status code. WakeupError(tHAL_UWB_STATUS status)218 void WakeupError(tHAL_UWB_STATUS status) { 219 auto sem = GetSemaphore(); 220 if (sem == nullptr) { 221 NXPLOG_UCIHAL_V("Got error while no one is waiting for CMD/RSP!"); 222 return; 223 } 224 sem->post(status); 225 } 226 227 private: GetSemaphore()228 std::shared_ptr<UciHalSemaphore> GetSemaphore() { 229 return sem_; 230 } ReleaseSemaphore()231 void ReleaseSemaphore() { 232 sem_ = nullptr; 233 } 234 std::shared_ptr<UciHalSemaphore> sem_; 235 uint8_t gid_; 236 uint8_t oid_; 237 }; 238 239 /* UCI Control structure */ 240 typedef struct phNxpUciHal_Control { 241 phNxpUci_HalStatus halStatus; /* Indicate if hal is open or closed */ 242 std::thread client_thread; /* Integration thread handle */ 243 244 // a main message queue on the "client" thread. 245 std::shared_ptr<MessageQueue<phLibUwb_Message>> pClientMq; 246 247 std::unique_ptr<NxpUwbChip> uwb_chip; 248 249 /* libuwb-uci callbacks */ 250 uwb_stack_callback_t* p_uwb_stack_cback; 251 uwb_stack_data_callback_t* p_uwb_stack_data_cback; 252 253 /* HAL extensions */ 254 uint8_t hal_ext_enabled; 255 256 /* Waiting semaphore */ 257 CmdRspCheck cmdrsp; 258 259 /* CORE_DEVICE_INFO_RSP cache */ 260 bool isDevInfoCached; 261 uint8_t dev_info_resp[256]; 262 263 phNxpUciHal_FW_Version_t fw_version; 264 device_type_t device_type; 265 uint8_t fw_boot_mode; 266 bool_t fw_dwnld_mode; 267 268 // Per-country settings 269 phNxpUciHal_Runtime_Settings_t rt_settings; 270 271 // AOA support handling 272 int numberOfAntennaPairs; 273 274 // Extra calibration 275 // Antenna Definitions for extra calibration, b0=Antenna1, b1=Antenna2, ... 276 uint8_t cal_rx_antenna_mask; 277 uint8_t cal_tx_antenna_mask; 278 279 bool_t recovery_ongoing; 280 bool_t uwb_device_initialized; 281 282 // Current country code 283 uint8_t country_code[2]; 284 } phNxpUciHal_Control_t; 285 286 // RX packet handler 287 struct phNxpUciHal_RxHandler; 288 289 /* Internal messages to handle callbacks */ 290 #define UCI_HAL_OPEN_CPLT_MSG 0x411 291 #define UCI_HAL_CLOSE_CPLT_MSG 0x412 292 #define UCI_HAL_INIT_CPLT_MSG 0x413 293 #define UCI_HAL_ERROR_MSG 0x415 294 295 #define UCIHAL_CMD_CODE_LEN_BYTE_OFFSET (2U) 296 #define UCIHAL_CMD_CODE_BYTE_LEN (3U) 297 298 #define NXP_CHIP_SR100 1 299 #define NXP_CHIP_SR200 2 300 #define NXP_ANDROID_VERSION (14U) /* Android version */ 301 #define UWB_NXP_MW_VERSION_MAJ (0x00) /* MW major version */ 302 #define UWB_NXP_MW_VERSION_MIN \ 303 (0x00) /* MS Nibble is MW minor version and LS Nibble is Test Object/Patch*/ 304 #define UWB_NXP_ANDROID_MW_RC_VERSION (0x02) /* Android MW RC Version */ 305 #define UWB_NXP_ANDROID_MW_DROP_VERSION (0x07) /* Android MW early drops */ 306 /******************** UCI HAL exposed functions *******************************/ 307 tHAL_UWB_STATUS phNxpUciHal_hw_init(); 308 void phNxpUciHal_hw_deinit(); 309 310 void phNxpUciHal_hw_suspend(); 311 void phNxpUciHal_hw_resume(); 312 313 tHAL_UWB_STATUS phNxpUciHal_write_unlocked(size_t cmd_len, const uint8_t* p_cmd); 314 void phNxpUciHal_read_complete(void* pContext, phTmlUwb_ReadTransactInfo* pInfo); 315 316 // Report UCI packet to upper layer 317 void report_uci_message(const uint8_t* buffer, size_t len); 318 319 tHAL_UWB_STATUS phNxpUciHal_uwb_reset(); 320 tHAL_UWB_STATUS phNxpUciHal_process_ext_cmd_rsp(size_t cmd_len, const uint8_t *p_cmd); 321 void phNxpUciHal_send_dev_error_status_ntf(); 322 bool phNxpUciHal_parse(size_t* data_len, uint8_t *p_data); 323 324 // RX packet handler 325 // handler should returns true if the packet is handled and 326 // shouldn't report it to the upper layer. 327 328 using RxHandlerCallback = std::function<bool(size_t packet_len, const uint8_t *packet)>; 329 330 std::shared_ptr<phNxpUciHal_RxHandler> phNxpUciHal_rx_handler_add( 331 uint8_t mt, uint8_t gid, uint8_t oid, 332 bool run_once, 333 RxHandlerCallback callback); 334 void phNxpUciHal_rx_handler_del(std::shared_ptr<phNxpUciHal_RxHandler> handler); 335 336 // Helper class for rx handler with run_once=false 337 // auto-unregistered from destructor 338 339 class UciHalRxHandler { 340 public: UciHalRxHandler()341 UciHalRxHandler() {} UciHalRxHandler(uint8_t mt,uint8_t gid,uint8_t oid,RxHandlerCallback callback)342 UciHalRxHandler(uint8_t mt, uint8_t gid, uint8_t oid, 343 RxHandlerCallback callback) { 344 handler_ = phNxpUciHal_rx_handler_add(mt, gid, oid, false, callback); 345 } 346 UciHalRxHandler& operator=(UciHalRxHandler &&handler) { 347 Unregister(); 348 handler_ = std::move(handler.handler_); 349 return *this; 350 } 351 352 UciHalRxHandler(const UciHalRxHandler&) = delete; 353 UciHalRxHandler& operator=(const UciHalRxHandler& handler) = delete; 354 ~UciHalRxHandler()355 ~UciHalRxHandler() { 356 Unregister(); 357 } 358 private: Unregister()359 void Unregister() { 360 if (handler_) { 361 phNxpUciHal_rx_handler_del(handler_); 362 handler_.reset(); 363 } 364 } 365 std::shared_ptr<phNxpUciHal_RxHandler> handler_; 366 }; 367 368 #endif /* _PHNXPUCIHAL_H_ */ 369