eth_save_process.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "eth_save_process.h"
  2. #include <furi.h>
  3. #include <storage/storage.h>
  4. #define TAG "EthSave"
  5. #define STORAGE_FILE_BUF_LEN 50
  6. // fuction spizzhena from archive_favorites.c
  7. static bool storage_read_line(File* file, FuriString* str_result) {
  8. furi_string_reset(str_result);
  9. uint8_t buffer[STORAGE_FILE_BUF_LEN];
  10. bool result = false;
  11. do {
  12. uint16_t read_count = storage_file_read(file, buffer, STORAGE_FILE_BUF_LEN);
  13. if(storage_file_get_error(file) != FSE_OK) {
  14. return false;
  15. }
  16. for(uint16_t i = 0; i < read_count; i++) {
  17. if(buffer[i] == '\n') {
  18. uint32_t position = storage_file_tell(file);
  19. if(storage_file_get_error(file) != FSE_OK) {
  20. return false;
  21. }
  22. position = position - read_count + i + 1;
  23. storage_file_seek(file, position, true);
  24. if(storage_file_get_error(file) != FSE_OK) {
  25. return false;
  26. }
  27. result = true;
  28. break;
  29. } else {
  30. furi_string_push_back(str_result, buffer[i]);
  31. }
  32. }
  33. if(result || read_count == 0) {
  34. break;
  35. }
  36. } while(true);
  37. return result;
  38. }
  39. static bool storage_printf(File* file, const char* format, ...) {
  40. va_list args;
  41. va_start(args, format);
  42. FuriString* fstring = furi_string_alloc_vprintf(format, args);
  43. va_end(args);
  44. if(storage_file_write(file, furi_string_get_cstr(fstring), furi_string_size(fstring)) &&
  45. storage_file_write(file, "\n", 1)) {
  46. furi_string_free(fstring);
  47. return true;
  48. }
  49. furi_string_free(fstring);
  50. return false;
  51. }
  52. static bool storage_write_config(File* file, const EthernetSaveConfig* cfg) {
  53. storage_file_seek(file, 0, true);
  54. storage_file_truncate(file);
  55. bool result = true;
  56. result = result ? storage_printf(
  57. file,
  58. "mac: %02X-%02X-%02X-%02X-%02X-%02X",
  59. cfg->mac[0],
  60. cfg->mac[1],
  61. cfg->mac[2],
  62. cfg->mac[3],
  63. cfg->mac[4],
  64. cfg->mac[5]) :
  65. result;
  66. result = result ?
  67. storage_printf(
  68. file, "ip: %d.%d.%d.%d", cfg->ip[0], cfg->ip[1], cfg->ip[2], cfg->ip[3]) :
  69. result;
  70. result =
  71. result ?
  72. storage_printf(
  73. file, "mask: %d.%d.%d.%d", cfg->mask[0], cfg->mask[1], cfg->mask[2], cfg->mask[3]) :
  74. result;
  75. result = result ? storage_printf(
  76. file,
  77. "gateway: %d.%d.%d.%d",
  78. cfg->gateway[0],
  79. cfg->gateway[1],
  80. cfg->gateway[2],
  81. cfg->gateway[3]) :
  82. result;
  83. result =
  84. result ?
  85. storage_printf(
  86. file, "dns: %d.%d.%d.%d", cfg->dns[0], cfg->dns[1], cfg->dns[2], cfg->dns[3]) :
  87. result;
  88. result = result ? storage_printf(
  89. file,
  90. "ping_ip: %d.%d.%d.%d",
  91. cfg->ping_ip[0],
  92. cfg->ping_ip[1],
  93. cfg->ping_ip[2],
  94. cfg->ping_ip[3]) :
  95. result;
  96. return result;
  97. }
  98. static void read_02X(const char* str, uint8_t* byte) {
  99. uint8_t b[2] = {str[0], str[1]};
  100. for(int i = 0; i < 2; ++i) {
  101. if('0' <= b[i] && b[i] <= '9') {
  102. b[i] -= '0';
  103. } else if('A' <= b[i] && b[i] <= 'F') {
  104. b[i] -= 'A' - 0x0A;
  105. } else {
  106. b[i] = 0;
  107. }
  108. }
  109. *byte = b[1] + (b[0] << 4);
  110. }
  111. static void read_ip(const char* str, uint8_t* ip) {
  112. uint8_t ip_i = 0;
  113. uint8_t i = 0;
  114. uint16_t tmp = 0;
  115. for(;;) {
  116. if('0' <= str[i] && str[i] <= '9') {
  117. tmp = tmp * 10 + str[i] - '0';
  118. } else if(str[i] == '.' || str[i] != '\n' || str[i] != '\0') {
  119. if(tmp <= 0xFF && ip_i < 4) {
  120. ip[ip_i] = tmp;
  121. ip_i += 1;
  122. tmp = 0;
  123. } else {
  124. break;
  125. }
  126. if(str[i] != '\n' && ip_i == 4) {
  127. return;
  128. }
  129. } else {
  130. break;
  131. }
  132. i += 1;
  133. }
  134. FURI_LOG_E(TAG, "cannot parse as ip string [%s]", str);
  135. ip[0] = ip[1] = ip[2] = ip[3] = 0;
  136. return;
  137. }
  138. static void set_default_config(EthernetSaveConfig* cfg) {
  139. const uint8_t def_mac[6] = ETHERNET_SAVE_DEFAULT_MAC;
  140. const uint8_t def_ip[4] = ETHERNET_SAVE_DEFAULT_IP;
  141. const uint8_t def_mask[4] = ETHERNET_SAVE_DEFAULT_MASK;
  142. const uint8_t def_gateway[4] = ETHERNET_SAVE_DEFAULT_GATEWAY;
  143. const uint8_t def_dns[4] = ETHERNET_SAVE_DEFAULT_DNS;
  144. const uint8_t def_ping_ip[4] = ETHERNET_SAVE_DEFAULT_PING_IP;
  145. memcpy(cfg->mac, def_mac, 6);
  146. memcpy(cfg->ip, def_ip, 4);
  147. memcpy(cfg->mask, def_mask, 4);
  148. memcpy(cfg->gateway, def_gateway, 4);
  149. memcpy(cfg->dns, def_dns, 4);
  150. memcpy(cfg->ping_ip, def_ping_ip, 4);
  151. }
  152. bool storage_read_config(File* file, EthernetSaveConfig* cfg) {
  153. FuriString* fstring = furi_string_alloc();
  154. while(storage_read_line(file, fstring)) {
  155. const char* str = furi_string_get_cstr(fstring);
  156. if(!strncmp(str, "mac: ", 5)) {
  157. read_02X(str + strlen("mac: "), &cfg->mac[0]);
  158. read_02X(str + strlen("mac: XX-"), &cfg->mac[1]);
  159. read_02X(str + strlen("mac: XX-XX-"), &cfg->mac[2]);
  160. read_02X(str + strlen("mac: XX-XX-XX-"), &cfg->mac[3]);
  161. read_02X(str + strlen("mac: XX-XX-XX-XX-"), &cfg->mac[4]);
  162. read_02X(str + strlen("mac: XX-XX-XX-XX-XX-"), &cfg->mac[5]);
  163. } else if(!strncmp(str, "ip: ", 4)) {
  164. read_ip(str + strlen("ip: "), cfg->ip);
  165. } else if(!strncmp(str, "mask: ", 6)) {
  166. read_ip(str + strlen("mask: "), cfg->mask);
  167. } else if(!strncmp(str, "gateway: ", 9)) {
  168. read_ip(str + strlen("gateway: "), cfg->gateway);
  169. } else if(!strncmp(str, "dns: ", 5)) {
  170. read_ip(str + strlen("dns: "), cfg->dns);
  171. } else if(!strncmp(str, "ping_ip: ", 9)) {
  172. read_ip(str + strlen("ping_ip: "), cfg->ping_ip);
  173. }
  174. }
  175. return true;
  176. }
  177. void ethernet_save_process_write(const EthernetSaveConfig* config) {
  178. Storage* storage = furi_record_open(RECORD_STORAGE);
  179. File* file = storage_file_alloc(storage);
  180. if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
  181. FURI_LOG_E(TAG, "Failed to open file");
  182. storage_file_free(file);
  183. furi_record_close(RECORD_STORAGE);
  184. return;
  185. }
  186. if(!storage_write_config(file, config)) {
  187. FURI_LOG_E(TAG, "Failed to write cpnfig to file");
  188. storage_file_close(file);
  189. storage_file_free(file);
  190. furi_record_close(RECORD_STORAGE);
  191. return;
  192. }
  193. storage_file_close(file);
  194. storage_file_free(file);
  195. furi_record_close(RECORD_STORAGE);
  196. }
  197. void ethernet_save_process_read(EthernetSaveConfig* config) {
  198. set_default_config(config);
  199. Storage* storage = furi_record_open(RECORD_STORAGE);
  200. File* file = storage_file_alloc(storage);
  201. if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_READ, FSOM_OPEN_EXISTING)) {
  202. FURI_LOG_E(TAG, "Failed to open file or file not exists");
  203. storage_file_free(file);
  204. furi_record_close(RECORD_STORAGE);
  205. return;
  206. }
  207. if(!storage_read_config(file, config)) {
  208. FURI_LOG_E(TAG, "Failed to read config from file");
  209. storage_file_close(file);
  210. storage_file_free(file);
  211. furi_record_close(RECORD_STORAGE);
  212. return;
  213. }
  214. storage_file_close(file);
  215. storage_file_free(file);
  216. furi_record_close(RECORD_STORAGE);
  217. }
  218. void ehternet_save_process_print(char* str) {
  219. }