eth_view_process.c 15 KB

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