eth_view_process.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include "eth_view_process.h"
  2. #include "eth_worker.h"
  3. #include "eth_worker_i.h"
  4. #include "finik_eth_icons.h"
  5. #include <furi_hal.h>
  6. #include <gui/gui.h>
  7. #include <gui/canvas.h>
  8. #include <string.h>
  9. #include "u8g2.h"
  10. #define TAG "EthView"
  11. EthViewProcess* ethernet_view_process_malloc(EthWorkerProcess type) {
  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. if(type == EthWorkerProcessInit) {
  20. evp->y += 22;
  21. evp->draw_struct = malloc(sizeof(EthViewDrawInit));
  22. memset(evp->draw_struct, 0, sizeof(EthViewDrawInit));
  23. } else if(type == EthWorkerProcessStatic) {
  24. evp->y += 22;
  25. evp->draw_struct = malloc(sizeof(EthViewDrawStatic));
  26. memset(evp->draw_struct, 0, sizeof(EthViewDrawStatic));
  27. }
  28. return evp;
  29. }
  30. void ethernet_view_process_free(EthViewProcess* evp) {
  31. if(evp->type == EthWorkerProcessInit || evp->type == EthWorkerProcessStatic) {
  32. free(evp->draw_struct);
  33. }
  34. free(evp);
  35. }
  36. static void draw_hex_digit(Canvas* canvas, uint8_t x, uint8_t y, uint8_t digit) {
  37. char digit_str[] = "0";
  38. if(digit < 0xA) {
  39. digit_str[0] += digit;
  40. } else if(digit < 0x10) {
  41. digit_str[0] = 'A';
  42. digit_str[0] += digit - 0xA;
  43. } else {
  44. return;
  45. }
  46. canvas_draw_str(canvas, x, y, digit_str);
  47. }
  48. static void draw_dec_number(Canvas* canvas, uint8_t x, uint8_t y, uint8_t num) {
  49. char num_str[] = "0";
  50. {
  51. num_str[0] = '0' + num % 10;
  52. canvas_draw_str(canvas, x + 6 + 6, y, num_str);
  53. }
  54. if(num >= 10) {
  55. num_str[0] = '0' + num / 10 - (num / 100) * 10;
  56. canvas_draw_str(canvas, x + 6, y, num_str);
  57. }
  58. if(num >= 100) {
  59. num_str[0] = '0' + num / 100;
  60. canvas_draw_str(canvas, x, y, num_str);
  61. }
  62. }
  63. static void draw_static_mode(Canvas* canvas, uint8_t mode) {
  64. const uint8_t s1 = 13;
  65. const uint8_t s2 = 30;
  66. const uint8_t s3 = 17;
  67. const uint8_t s4 = 20;
  68. const uint8_t s = 40;
  69. const uint8_t h = 7;
  70. const uint8_t y = 10;
  71. const uint8_t y1 = 15;
  72. if(mode == EthViewDrawStaticModeIp) {
  73. canvas_invert_color(canvas);
  74. canvas_draw_box(canvas, s, y, s1, h);
  75. canvas_invert_color(canvas);
  76. canvas_draw_str(canvas, 43, y1, "ip");
  77. }
  78. if(mode == EthViewDrawStaticModeMask) {
  79. canvas_invert_color(canvas);
  80. canvas_draw_box(canvas, s + s1, y, s2, h);
  81. canvas_invert_color(canvas);
  82. canvas_draw_str(canvas, 57, y1, "mask");
  83. }
  84. if(mode == EthViewDrawStaticModeGateway) {
  85. canvas_invert_color(canvas);
  86. canvas_draw_box(canvas, s + s1 + s2, y, s3, h);
  87. canvas_invert_color(canvas);
  88. canvas_draw_str(canvas, 85, y1, "gw");
  89. }
  90. if(mode == EthViewDrawStaticModeDNS) {
  91. canvas_invert_color(canvas);
  92. canvas_draw_box(canvas, s + s1 + s2 + s3, y, s4, h);
  93. canvas_invert_color(canvas);
  94. canvas_draw_str(canvas, 104, y1, "dns");
  95. }
  96. }
  97. static uint8_t* draw_static_get_current_adress(EthViewDrawStatic* evds) {
  98. furi_assert(evds);
  99. if(evds->current_mode == EthViewDrawStaticModeIp) return evds->ip;
  100. if(evds->current_mode == EthViewDrawStaticModeMask) return evds->mask;
  101. if(evds->current_mode == EthViewDrawStaticModeGateway) return evds->gateway;
  102. if(evds->current_mode == EthViewDrawStaticModeDNS) return evds->dns;
  103. return evds->ip;
  104. }
  105. void ethernet_view_process_draw(EthViewProcess* process, Canvas* canvas) {
  106. furi_assert(canvas);
  107. furi_assert(process);
  108. canvas_set_font(canvas, FontSecondary);
  109. const uint8_t x = process->x;
  110. const uint8_t y = process->y;
  111. const uint8_t str_height = 11;
  112. const uint8_t str_count = (64 - y) / str_height;
  113. uint8_t carriage = process->carriage;
  114. uint8_t position = process->position;
  115. if(process->autofill) {
  116. position = (carriage + SCREEN_STRINGS_COUNT - str_count) % SCREEN_STRINGS_COUNT;
  117. process->position = position;
  118. }
  119. for(uint8_t i = 0; i < str_count; ++i) {
  120. uint8_t y1 = y + (i + 1) * str_height;
  121. canvas_draw_str(canvas, x, y1, process->fifo[(position + i) % SCREEN_STRINGS_COUNT]);
  122. }
  123. if(process->type == EthWorkerProcessInit) {
  124. uint8_t editing = process->editing;
  125. canvas_draw_icon(canvas, 27, 10, &I_init_100x19px);
  126. uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
  127. uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
  128. for(uint8_t i = 0; i < 6; ++i) {
  129. uint8_t x1 = 29 + i * 17;
  130. uint8_t x2 = x1 + 6;
  131. draw_hex_digit(canvas, x1, 25, (mac[i] & 0x0F));
  132. draw_hex_digit(canvas, x2, 25, (mac[i] & 0xF0) >> 4);
  133. if(editing && (octet / 2 == i)) {
  134. uint8_t x = octet & 1 ? x2 : x1;
  135. canvas_draw_line(canvas, x, 26, x + 4, 26);
  136. canvas_draw_line(canvas, x, 27, x + 4, 27);
  137. }
  138. }
  139. } else if(process->type == EthWorkerProcessStatic) {
  140. canvas_draw_frame(canvas, 36, 18, 21, 13);
  141. canvas_draw_frame(canvas, 59, 18, 21, 13);
  142. canvas_draw_frame(canvas, 82, 18, 21, 13);
  143. canvas_draw_frame(canvas, 105, 18, 21, 13);
  144. canvas_draw_box(canvas, 36, 10, 90, 7);
  145. uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
  146. uint8_t current_digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
  147. uint8_t* adress = draw_static_get_current_adress((EthViewDrawStatic*)process->draw_struct);
  148. uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
  149. for(uint8_t i = 0; i < 4; ++i) {
  150. if(i == mode) {
  151. draw_static_mode(canvas, mode);
  152. } else {
  153. canvas_invert_color(canvas);
  154. draw_static_mode(canvas, i);
  155. canvas_invert_color(canvas);
  156. }
  157. }
  158. for(uint8_t i = 0; i < 4; ++i) {
  159. uint8_t x = 38 + i * 23;
  160. draw_dec_number(canvas, x, 27, adress[i]);
  161. if(editing && (current_digit / 3 == i)) {
  162. uint8_t x1 = x + 6 * (current_digit % 3);
  163. canvas_draw_line(canvas, x1, 28, x1 + 4, 28);
  164. canvas_draw_line(canvas, x1, 29, x1 + 4, 29);
  165. }
  166. }
  167. }
  168. }
  169. static void mac_change_hex_digit(uint8_t* mac, uint8_t octet, int8_t diff) {
  170. uint8_t digit = (octet & 1) ? (mac[octet / 2] >> 4) : (mac[octet / 2]);
  171. digit = (digit + diff) & 0xF;
  172. mac[octet / 2] = (mac[octet / 2] & ((octet & 1) ? 0x0F : 0xF0)) |
  173. (digit << ((octet & 1) ? 4 : 0));
  174. }
  175. static void adress_change_dec_digit(uint8_t* ip, uint8_t digit, int8_t diff) {
  176. {
  177. uint8_t k = 0;
  178. k = (digit % 3 == 0) ? 100 : k;
  179. k = (digit % 3 == 1) ? 10 : k;
  180. k = (digit % 3 == 2) ? 1 : k;
  181. diff *= k;
  182. }
  183. {
  184. int16_t ip1 = ip[digit / 3];
  185. if(diff > 0 && ((0x100 - ip1) > diff)) ip1 += diff;
  186. if(diff < 0 && (ip1 + diff >= 0)) ip1 += diff;
  187. ip[digit / 3] = ip1;
  188. }
  189. }
  190. void ethernet_view_process_keyevent(EthViewProcess* process, InputKey key) {
  191. furi_assert(process);
  192. if(process->type == EthWorkerProcessInit) {
  193. uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
  194. uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
  195. if(key == InputKeyLeft) {
  196. if(octet > 0) octet -= 1;
  197. } else if(key == InputKeyRight) {
  198. if(octet < 11) octet += 1;
  199. } else if(key == InputKeyUp) {
  200. mac_change_hex_digit(mac, octet, 1);
  201. } else if(key == InputKeyDown) {
  202. mac_change_hex_digit(mac, octet, -1);
  203. } else if(key == InputKeyOk) {
  204. process->editing = 0;
  205. }
  206. ((EthViewDrawInit*)process->draw_struct)->current_octet = octet;
  207. } else if(process->type == EthWorkerProcessStatic) {
  208. uint8_t digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
  209. uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
  210. uint8_t* adress = draw_static_get_current_adress((EthViewDrawStatic*)process->draw_struct);
  211. uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
  212. if(editing) {
  213. if(key == InputKeyLeft) {
  214. if(digit > 0) digit -= 1;
  215. } else if(key == InputKeyRight) {
  216. if(digit < 11) digit += 1;
  217. } else if(key == InputKeyUp) {
  218. adress_change_dec_digit(adress, digit, 1);
  219. } else if(key == InputKeyDown) {
  220. adress_change_dec_digit(adress, digit, -1);
  221. } else if(key == InputKeyOk) {
  222. ((EthViewDrawStatic*)process->draw_struct)->editing = 0;
  223. }
  224. } else {
  225. if(key == InputKeyLeft) {
  226. if(mode > 0) {
  227. mode -= 1;
  228. } else {
  229. process->editing = 0;
  230. }
  231. } else if(key == InputKeyRight) {
  232. if(mode < 3) {
  233. mode += 1;
  234. }
  235. } else if(key == InputKeyUp || key == InputKeyDown) {
  236. ((EthViewDrawStatic*)process->draw_struct)->editing = 1;
  237. }
  238. }
  239. ((EthViewDrawStatic*)process->draw_struct)->current_mode = mode;
  240. ((EthViewDrawStatic*)process->draw_struct)->current_digit = digit;
  241. }
  242. }
  243. void ethernet_view_process_move(EthViewProcess* process, int8_t shift) {
  244. furi_assert(process);
  245. uint8_t position = process->position;
  246. if(shift <= -SCREEN_STRINGS_COUNT) {
  247. position = 0;
  248. } else if(shift >= SCREEN_STRINGS_COUNT) {
  249. position = process->carriage - 1;
  250. } else {
  251. position = (position + (SCREEN_STRINGS_COUNT + shift)) % SCREEN_STRINGS_COUNT;
  252. }
  253. process->position = position;
  254. process->autofill = !shift;
  255. }
  256. void ethernet_view_process_autofill(EthViewProcess* process, uint8_t state) {
  257. furi_assert(process);
  258. process->autofill = state;
  259. }
  260. static uint16_t get_string_with_width(const char* str, uint16_t width) {
  261. u8g2_t canvas_memory;
  262. Canvas* canvas = (Canvas*)&canvas_memory; // grazniy hack
  263. canvas_set_font(canvas, FontSecondary);
  264. uint8_t end = 0;
  265. char copy[SCREEN_SYMBOLS_WIDTH + 1] = {0};
  266. for(;;) {
  267. if(str[end] == '\0') {
  268. break;
  269. }
  270. if(end == SCREEN_SYMBOLS_WIDTH) {
  271. break;
  272. }
  273. copy[end] = str[end];
  274. if(canvas_string_width(canvas, copy) > width) {
  275. end -= 1;
  276. break;
  277. }
  278. end += 1;
  279. }
  280. return end;
  281. }
  282. void ethernet_view_process_print(EthViewProcess* process, const char* str) {
  283. furi_assert(process);
  284. uint16_t max_width = 126 - process->x;
  285. uint16_t ptr = 0;
  286. uint16_t len = strlen(str);
  287. while(ptr < len) {
  288. uint16_t start = ptr;
  289. ptr += get_string_with_width(str + ptr, max_width);
  290. uint8_t carriage = process->carriage;
  291. uint8_t carriage1 = (carriage + 1) % SCREEN_STRINGS_COUNT;
  292. uint8_t carriage2 = (carriage + 2) % SCREEN_STRINGS_COUNT;
  293. FURI_LOG_I(TAG, "print %d %d %d %d %d", max_width, len, start, carriage, carriage1);
  294. memset(process->fifo[carriage], 0, SCREEN_SYMBOLS_WIDTH);
  295. memset(process->fifo[carriage1], 0, SCREEN_SYMBOLS_WIDTH);
  296. memset(process->fifo[carriage2], 0, SCREEN_SYMBOLS_WIDTH);
  297. memcpy(process->fifo[carriage], str + start, ptr - start);
  298. process->carriage = carriage1;
  299. }
  300. }