فهرست منبع

Implemented PIN changing via CLI (#32)

Alexander Kopachov 3 سال پیش
والد
کامیت
8d4abf92c2
61فایلهای تغییر یافته به همراه376 افزوده شده و 179 حذف شده
  1. 2 2
      FAQ.md
  2. 1 1
      build.ps1
  3. 1 1
      clang-format-all.ps1
  4. 18 1
      totp/application.fam
  5. 4 0
      totp/cli/cli.c
  6. 1 1
      totp/cli/cli.h
  7. 0 0
      totp/cli/cli_helpers.c
  8. 1 1
      totp/cli/cli_helpers.h
  9. 5 5
      totp/cli/commands/add/add.c
  10. 1 1
      totp/cli/commands/add/add.h
  11. 3 3
      totp/cli/commands/delete/delete.c
  12. 1 1
      totp/cli/commands/delete/delete.h
  13. 3 0
      totp/cli/commands/help/help.c
  14. 0 0
      totp/cli/commands/help/help.h
  15. 3 3
      totp/cli/commands/list/list.c
  16. 1 1
      totp/cli/commands/list/list.h
  17. 4 4
      totp/cli/commands/move/move.c
  18. 1 1
      totp/cli/commands/move/move.h
  19. 166 0
      totp/cli/commands/pin/pin.c
  20. 10 0
      totp/cli/commands/pin/pin.h
  21. 2 2
      totp/cli/commands/timezone/timezone.c
  22. 1 1
      totp/cli/commands/timezone/timezone.h
  23. 0 0
      totp/lib/base32/base32.c
  24. 0 0
      totp/lib/base32/base32.h
  25. 0 0
      totp/lib/list/list.c
  26. 0 0
      totp/lib/list/list.h
  27. 0 0
      totp/lib/polyfills/memset_s.c
  28. 0 0
      totp/lib/polyfills/memset_s.h
  29. 11 0
      totp/lib/polyfills/strnlen.c
  30. 3 0
      totp/lib/polyfills/strnlen.h
  31. 0 0
      totp/lib/roll_value/roll_value.c
  32. 0 0
      totp/lib/roll_value/roll_value.h
  33. 0 0
      totp/lib/timezone_utils/timezone_utils.c
  34. 0 0
      totp/lib/timezone_utils/timezone_utils.h
  35. 0 23
      totp/services/hid_worker/hid_worker.h
  36. 1 1
      totp/services/totp/totp.c
  37. 3 5
      totp/totp_app.c
  38. 0 0
      totp/types/nullable.h
  39. 2 2
      totp/types/plugin_state.h
  40. 2 2
      totp/types/token_info.c
  41. 8 0
      totp/types/user_pin_codes.h
  42. 0 0
      totp/ui/constants.h
  43. 5 5
      totp/ui/scene_director.c
  44. 0 0
      totp/ui/scene_director.h
  45. 1 11
      totp/ui/scenes/add_new_token/totp_input_text.c
  46. 2 4
      totp/ui/scenes/add_new_token/totp_input_text.h
  47. 9 10
      totp/ui/scenes/add_new_token/totp_scene_add_new_token.c
  48. 2 2
      totp/ui/scenes/add_new_token/totp_scene_add_new_token.h
  49. 7 6
      totp/ui/scenes/app_settings/totp_app_settings.c
  50. 2 4
      totp/ui/scenes/app_settings/totp_app_settings.h
  51. 12 15
      totp/ui/scenes/authenticate/totp_scene_authenticate.c
  52. 2 4
      totp/ui/scenes/authenticate/totp_scene_authenticate.h
  53. 19 19
      totp/ui/scenes/generate_token/totp_scene_generate_token.c
  54. 2 4
      totp/ui/scenes/generate_token/totp_scene_generate_token.h
  55. 8 8
      totp/ui/scenes/token_menu/totp_scene_token_menu.c
  56. 2 4
      totp/ui/scenes/token_menu/totp_scene_token_menu.h
  57. 0 0
      totp/ui/totp_scenes_enum.h
  58. 0 0
      totp/ui/ui_controls.c
  59. 0 0
      totp/ui/ui_controls.h
  60. 21 21
      totp/workers/type_code/type_code.c
  61. 23 0
      totp/workers/type_code/type_code.h

+ 2 - 2
FAQ.md

@@ -44,9 +44,9 @@ For now there is no way to change or recover PIN once it is set without loosing
 
 All token secrets are stored in encrypted form and are tied to an original Flipper device and PIN. Given that, there is no sense to try to backup `/ext/apps/Misc/totp.conf` file as it will not help you in situation when you loose your Flipper device. Instead use your favorite password manager to store plain token secrets and\or any other information which will help you recover your accounts.
 
-## Flipper Authenticator generates invalid tokens, why so?
+## Flipper Authenticator generates invalid codes, why so?
 
-There are multiple reasons why Flipper Authenticator generates invalid tokens:
+There are multiple reasons why Flipper Authenticator generates invalid codes:
 
 ### Clock is not precise
 

+ 1 - 1
build.ps1

@@ -8,7 +8,7 @@ function Get-LatestDirectory {
 
 $build_commands = @(
     [PSCustomObject]@{
-        Name = "Official Dev";
+        Name = "Official Dev \ Unleashed";
         FbtSwitch = "od";
         FirmwarePath = "flipperzero-firmware_official_dev";
         ArtifactName = "totp_official-dev_unleashed_fw.fap"

+ 1 - 1
clang-format-all.ps1

@@ -1,4 +1,4 @@
-$clang_format = Join-Path -Path $PSScriptRoot -ChildPath "flipperzero-firmware_unleashed/toolchain/x86_64-windows/bin/clang-format.exe"
+$clang_format = Join-Path -Path $PSScriptRoot -ChildPath "flipperzero-firmware_official_dev/toolchain/x86_64-windows/bin/clang-format.exe"
 Push-Location $PSScriptRoot
 Get-ChildItem -Path "totp" -File -Recurse -Include "*.c", "*.h" | ForEach-Object {
     Write-Host "Formatting $($_.FullName)"

+ 18 - 1
totp/application.fam

@@ -16,5 +16,22 @@ App(
     order=20,
     fap_category="Misc",
     fap_icon_assets="images",
-    fap_icon="totp_10px.png"
+    fap_icon="totp_10px.png",
+    fap_private_libs=[
+        Lib(
+            name="base32",
+        ),
+        Lib(
+            name="list",
+        ),
+        Lib(
+            name="timezone_utils",
+        ),
+        Lib(
+            name="polyfills",
+        ),
+        Lib(
+            name="roll_value",
+        ),
+    ],
 )

+ 4 - 0
totp/services/cli/cli.c → totp/cli/cli.c

@@ -9,6 +9,7 @@
 #include "commands/timezone/timezone.h"
 #include "commands/help/help.h"
 #include "commands/move/move.h"
+#include "commands/pin/pin.h"
 
 static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
     TOTP_CLI_PRINTF(
@@ -49,6 +50,9 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE) == 0 ||
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE_ALT) == 0) {
         totp_cli_command_move_handle(plugin_state, args, cli);
+    } else if(
+        furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_PIN) == 0) {
+        totp_cli_command_pin_handle(plugin_state, args, cli);
     } else {
         totp_cli_print_unknown_command(cmd);
     }

+ 1 - 1
totp/services/cli/cli.h → totp/cli/cli.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../types/plugin_state.h"
+#include "../types/plugin_state.h"
 
 void totp_cli_register_command_handler(PluginState* plugin_state);
 void totp_cli_unregister_command_handler();

+ 0 - 0
totp/services/cli/cli_helpers.c → totp/cli/cli_helpers.c


+ 1 - 1
totp/services/cli/cli_helpers.h → totp/cli/cli_helpers.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../types/plugin_state.h"
+#include "../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_NAME "totp"
 

+ 5 - 5
totp/services/cli/commands/add/add.c → totp/cli/commands/add/add.c

@@ -1,11 +1,11 @@
 #include "add.h"
 #include <stdlib.h>
 #include <lib/toolbox/args.h>
-#include "../../../list/list.h"
-#include "../../../../types/token_info.h"
-#include "../../../config/config.h"
+#include "../../../lib/list/list.h"
+#include "../../../types/token_info.h"
+#include "../../../services/config/config.h"
 #include "../../cli_helpers.h"
-#include "../../../../scenes/scene_director.h"
+#include "../../../ui/scene_director.h"
 
 #define TOTP_CLI_COMMAND_ADD_ARG_NAME "name"
 #define TOTP_CLI_COMMAND_ADD_ARG_ALGO "algo"
@@ -94,7 +94,7 @@ static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_i
     while(cli_read(cli, &c, 1) == 1) {
         if(c == CliSymbolAsciiEsc) {
             // Some keys generating escape-sequences
-            // We need to ignore them as we case about alpha-numerics only
+            // We need to ignore them as we care about alpha-numerics only
             uint8_t c2;
             cli_read_timeout(cli, &c2, 1, 0);
             cli_read_timeout(cli, &c2, 1, 0);

+ 1 - 1
totp/services/cli/commands/add/add.h → totp/cli/commands/add/add.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../../../types/plugin_state.h"
+#include "../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_ADD "add"
 #define TOTP_CLI_COMMAND_ADD_ALT "mk"

+ 3 - 3
totp/services/cli/commands/delete/delete.c → totp/cli/commands/delete/delete.c

@@ -3,10 +3,10 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <lib/toolbox/args.h>
-#include "../../../list/list.h"
-#include "../../../config/config.h"
+#include "../../../lib/list/list.h"
+#include "../../../services/config/config.h"
 #include "../../cli_helpers.h"
-#include "../../../../scenes/scene_director.h"
+#include "../../../ui/scene_director.h"
 
 #define TOTP_CLI_COMMAND_DELETE_ARG_INDEX "index"
 #define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX "-f"

+ 1 - 1
totp/services/cli/commands/delete/delete.h → totp/cli/commands/delete/delete.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../../../types/plugin_state.h"
+#include "../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_DELETE "delete"
 #define TOTP_CLI_COMMAND_DELETE_ALT "rm"

+ 3 - 0
totp/services/cli/commands/help/help.c → totp/cli/commands/help/help.c

@@ -5,6 +5,7 @@
 #include "../list/list.h"
 #include "../timezone/timezone.h"
 #include "../move/move.h"
+#include "../pin/pin.h"
 
 void totp_cli_command_help_docopt_commands() {
     TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
@@ -25,6 +26,7 @@ void totp_cli_command_help_handle() {
     totp_cli_command_delete_docopt_usage();
     totp_cli_command_timezone_docopt_usage();
     totp_cli_command_move_docopt_usage();
+    totp_cli_command_pin_docopt_usage();
     cli_nl();
     TOTP_CLI_PRINTF("Commands:\r\n");
     totp_cli_command_help_docopt_commands();
@@ -33,6 +35,7 @@ void totp_cli_command_help_handle() {
     totp_cli_command_delete_docopt_commands();
     totp_cli_command_timezone_docopt_commands();
     totp_cli_command_move_docopt_commands();
+    totp_cli_command_pin_docopt_commands();
     cli_nl();
     TOTP_CLI_PRINTF("Arguments:\r\n");
     totp_cli_command_add_docopt_arguments();

+ 0 - 0
totp/services/cli/commands/help/help.h → totp/cli/commands/help/help.h


+ 3 - 3
totp/services/cli/commands/list/list.c → totp/cli/commands/list/list.c

@@ -1,8 +1,8 @@
 #include "list.h"
 #include <stdlib.h>
-#include "../../../list/list.h"
-#include "../../../../types/token_info.h"
-#include "../../../config/constants.h"
+#include "../../../lib/list/list.h"
+#include "../../../types/token_info.h"
+#include "../../../services/config/constants.h"
 #include "../../cli_helpers.h"
 
 static char* get_algo_as_cstr(TokenHashAlgo algo) {

+ 1 - 1
totp/services/cli/commands/list/list.h → totp/cli/commands/list/list.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../../../types/plugin_state.h"
+#include "../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_LIST "list"
 #define TOTP_CLI_COMMAND_LIST_ALT "ls"

+ 4 - 4
totp/services/cli/commands/move/move.c → totp/cli/commands/move/move.c

@@ -2,11 +2,11 @@
 
 #include <stdlib.h>
 #include <lib/toolbox/args.h>
-#include "../../../list/list.h"
-#include "../../../../types/token_info.h"
-#include "../../../config/config.h"
+#include "../../../lib/list/list.h"
+#include "../../../types/token_info.h"
+#include "../../../services/config/config.h"
 #include "../../cli_helpers.h"
-#include "../../../../scenes/scene_director.h"
+#include "../../../ui/scene_director.h"
 
 #define TOTP_CLI_COMMAND_MOVE_ARG_INDEX "index"
 

+ 1 - 1
totp/services/cli/commands/move/move.h → totp/cli/commands/move/move.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../../../types/plugin_state.h"
+#include "../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_MOVE "move"
 #define TOTP_CLI_COMMAND_MOVE_ALT "mv"

+ 166 - 0
totp/cli/commands/pin/pin.c

@@ -0,0 +1,166 @@
+#include "pin.h"
+
+#include <stdlib.h>
+#include <lib/toolbox/args.h>
+#include "../../../types/token_info.h"
+#include "../../../types/user_pin_codes.h"
+#include "../../../services/config/config.h"
+#include "../../cli_helpers.h"
+#include "../../../lib/polyfills/memset_s.h"
+#include "../../../services/crypto/crypto.h"
+#include "../../../ui/scene_director.h"
+
+#define TOTP_CLI_COMMAND_PIN_COMMAND_SET "set"
+#define TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE "remove"
+
+void totp_cli_command_pin_docopt_commands() {
+    TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_PIN "              Set\\change\\remove PIN\r\n");
+}
+
+void totp_cli_command_pin_docopt_usage() {
+    TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_PIN " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_PIN_COMMAND_SET " | " TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) "\r\n");
+}
+
+static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
+    TOTP_CLI_PRINTF("Enter new PIN (use arrow keys on your keyboard): ");
+    fflush(stdout);
+    uint8_t c;
+    *pin_length = 0;
+    while(cli_read(cli, &c, 1) == 1) {
+        if(c == CliSymbolAsciiEsc) {
+            uint8_t c2;
+            uint8_t c3;
+            if (cli_read_timeout(cli, &c2, 1, 0) == 1 &&
+                cli_read_timeout(cli, &c3, 1, 0) == 1 &&
+                c2 == 0x5b) {
+                uint8_t code = 0;
+                switch (c3) {
+                    case 0x44: // left
+                        code = PinCodeArrowLeft;
+                        break;
+                    case 0x41: // up
+                        code = PinCodeArrowUp;
+                        break;
+                    case 0x43: // right
+                        code = PinCodeArrowRight;
+                        break;
+                    case 0x42: // down
+                        code = PinCodeArrowDown;
+                        break;
+                    default:
+                    break;
+                }
+
+                if (code > 0) {
+                    pin[*pin_length] = code;
+                    *pin_length = *pin_length + 1;
+                    putc('*', stdout);
+                    fflush(stdout);
+                }
+            }
+        } else if(c == CliSymbolAsciiETX) {
+            TOTP_CLI_DELETE_CURRENT_LINE();
+            TOTP_CLI_PRINTF("Cancelled by user\r\n");
+            return false;
+        } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
+            if (*pin_length > 0) {
+                *pin_length = *pin_length - 1;
+                pin[*pin_length] = 0;
+                TOTP_CLI_DELETE_LAST_CHAR();
+            }
+        } else if(c == CliSymbolAsciiCR) {
+            cli_nl();
+            break;
+        }
+    }
+
+    TOTP_CLI_DELETE_LAST_LINE();
+    return true;
+}
+
+void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+    UNUSED(plugin_state);
+    FuriString* temp_str = furi_string_alloc();
+
+    bool do_change = false;
+    bool do_remove = false;
+    UNUSED(do_remove);
+    do {
+        if (!args_read_string_and_trim(args, temp_str)) {
+            TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+            break;
+        }
+
+        if (furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_SET) == 0) {
+            do_change = true;
+        } else if (furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) == 0) {
+            do_remove = true;
+        } else {
+            TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+            break;
+        }
+    } while (false);
+
+    if ((do_change || do_remove) && totp_cli_ensure_authenticated(plugin_state, cli)) {
+        bool load_generate_token_scene = false;
+        do {
+            uint8_t old_iv[TOTP_IV_SIZE];
+            memcpy(&old_iv[0], &plugin_state->iv[0], TOTP_IV_SIZE);
+            uint8_t new_pin[TOTP_IV_SIZE];
+            uint8_t new_pin_length = 0;
+            if (do_change) {
+                if (!totp_cli_read_pin(cli, &new_pin[0], &new_pin_length) ||
+                    !totp_cli_ensure_authenticated(plugin_state, cli)) {
+                    memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE);
+                    break;
+                }
+            } else if (do_remove) {
+                new_pin_length = 0;
+                memset(&new_pin[0], 0, TOTP_IV_SIZE);
+            }
+
+            if(plugin_state->current_scene == TotpSceneGenerateToken) {
+                totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
+                load_generate_token_scene = true;
+            }
+
+            TOTP_CLI_PRINTF("Encrypting, please wait...\r\n");
+
+            memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE);
+            memset(&plugin_state->base_iv[0], 0, TOTP_IV_SIZE);
+            if (plugin_state->crypto_verify_data != NULL) {
+                free(plugin_state->crypto_verify_data);
+                plugin_state->crypto_verify_data = NULL;
+            }
+
+            totp_crypto_seed_iv(plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length);
+            ListNode* node = plugin_state->tokens_list;
+            while (node != NULL) {
+                TokenInfo* token_info = node->data;
+                size_t plain_token_length; 
+                uint8_t* plain_token = totp_crypto_decrypt(token_info->token, token_info->token_length, &old_iv[0], &plain_token_length);
+                free(token_info->token);
+                token_info->token = totp_crypto_encrypt(plain_token, plain_token_length, &plugin_state->iv[0], &token_info->token_length);
+                memset_s(plain_token, plain_token_length, 0, plain_token_length);
+                free(plain_token);
+                node = node->next;
+            }
+
+            totp_full_save_config_file(plugin_state);
+
+            TOTP_CLI_DELETE_LAST_LINE();
+
+            if (do_change) {
+                TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
+            } else if (do_remove) {
+                TOTP_CLI_PRINTF("PIN has been successfully removed\r\n");
+            }
+        } while (false);
+
+        if(load_generate_token_scene) {
+            totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
+        }
+    }
+
+    furi_string_free(temp_str);
+}

+ 10 - 0
totp/cli/commands/pin/pin.h

@@ -0,0 +1,10 @@
+#pragma once
+
+#include <cli/cli.h>
+#include "../../../types/plugin_state.h"
+
+#define TOTP_CLI_COMMAND_PIN "pin"
+
+void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
+void totp_cli_command_pin_docopt_commands();
+void totp_cli_command_pin_docopt_usage();

+ 2 - 2
totp/services/cli/commands/timezone/timezone.c → totp/cli/commands/timezone/timezone.c

@@ -1,7 +1,7 @@
 #include "timezone.h"
 #include <lib/toolbox/args.h>
-#include "../../../config/config.h"
-#include "../../../../scenes/scene_director.h"
+#include "../../../services/config/config.h"
+#include "../../../ui/scene_director.h"
 #include "../../cli_helpers.h"
 
 #define TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE "timezone"

+ 1 - 1
totp/services/cli/commands/timezone/timezone.h → totp/cli/commands/timezone/timezone.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <cli/cli.h>
-#include "../../../../types/plugin_state.h"
+#include "../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_TIMEZONE "timezone"
 #define TOTP_CLI_COMMAND_TIMEZONE_ALT "tz"

+ 0 - 0
totp/services/base32/base32.c → totp/lib/base32/base32.c


+ 0 - 0
totp/services/base32/base32.h → totp/lib/base32/base32.h


+ 0 - 0
totp/services/list/list.c → totp/lib/list/list.c


+ 0 - 0
totp/services/list/list.h → totp/lib/list/list.h


+ 0 - 0
totp/services/crypto/memset_s.c → totp/lib/polyfills/memset_s.c


+ 0 - 0
totp/services/crypto/memset_s.h → totp/lib/polyfills/memset_s.h


+ 11 - 0
totp/lib/polyfills/strnlen.c

@@ -0,0 +1,11 @@
+#include "strnlen.h"
+
+size_t strnlen(const char* s, size_t maxlen) {
+    size_t len;
+
+    for(len = 0; len < maxlen; len++, s++) {
+        if(!*s) break;
+    }
+
+    return len;
+}

+ 3 - 0
totp/lib/polyfills/strnlen.h

@@ -0,0 +1,3 @@
+#include <stddef.h>
+
+size_t strnlen(const char* s, size_t maxlen);

+ 0 - 0
totp/services/roll_value/roll_value.c → totp/lib/roll_value/roll_value.c


+ 0 - 0
totp/services/roll_value/roll_value.h → totp/lib/roll_value/roll_value.h


+ 0 - 0
totp/services/timezone_utils/timezone_utils.c → totp/lib/timezone_utils/timezone_utils.c


+ 0 - 0
totp/services/timezone_utils/timezone_utils.h → totp/lib/timezone_utils/timezone_utils.h


+ 0 - 23
totp/services/hid_worker/hid_worker.h

@@ -1,23 +0,0 @@
-#pragma once
-
-#include <stdlib.h>
-#include <furi/furi.h>
-#include <furi_hal.h>
-
-typedef struct {
-    char* string;
-    uint8_t string_length;
-    FuriThread* thread;
-    FuriMutex* string_sync;
-    FuriHalUsbInterface* usb_mode_prev;
-} TotpHidWorkerTypeContext;
-
-typedef enum {
-    TotpHidWorkerEvtReserved = (1 << 0),
-    TotpHidWorkerEvtStop = (1 << 1),
-    TotpHidWorkerEvtType = (1 << 2)
-} TotpHidWorkerEvtFlags;
-
-TotpHidWorkerTypeContext* totp_hid_worker_start();
-void totp_hid_worker_stop(TotpHidWorkerTypeContext* context);
-void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event);

+ 1 - 1
totp/services/totp/totp.c

@@ -9,7 +9,7 @@
 #include "../hmac/hmac_sha256.h"
 #include "../hmac/hmac_sha512.h"
 #include "../hmac/byteswap.h"
-#include "../timezone_utils/timezone_utils.h"
+#include "../../lib/timezone_utils/timezone_utils.h"
 
 #define HMAC_MAX_SIZE 64
 

+ 3 - 5
totp/totp_app.c

@@ -7,18 +7,16 @@
 #include <flipper_format/flipper_format.h>
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
-#include "services/base32/base32.h"
-#include "services/list/list.h"
 #include "services/config/config.h"
 #include "types/plugin_state.h"
 #include "types/token_info.h"
 #include "types/plugin_event.h"
 #include "types/event_type.h"
 #include "types/common.h"
-#include "scenes/scene_director.h"
-#include "services/ui/constants.h"
+#include "ui/scene_director.h"
+#include "ui/constants.h"
 #include "services/crypto/crypto.h"
-#include "services/cli/cli.h"
+#include "cli/cli.h"
 
 #define IDLE_TIMEOUT 60000
 

+ 0 - 0
totp/services/nullable/nullable.h → totp/types/nullable.h


+ 2 - 2
totp/types/plugin_state.h

@@ -3,8 +3,8 @@
 #include <notification/notification.h>
 #include <gui/gui.h>
 #include <dialogs/dialogs.h>
-#include "../services/list/list.h"
-#include "../scenes/totp_scenes_enum.h"
+#include "../lib/list/list.h"
+#include "../ui/totp_scenes_enum.h"
 
 #define TOTP_IV_SIZE 16
 

+ 2 - 2
totp/types/token_info.c

@@ -3,9 +3,9 @@
 #include "token_info.h"
 #include "stdlib.h"
 #include "common.h"
-#include "../services/base32/base32.h"
+#include "../lib/base32/base32.h"
 #include "../services/crypto/crypto.h"
-#include "../services/crypto/memset_s.h"
+#include "../lib/polyfills/memset_s.h"
 
 TokenInfo* token_info_alloc() {
     TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));

+ 8 - 0
totp/types/user_pin_codes.h

@@ -0,0 +1,8 @@
+#pragma once
+
+typedef enum uint8_t {
+    PinCodeArrowUp = 2,
+    PinCodeArrowRight = 8,
+    PinCodeArrowDown = 11,
+    PinCodeArrowLeft = 5
+} TotpUserPinCode;

+ 0 - 0
totp/services/ui/constants.h → totp/ui/constants.h


+ 5 - 5
totp/scenes/scene_director.c → totp/ui/scene_director.c

@@ -1,10 +1,10 @@
 #include "../types/common.h"
 #include "scene_director.h"
-#include "authenticate/totp_scene_authenticate.h"
-#include "generate_token/totp_scene_generate_token.h"
-#include "add_new_token/totp_scene_add_new_token.h"
-#include "token_menu/totp_scene_token_menu.h"
-#include "app_settings/totp_app_settings.h"
+#include "scenes/authenticate/totp_scene_authenticate.h"
+#include "scenes/generate_token/totp_scene_generate_token.h"
+#include "scenes/add_new_token/totp_scene_add_new_token.h"
+#include "scenes/token_menu/totp_scene_token_menu.h"
+#include "scenes/app_settings/totp_app_settings.h"
 
 void totp_scene_director_activate_scene(
     PluginState* const plugin_state,

+ 0 - 0
totp/scenes/scene_director.h → totp/ui/scene_director.h


+ 1 - 11
totp/scenes/add_new_token/totp_input_text.c → totp/ui/scenes/add_new_token/totp_input_text.c

@@ -1,16 +1,6 @@
 #include "totp_input_text.h"
 #include <gui/view_i.h>
-#include "../../types/common.h"
-
-size_t strnlen(const char* s, size_t maxlen) {
-    size_t len;
-
-    for(len = 0; len < maxlen; len++, s++) {
-        if(!*s) break;
-    }
-
-    return len;
-}
+#include "../../../lib/polyfills/strnlen.h"
 
 void view_draw(View* view, Canvas* canvas) {
     furi_assert(view);

+ 2 - 4
totp/scenes/add_new_token/totp_input_text.h → totp/ui/scenes/add_new_token/totp_input_text.h

@@ -3,10 +3,8 @@
 #include <gui/gui.h>
 #include <gui/view.h>
 #include <gui/modules/text_input.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 typedef struct {
     char* user_input;

+ 9 - 10
totp/scenes/add_new_token/totp_scene_add_new_token.c → totp/ui/scenes/add_new_token/totp_scene_add_new_token.c

@@ -1,15 +1,14 @@
 #include "totp_scene_add_new_token.h"
-#include "../../types/common.h"
-#include "../../services/ui/constants.h"
-#include "../scene_director.h"
+#include "../../../types/common.h"
+#include "../../constants.h"
+#include "../../scene_director.h"
 #include "totp_input_text.h"
-#include "../../types/token_info.h"
-#include "../../services/list/list.h"
-#include "../../services/base32/base32.h"
-#include "../../services/config/config.h"
-#include "../../services/ui/ui_controls.h"
-#include "../../services/roll_value/roll_value.h"
-#include "../../services/nullable/nullable.h"
+#include "../../../types/token_info.h"
+#include "../../../lib/list/list.h"
+#include "../../../services/config/config.h"
+#include "../../ui_controls.h"
+#include "../../../lib/roll_value/roll_value.h"
+#include "../../../types/nullable.h"
 #include "../generate_token/totp_scene_generate_token.h"
 
 #define TOKEN_ALGO_LIST_LENGTH 3

+ 2 - 2
totp/scenes/add_new_token/totp_scene_add_new_token.h → totp/ui/scenes/add_new_token/totp_scene_add_new_token.h

@@ -3,8 +3,8 @@
 #include <gui/gui.h>
 #include <furi.h>
 #include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 typedef struct {
     uint16_t current_token_index;

+ 7 - 6
totp/scenes/app_settings/totp_app_settings.c → totp/ui/scenes/app_settings/totp_app_settings.c

@@ -1,11 +1,12 @@
 #include "totp_app_settings.h"
-#include "../../services/ui/ui_controls.h"
-#include "../scene_director.h"
+#include <math.h>
+#include "../../ui_controls.h"
+#include "../../scene_director.h"
 #include "../token_menu/totp_scene_token_menu.h"
-#include "../../services/ui/constants.h"
-#include "../../services/config/config.h"
-#include "../../services/roll_value/roll_value.h"
-#include "../../services/nullable/nullable.h"
+#include "../../constants.h"
+#include "../../../services/config/config.h"
+#include "../../../lib/roll_value/roll_value.h"
+#include "../../../types/nullable.h"
 
 #define DIGIT_TO_CHAR(digit) ((digit) + '0')
 

+ 2 - 4
totp/scenes/app_settings/totp_app_settings.h → totp/ui/scenes/app_settings/totp_app_settings.h

@@ -1,10 +1,8 @@
 #pragma once
 
 #include <gui/gui.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 typedef struct {
     uint16_t current_token_index;

+ 12 - 15
totp/scenes/authenticate/totp_scene_authenticate.c → totp/ui/scenes/authenticate/totp_scene_authenticate.c

@@ -1,21 +1,18 @@
 #include "totp_scene_authenticate.h"
 #include <dialogs/dialogs.h>
 #include <totp_icons.h>
-#include "../../types/common.h"
-#include "../../services/ui/constants.h"
-#include "../../services/config/config.h"
-#include "../scene_director.h"
-#include "../totp_scenes_enum.h"
-#include "../../services/crypto/crypto.h"
+#include "../../../types/common.h"
+#include "../../constants.h"
+#include "../../../services/config/config.h"
+#include "../../scene_director.h"
+#include "../../totp_scenes_enum.h"
+#include "../../../services/crypto/crypto.h"
+#include "../../../types/user_pin_codes.h"
 
 #define MAX_CODE_LENGTH TOTP_IV_SIZE
-#define ARROW_UP_CODE 2
-#define ARROW_RIGHT_CODE 8
-#define ARROW_DOWN_CODE 11
-#define ARROW_LEFT_CODE 5
 
 typedef struct {
-    uint8_t code_input[MAX_CODE_LENGTH];
+    TotpUserPinCode code_input[MAX_CODE_LENGTH];
     uint8_t code_length;
 } SceneState;
 
@@ -98,25 +95,25 @@ bool totp_scene_authenticate_handle_event(
     switch(event->input.key) {
     case InputKeyUp:
         if(scene_state->code_length < MAX_CODE_LENGTH) {
-            scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE;
+            scene_state->code_input[scene_state->code_length] = PinCodeArrowUp;
             scene_state->code_length++;
         }
         break;
     case InputKeyDown:
         if(scene_state->code_length < MAX_CODE_LENGTH) {
-            scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE;
+            scene_state->code_input[scene_state->code_length] = PinCodeArrowDown;
             scene_state->code_length++;
         }
         break;
     case InputKeyRight:
         if(scene_state->code_length < MAX_CODE_LENGTH) {
-            scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE;
+            scene_state->code_input[scene_state->code_length] = PinCodeArrowRight;
             scene_state->code_length++;
         }
         break;
     case InputKeyLeft:
         if(scene_state->code_length < MAX_CODE_LENGTH) {
-            scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE;
+            scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft;
             scene_state->code_length++;
         }
         break;

+ 2 - 4
totp/scenes/authenticate/totp_scene_authenticate.h → totp/ui/scenes/authenticate/totp_scene_authenticate.h

@@ -1,10 +1,8 @@
 #pragma once
 
 #include <gui/gui.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 void totp_scene_authenticate_init(PluginState* plugin_state);
 void totp_scene_authenticate_activate(PluginState* plugin_state);

+ 19 - 19
totp/scenes/generate_token/totp_scene_generate_token.c → totp/ui/scenes/generate_token/totp_scene_generate_token.c

@@ -3,17 +3,17 @@
 #include <notification/notification_messages.h>
 #include <totp_icons.h>
 #include "totp_scene_generate_token.h"
-#include "../../types/token_info.h"
-#include "../../types/common.h"
-#include "../../services/ui/constants.h"
-#include "../../services/totp/totp.h"
-#include "../../services/config/config.h"
-#include "../../services/crypto/crypto.h"
-#include "../../services/crypto/memset_s.h"
-#include "../../services/roll_value/roll_value.h"
-#include "../scene_director.h"
+#include "../../../types/token_info.h"
+#include "../../../types/common.h"
+#include "../../constants.h"
+#include "../../../services/totp/totp.h"
+#include "../../../services/config/config.h"
+#include "../../../services/crypto/crypto.h"
+#include "../../../lib/polyfills/memset_s.h"
+#include "../../../lib/roll_value/roll_value.h"
+#include "../../scene_director.h"
 #include "../token_menu/totp_scene_token_menu.h"
-#include "../../services/hid_worker/hid_worker.h"
+#include "../../../workers/type_code/type_code.h"
 
 #define TOKEN_LIFETIME 30
 #define DIGIT_TO_CHAR(digit) ((digit) + '0')
@@ -24,7 +24,7 @@ typedef struct {
     char* last_code_name;
     bool need_token_update;
     uint32_t last_token_gen_time;
-    TotpHidWorkerTypeContext* hid_worker_context;
+    TotpTypeCodeWorkerContext* type_code_worker_context;
 } SceneState;
 
 static const NotificationSequence notification_sequence_new_token = {
@@ -152,9 +152,9 @@ void totp_scene_generate_token_activate(
     plugin_state->current_scene_state = scene_state;
     FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset);
     update_totp_params(plugin_state);
-    scene_state->hid_worker_context = totp_hid_worker_start();
-    scene_state->hid_worker_context->string = &scene_state->last_code[0];
-    scene_state->hid_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
+    scene_state->type_code_worker_context = totp_type_code_worker_start();
+    scene_state->type_code_worker_context->string = &scene_state->last_code[0];
+    scene_state->type_code_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
 }
 
 void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) {
@@ -196,7 +196,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
                              ->data);
 
         if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
-            furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
+            furi_mutex_acquire(scene_state->type_code_worker_context->string_sync, FuriWaitForever);
             size_t key_length;
             uint8_t* key = totp_crypto_decrypt(
                 tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
@@ -215,11 +215,11 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
             memset_s(key, key_length, 0, key_length);
             free(key);
         } else {
-            furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
+            furi_mutex_acquire(scene_state->type_code_worker_context->string_sync, FuriWaitForever);
             i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
         }
 
-        furi_mutex_release(scene_state->hid_worker_context->string_sync);
+        furi_mutex_release(scene_state->type_code_worker_context->string_sync);
 
         if(is_new_token_time) {
             notification_message(plugin_state->notification, &notification_sequence_new_token);
@@ -288,7 +288,7 @@ bool totp_scene_generate_token_handle_event(
     SceneState* scene_state;
     if(event->input.type == InputTypeLong && event->input.key == InputKeyDown) {
         scene_state = (SceneState*)plugin_state->current_scene_state;
-        totp_hid_worker_notify(scene_state->hid_worker_context, TotpHidWorkerEvtType);
+        totp_type_code_worker_notify(scene_state->type_code_worker_context, TotpTypeCodeWorkerEvtType);
         notification_message(plugin_state->notification, &notification_sequence_badusb);
         return true;
     }
@@ -342,7 +342,7 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
     if(plugin_state->current_scene_state == NULL) return;
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
 
-    totp_hid_worker_stop(scene_state->hid_worker_context);
+    totp_type_code_worker_stop(scene_state->type_code_worker_context);
 
     free(scene_state);
     plugin_state->current_scene_state = NULL;

+ 2 - 4
totp/scenes/generate_token/totp_scene_generate_token.h → totp/ui/scenes/generate_token/totp_scene_generate_token.h

@@ -1,10 +1,8 @@
 #pragma once
 
 #include <gui/gui.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 typedef struct {
     uint16_t current_token_index;

+ 8 - 8
totp/scenes/token_menu/totp_scene_token_menu.c → totp/ui/scenes/token_menu/totp_scene_token_menu.c

@@ -1,17 +1,17 @@
 #include "totp_scene_token_menu.h"
 #include <gui/gui.h>
 #include <dialogs/dialogs.h>
-#include "../../services/ui/ui_controls.h"
-#include "../../services/ui/constants.h"
-#include "../scene_director.h"
-#include "../../services/config/config.h"
-#include "../../services/list/list.h"
-#include "../../types/token_info.h"
+#include "../../ui_controls.h"
+#include "../../constants.h"
+#include "../../scene_director.h"
+#include "../../../services/config/config.h"
+#include "../../../lib/list/list.h"
+#include "../../../types/token_info.h"
 #include "../generate_token/totp_scene_generate_token.h"
 #include "../add_new_token/totp_scene_add_new_token.h"
 #include "../app_settings/totp_app_settings.h"
-#include "../../services/nullable/nullable.h"
-#include "../../services/roll_value/roll_value.h"
+#include "../../../types/nullable.h"
+#include "../../../lib/roll_value/roll_value.h"
 
 #define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3)
 #define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1)

+ 2 - 4
totp/scenes/token_menu/totp_scene_token_menu.h → totp/ui/scenes/token_menu/totp_scene_token_menu.h

@@ -1,10 +1,8 @@
 #pragma once
 
 #include <gui/gui.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include "../../types/plugin_state.h"
-#include "../../types/plugin_event.h"
+#include "../../../types/plugin_state.h"
+#include "../../../types/plugin_event.h"
 
 typedef struct {
     uint16_t current_token_index;

+ 0 - 0
totp/scenes/totp_scenes_enum.h → totp/ui/totp_scenes_enum.h


+ 0 - 0
totp/services/ui/ui_controls.c → totp/ui/ui_controls.c


+ 0 - 0
totp/services/ui/ui_controls.h → totp/ui/ui_controls.h


+ 21 - 21
totp/services/hid_worker/hid_worker.c → totp/workers/type_code/type_code.c

@@ -1,4 +1,4 @@
-#include "hid_worker.h"
+#include "type_code.h"
 
 static const uint8_t hid_number_keys[10] = {
     HID_KEYBOARD_0,
@@ -12,18 +12,18 @@ static const uint8_t hid_number_keys[10] = {
     HID_KEYBOARD_8,
     HID_KEYBOARD_9};
 
-static void totp_hid_worker_restore_usb_mode(TotpHidWorkerTypeContext* context) {
+static void totp_type_code_worker_restore_usb_mode(TotpTypeCodeWorkerContext* context) {
     if(context->usb_mode_prev != NULL) {
         furi_hal_usb_set_config(context->usb_mode_prev, NULL);
         context->usb_mode_prev = NULL;
     }
 }
 
-static inline bool totp_hid_worker_stop_requested() {
-    return furi_thread_flags_get() & TotpHidWorkerEvtStop;
+static inline bool totp_type_code_worker_stop_requested() {
+    return furi_thread_flags_get() & TotpTypeCodeWorkerEvtStop;
 }
 
-static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
+static void totp_type_code_worker_type_code(TotpTypeCodeWorkerContext* context) {
     context->usb_mode_prev = furi_hal_usb_get_config();
     furi_hal_usb_unlock();
     furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
@@ -31,7 +31,7 @@ static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
     do {
         furi_delay_ms(500);
         i++;
-    } while(!furi_hal_hid_is_connected() && i < 100 && !totp_hid_worker_stop_requested());
+    } while(!furi_hal_hid_is_connected() && i < 100 && !totp_type_code_worker_stop_requested());
 
     if(furi_hal_hid_is_connected() &&
        furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
@@ -52,24 +52,24 @@ static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
         furi_delay_ms(100);
     }
 
-    totp_hid_worker_restore_usb_mode(context);
+    totp_type_code_worker_restore_usb_mode(context);
 }
 
-static int32_t totp_hid_worker_callback(void* context) {
+static int32_t totp_type_code_worker_callback(void* context) {
     ValueMutex context_mutex;
-    if(!init_mutex(&context_mutex, context, sizeof(TotpHidWorkerTypeContext))) {
+    if(!init_mutex(&context_mutex, context, sizeof(TotpTypeCodeWorkerContext))) {
         return 251;
     }
 
     while(true) {
         uint32_t flags = furi_thread_flags_wait(
-            TotpHidWorkerEvtStop | TotpHidWorkerEvtType, FuriFlagWaitAny, FuriWaitForever);
+            TotpTypeCodeWorkerEvtStop | TotpTypeCodeWorkerEvtType, FuriFlagWaitAny, FuriWaitForever);
         furi_check((flags & FuriFlagError) == 0); //-V562
-        if(flags & TotpHidWorkerEvtStop) break;
+        if(flags & TotpTypeCodeWorkerEvtStop) break;
 
-        TotpHidWorkerTypeContext* h_context = acquire_mutex_block(&context_mutex);
-        if(flags & TotpHidWorkerEvtType) {
-            totp_hid_worker_type_code(h_context);
+        TotpTypeCodeWorkerContext* h_context = acquire_mutex_block(&context_mutex);
+        if(flags & TotpTypeCodeWorkerEvtType) {
+            totp_type_code_worker_type_code(h_context);
         }
 
         release_mutex(&context_mutex, h_context);
@@ -80,8 +80,8 @@ static int32_t totp_hid_worker_callback(void* context) {
     return 0;
 }
 
-TotpHidWorkerTypeContext* totp_hid_worker_start() {
-    TotpHidWorkerTypeContext* context = malloc(sizeof(TotpHidWorkerTypeContext));
+TotpTypeCodeWorkerContext* totp_type_code_worker_start() {
+    TotpTypeCodeWorkerContext* context = malloc(sizeof(TotpTypeCodeWorkerContext));
     furi_check(context != NULL);
     context->string_sync = furi_mutex_alloc(FuriMutexTypeNormal);
     context->thread = furi_thread_alloc();
@@ -89,22 +89,22 @@ TotpHidWorkerTypeContext* totp_hid_worker_start() {
     furi_thread_set_name(context->thread, "TOTPHidWorker");
     furi_thread_set_stack_size(context->thread, 1024);
     furi_thread_set_context(context->thread, context);
-    furi_thread_set_callback(context->thread, totp_hid_worker_callback);
+    furi_thread_set_callback(context->thread, totp_type_code_worker_callback);
     furi_thread_start(context->thread);
     return context;
 }
 
-void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
+void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context) {
     furi_assert(context != NULL);
-    furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
+    furi_thread_flags_set(furi_thread_get_id(context->thread), TotpTypeCodeWorkerEvtStop);
     furi_thread_join(context->thread);
     furi_thread_free(context->thread);
     furi_mutex_free(context->string_sync);
-    totp_hid_worker_restore_usb_mode(context);
+    totp_type_code_worker_restore_usb_mode(context);
     free(context);
 }
 
-void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
+void totp_type_code_worker_notify(TotpTypeCodeWorkerContext* context, TotpTypeCodeWorkerEvtFlags event) {
     furi_assert(context != NULL);
     furi_thread_flags_set(furi_thread_get_id(context->thread), event);
 }

+ 23 - 0
totp/workers/type_code/type_code.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include <stdlib.h>
+#include <furi/furi.h>
+#include <furi_hal.h>
+
+typedef struct {
+    char* string;
+    uint8_t string_length;
+    FuriThread* thread;
+    FuriMutex* string_sync;
+    FuriHalUsbInterface* usb_mode_prev;
+} TotpTypeCodeWorkerContext;
+
+typedef enum {
+    TotpTypeCodeWorkerEvtReserved = (1 << 0),
+    TotpTypeCodeWorkerEvtStop = (1 << 1),
+    TotpTypeCodeWorkerEvtType = (1 << 2)
+} TotpTypeCodeWorkerEvtFlags;
+
+TotpTypeCodeWorkerContext* totp_type_code_worker_start();
+void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context);
+void totp_type_code_worker_notify(TotpTypeCodeWorkerContext* context, TotpTypeCodeWorkerEvtFlags event);