|
|
@@ -0,0 +1,220 @@
|
|
|
+#include "eth_save_process.h"
|
|
|
+
|
|
|
+#include <furi.h>
|
|
|
+#include <storage/storage.h>
|
|
|
+
|
|
|
+#define TAG "EthSave"
|
|
|
+
|
|
|
+#define STORAGE_FILE_BUF_LEN 50
|
|
|
+
|
|
|
+// fuction spizzhena from archive_favorites.c
|
|
|
+static bool storage_read_line(File* file, FuriString* str_result) {
|
|
|
+ furi_string_reset(str_result);
|
|
|
+ uint8_t buffer[STORAGE_FILE_BUF_LEN];
|
|
|
+ bool result = false;
|
|
|
+
|
|
|
+ do {
|
|
|
+ uint16_t read_count = storage_file_read(file, buffer, STORAGE_FILE_BUF_LEN);
|
|
|
+ if(storage_file_get_error(file) != FSE_OK) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ for(uint16_t i = 0; i < read_count; i++) {
|
|
|
+ if(buffer[i] == '\n') {
|
|
|
+ uint32_t position = storage_file_tell(file);
|
|
|
+ if(storage_file_get_error(file) != FSE_OK) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ position = position - read_count + i + 1;
|
|
|
+
|
|
|
+ storage_file_seek(file, position, true);
|
|
|
+ if(storage_file_get_error(file) != FSE_OK) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ result = true;
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ furi_string_push_back(str_result, buffer[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(result || read_count == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while(true);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static bool storage_printf(File* file, const char* format, ...) {
|
|
|
+ va_list args;
|
|
|
+ va_start(args, format);
|
|
|
+ FuriString* fstring = furi_string_alloc_vprintf(format, args);
|
|
|
+ va_end(args);
|
|
|
+ if(storage_file_write(file, furi_string_get_cstr(fstring), furi_string_size(fstring)) &&
|
|
|
+ storage_file_write(file, "\n", 1)) {
|
|
|
+ furi_string_free(fstring);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ furi_string_free(fstring);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static bool storage_write_config(File* file, const EthernetSaveConfig* cfg) {
|
|
|
+ storage_file_seek(file, 0, true);
|
|
|
+ storage_file_truncate(file);
|
|
|
+
|
|
|
+ bool result = true;
|
|
|
+ result = result ? storage_printf(
|
|
|
+ file,
|
|
|
+ "mac: %02X-%02X-%02X-%02X-%02X-%02X",
|
|
|
+ cfg->mac[0],
|
|
|
+ cfg->mac[1],
|
|
|
+ cfg->mac[2],
|
|
|
+ cfg->mac[3],
|
|
|
+ cfg->mac[4],
|
|
|
+ cfg->mac[5]) :
|
|
|
+ result;
|
|
|
+ result = result ?
|
|
|
+ storage_printf(
|
|
|
+ file, "ip: %d.%d.%d.%d", cfg->ip[0], cfg->ip[1], cfg->ip[2], cfg->ip[3]) :
|
|
|
+ result;
|
|
|
+ result =
|
|
|
+ result ?
|
|
|
+ storage_printf(
|
|
|
+ file, "mask: %d.%d.%d.%d", cfg->mask[0], cfg->mask[1], cfg->mask[2], cfg->mask[3]) :
|
|
|
+ result;
|
|
|
+ result = result ? storage_printf(
|
|
|
+ file,
|
|
|
+ "gateway: %d.%d.%d.%d",
|
|
|
+ cfg->gateway[0],
|
|
|
+ cfg->gateway[1],
|
|
|
+ cfg->gateway[2],
|
|
|
+ cfg->gateway[3]) :
|
|
|
+ result;
|
|
|
+ result =
|
|
|
+ result ?
|
|
|
+ storage_printf(
|
|
|
+ file, "dns: %d.%d.%d.%d", cfg->dns[0], cfg->dns[1], cfg->dns[2], cfg->dns[3]) :
|
|
|
+ result;
|
|
|
+ result = result ? storage_printf(
|
|
|
+ file,
|
|
|
+ "ping_ip: %d.%d.%d.%d",
|
|
|
+ cfg->ping_ip[0],
|
|
|
+ cfg->ping_ip[1],
|
|
|
+ cfg->ping_ip[2],
|
|
|
+ cfg->ping_ip[3]) :
|
|
|
+ result;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static void read_02X(const char* str, uint8_t* byte) {
|
|
|
+ uint8_t b[2] = {str[0], str[1]};
|
|
|
+
|
|
|
+ for(int i = 0; i < 2; ++i) {
|
|
|
+ if('0' <= b[i] && b[i] <= '9') {
|
|
|
+ b[i] -= '0';
|
|
|
+ } else if('A' <= b[i] && b[i] <= 'F') {
|
|
|
+ b[i] -= 'A' - 0x0A;
|
|
|
+ } else {
|
|
|
+ b[i] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ *byte = b[1] + (b[0] << 4);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_default_config(EthernetSaveConfig* cfg) {
|
|
|
+ const uint8_t def_mac[6] = ETHERNET_SAVE_DEFAULT_MAC;
|
|
|
+ const uint8_t def_ip[4] = ETHERNET_SAVE_DEFAULT_IP;
|
|
|
+ const uint8_t def_mask[4] = ETHERNET_SAVE_DEFAULT_MASK;
|
|
|
+ const uint8_t def_gateway[4] = ETHERNET_SAVE_DEFAULT_GATEWAY;
|
|
|
+ const uint8_t def_dns[4] = ETHERNET_SAVE_DEFAULT_DNS;
|
|
|
+ const uint8_t def_ping_ip[4] = ETHERNET_SAVE_DEFAULT_PING_IP;
|
|
|
+
|
|
|
+ memcpy(cfg->mac, def_mac, 6);
|
|
|
+ memcpy(cfg->ip, def_ip, 4);
|
|
|
+ memcpy(cfg->mask, def_mask, 4);
|
|
|
+ memcpy(cfg->gateway, def_gateway, 4);
|
|
|
+ memcpy(cfg->dns, def_dns, 4);
|
|
|
+ memcpy(cfg->ping_ip, def_ping_ip, 4);
|
|
|
+}
|
|
|
+
|
|
|
+bool storage_read_config(File* file, EthernetSaveConfig* cfg) {
|
|
|
+ FuriString* fstring = furi_string_alloc();
|
|
|
+
|
|
|
+ while(storage_read_line(file, fstring)) {
|
|
|
+ const char* str = furi_string_get_cstr(fstring);
|
|
|
+ if(!strncmp(str, "mac: ", 5)) {
|
|
|
+ read_02X(str + strlen("mac: "), &cfg->mac[0]);
|
|
|
+ read_02X(str + strlen("mac: XX-"), &cfg->mac[1]);
|
|
|
+ read_02X(str + strlen("mac: XX-XX-"), &cfg->mac[2]);
|
|
|
+ read_02X(str + strlen("mac: XX-XX-XX-"), &cfg->mac[3]);
|
|
|
+ read_02X(str + strlen("mac: XX-XX-XX-XX-"), &cfg->mac[4]);
|
|
|
+ read_02X(str + strlen("mac: XX-XX-XX-XX-XX-"), &cfg->mac[5]);
|
|
|
+ } else if(!strncmp(str, "ip: ", 4)) {
|
|
|
+ } else if(!strncmp(str, "mask: ", 6)) {
|
|
|
+ } else if(!strncmp(str, "gateway: ", 9)) {
|
|
|
+ } else if(!strncmp(str, "dns: ", 5)) {
|
|
|
+ } else if(!strncmp(str, "ping_ip: ", 9)) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+void ethernet_save_process_write(const EthernetSaveConfig* config) {
|
|
|
+ Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
|
+
|
|
|
+ File* file = storage_file_alloc(storage);
|
|
|
+
|
|
|
+ if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
|
|
+ FURI_LOG_E(TAG, "Failed to open file");
|
|
|
+ storage_file_free(file);
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!storage_write_config(file, config)) {
|
|
|
+ FURI_LOG_E(TAG, "Failed to write cpnfig to file");
|
|
|
+ storage_file_close(file);
|
|
|
+ storage_file_free(file);
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ storage_file_close(file);
|
|
|
+ storage_file_free(file);
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+}
|
|
|
+
|
|
|
+void ethernet_save_process_read(EthernetSaveConfig* config) {
|
|
|
+ set_default_config(config);
|
|
|
+
|
|
|
+ Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
|
+
|
|
|
+ File* file = storage_file_alloc(storage);
|
|
|
+
|
|
|
+ if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
|
|
+ FURI_LOG_E(TAG, "Failed to open file or file not exists");
|
|
|
+ storage_file_free(file);
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(!storage_read_config(file, config)) {
|
|
|
+ FURI_LOG_E(TAG, "Failed to read config from file");
|
|
|
+ storage_file_close(file);
|
|
|
+ storage_file_free(file);
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ storage_file_close(file);
|
|
|
+
|
|
|
+ storage_file_free(file);
|
|
|
+
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+}
|
|
|
+
|
|
|
+void ehternet_save_process_print(char* str) {
|
|
|
+}
|