1 /*
2 * Copyright 2012-2019, 2022-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 #include <log/log.h>
17 #include <phNxpUciHal_ext.h>
18 #include <phNxpUciHal.h>
19 #include <phTmlUwb.h>
20 #include <phDal4Uwb_messageQueueLib.h>
21 #include <phNxpLog.h>
22 #include <phUwbCommon.h>
23 #include <sys/stat.h>
24 #include <cutils/properties.h>
25 #include "phNxpConfig.h"
26
27 #define MAX_PROPERTY_SIZE (PROPERTY_VALUE_MAX)
28 /* Timeout value to wait for response from SR1xx */
29 #define HAL_EXTNS_WRITE_RSP_TIMEOUT (100)
30
31 /******************* Global variables *****************************************/
32 extern phNxpUciHal_Control_t nxpucihal_ctrl;
33
34 extern uint32_t cleanup_timer;
35 extern bool uwb_debug_enabled;
36 extern uint32_t timeoutTimerId;
37
38 /************** HAL extension functions ***************************************/
39 static void hal_extns_write_rsp_timeout_cb(uint32_t TimerId, void *pContext);
40 /******************************************************************************
41 * Function phNxpUciHal_process_ext_cmd_rsp
42 *
43 * Description This function process the extension command response. It
44 * also checks the received response to expected response.
45 *
46 * Returns returns UWBSTATUS_SUCCESS if response is as expected else
47 * returns failure.
48 *
49 ******************************************************************************/
phNxpUciHal_process_ext_cmd_rsp(uint16_t cmd_len,uint8_t * p_cmd)50 static tHAL_UWB_STATUS phNxpUciHal_process_ext_cmd_rsp(uint16_t cmd_len,
51 uint8_t* p_cmd) {
52 tHAL_UWB_STATUS status = UWBSTATUS_FAILED;
53 uint16_t data_written = 0;
54 uint8_t ext_cmd_retry_cnt = 0;
55 uint8_t invalid_len_retry_cnt = 0;
56 bool exit_loop = 0;
57
58 /* Create the local semaphore */
59 if (phNxpUciHal_init_cb_data(&nxpucihal_ctrl.ext_cb_data, NULL) !=
60 UWBSTATUS_SUCCESS) {
61 NXPLOG_UCIHAL_D("Create ext_cb_data failed");
62 return UWBSTATUS_FAILED;
63 }
64
65
66 /* Send ext command */
67 do {
68 NXPLOG_UCIHAL_D("Entered do while loop");
69 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_SUCCESS;
70 data_written = phNxpUciHal_write_unlocked(cmd_len, p_cmd);
71 if (data_written != cmd_len) {
72 NXPLOG_UCIHAL_D("phNxpUciHal_write failed for hal ext");
73 goto clean_and_return;
74 }
75
76 NXPLOG_UCIHAL_D("ext_cmd_retry_cnt is %d",ext_cmd_retry_cnt);
77
78 /* Start timer */
79 status = phOsalUwb_Timer_Start(timeoutTimerId, HAL_EXTNS_WRITE_RSP_TIMEOUT,
80 &hal_extns_write_rsp_timeout_cb, NULL);
81 if (UWBSTATUS_SUCCESS == status) {
82 NXPLOG_UCIHAL_D("Response timer started");
83 } else {
84 NXPLOG_UCIHAL_E("Response timer not started!!!");
85 status = UWBSTATUS_FAILED;
86 goto clean_and_return;
87 }
88
89 /* Wait for rsp */
90 NXPLOG_UCIHAL_D("Waiting after ext cmd sent");
91 if (SEM_WAIT(nxpucihal_ctrl.ext_cb_data)) {
92 NXPLOG_UCIHAL_E("p_hal_ext->ext_cb_data.sem semaphore error");
93 goto clean_and_return;
94 }
95
96 switch(nxpucihal_ctrl.ext_cb_data.status) {
97 case UWBSTATUS_RESPONSE_TIMEOUT:
98 case UWBSTATUS_COMMAND_RETRANSMIT:
99 ext_cmd_retry_cnt++;
100 break;
101 case UWBSTATUS_INVALID_COMMAND_LENGTH:
102 invalid_len_retry_cnt ++;
103 break;
104 default:
105 exit_loop = 1;
106 break;
107 }
108 if ((ext_cmd_retry_cnt >= MAX_COMMAND_RETRY_COUNT) || (invalid_len_retry_cnt >= 0x03))
109 exit_loop = 1;
110 } while(exit_loop == 0);
111
112 /* Stop Timer */
113 status = phOsalUwb_Timer_Stop(timeoutTimerId);
114
115 if (UWBSTATUS_SUCCESS == status) {
116 NXPLOG_UCIHAL_D("Response timer stopped");
117 } else {
118 NXPLOG_UCIHAL_E("Response timer stop ERROR!!!");
119 status = UWBSTATUS_FAILED;
120 goto clean_and_return;
121 }
122
123 if (nxpucihal_ctrl.ext_cb_data.status != UWBSTATUS_SUCCESS) {
124 NXPLOG_UCIHAL_E("Response Status = 0x%x", nxpucihal_ctrl.ext_cb_data.status);
125 status = UWBSTATUS_FAILED;
126 goto clean_and_return;
127 }
128 NXPLOG_UCIHAL_D("Checking response");
129 status = UWBSTATUS_SUCCESS;
130
131 clean_and_return:
132 phNxpUciHal_cleanup_cb_data(&nxpucihal_ctrl.ext_cb_data);
133
134 return status;
135 }
136
137 /******************************************************************************
138 * Function phNxpUciHal_write_ext
139 *
140 * Description This function inform the status of phNxpUciHal_open
141 * function to libuwb-uci.
142 *
143 * Returns It return UWBSTATUS_SUCCESS then continue with send else
144 * sends UWBSTATUS_FAILED direct response is prepared and
145 * do not send anything to UWBC.
146 *
147 ******************************************************************************/
148
phNxpUciHal_write_ext(uint16_t * cmd_len,uint8_t * p_cmd_data,uint16_t * rsp_len,uint8_t * p_rsp_data)149 tHAL_UWB_STATUS phNxpUciHal_write_ext(uint16_t* cmd_len, uint8_t* p_cmd_data,
150 uint16_t* rsp_len, uint8_t* p_rsp_data) {
151 tHAL_UWB_STATUS status = UWBSTATUS_SUCCESS;
152
153 return status;
154 }
155
156 /******************************************************************************
157 * Function phNxpUciHal_send_ext_cmd
158 *
159 * Description This function send the extension command to UWBC. No
160 * response is checked by this function but it waits for
161 * the response to come.
162 *
163 * Returns Returns UWBSTATUS_SUCCESS if sending cmd is successful and
164 * response is received.
165 *
166 ******************************************************************************/
phNxpUciHal_send_ext_cmd(uint16_t cmd_len,const uint8_t * p_cmd)167 tHAL_UWB_STATUS phNxpUciHal_send_ext_cmd(uint16_t cmd_len, const uint8_t* p_cmd) {
168 tHAL_UWB_STATUS status;
169
170 if (cmd_len >= UCI_MAX_DATA_LEN) {
171 status = UWBSTATUS_FAILED;
172 return status;
173 }
174 HAL_ENABLE_EXT();
175 nxpucihal_ctrl.cmd_len = cmd_len;
176 memcpy(nxpucihal_ctrl.p_cmd_data, p_cmd, cmd_len);
177 status = phNxpUciHal_process_ext_cmd_rsp(nxpucihal_ctrl.cmd_len,
178 nxpucihal_ctrl.p_cmd_data);
179 HAL_DISABLE_EXT();
180
181 return status;
182 }
183
184 /******************************************************************************
185 * Function hal_extns_write_rsp_timeout_cb
186 *
187 * Description Timer call back function
188 *
189 * Returns None
190 *
191 ******************************************************************************/
hal_extns_write_rsp_timeout_cb(uint32_t timerId,void * pContext)192 static void hal_extns_write_rsp_timeout_cb(uint32_t timerId, void* pContext) {
193 UNUSED(timerId);
194 UNUSED(pContext);
195 NXPLOG_UCIHAL_E("hal_extns_write_rsp_timeout_cb - write timeout!!!");
196 nxpucihal_ctrl.ext_cb_data.status = UWBSTATUS_RESPONSE_TIMEOUT;
197 usleep(1);
198 SEM_POST(&(nxpucihal_ctrl.ext_cb_data));
199
200 return;
201 }
202
203 /******************************************************************************
204 * Function phNxpUciHal_set_board_config
205 *
206 * Description This function is called to set the board varaint config
207 * Returns return 0 on success and -1 on fail, On success
208 * update the acutual state of operation in arg pointer
209 *
210 ******************************************************************************/
phNxpUciHal_set_board_config()211 tHAL_UWB_STATUS phNxpUciHal_set_board_config(){
212 tHAL_UWB_STATUS status;
213 uint8_t buffer[] = {0x2E,0x00,0x00,0x02,0x01,0x01};
214 /* Set the board variant configurations */
215 unsigned long num = 0;
216 NXPLOG_UCIHAL_D("%s: enter; ", __func__);
217 uint8_t boardConfig = 0, boardVersion = 0;
218
219 if(GetNxpConfigNumValue(NAME_UWB_BOARD_VARIANT_CONFIG, &num, sizeof(num))){
220 boardConfig = (uint8_t)num;
221 NXPLOG_UCIHAL_D("%s: NAME_UWB_BOARD_VARIANT_CONFIG: %x", __func__,boardConfig);
222 } else {
223 NXPLOG_UCIHAL_D("%s: NAME_UWB_BOARD_VARIANT_CONFIG: failed %x", __func__,boardConfig);
224 }
225 if(GetNxpConfigNumValue(NAME_UWB_BOARD_VARIANT_VERSION, &num, sizeof(num))){
226 boardVersion = (uint8_t)num;
227 NXPLOG_UCIHAL_D("%s: NAME_UWB_BOARD_VARIANT_VERSION: %x", __func__,boardVersion);
228 } else{
229 NXPLOG_UCIHAL_D("%s: NAME_UWB_BOARD_VARIANT_VERSION: failed %lx", __func__,num);
230 }
231 buffer[4] = boardConfig;
232 buffer[5] = boardVersion;
233
234 status = phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
235
236 return status;
237 }
238
239 /*******************************************************************************
240 **
241 ** Function phNxpUciHal_process_ext_rsp
242 **
243 ** Description Process extension function response
244 **
245 ** Returns UWBSTATUS_SUCCESS if success
246 **
247 *******************************************************************************/
phNxpUciHal_process_ext_rsp(uint16_t rsp_len,uint8_t * p_buff)248 tHAL_UWB_STATUS phNxpUciHal_process_ext_rsp(uint16_t rsp_len, uint8_t* p_buff){
249 tHAL_UWB_STATUS status;
250 int NumOfTlv, index;
251 uint8_t paramId, extParamId, IdStatus;
252 index = UCI_NTF_PAYLOAD_OFFSET; // index for payload start
253 status = p_buff[index++];
254 if(status == UCI_STATUS_OK){
255 NXPLOG_UCIHAL_D("%s: status success %d", __func__, status);
256 return UWBSTATUS_SUCCESS;
257 }
258 NumOfTlv = p_buff[index++];
259 while (index < rsp_len) {
260 paramId = p_buff[index++];
261 if(paramId == EXTENDED_DEVICE_CONFIG_ID) {
262 extParamId = p_buff[index++];
263 IdStatus = p_buff[index++];
264
265 switch(extParamId) {
266 case UCI_EXT_PARAM_DELAY_CALIBRATION_VALUE:
267 case UCI_EXT_PARAM_AOA_CALIBRATION_CTRL:
268 case UCI_EXT_PARAM_DPD_WAKEUP_SRC:
269 case UCI_EXT_PARAM_WTX_COUNT_CONFIG:
270 case UCI_EXT_PARAM_DPD_ENTRY_TIMEOUT:
271 case UCI_EXT_PARAM_WIFI_COEX_FEATURE:
272 case UCI_EXT_PARAM_TX_BASE_BAND_CONFIG:
273 case UCI_EXT_PARAM_DDFS_TONE_CONFIG:
274 case UCI_EXT_PARAM_TX_PULSE_SHAPE_CONFIG:
275 case UCI_EXT_PARAM_CLK_CONFIG_CTRL:
276 if(IdStatus == UCI_STATUS_FEATURE_NOT_SUPPORTED){
277 NXPLOG_UCIHAL_E("%s: Vendor config param: %x %x is Not Supported", __func__, paramId, extParamId);
278 status = UWBSTATUS_SUCCESS;
279 } else {
280 status = UWBSTATUS_FAILED;
281 return status;
282 }
283 break;
284 default:
285 NXPLOG_UCIHAL_D("%s: Vendor param ID: %x", __func__, extParamId);
286 break;
287 }
288 } else {
289 IdStatus = p_buff[index++];
290 switch(paramId) {
291 case UCI_PARAM_ID_LOW_POWER_MODE:
292 if(IdStatus == UCI_STATUS_FEATURE_NOT_SUPPORTED){
293 NXPLOG_UCIHAL_E("%s: Generic config param: %x is Not Supported", __func__, paramId);
294 status = UWBSTATUS_SUCCESS;
295 } else {
296 status = UWBSTATUS_FAILED;
297 return status;
298 }
299 break;
300 default:
301 NXPLOG_UCIHAL_D("%s: Generic param ID: %x", __func__, paramId);
302 break;
303 }
304 }
305 }
306 NXPLOG_UCIHAL_D("%s: exit %d", __func__, status);
307 return status;
308 }
309