eth_view_process.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #include "eth_view_process.h"
  2. #include "eth_worker.h"
  3. #include "eth_worker_i.h"
  4. #include "eth_troubleshooter_icons.h"
  5. #include "ui_hacks_again/u8g2.h"
  6. #include <furi_hal.h>
  7. #include <gui/gui.h>
  8. #include <gui/canvas.h>
  9. #include <string.h>
  10. #define TAG "EthView"
  11. EthViewProcess* ethernet_view_process_malloc(EthWorkerProcess type, EthernetSaveConfig* config) {
  12. EthViewProcess* evp = malloc(sizeof(EthViewProcess));
  13. evp->type = type;
  14. evp->autofill = 1;
  15. evp->carriage = 0;
  16. evp->position = 0;
  17. evp->x = 27;
  18. evp->y = 6;
  19. evp->strings_cnt = 10;
  20. if(type == EthWorkerProcessInit) {
  21. evp->y += 22;
  22. EthViewDrawInit* init = malloc(sizeof(EthViewDrawInit));
  23. memset(init, 0, sizeof(EthViewDrawInit));
  24. init->mac = (uint8_t*)config->mac;
  25. evp->draw_struct = init;
  26. } else if(type == EthWorkerProcessStatic) {
  27. evp->y += 22;
  28. EthViewDrawStatic* stat = malloc(sizeof(EthViewDrawStatic));
  29. memset(stat, 0, sizeof(EthViewDrawStatic));
  30. stat->ip = config->ip;
  31. stat->mask = config->mask;
  32. stat->gateway = config->gateway;
  33. stat->dns = config->dns;
  34. evp->draw_struct = stat;
  35. evp->strings_cnt = 20;
  36. } else if(type == EthWorkerProcessDHCP) {
  37. evp->strings_cnt = 20;
  38. } else if(type == EthWorkerProcessPing) {
  39. evp->y += 11;
  40. EthViewDrawPing* ping = malloc(sizeof(EthViewDrawPing));
  41. memset(ping, 0, sizeof(EthViewDrawPing));
  42. ping->ip = config->ping_ip;
  43. evp->draw_struct = ping;
  44. evp->strings_cnt = 20;
  45. }
  46. evp->fifo = malloc(sizeof(EthViewProcessLine) * evp->strings_cnt);
  47. return evp;
  48. }
  49. void ethernet_view_process_free(EthViewProcess* evp) {
  50. free(evp->fifo);
  51. if(evp->type == EthWorkerProcessInit || evp->type == EthWorkerProcessStatic ||
  52. evp->type == EthWorkerProcessPing) {
  53. free(evp->draw_struct);
  54. }
  55. free(evp);
  56. }
  57. static void draw_hex_digit(Canvas* canvas, uint8_t x, uint8_t y, uint8_t digit) {
  58. char digit_str[] = "0";
  59. if(digit < 0xA) {
  60. digit_str[0] += digit;
  61. } else if(digit < 0x10) {
  62. digit_str[0] = 'A';
  63. digit_str[0] += digit - 0xA;
  64. } else {
  65. return;
  66. }
  67. canvas_draw_str(canvas, x, y, digit_str);
  68. }
  69. static void draw_dec_number(Canvas* canvas, uint8_t x, uint8_t y, uint8_t num) {
  70. char num_str[] = "0";
  71. {
  72. num_str[0] = '0' + num % 10;
  73. canvas_draw_str(canvas, x + 6 + 6, y, num_str);
  74. }
  75. if(num >= 10) {
  76. num_str[0] = '0' + num / 10 - (num / 100) * 10;
  77. canvas_draw_str(canvas, x + 6, y, num_str);
  78. }
  79. if(num >= 100) {
  80. num_str[0] = '0' + num / 100;
  81. canvas_draw_str(canvas, x, y, num_str);
  82. }
  83. }
  84. static void draw_static_mode(Canvas* canvas, uint8_t mode) {
  85. const uint8_t s1 = 13;
  86. const uint8_t s2 = 31;
  87. const uint8_t s3 = 19;
  88. const uint8_t s4 = 21;
  89. const uint8_t s = 35;
  90. const uint8_t h = 7;
  91. const uint8_t y = 10;
  92. const uint8_t y1 = 15;
  93. if(mode == EthViewDrawStaticModeIp) {
  94. canvas_invert_color(canvas);
  95. canvas_draw_box(canvas, s, y, s1, h);
  96. canvas_invert_color(canvas);
  97. canvas_draw_str(canvas, 38, y1, "ip");
  98. }
  99. if(mode == EthViewDrawStaticModeMask) {
  100. canvas_invert_color(canvas);
  101. canvas_draw_box(canvas, s + s1, y, s2, h);
  102. canvas_invert_color(canvas);
  103. canvas_draw_str(canvas, 53, y1, "mask");
  104. }
  105. if(mode == EthViewDrawStaticModeGateway) {
  106. canvas_invert_color(canvas);
  107. canvas_draw_box(canvas, s + s1 + s2, y, s3, h);
  108. canvas_invert_color(canvas);
  109. canvas_draw_str(canvas, 82, y1, "gw");
  110. }
  111. if(mode == EthViewDrawStaticModeDNS) {
  112. canvas_invert_color(canvas);
  113. canvas_draw_box(canvas, s + s1 + s2 + s3, y, s4, h);
  114. canvas_invert_color(canvas);
  115. canvas_draw_str(canvas, 102, y1, "dns");
  116. }
  117. }
  118. static uint8_t* draw_static_get_current_address(EthViewDrawStatic* evds) {
  119. furi_assert(evds);
  120. if(evds->current_mode == EthViewDrawStaticModeIp) return evds->ip;
  121. if(evds->current_mode == EthViewDrawStaticModeMask) return evds->mask;
  122. if(evds->current_mode == EthViewDrawStaticModeGateway) return evds->gateway;
  123. if(evds->current_mode == EthViewDrawStaticModeDNS) return evds->dns;
  124. return evds->ip;
  125. }
  126. void ethernet_view_process_draw(EthViewProcess* process, Canvas* canvas) {
  127. furi_assert(canvas);
  128. furi_assert(process);
  129. canvas_set_font(canvas, FontSecondary);
  130. const uint8_t x = process->x;
  131. const uint8_t y = process->y;
  132. const uint8_t str_height = 11;
  133. const uint8_t str_count = (64 - y) / str_height;
  134. uint8_t carriage = process->carriage;
  135. uint8_t position = process->position;
  136. if(process->autofill) {
  137. position = (carriage + process->strings_cnt - str_count) % process->strings_cnt;
  138. process->position = position;
  139. }
  140. for(uint8_t i = 0; i < str_count; ++i) {
  141. uint8_t y1 = y + (i + 1) * str_height;
  142. canvas_draw_str(canvas, x, y1, process->fifo[(position + i) % process->strings_cnt].data);
  143. }
  144. if(process->type == EthWorkerProcessInit) {
  145. uint8_t editing = process->editing;
  146. canvas_draw_icon(canvas, 27, 10, &I_init_100x19px);
  147. uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
  148. uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
  149. for(uint8_t i = 0; i < 6; ++i) {
  150. uint8_t x1 = 29 + i * 17;
  151. uint8_t x2 = x1 + 6;
  152. draw_hex_digit(canvas, x1, 25, (mac[i] & 0xF0) >> 4);
  153. draw_hex_digit(canvas, x2, 25, (mac[i] & 0x0F));
  154. if(editing && (octet / 2 == i)) {
  155. uint8_t x = octet & 1 ? x2 : x1;
  156. canvas_draw_line(canvas, x, 26, x + 4, 26);
  157. canvas_draw_line(canvas, x, 27, x + 4, 27);
  158. }
  159. }
  160. } else if(process->type == EthWorkerProcessStatic) {
  161. canvas_draw_frame(canvas, 31, 18, 21, 13);
  162. canvas_draw_frame(canvas, 55, 18, 21, 13);
  163. canvas_draw_frame(canvas, 79, 18, 21, 13);
  164. canvas_draw_frame(canvas, 103, 18, 21, 13);
  165. canvas_draw_box(canvas, 29, 10, 97, 7);
  166. uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
  167. uint8_t current_digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
  168. uint8_t* address =
  169. draw_static_get_current_address((EthViewDrawStatic*)process->draw_struct);
  170. uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
  171. for(uint8_t i = 0; i < 4; ++i) {
  172. if(i == mode && process->editing) {
  173. draw_static_mode(canvas, mode);
  174. } else {
  175. canvas_invert_color(canvas);
  176. draw_static_mode(canvas, i);
  177. canvas_invert_color(canvas);
  178. }
  179. }
  180. for(uint8_t i = 0; i < 4; ++i) {
  181. uint8_t x = 33 + i * 24;
  182. draw_dec_number(canvas, x, 27, address[i]);
  183. if(editing && (current_digit / 3 == i)) {
  184. uint8_t x1 = x + 6 * (current_digit % 3);
  185. canvas_draw_line(canvas, x1, 28, x1 + 4, 28);
  186. canvas_draw_line(canvas, x1, 29, x1 + 4, 29);
  187. }
  188. }
  189. } else if(process->type == EthWorkerProcessPing) {
  190. canvas_draw_frame(canvas, 35, 8, 21, 13);
  191. canvas_draw_frame(canvas, 59, 8, 21, 13);
  192. canvas_draw_frame(canvas, 83, 8, 21, 13);
  193. canvas_draw_frame(canvas, 107, 8, 21, 13);
  194. uint8_t current_digit = ((EthViewDrawPing*)process->draw_struct)->current_digit;
  195. uint8_t* address = ((EthViewDrawPing*)process->draw_struct)->ip;
  196. for(uint8_t i = 0; i < 4; ++i) {
  197. uint8_t x = 37 + i * 24;
  198. draw_dec_number(canvas, x, 17, address[i]);
  199. if(process->editing && (current_digit / 3 == i)) {
  200. uint8_t x1 = x + 6 * (current_digit % 3);
  201. canvas_draw_line(canvas, x1, 18, x1 + 4, 18);
  202. canvas_draw_line(canvas, x1, 19, x1 + 4, 19);
  203. }
  204. }
  205. } else if(process->type == EthWorkerProcessReset) {
  206. process->editing = 0;
  207. }
  208. }
  209. static void mac_change_hex_digit(uint8_t* mac, uint8_t octet, int8_t diff) {
  210. uint8_t digit = (octet & 1) ? (mac[octet / 2] & 0x0F) : (mac[octet / 2] >> 4);
  211. digit = (digit + diff) & 0xF;
  212. if(octet & 1) {
  213. mac[octet / 2] = (mac[octet / 2] & 0xF0) | digit;
  214. } else {
  215. mac[octet / 2] = (digit << 4) | (mac[octet / 2] & 0x0F);
  216. }
  217. }
  218. static void address_change_dec_digit(uint8_t* ip, uint8_t digit, int8_t diff) {
  219. {
  220. uint8_t k = 0;
  221. k = (digit % 3 == 0) ? 100 : k;
  222. k = (digit % 3 == 1) ? 10 : k;
  223. k = (digit % 3 == 2) ? 1 : k;
  224. diff *= k;
  225. }
  226. {
  227. int16_t ip1 = ip[digit / 3];
  228. if(diff > 0 && ((0x100 - ip1) > diff)) ip1 += diff;
  229. if(diff < 0 && (ip1 + diff >= 0)) ip1 += diff;
  230. ip[digit / 3] = ip1;
  231. }
  232. }
  233. void ethernet_view_process_keyevent(EthViewProcess* process, InputKey key) {
  234. furi_assert(process);
  235. if(process->type == EthWorkerProcessInit) {
  236. uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
  237. uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
  238. if(key == InputKeyLeft) {
  239. if(octet > 0) octet -= 1;
  240. } else if(key == InputKeyRight) {
  241. if(octet < 11) octet += 1;
  242. } else if(key == InputKeyUp) {
  243. mac_change_hex_digit(mac, octet, 1);
  244. } else if(key == InputKeyDown) {
  245. mac_change_hex_digit(mac, octet, -1);
  246. } else if(key == InputKeyOk || key == InputKeyBack) {
  247. process->editing = 0;
  248. }
  249. ((EthViewDrawInit*)process->draw_struct)->current_octet = octet;
  250. } else if(process->type == EthWorkerProcessDHCP) {
  251. process->editing = 0;
  252. if(key == InputKeyUp || key == InputKeyDown) {
  253. ethernet_view_process_move(process, (key == InputKeyDown) ? 1 : -1);
  254. }
  255. } else if(process->type == EthWorkerProcessStatic) {
  256. uint8_t digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
  257. uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
  258. uint8_t* address =
  259. draw_static_get_current_address((EthViewDrawStatic*)process->draw_struct);
  260. uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
  261. if(editing) {
  262. if(key == InputKeyLeft) {
  263. if(digit > 0) {
  264. digit -= 1;
  265. } else {
  266. ((EthViewDrawStatic*)process->draw_struct)->editing = 0;
  267. }
  268. } else if(key == InputKeyRight) {
  269. if(digit < 11) digit += 1;
  270. } else if(key == InputKeyUp) {
  271. address_change_dec_digit(address, digit, 1);
  272. } else if(key == InputKeyDown) {
  273. address_change_dec_digit(address, digit, -1);
  274. } else if(key == InputKeyOk || key == InputKeyBack) {
  275. ((EthViewDrawStatic*)process->draw_struct)->editing = 0;
  276. }
  277. } else {
  278. if(key == InputKeyLeft) {
  279. if(mode > 0) {
  280. mode -= 1;
  281. } else {
  282. process->editing = 0;
  283. }
  284. } else if(key == InputKeyRight) {
  285. if(mode < 3) {
  286. mode += 1;
  287. }
  288. } else if(key == InputKeyUp || key == InputKeyDown) {
  289. ethernet_view_process_move(process, (key == InputKeyDown) ? 1 : -1);
  290. } else if(key == InputKeyOk) {
  291. ((EthViewDrawStatic*)process->draw_struct)->editing = 1;
  292. } else if(key == InputKeyBack) {
  293. mode = 0;
  294. process->editing = 0;
  295. }
  296. }
  297. ((EthViewDrawStatic*)process->draw_struct)->current_mode = mode;
  298. ((EthViewDrawStatic*)process->draw_struct)->current_digit = digit;
  299. } else if(process->type == EthWorkerProcessPing) {
  300. uint8_t digit = ((EthViewDrawPing*)process->draw_struct)->current_digit;
  301. uint8_t* address = ((EthViewDrawPing*)process->draw_struct)->ip;
  302. if(key == InputKeyLeft) {
  303. if(digit > 0) {
  304. digit -= 1;
  305. } else {
  306. process->editing = 0;
  307. }
  308. } else if(key == InputKeyRight) {
  309. if(digit < 11) digit += 1;
  310. } else if(key == InputKeyUp) {
  311. address_change_dec_digit(address, digit, 1);
  312. } else if(key == InputKeyDown) {
  313. address_change_dec_digit(address, digit, -1);
  314. } else if(key == InputKeyOk || key == InputKeyBack) {
  315. process->editing = 0;
  316. }
  317. ((EthViewDrawPing*)process->draw_struct)->current_digit = digit;
  318. } else {
  319. if(key == InputKeyBack || key == InputKeyLeft) {
  320. process->editing = 0;
  321. }
  322. }
  323. }
  324. void ethernet_view_process_move(EthViewProcess* process, int8_t shift) {
  325. furi_assert(process);
  326. uint8_t position = process->position;
  327. if(shift <= -process->strings_cnt) {
  328. position = 0;
  329. } else if(shift >= process->strings_cnt) {
  330. position = process->carriage - 1;
  331. } else {
  332. position = (position + (process->strings_cnt + shift)) % process->strings_cnt;
  333. }
  334. process->position = position;
  335. process->autofill = !shift;
  336. }
  337. void ethernet_view_process_autofill(EthViewProcess* process, uint8_t state) {
  338. furi_assert(process);
  339. process->autofill = state;
  340. }
  341. static uint16_t get_string_with_width(const char* str, uint16_t width) {
  342. u8g2_t canvas_memory;
  343. Canvas* canvas = (Canvas*)&canvas_memory; // grazniy hack
  344. canvas_set_font(canvas, FontSecondary);
  345. uint8_t end = 0;
  346. char copy[SCREEN_SYMBOLS_WIDTH + 1] = {0};
  347. for(;;) {
  348. if(str[end] == '\n') {
  349. break;
  350. }
  351. if(str[end] == '\0') {
  352. break;
  353. }
  354. if(end == SCREEN_SYMBOLS_WIDTH) {
  355. break;
  356. }
  357. copy[end] = str[end];
  358. if(canvas_string_width(canvas, copy) > width) {
  359. end -= 1;
  360. break;
  361. }
  362. end += 1;
  363. }
  364. return end;
  365. }
  366. void evp_printf(EthViewProcess* process, const char* format, ...) {
  367. va_list args;
  368. va_start(args, format);
  369. FuriString* fstring = furi_string_alloc_vprintf(format, args);
  370. va_end(args);
  371. ethernet_view_process_print(process, furi_string_get_cstr(fstring));
  372. furi_string_free(fstring);
  373. }
  374. void ethernet_view_process_print(EthViewProcess* process, const char* str) {
  375. furi_assert(process);
  376. uint16_t max_width = 126 - process->x;
  377. uint16_t ptr = 0;
  378. uint16_t len = strlen(str);
  379. while(ptr < len) {
  380. if(str[ptr] == '\n') ptr += 1;
  381. uint16_t start = ptr;
  382. ptr += get_string_with_width(str + ptr, max_width);
  383. uint8_t carriage = process->carriage;
  384. uint8_t carriage1 = (carriage + 1) % process->strings_cnt;
  385. uint8_t carriage2 = (carriage + 2) % process->strings_cnt;
  386. memset(process->fifo[carriage].data, 0, SCREEN_SYMBOLS_WIDTH);
  387. memset(process->fifo[carriage1].data, 0, SCREEN_SYMBOLS_WIDTH);
  388. memset(process->fifo[carriage2].data, 0, SCREEN_SYMBOLS_WIDTH);
  389. memcpy(process->fifo[carriage].data, str + start, ptr - start);
  390. process->carriage = carriage1;
  391. }
  392. }