#include #include #include #include #include "ql_func.h" #include "ql_rtos.h" #include "ql_rtc.h" #include "ql_atcmd.h" #include "app_sys_time_probe.h" /* Exact signatures from the existing kernel pmic_rtc.h/duster.h. * Lookup only: never add exports, use fixed addresses, or use our diagnostic API. * SYS_OFFSET is 0 in pmic_rtc.h. Missing exports are an expected result. */ typedef unsigned int (*sys_count_fn)(int); typedef int (*zone_minutes_fn)(void); static void probe_sys_exports(void) { sys_count_fn get_count; zone_minutes_fn get_zone; unsigned int raw[2], ticks[2]; int zone[2], i; long long utc[2], advance, elapsed, drift; get_count = (sys_count_fn)(intptr_t)m_get_api_ptr("PMIC_RTC_GetTime_Count"); get_zone = (zone_minutes_fn)(intptr_t)m_get_api_ptr("GetTimeZone"); printf("[APP-SYS-PROBE] exports sys_count=%d network_zone=%d\r\n", get_count != NULL, get_zone != NULL); if (!get_count || !get_zone) { printf("[APP-SYS-PROBE] direct_sys=unavailable no_kernel_change=1\r\n"); return; } for (i = 0; i < 2; ++i) { raw[i] = get_count(0); zone[i] = get_zone(); ticks[i] = ql_rtos_get_systicks(); utc[i] = (long long)raw[i] - (long long)zone[i] * 60; printf("[APP-SYS-PROBE] direct index=%d raw=%lu zone_minutes=%d " "utc=%lld ticks=%lu\r\n", i + 1, (unsigned long)raw[i], zone[i], utc[i], (unsigned long)ticks[i]); if (i == 0) ql_rtos_task_sleep_ms(3000); } elapsed = (ticks[1] - ticks[0]) / 200U; advance = utc[1] - utc[0]; drift = advance - elapsed; if (utc[0] >= 1704067200LL && utc[1] <= 2147483647LL && zone[0] >= -720 && zone[0] <= 840 && zone[0] == zone[1] && elapsed >= 2 && elapsed <= 10 && advance > 0 && drift >= -1 && drift <= 1) { printf("[APP-SYS-PROBE] direct_sys=candidate advancing=1 " "advance_s=%lld elapsed_s=%lld external_utc_check_required=1\r\n", advance, elapsed); } else { printf("[APP-SYS-PROBE] direct_sys=rejected advance_s=%lld " "elapsed_s=%lld drift_s=%lld\r\n", advance, elapsed, drift); } } static void probe_app_rtc(int round) { ql_rtc_time_t calendar; int rc; printf("[APP-SYS-PROBE] app round=%d utc=%ld ticks=%lu\r\n", round, (long)time(NULL), (unsigned long)ql_rtos_get_systicks()); if (!m_get_api_ptr("ql_rtc_get_time_ex")) { printf("[APP-SYS-PROBE] rtc_ex=unavailable\r\n"); return; } memset(&calendar, 0, sizeof(calendar)); rc = ql_rtc_get_time_ex(&calendar); printf("[APP-SYS-PROBE] rtc_ex round=%d rc=%d calendar=" "%04d-%02d-%02dT%02d:%02d:%02d source_not_assumed=1\r\n", round, rc, calendar.tm_year, calendar.tm_mon, calendar.tm_mday, calendar.tm_hour, calendar.tm_min, calendar.tm_sec); } static void probe_at(int round, char *command, const char *label) { char response[256]; unsigned int began = ql_rtos_get_systicks(), ended; int rc, terminated; size_t i; memset(response, 0, sizeof(response)); rc = ql_atcmd_send_sync(command, response, sizeof(response), NULL, 2); ended = ql_rtos_get_systicks(); terminated = memchr(response, '\0', sizeof(response)) != NULL; response[sizeof(response) - 1] = '\0'; for (i = 0; response[i]; ++i) if ((unsigned char)response[i] < 32 || response[i] == '"') response[i] = ' '; printf("[APP-SYS-PROBE] at round=%d query=%s rc=%d duration_ms=%lu " "ticks=%lu terminated=%d raw=\"%s\"\r\n", round, label, rc, (unsigned long)(ended - began) * 5UL, (unsigned long)ended, terminated, response); } void app_sys_time_probe_run(void) { int round; printf("[APP-SYS-PROBE] begin version=1 read_only=1 kernel_diag_used=0\r\n"); if (!m_get_api_ptr) { printf("[APP-SYS-PROBE] FAIL stage=api_lookup_unavailable\r\n"); goto done; } probe_sys_exports(); if (!m_get_api_ptr("ql_atcmd_send_sync")) { printf("[APP-SYS-PROBE] at=unavailable\r\n"); goto done; } for (round = 1; round <= 2; ++round) { probe_app_rtc(round); /* QLTS support/semantics on this model must be established on-device. * Mode 0 may be a snapshot; mode 1/2 on supported models advances. * CCLK is comparison only; it may expose the same broken APP RTC. */ probe_at(round, "AT+QLTS=0\r\n", "QLTS_0"); probe_at(round, "AT+QLTS=1\r\n", "QLTS_1"); probe_at(round, "AT+QLTS=2\r\n", "QLTS_2"); probe_at(round, "AT+CCLK?\r\n", "CCLK"); if (round == 1) ql_rtos_task_sleep_ms(3000); } done: printf("[APP-SYS-PROBE] finished rtc_not_written=1\r\n"); }