CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
HardwareInfo.cpp
Go to the documentation of this file.
2
4#include "cdc_ui/I18n.h"
5#include "cdc_core/CpuStats.h"
6#include "cdc_hal/II2cBus.h"
8#include "cdc_hal/IKeypad.h"
9#include "cdc_hal/IDisplay.h"
14#include "esp_system.h"
15#include "esp_heap_caps.h"
16#include "esp_timer.h"
17#include "nvs.h"
18
19#include <cstdarg>
20#include <cstdio>
21
22namespace cdc::ui {
23
30static void buildHardwareInfoText(char* buf, size_t bufSize) {
31 if (!buf || bufSize == 0) return;
32 size_t pos = 0;
33
34 auto append = [&](const char* fmt, ...) {
35 if (pos >= bufSize) return;
36 va_list args;
37 va_start(args, fmt);
38 int written = vsnprintf(buf + pos, bufSize - pos, fmt, args);
39 va_end(args);
40 if (written > 0) {
41 size_t w = static_cast<size_t>(written);
42 pos += (w < (bufSize - pos)) ? w : (bufSize - pos - 1);
43 }
44 };
45
46 const char* okText = ui::tr("core.ok");
47 const char* failText = ui::tr("core.failed");
48 const char* naText = ui::tr("core.hw_not_available");
49
50 append("=== %s ===\n", ui::tr("core.hardware_info"));
51
52 // I2C Bus (use bus 0 as primary)
53 auto* i2c = hal::getI2cBus0();
54 bool i2cOk = i2c && (i2c->getState() == core::ServiceState::INITIALIZED ||
55 i2c->getState() == core::ServiceState::STARTED);
56 append("%s: %s\n", ui::tr("core.hw_i2c_bus"), i2cOk ? okText : failText);
57
58 // Power Management
59 auto* power = hal::getPowerManagerInstance();
60 bool powerOk = power && (power->getState() == core::ServiceState::INITIALIZED ||
61 power->getState() == core::ServiceState::STARTED);
62 append("%s: %s\n", ui::tr("core.hw_bq25895"), powerOk ? okText : failText);
63
64 // Keypad
65 auto* keypad = hal::getKeypadInstance();
66 bool keypadOk = keypad && (keypad->getState() == core::ServiceState::INITIALIZED ||
67 keypad->getState() == core::ServiceState::STARTED);
68 append("%s: %s\n", ui::tr("core.hw_tca9535"), keypadOk ? okText : failText);
69
70 // Display
72 bool displayOk = display && (display->getState() == core::ServiceState::INITIALIZED ||
74 append("%s: %s\n", ui::tr("core.hw_display"), displayOk ? okText : failText);
75
76 // TROPIC01
78 bool seOk = se && (se->getState() == core::ServiceState::INITIALIZED ||
79 se->getState() == core::ServiceState::STARTED);
80 append("%s: %s\n", ui::tr("core.hw_tropic01"), seOk ? okText : failText);
81 append("%s: %s\n", ui::tr("core.hw_tr01_session"),
82 (se && se->isSessionActive()) ? okText : naText);
83
84 if (seOk) {
85 uint8_t riscvVer[4] = {0};
86 uint8_t spectVer[4] = {0};
87 if (se->getFwVersion(riscvVer, spectVer)) {
88 append("%s: %u.%u.%u.%u\n", ui::tr("core.hw_tr01_riscv_fw"),
89 riscvVer[3], riscvVer[2], riscvVer[1], riscvVer[0]);
90 append("%s: %u.%u.%u.%u\n", ui::tr("core.hw_tr01_spect_fw"),
91 spectVer[3], spectVer[2], spectVer[1], spectVer[0]);
92 } else {
93 append("%s: %s\n", ui::tr("core.hw_tr01_riscv_fw"), naText);
94 append("%s: %s\n", ui::tr("core.hw_tr01_spect_fw"), naText);
95 }
96 append("%s: %u B\n", ui::tr("core.hw_tr01_rmem_slot"), se->getRmemSlotSize());
97 } else {
98 append("%s: %s\n", ui::tr("core.hw_tr01_riscv_fw"), naText);
99 append("%s: %s\n", ui::tr("core.hw_tr01_spect_fw"), naText);
100 append("%s: %s\n", ui::tr("core.hw_tr01_rmem_slot"), naText);
101 }
102
103 // WiFi
104 auto* wifi = hal::getWifiControllerInstance();
105 bool wifiOk = wifi && (wifi->getState() == core::ServiceState::INITIALIZED ||
106 wifi->getState() == core::ServiceState::STARTED);
107 append("%s: %s\n", ui::tr("core.hw_wifi"), wifiOk ? okText : naText);
108
109 // Bluetooth
111 bool bleOk = ble && (ble->getState() == core::ServiceState::INITIALIZED ||
112 ble->getState() == core::ServiceState::STARTED);
113 append("%s: %s\n", ui::tr("core.hw_ble"), bleOk ? okText : naText);
114
115 append("\n--- %s ---\n", ui::tr("core.hw_section_memory"));
116
117 size_t freeHeap = esp_get_free_heap_size();
118 size_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
119 size_t usedHeap = (totalHeap > freeHeap) ? (totalHeap - freeHeap) : 0;
120 append("%s: %lu/%lu KB\n",
121 ui::tr("core.hw_heap"),
122 (unsigned long)(usedHeap / 1024),
123 (unsigned long)(totalHeap / 1024));
124
125 size_t intFree = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
126 size_t intTotal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
127 size_t intLargest = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
128 append("DRAM: %lu/%lu KB free, largest %lu B\n",
129 (unsigned long)(intFree / 1024),
130 (unsigned long)(intTotal / 1024),
131 (unsigned long)intLargest);
132
133 size_t dmaFree = heap_caps_get_free_size(MALLOC_CAP_DMA);
134 size_t dmaLargest = heap_caps_get_largest_free_block(MALLOC_CAP_DMA);
135 append("DMA: %lu KB free, largest %lu B\n",
136 (unsigned long)(dmaFree / 1024),
137 (unsigned long)dmaLargest);
138
139 size_t psramFree = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
140 size_t psramTotal = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
141 size_t psramUsed = (psramTotal > psramFree) ? (psramTotal - psramFree) : 0;
142 append("%s: %lu/%lu KB\n",
143 ui::tr("core.hw_psram"),
144 (unsigned long)(psramUsed / 1024),
145 (unsigned long)(psramTotal / 1024));
146
147 nvs_stats_t nvsStats;
148 if (nvs_get_stats(nullptr, &nvsStats) == ESP_OK) {
149 append("%s: %lu/%lu %s\n",
150 ui::tr("core.hw_nvs"),
151 (unsigned long)nvsStats.used_entries,
152 (unsigned long)nvsStats.total_entries,
153 ui::tr("core.hw_entries"));
154 }
155
156 append("\n--- %s ---\n", ui::tr("core.hw_section_runtime"));
157
158 if (power) {
159 const char* chg = (power->getChargeStatus() == hal::ChargeStatus::FAST_CHARGE ||
160 power->getChargeStatus() == hal::ChargeStatus::PRE_CHARGE)
161 ? ui::tr("core.hw_charging_suffix")
162 : "";
163 append("%s: %u%%%s\n", ui::tr("core.hw_battery"), power->getBatteryPercent(), chg);
164 } else {
165 append("%s: %s\n", ui::tr("core.hw_battery"), naText);
166 }
167
168 float tempC = 0.0f;
169 auto* espHw = hal::getEspHardwareInstance();
170 if (espHw && espHw->getTemperatureC(&tempC)) {
171 append("%s: %.1f C\n", ui::tr("core.hw_temp"), tempC);
172 } else {
173 append("%s: %s\n", ui::tr("core.hw_temp"), naText);
174 }
175
176 uint64_t uptimeS = esp_timer_get_time() / 1000000ULL;
177 append("%s: %llu s\n", ui::tr("core.hw_uptime"), (unsigned long long)uptimeS);
178
179 append("%s: %u%%\n", ui::tr("core.hw_cpu_load"), cdc::core::CpuStats::loadOverWindow());
180}
181
187 static char hwInfo[512];
188 buildHardwareInfoText(hwInfo, sizeof(hwInfo));
189 showInfo(ui::tr("core.hardware_info"), hwInfo);
190}
191
192} // namespace cdc::ui
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
static uint8_t loadOverWindow(uint32_t windowMs=250)
Measure aggregate CPU load over a blocking window.
Definition CpuStats.cpp:40
IDisplay * getDisplayInstance()
Returns lazily created singleton display instance.
IWifiController * getWifiControllerInstance()
Returns the singleton Wi-Fi controller service instance.
II2cBus * getI2cBus0()
Returns singleton instance of I2C bus 0.
Definition I2cBus.cpp:275
IKeypad * getKeypadInstance()
Returns the singleton keypad service instance.
IBluetoothController * getBluetoothControllerInstance()
Returns singleton Bluetooth stub when NimBLE is unavailable.
IPowerManager * getPowerManagerInstance()
Returns the singleton power manager instance.
IEspHardware * getEspHardwareInstance()
ISecureElement * getSecureElementInstance()
Returns singleton secure-element stub instance.
Centralized key-code constants for cdc_views.
Definition IModule.h:8
const char * tr(const char *key)
Look up a translation by string key.
Definition I18n.h:208
InfoView * showInfo(const char *title, const char *text, const char *hint=nullptr)
Shows a shared info view instance and pushes it onto the view stack.
Definition InfoView.cpp:310
Gdey029T94 * display
static void buildHardwareInfoText(char *buf, size_t bufSize)
Builds localized hardware info text into a caller-provided buffer.
void showHardwareInfo()
Opens hardware info screen using shared info view.