Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions main/pages/capture_entropy.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,21 +183,12 @@ static void camera_frame_cb(uint8_t *camera_buf, uint8_t camera_buf_index,
? display_buffer_b
: display_buffer_a;

#ifdef SIMULATOR
uint32_t in_w = camera_buf_hes;
uint32_t in_h = camera_buf_ves;
uint32_t in_w = camera_buf_hes ? camera_buf_hes : CAMERA_INPUT_WIDTH;
uint32_t in_h = camera_buf_ves ? camera_buf_ves : CAMERA_INPUT_HEIGHT;
uint32_t crop = (in_w < in_h) ? in_w : in_h;
uint32_t crop_ox = (in_w - crop) / 2;
uint32_t crop_oy = (in_h - crop) / 2;
float scale = (float)CAMERA_WIDTH / (float)crop;
#else
uint32_t in_w = CAMERA_INPUT_WIDTH;
uint32_t in_h = CAMERA_INPUT_HEIGHT;
uint32_t crop = CAMERA_INPUT_CROP;
uint32_t crop_ox = CAMERA_INPUT_CROP_OFFSET_X;
uint32_t crop_oy = CAMERA_INPUT_CROP_OFFSET_Y;
float scale = CAMERA_PPA_SCALE;
#endif

ppa_srm_oper_config_t srm = {
.in.buffer = camera_buf,
Expand Down
2 changes: 1 addition & 1 deletion main/qr/encoder.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "encoder.h"
#include "../managed_components/lvgl__lvgl/src/libs/qrcode/qrcodegen.h"
#include "src/libs/qrcode/qrcodegen.h"
#include <ctype.h>
#include <lvgl.h>
#include <stdio.h>
Expand Down
25 changes: 4 additions & 21 deletions main/qr/scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,18 +807,10 @@ static void camera_video_frame_operation(uint8_t *camera_buf,
return;
}

#ifndef SIMULATOR
if (camera_buf_hes != CAMERA_INPUT_WIDTH ||
camera_buf_ves != CAMERA_INPUT_HEIGHT) {
ESP_LOGE(TAG,
"Unexpected camera resolution %" PRIu32 "x%" PRIu32
", expected %dx%d",
camera_buf_hes, camera_buf_ves, CAMERA_INPUT_WIDTH,
CAMERA_INPUT_HEIGHT);
if (camera_buf_hes == 0 || camera_buf_ves == 0) {
__atomic_sub_fetch(&active_frame_operations, 1, __ATOMIC_SEQ_CST);
return;
}
#endif

uint8_t *back_buffer = (current_display_buffer == display_buffer_a)
? display_buffer_b
Expand All @@ -828,24 +820,15 @@ static void camera_video_frame_operation(uint8_t *camera_buf,
// counter-rotation
uint8_t *display_src = back_buffer;
if (cam_ppa_client && !closing) {
#ifdef SIMULATOR
// Simulator webcam can be any resolution; derive crop from actual frame
uint32_t in_w = camera_buf_hes;
uint32_t in_h = camera_buf_ves;
uint32_t crop = (in_w < in_h) ? in_w : in_h;
if (crop > (uint32_t)(CAMERA_SCREEN_SIZE * 2))
crop = CAMERA_SCREEN_SIZE * 2;
if (crop > CAMERA_INPUT_CROP) {
crop = CAMERA_INPUT_CROP;
}
uint32_t crop_ox = (in_w - crop) / 2;
uint32_t crop_oy = (in_h - crop) / 2;
float sim_scale = (float)CAMERA_SCREEN_WIDTH / (float)crop;
#else
uint32_t in_w = CAMERA_INPUT_WIDTH;
uint32_t in_h = CAMERA_INPUT_HEIGHT;
uint32_t crop = CAMERA_INPUT_CROP;
uint32_t crop_ox = CAMERA_INPUT_CROP_OFFSET_X;
uint32_t crop_oy = CAMERA_INPUT_CROP_OFFSET_Y;
float sim_scale = CAMERA_PPA_SCALE;
#endif
ppa_srm_oper_config_t srm = {
.in.buffer = camera_buf,
.in.pic_w = in_w,
Expand Down
96 changes: 79 additions & 17 deletions simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,23 @@ find_package(Threads REQUIRED)
find_library(MBEDTLS_LIB mbedtls)
find_library(MBEDCRYPTO_LIB mbedcrypto)
find_library(MBEDX509_LIB mbedx509)
find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/pkcs5.h mbedtls/private/pkcs5.h)
if(NOT MBEDTLS_LIB OR NOT MBEDCRYPTO_LIB)
message(FATAL_ERROR
"mbedTLS not found. Install with: sudo apt install libmbedtls-dev")
endif()
if(NOT MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIB)
get_filename_component(_mbedtls_lib_dir "${MBEDTLS_LIB}" DIRECTORY)
get_filename_component(_mbedtls_prefix "${_mbedtls_lib_dir}" DIRECTORY)
set(MBEDTLS_INCLUDE_DIR "${_mbedtls_prefix}/include")
endif()

set(MBEDTLS_COMPAT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../components/mbedtls_compat)
set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})
if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/private/pkcs5.h"
AND NOT EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/pkcs5.h")
list(PREPEND MBEDTLS_INCLUDE_DIRS ${MBEDTLS_COMPAT_DIR})
endif()

# --- libwally-core (native desktop build) ---
set(WALLY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../components/libwally-core)
Expand Down Expand Up @@ -93,7 +106,20 @@ target_link_libraries(wally PUBLIC
)

# --- LVGL ---
include(FetchContent)
set(LVGL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../managed_components/lvgl__lvgl)
if(NOT EXISTS "${LVGL_DIR}/src/lvgl.h")
FetchContent_Declare(
lvgl_upstream
GIT_REPOSITORY https://github.com/lvgl/lvgl.git
GIT_TAG v9.3.0
)
FetchContent_GetProperties(lvgl_upstream)
if(NOT lvgl_upstream_POPULATED)
FetchContent_Populate(lvgl_upstream)
endif()
set(LVGL_DIR ${lvgl_upstream_SOURCE_DIR})
endif()
file(GLOB_RECURSE LVGL_SOURCES ${LVGL_DIR}/src/*.c)

set(APP_UI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../main/ui)
Expand Down Expand Up @@ -164,7 +190,7 @@ set(PIN_PAGE_SOURCES
)

# --- Platform simulators (BSP, SD card, video/camera) ---
option(SIM_WEBCAM "Enable webcam capture via V4L2" OFF)
option(SIM_WEBCAM "Enable webcam capture" OFF)

set(PLATFORM_SIM_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/platform/bsp_sim/bsp_sim.c
Expand All @@ -177,9 +203,26 @@ set(PLATFORM_SIM_SOURCES
if(SIM_WEBCAM)
# v4l2_capture uses real kernel V4L2 headers (not the ESP-IDF stubs),
# so it is compiled as a separate library without the stubs include path.
add_library(v4l2_capture STATIC
${CMAKE_CURRENT_SOURCE_DIR}/platform/video_sim/v4l2_capture.c
)
if(APPLE)
enable_language(OBJCXX)
add_library(v4l2_capture STATIC
${CMAKE_CURRENT_SOURCE_DIR}/platform/video_sim/v4l2_capture_macos.mm
)
find_library(AVFOUNDATION_FRAMEWORK AVFoundation)
find_library(COREMEDIA_FRAMEWORK CoreMedia)
find_library(COREVIDEO_FRAMEWORK CoreVideo)
find_library(FOUNDATION_FRAMEWORK Foundation)
target_link_libraries(v4l2_capture PRIVATE
${AVFOUNDATION_FRAMEWORK}
${COREMEDIA_FRAMEWORK}
${COREVIDEO_FRAMEWORK}
${FOUNDATION_FRAMEWORK}
)
else()
add_library(v4l2_capture STATIC
${CMAKE_CURRENT_SOURCE_DIR}/platform/video_sim/v4l2_capture.c
)
endif()
target_include_directories(v4l2_capture PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/platform/video_sim/include
${CMAKE_CURRENT_SOURCE_DIR}/platform/video_sim
Expand Down Expand Up @@ -247,6 +290,26 @@ set(QR_SOURCES
file(GLOB KQUIRC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../components/k_quirc/src/*.c)
file(GLOB_RECURSE CUR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../components/cUR/src/*.c)

add_library(lvgl STATIC
${LVGL_SOURCES}
)
target_include_directories(lvgl PUBLIC
${LVGL_DIR}
${LVGL_DIR}/src
)
target_include_directories(lvgl PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(lvgl PRIVATE
LV_CONF_INCLUDE_SIMPLE
SIM_LCD_H_RES=${SIM_LCD_H_RES}
SIM_LCD_V_RES=${SIM_LCD_V_RES}
lv_refr_now=kern_lv_refr_now_real
)
target_link_libraries(lvgl PUBLIC
SDL2
)

add_executable(kern_simulator
${SIM_SOURCES}
${STUB_SOURCES}
Expand All @@ -259,7 +322,6 @@ add_executable(kern_simulator
${PLATFORM_SIM_SOURCES}
${KQUIRC_SOURCES}
${CUR_SOURCES}
${LVGL_SOURCES}
)

# Include paths β€” order matters: simulator headers shadow ESP-IDF
Expand All @@ -271,6 +333,7 @@ target_include_directories(kern_simulator PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/platform/sd_card_sim/include
${CMAKE_CURRENT_SOURCE_DIR}/platform # sdkconfig.h
${CMAKE_CURRENT_SOURCE_DIR} # lv_conf.h
${MBEDTLS_INCLUDE_DIRS}
# Application source tree
${CMAKE_CURRENT_SOURCE_DIR}/../main # ui/theme.h, core/, utils/, pages/
# Component headers (for kef.c -> bbqr/miniz, cUR, k_quirc, video)
Expand Down Expand Up @@ -316,20 +379,19 @@ target_compile_options(kern_simulator PRIVATE
)
set_target_properties(kern_simulator PROPERTIES POSITION_INDEPENDENT_CODE ON)

target_link_options(kern_simulator PRIVATE
# Redirect lv_refr_now() to a no-op wrapper in bsp_sim.c.
# Background threads (camera stream) call lv_refr_now() which clears
# LVGL's dirty state without rendering (SDL2 requires the main thread).
# The wrapper keeps widgets dirty so lv_timer_handler() renders them.
-Wl,--wrap=lv_refr_now
# Hardening linker flags
-pie
-Wl,-z,relro
-Wl,-z,now
-Wl,-z,noexecstack
)
if(APPLE)
else()
target_link_options(kern_simulator PRIVATE
# Hardening linker flags
-pie
-Wl,-z,relro
-Wl,-z,now
-Wl,-z,noexecstack
)
endif()

target_link_libraries(kern_simulator PRIVATE
lvgl
SDL2
Threads::Threads
m
Expand Down
74 changes: 61 additions & 13 deletions simulator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,37 @@ your main workstation.

## Prerequisites

### Linux (Debian/Ubuntu)

```bash
sudo apt install build-essential cmake libsdl2-dev libmbedtls-dev
```

### macOS

```bash
brew install cmake sdl2 mbedtls
```

## Build

### Linux

```bash
cd simulator \
&& cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug \
&& cmake --build build -- -j$(nproc)
```

### macOS

```bash
cd simulator \
&& cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_PREFIX_PATH="$(brew --prefix mbedtls);$(brew --prefix sdl2)" \
&& cmake --build build -- -j"$(sysctl -n hw.ncpu)"
```

Or with just (from the repo root):

```bash
Expand All @@ -35,6 +54,16 @@ just sim-build

## Run

### Linux

```bash
./simulator/build/kern_simulator
# or, from the repo root:
just sim
```

### macOS

```bash
./simulator/build/kern_simulator
# or, from the repo root:
Expand All @@ -43,16 +72,16 @@ just sim

## CLI Options

| Option | Description |
|---------------------|--------------------------------------------|
| `--qr-image <path>` | Load a single QR image for camera sim |
| `--qr-dir <path>` | Load QR images from dir (cycled through) |
| `--data-dir <path>` | Base data directory (default: `sim_data/`) |
| `--width <N>` | Display width in pixels (default: 720) |
| `--height <N>` | Display height in pixels (default: 720) |
| Option | Description |
| ------------------- | --------------------------------------------------------------------- |
| `--qr-image <path>` | Load a single QR image for camera sim |
| `--qr-dir <path>` | Load QR images from dir (cycled through) |
| `--data-dir <path>` | Base data directory (default: `sim_data/`) |
| `--width <N>` | Display width in pixels (default: 720) |
| `--height <N>` | Display height in pixels (default: 720) |
| `--webcam [device]` | Use webcam (default: `/dev/video0`). Requires `-DSIM_WEBCAM=ON` build |
| `--verbose` | Enable DEBUG-level logging |
| `--help` | Show usage and exit |
| `--verbose` | Enable DEBUG-level logging |
| `--help` | Show usage and exit |

## Examples

Expand Down Expand Up @@ -98,8 +127,10 @@ factory state.

## Webcam Support (Optional)

Build with V4L2 webcam capture to scan real QR codes and generate
real entropy:
Build with real webcam capture to scan QR codes and generate
real entropy (V4L2 on Linux, AVFoundation on macOS):

### Linux

```bash
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DSIM_WEBCAM=ON
Expand All @@ -115,6 +146,23 @@ Your user must be in the `video` group to access the webcam device:
sudo usermod -aG video $USER # then log out/in
```

### macOS

```bash
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DSIM_WEBCAM=ON \
-DCMAKE_PREFIX_PATH="$(brew --prefix mbedtls);$(brew --prefix sdl2)"
cmake --build build -- -j"$(sysctl -n hw.ncpu)"
./build/kern_simulator --webcam
# Or specify a device by index:
./build/kern_simulator --webcam 0
```

On macOS, the first run will prompt for Camera permission. If the
permission dialog does not appear, enable camera access for your
terminal in:

- System Settings β†’ Privacy & Security β†’ Camera

When `--webcam` is passed but the device cannot be opened, the
simulator falls back to blank-frame mode.

Expand All @@ -138,7 +186,7 @@ Forcing the software renderer works around this.
## Known Limitations

- Camera simulation is file-based by default (build with
`-DSIM_WEBCAM=ON` for real webcam support via V4L2)
`-DSIM_WEBCAM=ON` for real webcam support)
- eFuse HMAC uses a hardcoded test key (anti-phishing
words differ from real device, and PIN-derived keys are
trivially recoverable from `sim_data/`)
Expand All @@ -150,4 +198,4 @@ Forcing the software renderer works around this.
hashes, or any other cryptographic output produced by the
simulator will round-trip on a physical Kern device.
- PPA rotation may not match hardware exactly
- Linux only (SDL2 backend)
- Webcam support differs by OS (V4L2 on Linux, AVFoundation on macOS)
Loading
Loading