239 lines
7.1 KiB
C
239 lines
7.1 KiB
C
#include <zephyr/settings/settings.h>
|
|
#include <zephyr/logging/log.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "settings_mgmt.h"
|
|
|
|
LOG_MODULE_REGISTER(settings_mgmt, LOG_LEVEL_INF);
|
|
|
|
/* Sanity check limits */
|
|
#define VOL_MIN 0
|
|
#define VOL_MAX 100
|
|
#define SHUFFLE_MODE_MIN 0
|
|
#define SHUFFLE_MODE_MAX 1
|
|
#define BLE_TIMEOUT_MIN 1000
|
|
#define BLE_TIMEOUT_MAX 0xFFFFFFFF
|
|
#define BLE_INTERVAL_MIN 10
|
|
#define BLE_INTERVAL_MAX 10000
|
|
#define CHG_MODE_MIN 0
|
|
#define CHG_MODE_MAX 2
|
|
#define OFF_THRESHOLD_MIN 2900 /* mV, LiPo cut-off */
|
|
#define OFF_THRESHOLD_MAX 3500 /* mV, LiPo nominal */
|
|
#define ADC_GAIN_MIN -100
|
|
#define ADC_GAIN_MAX 100
|
|
#define ADC_OFFSET_MIN -1000
|
|
#define ADC_OFFSET_MAX 1000
|
|
|
|
/* The "Source of Truth" in RAM */
|
|
struct app_settings_t app_cfg = {
|
|
.dev_name = "Edis Buzzer",
|
|
.vol = 100, /* 0-100 % */
|
|
.shuffle_mode = 0,
|
|
.ble_timeout = 0xFFFFFFFF,
|
|
.ble_interval = 100,
|
|
.chg_mode = 2, /* Auto */
|
|
.off_threshold = 3000, /* mV */
|
|
.adc_gain = 0,
|
|
.adc_offset = 0,
|
|
};
|
|
|
|
static int read_exact(settings_read_cb read_cb, void *cb_arg,
|
|
void *dst, size_t expected_len)
|
|
{
|
|
int rc = read_cb(cb_arg, dst, expected_len);
|
|
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
if ((size_t)rc != expected_len) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sanity check helpers */
|
|
static int check_uint8_range(uint8_t val, uint8_t min, uint8_t max,
|
|
const char *name)
|
|
{
|
|
if (val < min || val > max) {
|
|
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int check_uint16_range(uint16_t val, uint16_t min, uint16_t max,
|
|
const char *name)
|
|
{
|
|
if (val < min || val > max) {
|
|
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int check_uint32_range(uint32_t val, uint32_t min, uint32_t max,
|
|
const char *name)
|
|
{
|
|
if (val < min || val > max) {
|
|
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int check_int16_range(int16_t val, int16_t min, int16_t max,
|
|
const char *name)
|
|
{
|
|
if (val < min || val > max) {
|
|
LOG_WRN("%s out of range: %d (valid: %d-%d)", name, val, min, max);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Callback: Called by settings_load() or settings_runtime_set() */
|
|
static int buzzy_settings_set(const char *name, size_t len,
|
|
settings_read_cb read_cb, void *cb_arg)
|
|
{
|
|
const char *next;
|
|
int rc;
|
|
|
|
/* Path matching: "buzzy/sys/name" -> name is "sys/name" here */
|
|
if (settings_name_steq(name, "sys/name", &next) && !next) {
|
|
rc = read_cb(cb_arg, app_cfg.dev_name, sizeof(app_cfg.dev_name) - 1);
|
|
if (rc >= 0) app_cfg.dev_name[rc] = '\0';
|
|
return 0;
|
|
}
|
|
|
|
if (settings_name_steq(name, "audio/vol", &next) && !next) {
|
|
uint8_t vol;
|
|
rc = read_exact(read_cb, cb_arg, &vol, sizeof(vol));
|
|
if (rc == 0) {
|
|
rc = check_uint8_range(vol, VOL_MIN, VOL_MAX, "audio/vol");
|
|
if (rc == 0) {
|
|
app_cfg.vol = vol;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if ((settings_name_steq(name, "audio/shuffle", &next) ||
|
|
settings_name_steq(name, "audio/shuffle_mode", &next)) && !next) {
|
|
uint8_t shuffle;
|
|
rc = read_exact(read_cb, cb_arg, &shuffle, sizeof(shuffle));
|
|
if (rc == 0) {
|
|
rc = check_uint8_range(shuffle, SHUFFLE_MODE_MIN, SHUFFLE_MODE_MAX, "shuffle_mode");
|
|
if (rc == 0) {
|
|
app_cfg.shuffle_mode = shuffle;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if (settings_name_steq(name, "ble/to", &next) && !next) {
|
|
uint32_t timeout;
|
|
rc = read_exact(read_cb, cb_arg, &timeout, sizeof(timeout));
|
|
if (rc == 0) {
|
|
rc = check_uint32_range(timeout, BLE_TIMEOUT_MIN, BLE_TIMEOUT_MAX, "ble/to");
|
|
if (rc == 0) {
|
|
app_cfg.ble_timeout = timeout;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if ((settings_name_steq(name, "ble/interval", &next) ||
|
|
settings_name_steq(name, "ble/int", &next)) && !next) {
|
|
uint16_t interval;
|
|
rc = read_exact(read_cb, cb_arg, &interval, sizeof(interval));
|
|
if (rc == 0) {
|
|
rc = check_uint16_range(interval, BLE_INTERVAL_MIN, BLE_INTERVAL_MAX, "ble/interval");
|
|
if (rc == 0) {
|
|
app_cfg.ble_interval = interval;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if ((settings_name_steq(name, "power/chg_mode", &next) ||
|
|
settings_name_steq(name, "sys/chg_mode", &next)) && !next) {
|
|
uint8_t chg_mode;
|
|
rc = read_exact(read_cb, cb_arg, &chg_mode, sizeof(chg_mode));
|
|
if (rc == 0) {
|
|
rc = check_uint8_range(chg_mode, CHG_MODE_MIN, CHG_MODE_MAX, "chg_mode");
|
|
if (rc == 0) {
|
|
app_cfg.chg_mode = chg_mode;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if ((settings_name_steq(name, "power/off_threshold", &next) ||
|
|
settings_name_steq(name, "sys/off_threshold", &next)) && !next) {
|
|
uint16_t threshold;
|
|
rc = read_exact(read_cb, cb_arg, &threshold, sizeof(threshold));
|
|
if (rc == 0) {
|
|
rc = check_uint16_range(threshold, OFF_THRESHOLD_MIN, OFF_THRESHOLD_MAX, "off_threshold [mV]");
|
|
if (rc == 0) {
|
|
app_cfg.off_threshold = threshold;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if (settings_name_steq(name, "adc/gain", &next) && !next) {
|
|
int16_t gain;
|
|
rc = read_exact(read_cb, cb_arg, &gain, sizeof(gain));
|
|
if (rc == 0) {
|
|
rc = check_int16_range(gain, ADC_GAIN_MIN, ADC_GAIN_MAX, "adc/gain");
|
|
if (rc == 0) {
|
|
app_cfg.adc_gain = gain;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if (settings_name_steq(name, "adc/offset", &next) && !next) {
|
|
int16_t offset;
|
|
rc = read_exact(read_cb, cb_arg, &offset, sizeof(offset));
|
|
if (rc == 0) {
|
|
rc = check_int16_range(offset, ADC_OFFSET_MIN, ADC_OFFSET_MAX, "adc/offset");
|
|
if (rc == 0) {
|
|
app_cfg.adc_offset = offset;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
return -ENOENT;
|
|
}
|
|
|
|
struct settings_handler buzzy_handler = {
|
|
.name = "buzzy",
|
|
.h_set = buzzy_settings_set
|
|
};
|
|
|
|
int settings_mgmt_set_by_path(const char *path, const void *value, size_t len)
|
|
{
|
|
char full_path[64];
|
|
snprintf(full_path, sizeof(full_path), "buzzy/%s", path);
|
|
|
|
/* Schreibt in ZMS UND triggert buzzy_settings_set zur RAM-Aktualisierung */
|
|
return settings_runtime_set(full_path, value, len);
|
|
}
|
|
|
|
int settings_mgmt_init(void)
|
|
{
|
|
int rc = settings_subsys_init();
|
|
if (rc) return rc;
|
|
|
|
rc = settings_register(&buzzy_handler);
|
|
if (rc) return rc;
|
|
|
|
/* Lädt alle gespeicherten Werte aus dem ZMS in die app_cfg Struktur */
|
|
return settings_load();
|
|
} |