1 /*
2 *
3 * Copyright 2025 NXP.
4 *
5 * NXP Confidential. This software is owned or controlled by NXP and may only be
6 * used strictly in accordance with the applicable license terms. By expressly
7 * accepting such terms or by downloading,installing, activating and/or
8 * otherwise using the software, you are agreeing that you have read,and that
9 * you agree to comply with and are bound by, such license terms. If you do not
10 * agree to be bound by the applicable license terms, then you may not retain,
11 * install, activate or otherwise use the software.
12 *
13 */
14
15 #include "phNxpUciHal_ext.h"
16 #include "phUwbTypes.h"
17 #include <stdio.h>
18 #include <sys/stat.h>
19 #include <time.h>
20
21 /******************* Global variables *****************************************/
22 phNxpUciHalLog_Control_t nxpucihallog_ctrl;
23 extern phNxpUciHal_Control_t nxpucihal_ctrl;
24 extern uci_debug_log_file_t gLogFile;
25
26 /******************************************************************************
27 * Function phNxpUciLog_initialize
28 *
29 * Description This function is called during the initialization of the UWB
30 *
31 * Returns void
32 *
33 ******************************************************************************/
phNxpUciLog_initialize()34 void phNxpUciLog_initialize() {
35
36 char UCI_Logger_log_path[100] = {0};
37
38 if (!gLogFile.is_log_file_required) {
39 return;
40 }
41
42 gLogFile.debuglogFile = NULL;
43 sprintf(UCI_Logger_log_path, "%suci_debug_log.txt", debug_log_path);
44 if (NULL == (gLogFile.debuglogFile = fopen(UCI_Logger_log_path, "rb+"))) {
45 NXPLOG_UCIHAL_D("unable to open log file");
46 if (NULL == (gLogFile.debuglogFile = fopen(UCI_Logger_log_path, "wb"))) {
47 NXPLOG_UCIHAL_D("unable to create log file");
48 } else {
49 long offset = 0;
50 NXPLOG_UCIHAL_D("Created debug log file set 0 as offset");
51 fwrite(&offset, sizeof(offset), 1, gLogFile.debuglogFile);
52 fwrite("\n", sizeof(char), 1, gLogFile.debuglogFile);
53 }
54 } else {
55 long offset = 0;
56 NXPLOG_UCIHAL_D("debug log file exist set offset");
57 if (1 != fread(&offset, sizeof(long), 1, gLogFile.debuglogFile)) {
58 NXPLOG_UCIHAL_D("phNxpUciPropHal_initialize: fread() failed at %d",
59 __LINE__);
60 return;
61 }
62 if (fseek(gLogFile.debuglogFile, offset, SEEK_SET)) {
63 NXPLOG_UCIHAL_E("phNxpUciHalProp_print_log: fseek() failed at %d",
64 __LINE__);
65 return;
66 }
67 }
68
69 if (chmod(UCI_Logger_log_path, 0744) != 0) {
70 NXPLOG_UCIHAL_E("Can't change chmod log");
71 }
72 }
73
74 /******************************************************************************
75 * Function phNxpUciHalProp_fw_crash
76 *
77 * Description FW crash dump log function
78 *
79 * Returns None
80 *
81 ******************************************************************************/
phNxpUciHalProp_fw_crash()82 static void phNxpUciHalProp_fw_crash() {
83 NXPLOG_UCIHAL_D("[%s]", __func__);
84 tHAL_UWB_STATUS status;
85 // Debug get error log command: GID = UCI_GID_PROPRIETARY
86 // OID = EXT_UCI_MSG_DBG_GET_ERROR_LOG
87 std::vector<uint8_t> payload = {0x2E, 0x02, 0x00, 0x00};
88 phNxpUciHal_rx_handler_add(UCI_MT_RSP, UCI_GID_PROPRIETARY,
89 EXT_UCI_MSG_DBG_GET_ERROR_LOG, true,
90 phNxpUciHal_dump_log);
91 status = phNxpUciHal_send_ext_cmd(payload.size(), payload.data());
92
93 if (status != HAL_UWB_STATUS_OK) {
94 NXPLOG_UCIHAL_E("Failed to send firmware crash command");
95 return;
96 }
97
98 /* Send FW crash NTF to upper layer for triggering MW recovery */
99 phNxpUciHal_send_dev_error_status_ntf();
100
101 NXPLOG_UCIHAL_D("[%s] Firmware crash handling completed", __func__);
102 }
103
104 /******************************************************************************
105 * Function phNxpUciHalProp_trigger_fw_crash_log_dump
106 *
107 * Description dump FW crash log when fw is crashed
108 *
109 *
110 ******************************************************************************/
phNxpUciHalProp_trigger_fw_crash_log_dump()111 void phNxpUciHalProp_trigger_fw_crash_log_dump() {
112 nxpucihallog_ctrl.log_thread_handler = std::thread(&phNxpUciHalProp_fw_crash);
113 nxpucihallog_ctrl.log_thread_handler.detach();
114 }
115
116 /******************************************************************************
117 * Function phNxpUciHalProp_dump_log
118 *
119 * Description This function is responsible for collecting and processing
120 * debug logs. It is triggered whenever debug log data needs
121 * to be retrieved and analyzed.
122 *
123 * Returns void.
124 *
125 ******************************************************************************/
phNxpUciHal_dump_log(size_t data_len,const uint8_t * p_rx_data)126 bool phNxpUciHal_dump_log(size_t data_len, const uint8_t *p_rx_data) {
127 int cmd_len, len;
128 bool isSkipPacket = false;
129 const uint8_t mt = ((p_rx_data[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
130 const uint8_t gid = p_rx_data[0] & UCI_GID_MASK;
131 const uint8_t oid = p_rx_data[1] & UCI_OID_MASK;
132 const uint8_t pbf = (p_rx_data[0] & UCI_PBF_MASK) >> UCI_PBF_SHIFT;
133
134 uint8_t isExtendedLength =
135 (p_rx_data[EXTND_LEN_INDICATOR_OFFSET] & EXTND_LEN_INDICATOR_OFFSET_MASK);
136 cmd_len = p_rx_data[NORMAL_MODE_LENGTH_OFFSET];
137
138 if (isExtendedLength) {
139 cmd_len = ((cmd_len << EXTENDED_MODE_LEN_SHIFT) |
140 p_rx_data[EXTENDED_MODE_LEN_OFFSET]);
141 }
142
143 if ((gid == UCI_GID_PROPRIETARY) && (oid == EXT_UCI_MSG_DBG_GET_ERROR_LOG)) {
144 if (nxpucihal_ctrl.hal_ext_enabled == 1) {
145 char FW_crash_log_path[100] = {0};
146 sprintf(FW_crash_log_path, "%suwb_FW_crash.log", debug_log_path);
147 if (NULL ==
148 (nxpucihallog_ctrl.FwCrashLogFile = fopen(FW_crash_log_path, "wb"))) {
149 NXPLOG_UCIHAL_E("unable to open log file %s", FW_crash_log_path);
150 nxpucihal_ctrl.cmdrsp.WakeupError(UWBSTATUS_FAILED);
151 } else {
152 len = fwrite(&p_rx_data[UCI_NTF_PAYLOAD_OFFSET], 1, cmd_len,
153 nxpucihallog_ctrl.FwCrashLogFile);
154 fflush(nxpucihallog_ctrl.FwCrashLogFile);
155 NXPLOG_UCIHAL_D("FW crash dump: %d bytes written", len);
156 fclose(nxpucihallog_ctrl.FwCrashLogFile);
157 }
158 if (!pbf) {
159 nxpucihal_ctrl.cmdrsp.Wakeup(gid, oid);
160 }
161 }
162 isSkipPacket = true;
163 }
164 return isSkipPacket;
165 }
166
phNxpUciHalProp_print_log(uint8_t what,const uint8_t * p_data,uint16_t len)167 void phNxpUciHalProp_print_log(uint8_t what, const uint8_t *p_data,
168 uint16_t len) {
169 char print_buffer[len * 3 + 1];
170 char dd_mm_buffer[8];
171 char UCI_Logger_log_path[100] = {0};
172 const uint8_t mt = ((p_data[0]) & UCI_MT_MASK) >> UCI_MT_SHIFT;
173 const uint8_t gid = p_data[0] & UCI_GID_MASK;
174 const uint8_t oid = p_data[1] & UCI_OID_MASK;
175 bool is_range_ntf = false;
176 uint8_t status_index = 29;
177
178 if (!gLogFile.is_log_file_required) {
179 return;
180 }
181
182 if (gLogFile.debuglogFile == NULL) {
183 NXPLOG_UCIHAL_E("debuglogFile file pointer is null...");
184 return;
185 }
186
187 char yy_time[20];
188 time_t current_time = time(0);
189 tm *dd_mm_tm = localtime(¤t_time);
190 strftime(yy_time, sizeof(yy_time), "%x %T", dd_mm_tm);
191 if (gLogFile.fileSize < 100000) {
192 if (!nxpucihal_ctrl.uwb_device_initialized) {
193 // Check file size
194 if (ftell(gLogFile.debuglogFile) + 5 + strlen(yy_time) +
195 strlen(NXPLOG_ITEM_UCIR) + 4 >
196 gLogFile.fileSize) {
197 if (fseek(gLogFile.debuglogFile, 9L, SEEK_SET)) {
198 NXPLOG_UCIHAL_E("phNxpUciHalProp_print_log: fseek() failed at %d",
199 __LINE__);
200 return;
201 }
202 if (ftell(gLogFile.debuglogFile) > gLogFile.fileSize) {
203 return;
204 }
205 }
206 if (mt == UCI_MT_RSP && p_data[4] != UCI_STATUS_OK) {
207 fprintf(gLogFile.debuglogFile, "\n%s %s:", yy_time, NXPLOG_ITEM_UCIR);
208 len = fwrite(p_data, 1, len, gLogFile.debuglogFile);
209 fwrite("\n", 1, 1, gLogFile.debuglogFile);
210 gLogFile.init_sequence_started = false;
211 }
212 if (!gLogFile.init_sequence_started) {
213 fprintf(gLogFile.debuglogFile, "\n%s INIT", yy_time);
214 }
215 gLogFile.init_sequence_started = true;
216 return;
217 }
218 gLogFile.init_sequence_started = false;
219 if (((gid != UCI_GID_SESSION_MANAGE) ||
220 (oid != UCI_MSG_SESSION_SET_APP_CONFIG)) &&
221 ((gid != UCI_GID_PROPRIETARY_0X0F) ||
222 (oid != SET_VENDOR_SET_CALIBRATION))) {
223 switch (mt) {
224 case UCI_MT_CMD:
225 len = UCI_MSG_HDR_SIZE;
226 break;
227 case UCI_MT_RSP:
228 len = UCI_RESPONSE_PAYLOAD_OFFSET;
229 break;
230 case UCI_MT_NTF:
231 // Handle range data ntf
232 if ((gid == UCI_GID_SESSION_CONTROL) &&
233 (oid == UCI_OID_RANGE_DATA_NTF)) {
234 // Sequence number - 4
235 // first 4 bytes
236 // session handle - 4
237 // status
238 if (p_data[4 + 15] == 0x00) {
239 status_index += 2;
240 } else {
241 status_index += 8;
242 }
243 is_range_ntf = true;
244 }
245 break;
246 default:
247 break;
248 }
249 }
250 }
251
252 if ((gid == UCI_GID_PROPRIETARY && oid == EXT_UCI_MSG_DBG_DATA_LOGGER_NTF) ||
253 ((gid == UCI_GID_PROPRIETARY_0X0F) &&
254 (oid == EXT_UCI_MSG_DBG_PSDU_LOG_NTF)) ||
255 ((gid == UCI_GID_PROPRIETARY_0X0F) &&
256 (oid == EXT_UCI_MSG_DBG_CIR_LOG_NTF))) {
257 return;
258 }
259
260 uint32_t file_size = ftell(gLogFile.debuglogFile);
261
262 if ((file_size + (strlen(yy_time) + 1 + strlen(NXPLOG_ITEM_UCIX) + 1 + len) >=
263 gLogFile.fileSize)) {
264 int val = fseek(gLogFile.debuglogFile, 9L, SEEK_SET);
265 if (ftell(gLogFile.debuglogFile) > gLogFile.fileSize) {
266 return;
267 }
268 }
269
270 switch (what) {
271 case 0: {
272 fprintf(gLogFile.debuglogFile, "\n%s %s:", yy_time, NXPLOG_ITEM_UCIX);
273 } break;
274 case 1: {
275 fprintf(gLogFile.debuglogFile, "\n%s %s:", yy_time, NXPLOG_ITEM_UCIR);
276 } break;
277 default:
278 return;
279 break;
280 }
281 memset(print_buffer, 0, sizeof(print_buffer));
282 int i = 0, j = 0;
283 if (is_range_ntf) {
284 fwrite(&p_data[j], 1, 9, gLogFile.debuglogFile);
285 fwrite(&p_data[status_index], 1, 1, gLogFile.debuglogFile);
286 } else {
287
288 len = fwrite(&p_data[j], 1, len, gLogFile.debuglogFile);
289 fflush(gLogFile.debuglogFile);
290 }
291 }
292
293 /******************************************************************************
294 * Function phNxpUciLog_deinitialize
295 *
296 * Description This function close files and frees up memory used by
297 * proprietary hal.
298 *
299 * Returns void
300 *
301 ******************************************************************************/
phNxpUciLog_deinitialize()302 void phNxpUciLog_deinitialize() {
303 /* FW debug log dump file closed */
304 if (nxpucihallog_ctrl.FwCrashLogFile != NULL) {
305 fclose(nxpucihallog_ctrl.FwCrashLogFile);
306 }
307
308 if (gLogFile.debuglogFile != NULL) {
309 long offset = ftell(gLogFile.debuglogFile);
310 fseek(gLogFile.debuglogFile, 0L, SEEK_SET);
311 fwrite(&offset, sizeof(long), 1, gLogFile.debuglogFile);
312 fwrite("\n", sizeof(char), 1, gLogFile.debuglogFile);
313 fclose(gLogFile.debuglogFile);
314 gLogFile.debuglogFile = NULL;
315 }
316 }
317