|
@@ -1,107 +1,20 @@
|
|
|
-#include <furi.h>
|
|
|
|
|
#include <furi_hal.h>
|
|
#include <furi_hal.h>
|
|
|
#include <gui/elements.h>
|
|
#include <gui/elements.h>
|
|
|
#include <gui/gui.h>
|
|
#include <gui/gui.h>
|
|
|
-#include <gui/modules/text_box.h>
|
|
|
|
|
-#include <gui/modules/text_input.h>
|
|
|
|
|
-#include <gui/view_dispatcher_i.h>
|
|
|
|
|
-#include <gui/view_port_i.h>
|
|
|
|
|
-#include <gui/scene_manager.h>
|
|
|
|
|
-#include <toolbox/sha256.h>
|
|
|
|
|
-#include <notification/notification_messages.h>
|
|
|
|
|
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
|
|
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
|
|
|
-#include <lib/subghz/subghz_tx_rx_worker.h>
|
|
|
|
|
|
|
|
|
|
#include "esubghz_chat_icons.h"
|
|
#include "esubghz_chat_icons.h"
|
|
|
|
|
|
|
|
-#include "crypto/gcm.h"
|
|
|
|
|
-
|
|
|
|
|
-#define APPLICATION_NAME "ESubGhzChat"
|
|
|
|
|
-
|
|
|
|
|
-#define DEFAULT_FREQ 433920000
|
|
|
|
|
-
|
|
|
|
|
-#define KEY_BITS 256
|
|
|
|
|
-#define IV_BYTES 12
|
|
|
|
|
-#define TAG_BYTES 16
|
|
|
|
|
-
|
|
|
|
|
-#define RX_TX_BUFFER_SIZE 1024
|
|
|
|
|
-
|
|
|
|
|
-#define CHAT_BOX_STORE_SIZE 4096
|
|
|
|
|
-#define TEXT_INPUT_STORE_SIZE 256
|
|
|
|
|
|
|
+#include "esubghz_chat_i.h"
|
|
|
|
|
|
|
|
|
|
+#define CHAT_LEAVE_DELAY 10
|
|
|
#define TICK_INTERVAL 50
|
|
#define TICK_INTERVAL 50
|
|
|
#define MESSAGE_COMPLETION_TIMEOUT 500
|
|
#define MESSAGE_COMPLETION_TIMEOUT 500
|
|
|
#define TIMEOUT_BETWEEN_MESSAGES 500
|
|
#define TIMEOUT_BETWEEN_MESSAGES 500
|
|
|
-#define CHAT_LEAVE_DELAY 10
|
|
|
|
|
|
|
|
|
|
#define KBD_UNLOCK_CNT 3
|
|
#define KBD_UNLOCK_CNT 3
|
|
|
#define KBD_UNLOCK_TIMEOUT 1000
|
|
#define KBD_UNLOCK_TIMEOUT 1000
|
|
|
|
|
|
|
|
-typedef struct {
|
|
|
|
|
- SceneManager *scene_manager;
|
|
|
|
|
- ViewDispatcher *view_dispatcher;
|
|
|
|
|
- NotificationApp *notification;
|
|
|
|
|
-
|
|
|
|
|
- // UI elements
|
|
|
|
|
- TextBox *chat_box;
|
|
|
|
|
- FuriString *chat_box_store;
|
|
|
|
|
- TextInput *text_input;
|
|
|
|
|
- char text_input_store[TEXT_INPUT_STORE_SIZE + 1];
|
|
|
|
|
-
|
|
|
|
|
- // for Sub-GHz
|
|
|
|
|
- uint32_t frequency;
|
|
|
|
|
- SubGhzTxRxWorker *subghz_worker;
|
|
|
|
|
- const SubGhzDevice *subghz_device;
|
|
|
|
|
-
|
|
|
|
|
- // message assembly before TX
|
|
|
|
|
- FuriString *name_prefix;
|
|
|
|
|
- FuriString *msg_input;
|
|
|
|
|
-
|
|
|
|
|
- // encryption
|
|
|
|
|
- bool encrypted;
|
|
|
|
|
- gcm_context gcm_ctx;
|
|
|
|
|
-
|
|
|
|
|
- // RX and TX buffers
|
|
|
|
|
- uint8_t rx_buffer[RX_TX_BUFFER_SIZE];
|
|
|
|
|
- uint8_t tx_buffer[RX_TX_BUFFER_SIZE];
|
|
|
|
|
- char rx_str_buffer[RX_TX_BUFFER_SIZE + 1];
|
|
|
|
|
- volatile uint32_t last_time_rx_data;
|
|
|
|
|
-
|
|
|
|
|
- // for locking
|
|
|
|
|
- ViewPortDrawCallback orig_draw_cb;
|
|
|
|
|
- ViewPortInputCallback orig_input_cb;
|
|
|
|
|
- bool kbd_locked;
|
|
|
|
|
- uint32_t kbd_lock_msg_ticks;
|
|
|
|
|
- uint8_t kbd_lock_count;
|
|
|
|
|
- bool kbd_ok_input_ongoing;
|
|
|
|
|
-} ESubGhzChatState;
|
|
|
|
|
-
|
|
|
|
|
-typedef enum {
|
|
|
|
|
- ESubGhzChatScene_FreqInput,
|
|
|
|
|
- ESubGhzChatScene_PassInput,
|
|
|
|
|
- ESubGhzChatScene_ChatInput,
|
|
|
|
|
- ESubGhzChatScene_ChatBox,
|
|
|
|
|
- ESubGhzChatScene_MAX
|
|
|
|
|
-} ESubGhzChatScene;
|
|
|
|
|
-
|
|
|
|
|
-typedef enum {
|
|
|
|
|
- ESubGhzChatView_Input,
|
|
|
|
|
- ESubGhzChatView_ChatBox,
|
|
|
|
|
-} ESubGhzChatView;
|
|
|
|
|
-
|
|
|
|
|
-typedef enum {
|
|
|
|
|
- ESubGhzChatEvent_FreqEntered,
|
|
|
|
|
- ESubGhzChatEvent_PassEntered,
|
|
|
|
|
- ESubGhzChatEvent_MsgEntered
|
|
|
|
|
-} ESubGhzChatEvent;
|
|
|
|
|
-
|
|
|
|
|
-/* Function to clear sensitive memory. */
|
|
|
|
|
-static void esubghz_chat_explicit_bzero(void *s, size_t len)
|
|
|
|
|
-{
|
|
|
|
|
- memset(s, 0, len);
|
|
|
|
|
- asm volatile("" ::: "memory");
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
/* Callback for RX events from the Sub-GHz worker. Records the current ticks as
|
|
/* Callback for RX events from the Sub-GHz worker. Records the current ticks as
|
|
|
* the time of the last reception. */
|
|
* the time of the last reception. */
|
|
|
static void have_read_cb(void* context)
|
|
static void have_read_cb(void* context)
|
|
@@ -115,21 +28,17 @@ static void have_read_cb(void* context)
|
|
|
/* Decrypts a message for post_rx(). */
|
|
/* Decrypts a message for post_rx(). */
|
|
|
static bool post_rx_decrypt(ESubGhzChatState *state, size_t rx_size)
|
|
static bool post_rx_decrypt(ESubGhzChatState *state, size_t rx_size)
|
|
|
{
|
|
{
|
|
|
- if (rx_size < IV_BYTES + TAG_BYTES + 1) {
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ bool ret = crypto_ctx_decrypt(state->crypto_ctx,
|
|
|
|
|
+ state->rx_buffer, rx_size,
|
|
|
|
|
+ (uint8_t*) state->rx_str_buffer);
|
|
|
|
|
+
|
|
|
|
|
+ if (ret) {
|
|
|
|
|
+ state->rx_str_buffer[rx_size - (MSG_OVERHEAD)] = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ state->rx_str_buffer[0] = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- int ret = gcm_auth_decrypt(&(state->gcm_ctx),
|
|
|
|
|
- state->rx_buffer, IV_BYTES,
|
|
|
|
|
- NULL, 0,
|
|
|
|
|
- state->rx_buffer + IV_BYTES,
|
|
|
|
|
- (uint8_t *) state->rx_str_buffer,
|
|
|
|
|
- rx_size - (IV_BYTES + TAG_BYTES),
|
|
|
|
|
- state->rx_buffer + rx_size - TAG_BYTES,
|
|
|
|
|
- TAG_BYTES);
|
|
|
|
|
- state->rx_str_buffer[rx_size - (IV_BYTES + TAG_BYTES)] = 0;
|
|
|
|
|
-
|
|
|
|
|
- return (ret == 0);
|
|
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Post RX handler, decrypts received messages, displays them in the text box
|
|
/* Post RX handler, decrypts received messages, displays them in the text box
|
|
@@ -176,25 +85,20 @@ static void post_rx(ESubGhzChatState *state, size_t rx_size)
|
|
|
|
|
|
|
|
/* Reads the message from msg_input, encrypts it if necessary and then
|
|
/* Reads the message from msg_input, encrypts it if necessary and then
|
|
|
* transmits it. */
|
|
* transmits it. */
|
|
|
-static void tx_msg_input(ESubGhzChatState *state)
|
|
|
|
|
|
|
+void tx_msg_input(ESubGhzChatState *state)
|
|
|
{
|
|
{
|
|
|
/* encrypt message if necessary */
|
|
/* encrypt message if necessary */
|
|
|
size_t msg_len = strlen(furi_string_get_cstr(state->msg_input));
|
|
size_t msg_len = strlen(furi_string_get_cstr(state->msg_input));
|
|
|
size_t tx_size = msg_len;
|
|
size_t tx_size = msg_len;
|
|
|
if (state->encrypted) {
|
|
if (state->encrypted) {
|
|
|
- tx_size += IV_BYTES + TAG_BYTES;
|
|
|
|
|
|
|
+ tx_size += MSG_OVERHEAD;
|
|
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
|
|
|
|
|
|
|
- furi_hal_random_fill_buf(state->tx_buffer, IV_BYTES);
|
|
|
|
|
- gcm_crypt_and_tag(&(state->gcm_ctx), ENCRYPT,
|
|
|
|
|
- state->tx_buffer, IV_BYTES,
|
|
|
|
|
- NULL, 0,
|
|
|
|
|
- (unsigned char *)
|
|
|
|
|
|
|
+ crypto_ctx_encrypt(state->crypto_ctx,
|
|
|
|
|
+ (uint8_t *)
|
|
|
furi_string_get_cstr(state->msg_input),
|
|
furi_string_get_cstr(state->msg_input),
|
|
|
- state->tx_buffer + IV_BYTES,
|
|
|
|
|
msg_len,
|
|
msg_len,
|
|
|
- state->tx_buffer + IV_BYTES + msg_len,
|
|
|
|
|
- TAG_BYTES);
|
|
|
|
|
|
|
+ state->tx_buffer);
|
|
|
} else {
|
|
} else {
|
|
|
tx_size += 2;
|
|
tx_size += 2;
|
|
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
|
@@ -212,72 +116,14 @@ static void tx_msg_input(ESubGhzChatState *state)
|
|
|
tx_size);
|
|
tx_size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* Sends FreqEntered event to scene manager and displays the frequency in the
|
|
|
|
|
- * text box. */
|
|
|
|
|
-static void freq_input_cb(void *context)
|
|
|
|
|
-{
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- furi_string_cat_printf(state->chat_box_store, "Frequency: %lu",
|
|
|
|
|
- state->frequency);
|
|
|
|
|
-
|
|
|
|
|
- scene_manager_handle_custom_event(state->scene_manager,
|
|
|
|
|
- ESubGhzChatEvent_FreqEntered);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Validates the entered frequency. */
|
|
|
|
|
-static bool freq_input_validator(const char *text, FuriString *error,
|
|
|
|
|
- void *context)
|
|
|
|
|
-{
|
|
|
|
|
- furi_assert(text);
|
|
|
|
|
- furi_assert(error);
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- int ret = sscanf(text, "%lu", &(state->frequency));
|
|
|
|
|
- if (ret != 1) {
|
|
|
|
|
- furi_string_printf(error, "Please enter\nfrequency\nin Hz!");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!subghz_devices_is_frequency_valid(state->subghz_device,
|
|
|
|
|
- state->frequency)) {
|
|
|
|
|
- furi_string_printf(error, "Frequency\n%lu\n is invalid!",
|
|
|
|
|
- state->frequency);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-#ifdef FW_ORIGIN_Official
|
|
|
|
|
- if (!furi_hal_region_is_frequency_allowed(state->frequency)) {
|
|
|
|
|
-#else /* FW_ORIGIN_Official */
|
|
|
|
|
- if (!furi_hal_subghz_is_tx_allowed(state->frequency)) {
|
|
|
|
|
-#endif /* FW_ORIGIN_Official */
|
|
|
|
|
- furi_string_printf(error, "TX forbidden\non frequency\n%lu!",
|
|
|
|
|
- state->frequency);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Sends PassEntered event to scene manager and displays whether or not
|
|
|
|
|
- * encryption has been enabled in the text box. Also clears the text input
|
|
|
|
|
- * buffer to remove the password and starts the Sub-GHz worker. After starting
|
|
|
|
|
- * the worker a join message is transmitted. */
|
|
|
|
|
-static void pass_input_cb(void *context)
|
|
|
|
|
|
|
+/* Displays whether or not encryption has been enabled in the text box. Also
|
|
|
|
|
+ * clears the text input buffer to remove the password and starts the Sub-GHz
|
|
|
|
|
+ * worker. After starting the worker a join message is transmitted. */
|
|
|
|
|
+void enter_chat(ESubGhzChatState *state)
|
|
|
{
|
|
{
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
furi_string_cat_printf(state->chat_box_store, "\nEncrypted: %s",
|
|
furi_string_cat_printf(state->chat_box_store, "\nEncrypted: %s",
|
|
|
(state->encrypted ? "yes" : "no"));
|
|
(state->encrypted ? "yes" : "no"));
|
|
|
|
|
|
|
|
- /* clear the text input buffer to remove the password */
|
|
|
|
|
- esubghz_chat_explicit_bzero(state->text_input_store,
|
|
|
|
|
- sizeof(state->text_input_store));
|
|
|
|
|
-
|
|
|
|
|
subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device,
|
|
subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device,
|
|
|
state->frequency);
|
|
state->frequency);
|
|
|
|
|
|
|
@@ -290,90 +136,14 @@ static void pass_input_cb(void *context)
|
|
|
|
|
|
|
|
/* clear message input buffer */
|
|
/* clear message input buffer */
|
|
|
furi_string_set_char(state->msg_input, 0, 0);
|
|
furi_string_set_char(state->msg_input, 0, 0);
|
|
|
-
|
|
|
|
|
- scene_manager_handle_custom_event(state->scene_manager,
|
|
|
|
|
- ESubGhzChatEvent_PassEntered);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* If a password was entered this derives a key from the password using a
|
|
|
|
|
- * single pass of SHA256 and initiates the AES-GCM context for encryption. If
|
|
|
|
|
- * the initiation fails, the password is rejected. */
|
|
|
|
|
-static bool pass_input_validator(const char *text, FuriString *error,
|
|
|
|
|
- void *context)
|
|
|
|
|
-{
|
|
|
|
|
- furi_assert(text);
|
|
|
|
|
- furi_assert(error);
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
-#ifdef FW_ORIGIN_Official
|
|
|
|
|
- if (strlen(text) == 0) {
|
|
|
|
|
- furi_string_printf(error, "Enter a\npassword!");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(text, " ") == 0) {
|
|
|
|
|
-#else /* FW_ORIGIN_Official */
|
|
|
|
|
- if (strlen(text) == 0) {
|
|
|
|
|
-#endif /* FW_ORIGIN_Official */
|
|
|
|
|
- state->encrypted = false;
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- unsigned char key[KEY_BITS / 8];
|
|
|
|
|
-
|
|
|
|
|
- /* derive a key from the password */
|
|
|
|
|
- sha256((unsigned char *) text, strlen(text), key);
|
|
|
|
|
-
|
|
|
|
|
- /* initiate the AES-GCM context */
|
|
|
|
|
- int ret = gcm_setkey(&(state->gcm_ctx), key, KEY_BITS / 8);
|
|
|
|
|
-
|
|
|
|
|
- /* cleanup */
|
|
|
|
|
- esubghz_chat_explicit_bzero(key, sizeof(key));
|
|
|
|
|
-
|
|
|
|
|
- if (ret != 0) {
|
|
|
|
|
- esubghz_chat_explicit_bzero(&(state->gcm_ctx),
|
|
|
|
|
- sizeof(state->gcm_ctx));
|
|
|
|
|
- furi_string_printf(error, "Failed to\nset key!");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- state->encrypted = true;
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* If no message was entred this simply emits a MsgEntered event to the scene
|
|
|
|
|
- * manager to switch to the text box. If a message was entered it is appended
|
|
|
|
|
- * to the name string. The result is encrypted, if encryption is enabled, and
|
|
|
|
|
- * then copied into the TX buffer. The contents of the TX buffer are then
|
|
|
|
|
- * transmitted. The sent message is appended to the text box and a MsgEntered
|
|
|
|
|
- * event is sent to the scene manager to switch to the text box view. */
|
|
|
|
|
-static void chat_input_cb(void *context)
|
|
|
|
|
|
|
+/* Sends a leave message */
|
|
|
|
|
+void exit_chat(ESubGhzChatState *state)
|
|
|
{
|
|
{
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- /* no message, just switch to the text box view */
|
|
|
|
|
-#ifdef FW_ORIGIN_Official
|
|
|
|
|
- if (strcmp(state->text_input_store, " ") == 0) {
|
|
|
|
|
-#else /* FW_ORIGIN_Official */
|
|
|
|
|
- if (strlen(state->text_input_store) == 0) {
|
|
|
|
|
-#endif /* FW_ORIGIN_Official */
|
|
|
|
|
- scene_manager_handle_custom_event(state->scene_manager,
|
|
|
|
|
- ESubGhzChatEvent_MsgEntered);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /* concatenate the name prefix and the actual message */
|
|
|
|
|
|
|
+ /* concatenate the name prefix and leave message */
|
|
|
furi_string_set(state->msg_input, state->name_prefix);
|
|
furi_string_set(state->msg_input, state->name_prefix);
|
|
|
- furi_string_cat_str(state->msg_input, ": ");
|
|
|
|
|
- furi_string_cat_str(state->msg_input, state->text_input_store);
|
|
|
|
|
-
|
|
|
|
|
- /* append the message to the chat box */
|
|
|
|
|
- furi_string_cat_printf(state->chat_box_store, "\n%s",
|
|
|
|
|
- furi_string_get_cstr(state->msg_input));
|
|
|
|
|
|
|
+ furi_string_cat_str(state->msg_input, " left chat.");
|
|
|
|
|
|
|
|
/* encrypt and transmit message */
|
|
/* encrypt and transmit message */
|
|
|
tx_msg_input(state);
|
|
tx_msg_input(state);
|
|
@@ -381,333 +151,10 @@ static void chat_input_cb(void *context)
|
|
|
/* clear message input buffer */
|
|
/* clear message input buffer */
|
|
|
furi_string_set_char(state->msg_input, 0, 0);
|
|
furi_string_set_char(state->msg_input, 0, 0);
|
|
|
|
|
|
|
|
- /* switch to text box view */
|
|
|
|
|
- scene_manager_handle_custom_event(state->scene_manager,
|
|
|
|
|
- ESubGhzChatEvent_MsgEntered);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Prepares the frequency input scene. */
|
|
|
|
|
-static void scene_on_enter_freq_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_freq_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu",
|
|
|
|
|
- (uint32_t) DEFAULT_FREQ);
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
- text_input_set_result_callback(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- freq_input_cb,
|
|
|
|
|
- state,
|
|
|
|
|
- state->text_input_store,
|
|
|
|
|
- sizeof(state->text_input_store),
|
|
|
|
|
- true);
|
|
|
|
|
- text_input_set_validator(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- freq_input_validator,
|
|
|
|
|
- state);
|
|
|
|
|
- text_input_set_header_text(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- "Frequency");
|
|
|
|
|
-
|
|
|
|
|
- view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Handles scene manager events for the frequency input scene. */
|
|
|
|
|
-static bool scene_on_event_freq_input(void* context, SceneManagerEvent event)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_event_freq_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- bool consumed = false;
|
|
|
|
|
-
|
|
|
|
|
- switch(event.type) {
|
|
|
|
|
- case SceneManagerEventTypeCustom:
|
|
|
|
|
- switch(event.event) {
|
|
|
|
|
- /* switch to password input scene */
|
|
|
|
|
- case ESubGhzChatEvent_FreqEntered:
|
|
|
|
|
- scene_manager_next_scene(state->scene_manager,
|
|
|
|
|
- ESubGhzChatScene_PassInput);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case SceneManagerEventTypeBack:
|
|
|
|
|
- /* stop the application if the user presses back here */
|
|
|
|
|
- view_dispatcher_stop(state->view_dispatcher);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- consumed = false;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return consumed;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Cleans up the frequency input scene. */
|
|
|
|
|
-static void scene_on_exit_freq_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_freq_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
|
|
+ /* wait for leave message to be delivered */
|
|
|
|
|
+ furi_delay_ms(CHAT_LEAVE_DELAY);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* Prepares the password input scene. */
|
|
|
|
|
-static void scene_on_enter_pass_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_pass_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- state->text_input_store[0] = 0;
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
- text_input_set_result_callback(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- pass_input_cb,
|
|
|
|
|
- state,
|
|
|
|
|
- state->text_input_store,
|
|
|
|
|
- sizeof(state->text_input_store),
|
|
|
|
|
- true);
|
|
|
|
|
- text_input_set_validator(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- pass_input_validator,
|
|
|
|
|
- state);
|
|
|
|
|
- text_input_set_header_text(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
-#ifdef FW_ORIGIN_Official
|
|
|
|
|
- "Password (space for no encr.)");
|
|
|
|
|
-#else /* FW_ORIGIN_Official */
|
|
|
|
|
- "Password (empty for no encr.)");
|
|
|
|
|
- text_input_set_minimum_length(state->text_input, 0);
|
|
|
|
|
-#endif /* FW_ORIGIN_Official */
|
|
|
|
|
-
|
|
|
|
|
- view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Handles scene manager events for the password input scene. */
|
|
|
|
|
-static bool scene_on_event_pass_input(void* context, SceneManagerEvent event)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_event_pass_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- bool consumed = false;
|
|
|
|
|
-
|
|
|
|
|
- switch(event.type) {
|
|
|
|
|
- case SceneManagerEventTypeCustom:
|
|
|
|
|
- switch(event.event) {
|
|
|
|
|
- /* switch to message input scene */
|
|
|
|
|
- case ESubGhzChatEvent_PassEntered:
|
|
|
|
|
- scene_manager_next_scene(state->scene_manager,
|
|
|
|
|
- ESubGhzChatScene_ChatInput);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case SceneManagerEventTypeBack:
|
|
|
|
|
- /* stop the application if the user presses back here */
|
|
|
|
|
- view_dispatcher_stop(state->view_dispatcher);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- consumed = false;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return consumed;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Cleans up the password input scene. */
|
|
|
|
|
-static void scene_on_exit_pass_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_pass_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Prepares the message input scene. */
|
|
|
|
|
-static void scene_on_enter_chat_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- state->text_input_store[0] = 0;
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
- text_input_set_result_callback(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- chat_input_cb,
|
|
|
|
|
- state,
|
|
|
|
|
- state->text_input_store,
|
|
|
|
|
- sizeof(state->text_input_store),
|
|
|
|
|
- true);
|
|
|
|
|
- text_input_set_validator(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
- NULL,
|
|
|
|
|
- NULL);
|
|
|
|
|
- text_input_set_header_text(
|
|
|
|
|
- state->text_input,
|
|
|
|
|
-#ifdef FW_ORIGIN_Official
|
|
|
|
|
- "Message (space for none)");
|
|
|
|
|
-#else /* FW_ORIGIN_Official */
|
|
|
|
|
- "Message");
|
|
|
|
|
- text_input_set_minimum_length(state->text_input, 0);
|
|
|
|
|
-#endif /* FW_ORIGIN_Official */
|
|
|
|
|
-
|
|
|
|
|
- view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Handles scene manager events for the message input scene. */
|
|
|
|
|
-static bool scene_on_event_chat_input(void* context, SceneManagerEvent event)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- bool consumed = false;
|
|
|
|
|
-
|
|
|
|
|
- switch(event.type) {
|
|
|
|
|
- case SceneManagerEventTypeCustom:
|
|
|
|
|
- switch(event.event) {
|
|
|
|
|
- /* switch to text box scene */
|
|
|
|
|
- case ESubGhzChatEvent_MsgEntered:
|
|
|
|
|
- scene_manager_next_scene(state->scene_manager,
|
|
|
|
|
- ESubGhzChatScene_ChatBox);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case SceneManagerEventTypeBack:
|
|
|
|
|
- /* stop the application and send a leave message if the user
|
|
|
|
|
- * presses back here */
|
|
|
|
|
-
|
|
|
|
|
- /* concatenate the name prefix and leave message */
|
|
|
|
|
- furi_string_set(state->msg_input, state->name_prefix);
|
|
|
|
|
- furi_string_cat_str(state->msg_input, " left chat.");
|
|
|
|
|
-
|
|
|
|
|
- /* encrypt and transmit message */
|
|
|
|
|
- tx_msg_input(state);
|
|
|
|
|
-
|
|
|
|
|
- /* clear message input buffer */
|
|
|
|
|
- furi_string_set_char(state->msg_input, 0, 0);
|
|
|
|
|
-
|
|
|
|
|
- /* wait for leave message to be delivered */
|
|
|
|
|
- furi_delay_ms(CHAT_LEAVE_DELAY);
|
|
|
|
|
-
|
|
|
|
|
- view_dispatcher_stop(state->view_dispatcher);
|
|
|
|
|
- consumed = true;
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- consumed = false;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return consumed;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Cleans up the password input scene. */
|
|
|
|
|
-static void scene_on_exit_chat_input(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_input");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- text_input_reset(state->text_input);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Prepares the text box scene. */
|
|
|
|
|
-static void scene_on_enter_chat_box(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_box");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- text_box_reset(state->chat_box);
|
|
|
|
|
- text_box_set_text(state->chat_box,
|
|
|
|
|
- furi_string_get_cstr(state->chat_box_store));
|
|
|
|
|
- text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
|
|
|
|
-
|
|
|
|
|
- view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Handles scene manager events for the text box scene. No events are handled
|
|
|
|
|
- * here. */
|
|
|
|
|
-static bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
|
|
|
|
|
-{
|
|
|
|
|
- UNUSED(event);
|
|
|
|
|
-
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
-
|
|
|
|
|
- return false;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Cleans up the text box scene. */
|
|
|
|
|
-static void scene_on_exit_chat_box(void* context)
|
|
|
|
|
-{
|
|
|
|
|
- FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_box");
|
|
|
|
|
-
|
|
|
|
|
- furi_assert(context);
|
|
|
|
|
- ESubGhzChatState* state = context;
|
|
|
|
|
-
|
|
|
|
|
- text_box_reset(state->chat_box);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* Scene entry handlers. */
|
|
|
|
|
-static void (*const esubghz_chat_scene_on_enter_handlers[])(void*) = {
|
|
|
|
|
- scene_on_enter_freq_input,
|
|
|
|
|
- scene_on_enter_pass_input,
|
|
|
|
|
- scene_on_enter_chat_input,
|
|
|
|
|
- scene_on_enter_chat_box
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-/* Scene event handlers. */
|
|
|
|
|
-static bool (*const esubghz_chat_scene_on_event_handlers[])(void*, SceneManagerEvent) = {
|
|
|
|
|
- scene_on_event_freq_input,
|
|
|
|
|
- scene_on_event_pass_input,
|
|
|
|
|
- scene_on_event_chat_input,
|
|
|
|
|
- scene_on_event_chat_box
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-/* Scene exit handlers. */
|
|
|
|
|
-static void (*const esubghz_chat_scene_on_exit_handlers[])(void*) = {
|
|
|
|
|
- scene_on_exit_freq_input,
|
|
|
|
|
- scene_on_exit_pass_input,
|
|
|
|
|
- scene_on_exit_chat_input,
|
|
|
|
|
- scene_on_exit_chat_box
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-/* Handlers for the scene manager. */
|
|
|
|
|
-static const SceneManagerHandlers esubghz_chat_scene_event_handlers = {
|
|
|
|
|
- .on_enter_handlers = esubghz_chat_scene_on_enter_handlers,
|
|
|
|
|
- .on_event_handlers = esubghz_chat_scene_on_event_handlers,
|
|
|
|
|
- .on_exit_handlers = esubghz_chat_scene_on_exit_handlers,
|
|
|
|
|
- .scene_num = ESubGhzChatScene_MAX};
|
|
|
|
|
-
|
|
|
|
|
/* Whether or not to display the locked message. */
|
|
/* Whether or not to display the locked message. */
|
|
|
static bool kbd_lock_msg_display(ESubGhzChatState *state)
|
|
static bool kbd_lock_msg_display(ESubGhzChatState *state)
|
|
|
{
|
|
{
|
|
@@ -892,7 +339,7 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* handle ongoing inputs when chaning to chat view */
|
|
|
|
|
|
|
+ /* handle ongoing inputs when changing to chat view */
|
|
|
if (event->type == InputTypePress) {
|
|
if (event->type == InputTypePress) {
|
|
|
state->kbd_ok_input_ongoing = true;
|
|
state->kbd_ok_input_ongoing = true;
|
|
|
} else if (event->type == InputTypeRelease) {
|
|
} else if (event->type == InputTypeRelease) {
|
|
@@ -900,6 +347,57 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (event->key == InputKeyLeft) {
|
|
|
|
|
+ /* if we are in the chat view and no input is ongoing, allow
|
|
|
|
|
+ * switching to msg input */
|
|
|
|
|
+ if (state->view_dispatcher->current_view ==
|
|
|
|
|
+ text_box_get_view(state->chat_box) &&
|
|
|
|
|
+ !(state->kbd_left_input_ongoing)) {
|
|
|
|
|
+ /* go to msg input upon short press of Left button */
|
|
|
|
|
+ if (event->type == InputTypeShort) {
|
|
|
|
|
+ view_dispatcher_send_custom_event(state->view_dispatcher,
|
|
|
|
|
+ ESubGhzChatEvent_GotoMsgInput);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* do not handle any Left key events to prevent
|
|
|
|
|
+ * blocking of other keys */
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* handle ongoing inputs when changing to chat view */
|
|
|
|
|
+ if (event->type == InputTypePress) {
|
|
|
|
|
+ state->kbd_left_input_ongoing = true;
|
|
|
|
|
+ } else if (event->type == InputTypeRelease) {
|
|
|
|
|
+ state->kbd_left_input_ongoing = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (event->key == InputKeyRight) {
|
|
|
|
|
+ /* if we are in the chat view and no input is ongoing, allow
|
|
|
|
|
+ * switching to key display */
|
|
|
|
|
+ if (state->view_dispatcher->current_view ==
|
|
|
|
|
+ text_box_get_view(state->chat_box) &&
|
|
|
|
|
+ !(state->kbd_right_input_ongoing)) {
|
|
|
|
|
+ /* go to key display upon short press of Right button
|
|
|
|
|
+ */
|
|
|
|
|
+ if (event->type == InputTypeShort) {
|
|
|
|
|
+ view_dispatcher_send_custom_event(state->view_dispatcher,
|
|
|
|
|
+ ESubGhzChatEvent_GotoKeyDisplay);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* do not handle any Right key events to prevent
|
|
|
|
|
+ * blocking of other keys */
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* handle ongoing inputs when changing to chat view */
|
|
|
|
|
+ if (event->type == InputTypePress) {
|
|
|
|
|
+ state->kbd_right_input_ongoing = true;
|
|
|
|
|
+ } else if (event->type == InputTypeRelease) {
|
|
|
|
|
+ state->kbd_right_input_ongoing = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/* call original callback */
|
|
/* call original callback */
|
|
|
state->orig_input_cb(event, state->view_dispatcher);
|
|
state->orig_input_cb(event, state->view_dispatcher);
|
|
|
}
|
|
}
|
|
@@ -964,8 +462,8 @@ static void chat_box_free(ESubGhzChatState *state)
|
|
|
|
|
|
|
|
int32_t esubghz_chat(void)
|
|
int32_t esubghz_chat(void)
|
|
|
{
|
|
{
|
|
|
- /* init the GCM and AES tables */
|
|
|
|
|
- gcm_initialize();
|
|
|
|
|
|
|
+ /* init the crypto system */
|
|
|
|
|
+ crypto_init();
|
|
|
|
|
|
|
|
int32_t err = -1;
|
|
int32_t err = -1;
|
|
|
|
|
|
|
@@ -994,20 +492,40 @@ int32_t esubghz_chat(void)
|
|
|
goto err_alloc_hs;
|
|
goto err_alloc_hs;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ state->menu = menu_alloc();
|
|
|
|
|
+ if (state->menu == NULL) {
|
|
|
|
|
+ goto err_alloc_menu;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
state->text_input = text_input_alloc();
|
|
state->text_input = text_input_alloc();
|
|
|
if (state->text_input == NULL) {
|
|
if (state->text_input == NULL) {
|
|
|
goto err_alloc_ti;
|
|
goto err_alloc_ti;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ state->hex_key_input = byte_input_alloc();
|
|
|
|
|
+ if (state->hex_key_input == NULL) {
|
|
|
|
|
+ goto err_alloc_hki;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (!chat_box_alloc(state)) {
|
|
if (!chat_box_alloc(state)) {
|
|
|
goto err_alloc_cb;
|
|
goto err_alloc_cb;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ state->key_display = dialog_ex_alloc();
|
|
|
|
|
+ if (state->key_display == NULL) {
|
|
|
|
|
+ goto err_alloc_kd;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
state->subghz_worker = subghz_tx_rx_worker_alloc();
|
|
state->subghz_worker = subghz_tx_rx_worker_alloc();
|
|
|
if (state->subghz_worker == NULL) {
|
|
if (state->subghz_worker == NULL) {
|
|
|
goto err_alloc_worker;
|
|
goto err_alloc_worker;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ state->crypto_ctx = crypto_ctx_alloc();
|
|
|
|
|
+ if (state->crypto_ctx == NULL) {
|
|
|
|
|
+ goto err_alloc_crypto;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/* set the have_read callback of the Sub-GHz worker */
|
|
/* set the have_read callback of the Sub-GHz worker */
|
|
|
subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker,
|
|
subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker,
|
|
|
have_read_cb, state);
|
|
have_read_cb, state);
|
|
@@ -1051,10 +569,16 @@ int32_t esubghz_chat(void)
|
|
|
TICK_INTERVAL);
|
|
TICK_INTERVAL);
|
|
|
|
|
|
|
|
/* add our two views to the view dispatcher */
|
|
/* add our two views to the view dispatcher */
|
|
|
|
|
+ view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_Menu,
|
|
|
|
|
+ menu_get_view(state->menu));
|
|
|
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_Input,
|
|
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_Input,
|
|
|
text_input_get_view(state->text_input));
|
|
text_input_get_view(state->text_input));
|
|
|
|
|
+ view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_HexKeyInput,
|
|
|
|
|
+ byte_input_get_view(state->hex_key_input));
|
|
|
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_ChatBox,
|
|
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_ChatBox,
|
|
|
text_box_get_view(state->chat_box));
|
|
text_box_get_view(state->chat_box));
|
|
|
|
|
+ view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay,
|
|
|
|
|
+ dialog_ex_get_view(state->key_display));
|
|
|
|
|
|
|
|
/* get the GUI record and attach the view dispatcher to the GUI */
|
|
/* get the GUI record and attach the view dispatcher to the GUI */
|
|
|
/* no error handling here, don't know how */
|
|
/* no error handling here, don't know how */
|
|
@@ -1071,6 +595,7 @@ int32_t esubghz_chat(void)
|
|
|
|
|
|
|
|
/* if it is running, stop the Sub-GHz worker */
|
|
/* if it is running, stop the Sub-GHz worker */
|
|
|
if (subghz_tx_rx_worker_is_running(state->subghz_worker)) {
|
|
if (subghz_tx_rx_worker_is_running(state->subghz_worker)) {
|
|
|
|
|
+ exit_chat(state);
|
|
|
subghz_tx_rx_worker_stop(state->subghz_worker);
|
|
subghz_tx_rx_worker_stop(state->subghz_worker);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1080,18 +605,27 @@ int32_t esubghz_chat(void)
|
|
|
furi_record_close(RECORD_GUI);
|
|
furi_record_close(RECORD_GUI);
|
|
|
|
|
|
|
|
/* remove our two views from the view dispatcher */
|
|
/* remove our two views from the view dispatcher */
|
|
|
|
|
+ view_dispatcher_remove_view(state->view_dispatcher,
|
|
|
|
|
+ ESubGhzChatView_Menu);
|
|
|
view_dispatcher_remove_view(state->view_dispatcher,
|
|
view_dispatcher_remove_view(state->view_dispatcher,
|
|
|
ESubGhzChatView_Input);
|
|
ESubGhzChatView_Input);
|
|
|
|
|
+ view_dispatcher_remove_view(state->view_dispatcher,
|
|
|
|
|
+ ESubGhzChatView_HexKeyInput);
|
|
|
view_dispatcher_remove_view(state->view_dispatcher,
|
|
view_dispatcher_remove_view(state->view_dispatcher,
|
|
|
ESubGhzChatView_ChatBox);
|
|
ESubGhzChatView_ChatBox);
|
|
|
|
|
+ view_dispatcher_remove_view(state->view_dispatcher,
|
|
|
|
|
+ ESubGhzChatView_KeyDisplay);
|
|
|
|
|
|
|
|
/* close notification record */
|
|
/* close notification record */
|
|
|
furi_record_close(RECORD_NOTIFICATION);
|
|
furi_record_close(RECORD_NOTIFICATION);
|
|
|
|
|
|
|
|
/* clear the key and potential password */
|
|
/* clear the key and potential password */
|
|
|
- esubghz_chat_explicit_bzero(state->text_input_store,
|
|
|
|
|
|
|
+ crypto_explicit_bzero(state->text_input_store,
|
|
|
sizeof(state->text_input_store));
|
|
sizeof(state->text_input_store));
|
|
|
- esubghz_chat_explicit_bzero(&(state->gcm_ctx), sizeof(state->gcm_ctx));
|
|
|
|
|
|
|
+ crypto_explicit_bzero(state->hex_key_input_store,
|
|
|
|
|
+ sizeof(state->hex_key_input_store));
|
|
|
|
|
+ crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
|
|
|
|
|
+ crypto_ctx_clear(state->crypto_ctx);
|
|
|
|
|
|
|
|
/* deinit devices */
|
|
/* deinit devices */
|
|
|
subghz_devices_deinit();
|
|
subghz_devices_deinit();
|
|
@@ -1101,15 +635,27 @@ int32_t esubghz_chat(void)
|
|
|
|
|
|
|
|
/* free everything we allocated */
|
|
/* free everything we allocated */
|
|
|
|
|
|
|
|
|
|
+ crypto_ctx_free(state->crypto_ctx);
|
|
|
|
|
+
|
|
|
|
|
+err_alloc_crypto:
|
|
|
subghz_tx_rx_worker_free(state->subghz_worker);
|
|
subghz_tx_rx_worker_free(state->subghz_worker);
|
|
|
|
|
|
|
|
err_alloc_worker:
|
|
err_alloc_worker:
|
|
|
|
|
+ dialog_ex_free(state->key_display);
|
|
|
|
|
+
|
|
|
|
|
+err_alloc_kd:
|
|
|
chat_box_free(state);
|
|
chat_box_free(state);
|
|
|
|
|
|
|
|
err_alloc_cb:
|
|
err_alloc_cb:
|
|
|
|
|
+ byte_input_free(state->hex_key_input);
|
|
|
|
|
+
|
|
|
|
|
+err_alloc_hki:
|
|
|
text_input_free(state->text_input);
|
|
text_input_free(state->text_input);
|
|
|
|
|
|
|
|
err_alloc_ti:
|
|
err_alloc_ti:
|
|
|
|
|
+ menu_free(state->menu);
|
|
|
|
|
+
|
|
|
|
|
+err_alloc_menu:
|
|
|
helper_strings_free(state);
|
|
helper_strings_free(state);
|
|
|
|
|
|
|
|
err_alloc_hs:
|
|
err_alloc_hs:
|