feat: add GPIO policy module and tool header
This commit is contained in:
107
main/tools/gpio_policy.c
Normal file
107
main/tools/gpio_policy.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "tools/gpio_policy.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GPIO_IS_VALID_GPIO
|
||||
#define GPIO_IS_VALID_GPIO(pin) ((pin) >= 0)
|
||||
#endif
|
||||
|
||||
static bool pin_in_allowlist(int pin, const char *csv)
|
||||
{
|
||||
const char *cursor;
|
||||
|
||||
if (!csv || csv[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
cursor = csv;
|
||||
while (*cursor != '\0') {
|
||||
char *endptr = NULL;
|
||||
long value;
|
||||
|
||||
while (*cursor == ' ' || *cursor == '\t' || *cursor == ',') {
|
||||
cursor++;
|
||||
}
|
||||
if (*cursor == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
value = strtol(cursor, &endptr, 10);
|
||||
if (endptr == cursor) {
|
||||
while (*cursor != '\0' && *cursor != ',') {
|
||||
cursor++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)value == pin) {
|
||||
return true;
|
||||
}
|
||||
cursor = endptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pin_is_allowed_impl(int pin,
|
||||
const char *allowlist_csv,
|
||||
int min_pin,
|
||||
int max_pin,
|
||||
bool block_esp32_flash_pins)
|
||||
{
|
||||
bool in_policy;
|
||||
|
||||
if (pin < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Block ESP32 flash/PSRAM pins (GPIO 6-11) */
|
||||
if (block_esp32_flash_pins && pin >= 6 && pin <= 11) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (allowlist_csv && allowlist_csv[0] != '\0') {
|
||||
in_policy = pin_in_allowlist(pin, allowlist_csv);
|
||||
} else {
|
||||
in_policy = pin >= min_pin && pin <= max_pin;
|
||||
}
|
||||
|
||||
if (!in_policy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GPIO_IS_VALID_GPIO((gpio_num_t)pin);
|
||||
}
|
||||
|
||||
bool gpio_policy_pin_is_allowed(int pin)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
return pin_is_allowed_impl(pin, MIMI_GPIO_ALLOWED_CSV,
|
||||
MIMI_GPIO_MIN_PIN, MIMI_GPIO_MAX_PIN, true);
|
||||
#else
|
||||
return pin_is_allowed_impl(pin, MIMI_GPIO_ALLOWED_CSV,
|
||||
MIMI_GPIO_MIN_PIN, MIMI_GPIO_MAX_PIN, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool gpio_policy_pin_forbidden_hint(int pin, char *result, size_t result_len)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
if (pin >= 6 && pin <= 11) {
|
||||
snprintf(result, result_len,
|
||||
"Error: pin %d is reserved for ESP32 flash/PSRAM (GPIO6-11); choose a different pin",
|
||||
pin);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
(void)pin;
|
||||
(void)result;
|
||||
(void)result_len;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
22
main/tools/gpio_policy.h
Normal file
22
main/tools/gpio_policy.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* GPIO pin range defaults for ESP32-S3 (safe user-accessible pins) */
|
||||
#define MIMI_GPIO_MIN_PIN 1
|
||||
#define MIMI_GPIO_MAX_PIN 21
|
||||
#define MIMI_GPIO_ALLOWED_CSV "" /* empty = use min/max range */
|
||||
|
||||
/**
|
||||
* Check if a pin is allowed for user GPIO operations.
|
||||
* Validates against the allowlist or default range, and blocks
|
||||
* pins reserved for flash/PSRAM on ESP32.
|
||||
*/
|
||||
bool gpio_policy_pin_is_allowed(int pin);
|
||||
|
||||
/**
|
||||
* Write a human-readable hint if the pin is forbidden for a known reason.
|
||||
* Returns true if a hint was written (and the caller should return the error).
|
||||
*/
|
||||
bool gpio_policy_pin_forbidden_hint(int pin, char *result, size_t result_len);
|
||||
27
main/tools/tool_gpio.h
Normal file
27
main/tools/tool_gpio.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Initialize GPIO tool — configure allowed pins and directions.
|
||||
*/
|
||||
esp_err_t tool_gpio_init(void);
|
||||
|
||||
/**
|
||||
* Write a GPIO pin HIGH or LOW.
|
||||
* Input JSON: {"pin": <int>, "state": <0|1>}
|
||||
*/
|
||||
esp_err_t tool_gpio_write_execute(const char *input_json, char *output, size_t output_size);
|
||||
|
||||
/**
|
||||
* Read a single GPIO pin state.
|
||||
* Input JSON: {"pin": <int>}
|
||||
*/
|
||||
esp_err_t tool_gpio_read_execute(const char *input_json, char *output, size_t output_size);
|
||||
|
||||
/**
|
||||
* Read all allowed GPIO pin states at once.
|
||||
* Input JSON: {} (no parameters)
|
||||
*/
|
||||
esp_err_t tool_gpio_read_all_execute(const char *input_json, char *output, size_t output_size);
|
||||
Reference in New Issue
Block a user