CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
QrRaster.cpp
Go to the documentation of this file.
1
10
11#include "cdc_views/QrRaster.h"
12#include "qrcode.h"
13
14#include "freertos/FreeRTOS.h"
15#include "freertos/semphr.h"
16
17#include <cstring>
18
19namespace cdc::ui::qr {
20
21namespace {
22
23constexpr uint8_t QR_VERSION_MAX = 20;
24
25struct RasterCtx {
26 bool sizing = true;
27 int modules = 0;
28 uint8_t scale = 1;
29 uint8_t quiet = 0;
30 uint8_t* out = nullptr;
31 uint16_t stride = 0;
32 uint16_t side_px = 0;
33};
34RasterCtx s_ctx;
35
36SemaphoreHandle_t s_lock = nullptr;
37void lock_init() { if (!s_lock) s_lock = xSemaphoreCreateMutex(); }
38struct Guard {
39 bool held = false;
40 Guard() { lock_init(); if (s_lock) held = (xSemaphoreTake(s_lock, portMAX_DELAY) == pdTRUE); }
41 ~Guard() { if (held) xSemaphoreGive(s_lock); }
42};
43
44void raster_callback(esp_qrcode_handle_t qrcode) {
45 int size = esp_qrcode_get_size(qrcode);
46 s_ctx.modules = size;
47 if (s_ctx.sizing || !s_ctx.out) return;
48
49 for (int my = 0; my < size; my++) {
50 for (int mx = 0; mx < size; mx++) {
51 if (!esp_qrcode_get_module(qrcode, mx, my)) continue;
52 packModule(s_ctx.out, s_ctx.stride, s_ctx.scale, s_ctx.quiet, mx, my);
53 }
54 }
55}
56
57esp_qrcode_config_t make_cfg(uint8_t max_version, uint8_t ecc) {
58 esp_qrcode_config_t cfg = {};
59 cfg.display_func = raster_callback;
60 cfg.max_qrcode_version = (max_version >= 1 && max_version <= QR_VERSION_MAX)
61 ? max_version : QR_VERSION_MAX;
62 switch (ecc) {
63 case 1: cfg.qrcode_ecc_level = ESP_QRCODE_ECC_MED; break;
64 case 2: cfg.qrcode_ecc_level = ESP_QRCODE_ECC_QUART; break;
65 case 3: cfg.qrcode_ecc_level = ESP_QRCODE_ECC_HIGH; break;
66 default: cfg.qrcode_ecc_level = ESP_QRCODE_ECC_LOW; break;
67 }
68 return cfg;
69}
70
71} // namespace
72
73int measure(const char* data, uint8_t max_version, uint8_t ecc, uint16_t* out_modules) {
74 if (!data || !data[0] || !out_modules) return -2;
75 Guard g;
76 s_ctx = RasterCtx{};
77 s_ctx.sizing = true;
78 esp_qrcode_config_t cfg = make_cfg(max_version, ecc);
79 if (esp_qrcode_generate(&cfg, data) != ESP_OK || s_ctx.modules <= 0) return -1;
80 *out_modules = static_cast<uint16_t>(s_ctx.modules);
81 return 0;
82}
83
84int render(const char* data, uint8_t max_version, uint8_t ecc,
85 uint8_t scale, uint8_t quiet_modules,
86 uint8_t* out, size_t out_size,
87 uint16_t* out_stride_bytes, uint16_t* out_height_px) {
88 if (!data || !data[0] || !out || !out_stride_bytes || !out_height_px) return -2;
89 if (scale == 0) scale = 1;
90
91 uint16_t modules = 0;
92 int rc = measure(data, max_version, ecc, &modules);
93 if (rc != 0) return rc;
94
95 const uint32_t side_px = (static_cast<uint32_t>(modules) + 2u * quiet_modules) * scale;
96 if (side_px == 0 || side_px > QR_MAX_SIDE_PX) return -2;
97 const uint16_t stride = static_cast<uint16_t>((side_px + 7) / 8);
98 const size_t needed = static_cast<size_t>(stride) * side_px;
99 if (out_size < needed) return -3;
100
101 Guard g;
102 std::memset(out, 0, needed);
103 s_ctx = RasterCtx{};
104 s_ctx.sizing = false;
105 s_ctx.scale = scale;
106 s_ctx.quiet = quiet_modules;
107 s_ctx.out = out;
108 s_ctx.stride = stride;
109 s_ctx.side_px = static_cast<uint16_t>(side_px);
110
111 esp_qrcode_config_t cfg = make_cfg(max_version, ecc);
112 esp_err_t err = esp_qrcode_generate(&cfg, data);
113 s_ctx.out = nullptr;
114 if (err != ESP_OK) return -1;
115
116 *out_stride_bytes = stride;
117 *out_height_px = static_cast<uint16_t>(side_px);
118 return 0;
119}
120
121} // namespace cdc::ui::qr
QR encoding into a caller-provided 1-bpp packed raster (no display).
void packModule(uint8_t *out, uint16_t stride, uint8_t scale, uint8_t quiet, int mx, int my)
Sets the packed pixels of one black QR module.
Definition QrRaster.h:33
constexpr uint16_t QR_MAX_SIDE_PX
Hard cap on the rendered side length in pixels (incl. quiet zone, scaled).
Definition QrRaster.h:18
int measure(const char *data, uint8_t max_version, uint8_t ecc, uint16_t *out_modules)
Measures the module count for data without rendering.
Definition QrRaster.cpp:73