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