mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 20:18:35 -07:00
Add e-subghz chat app (by @twisted-pear)
This commit is contained in:
65
applications/external/esubghz_chat/scenes/esubghz_chat_chat_box.c
vendored
Normal file
65
applications/external/esubghz_chat/scenes/esubghz_chat_chat_box.c
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
/* Prepares the text box scene. */
|
||||
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. */
|
||||
bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
switch(event.type) {
|
||||
case SceneManagerEventTypeCustom:
|
||||
switch(event.event) {
|
||||
/* switch to message input scene */
|
||||
case ESubGhzChatEvent_GotoMsgInput:
|
||||
if (!scene_manager_previous_scene(
|
||||
state->scene_manager)) {
|
||||
view_dispatcher_stop(state->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
case ESubGhzChatEvent_GotoKeyDisplay:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_KeyDisplay);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* Cleans up the text box scene. */
|
||||
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);
|
||||
}
|
||||
118
applications/external/esubghz_chat/scenes/esubghz_chat_chat_input.c
vendored
Normal file
118
applications/external/esubghz_chat/scenes/esubghz_chat_chat_input.c
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
/* 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 bool chat_input_validator(const char *text, FuriString *error,
|
||||
void *context)
|
||||
{
|
||||
UNUSED(error);
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
/* no message, just switch to the text box view */
|
||||
if (strlen(text) == 0) {
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_MsgEntered);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* concatenate the name prefix and the actual message */
|
||||
furi_string_set(state->msg_input, state->name_prefix);
|
||||
furi_string_cat_str(state->msg_input, ": ");
|
||||
furi_string_cat_str(state->msg_input, text);
|
||||
|
||||
/* append the message to the chat box and prepare message preview */
|
||||
append_msg(state, furi_string_get_cstr(state->msg_input));
|
||||
|
||||
/* encrypt and transmit message */
|
||||
tx_msg_input(state);
|
||||
|
||||
/* clear message input buffer */
|
||||
furi_string_set_char(state->msg_input, 0, 0);
|
||||
|
||||
/* switch to text box view */
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_MsgEntered);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Prepares the message input scene. */
|
||||
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);
|
||||
/* use validator for scene change to get around minimum length
|
||||
* requirement */
|
||||
text_input_set_result_callback(
|
||||
state->text_input,
|
||||
NULL,
|
||||
NULL,
|
||||
state->text_input_store,
|
||||
sizeof(state->text_input_store),
|
||||
true);
|
||||
text_input_set_validator(
|
||||
state->text_input,
|
||||
chat_input_validator,
|
||||
state);
|
||||
set_chat_input_header(state);
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the message input scene. */
|
||||
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 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. */
|
||||
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);
|
||||
}
|
||||
127
applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c
vendored
Normal file
127
applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
/* 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);
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
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;
|
||||
}
|
||||
|
||||
/* Prepares the frequency input scene. */
|
||||
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. */
|
||||
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_KeyMenu);
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
91
applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c
vendored
Normal file
91
applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered
|
||||
* event to the scene manager. */
|
||||
static void hex_key_input_cb(void* context)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
/* initiate the crypto context */
|
||||
bool ret = crypto_ctx_set_key(state->crypto_ctx,
|
||||
state->hex_key_input_store, state->name_prefix,
|
||||
furi_get_tick());
|
||||
|
||||
/* cleanup */
|
||||
crypto_explicit_bzero(state->hex_key_input_store,
|
||||
sizeof(state->hex_key_input_store));
|
||||
|
||||
if (!ret) {
|
||||
crypto_ctx_clear(state->crypto_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
state->encrypted = true;
|
||||
|
||||
enter_chat(state);
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_HexKeyEntered);
|
||||
}
|
||||
|
||||
/* Prepares the hex key input scene. */
|
||||
void scene_on_enter_hex_key_input(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_hex_key_input");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
byte_input_set_result_callback(state->hex_key_input,
|
||||
hex_key_input_cb,
|
||||
NULL,
|
||||
state,
|
||||
state->hex_key_input_store,
|
||||
sizeof(state->hex_key_input_store));
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
||||
ESubGhzChatView_HexKeyInput);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the hex key input scene. */
|
||||
bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_hex_key_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_HexKeyEntered:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_ChatInput);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* Cleans up the hex key input scene. */
|
||||
void scene_on_exit_hex_key_input(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_hex_key_input");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
crypto_explicit_bzero(state->hex_key_input_store,
|
||||
sizeof(state->hex_key_input_store));
|
||||
}
|
||||
128
applications/external/esubghz_chat/scenes/esubghz_chat_key_display.c
vendored
Normal file
128
applications/external/esubghz_chat/scenes/esubghz_chat_key_display.c
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
void key_display_result_cb(DialogExResult result, void* context)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
switch(result) {
|
||||
case DialogExResultLeft:
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyDisplayBack);
|
||||
break;
|
||||
|
||||
case DialogExResultCenter:
|
||||
if (state->encrypted) {
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyDisplayShare);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepares the key display scene. */
|
||||
void scene_on_enter_key_display(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_display");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
if (state->encrypted) {
|
||||
uint8_t key[KEY_BITS / 8];
|
||||
crypto_ctx_get_key(state->crypto_ctx, key);
|
||||
snprintf(state->key_hex_str, KEY_HEX_STR_SIZE,
|
||||
"%02hX%02hX%02hX%02hX"
|
||||
"%02hX%02hX%02hX%02hX\n"
|
||||
"%02hX%02hX%02hX%02hX"
|
||||
"%02hX%02hX%02hX%02hX\n"
|
||||
"%02hX%02hX%02hX%02hX"
|
||||
"%02hX%02hX%02hX%02hX\n"
|
||||
"%02hX%02hX%02hX%02hX"
|
||||
"%02hX%02hX%02hX%02hX",
|
||||
key[0], key[1], key[2], key[3],
|
||||
key[4], key[5], key[6], key[7],
|
||||
key[8], key[9], key[10], key[11],
|
||||
key[12], key[13], key[14], key[15],
|
||||
key[16], key[17], key[18], key[19],
|
||||
key[20], key[21], key[22], key[23],
|
||||
key[24], key[25], key[26], key[27],
|
||||
key[28], key[29], key[30], key[31]);
|
||||
crypto_explicit_bzero(key, sizeof(key));
|
||||
} else {
|
||||
strcpy(state->key_hex_str, "No Key");
|
||||
}
|
||||
|
||||
dialog_ex_reset(state->key_display);
|
||||
|
||||
dialog_ex_set_text(state->key_display, state->key_hex_str, 64, 2,
|
||||
AlignCenter, AlignTop);
|
||||
|
||||
dialog_ex_set_icon(state->key_display, 0, 0, NULL);
|
||||
|
||||
dialog_ex_set_left_button_text(state->key_display, "Back");
|
||||
|
||||
if (state->encrypted) {
|
||||
dialog_ex_set_center_button_text(state->key_display, "Share");
|
||||
}
|
||||
|
||||
dialog_ex_set_result_callback(state->key_display,
|
||||
key_display_result_cb);
|
||||
dialog_ex_set_context(state->key_display, state);
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the key display scene. */
|
||||
bool scene_on_event_key_display(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_display");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
switch(event.type) {
|
||||
case SceneManagerEventTypeCustom:
|
||||
switch(event.event) {
|
||||
/* switch to message input scene */
|
||||
case ESubGhzChatEvent_KeyDisplayBack:
|
||||
if (!scene_manager_previous_scene(
|
||||
state->scene_manager)) {
|
||||
view_dispatcher_stop(state->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* open key sharing popup */
|
||||
case ESubGhzChatEvent_KeyDisplayShare:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_KeySharePopup);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* Cleans up the key display scene. */
|
||||
void scene_on_exit_key_display(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_display");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
dialog_ex_reset(state->key_display);
|
||||
crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
|
||||
}
|
||||
194
applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c
vendored
Normal file
194
applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
typedef enum {
|
||||
ESubGhzChatKeyMenuItems_NoEncryption,
|
||||
ESubGhzChatKeyMenuItems_Password,
|
||||
ESubGhzChatKeyMenuItems_HexKey,
|
||||
ESubGhzChatKeyMenuItems_GenKey,
|
||||
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
||||
} ESubGhzChatKeyMenuItems;
|
||||
|
||||
static void key_menu_cb(void* context, uint32_t index)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
uint8_t key[KEY_BITS / 8];
|
||||
|
||||
switch(index) {
|
||||
case ESubGhzChatKeyMenuItems_NoEncryption:
|
||||
state->encrypted = false;
|
||||
enter_chat(state);
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyMenuNoEncryption);
|
||||
break;
|
||||
|
||||
case ESubGhzChatKeyMenuItems_Password:
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyMenuPassword);
|
||||
break;
|
||||
|
||||
case ESubGhzChatKeyMenuItems_HexKey:
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyMenuHexKey);
|
||||
break;
|
||||
|
||||
case ESubGhzChatKeyMenuItems_GenKey:
|
||||
/* generate a random key */
|
||||
furi_hal_random_fill_buf(key, KEY_BITS / 8);
|
||||
|
||||
/* initiate the crypto context */
|
||||
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
|
||||
state->name_prefix, furi_get_tick());
|
||||
|
||||
/* cleanup */
|
||||
crypto_explicit_bzero(key, sizeof(key));
|
||||
|
||||
if (!ret) {
|
||||
crypto_ctx_clear(state->crypto_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set encrypted flag and enter the chat */
|
||||
state->encrypted = true;
|
||||
enter_chat(state);
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyMenuGenKey);
|
||||
break;
|
||||
|
||||
case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepares the key menu scene. */
|
||||
void scene_on_enter_key_menu(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_menu");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
menu_reset(state->menu);
|
||||
|
||||
menu_add_item(
|
||||
state->menu,
|
||||
"No encryption",
|
||||
NULL,
|
||||
ESubGhzChatKeyMenuItems_NoEncryption,
|
||||
key_menu_cb,
|
||||
state
|
||||
);
|
||||
menu_add_item(
|
||||
state->menu,
|
||||
"Password",
|
||||
NULL,
|
||||
ESubGhzChatKeyMenuItems_Password,
|
||||
key_menu_cb,
|
||||
state
|
||||
);
|
||||
menu_add_item(
|
||||
state->menu,
|
||||
"Hex Key",
|
||||
NULL,
|
||||
ESubGhzChatKeyMenuItems_HexKey,
|
||||
key_menu_cb,
|
||||
state
|
||||
);
|
||||
menu_add_item(
|
||||
state->menu,
|
||||
"Generate Key",
|
||||
NULL,
|
||||
ESubGhzChatKeyMenuItems_GenKey,
|
||||
key_menu_cb,
|
||||
state
|
||||
);
|
||||
menu_add_item(
|
||||
state->menu,
|
||||
"Read Key from NFC",
|
||||
NULL,
|
||||
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
||||
key_menu_cb,
|
||||
state
|
||||
);
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the key menu scene. */
|
||||
bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_menu");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
switch(event.type) {
|
||||
case SceneManagerEventTypeCustom:
|
||||
switch(event.event) {
|
||||
/* switch to message input scene */
|
||||
case ESubGhzChatEvent_KeyMenuNoEncryption:
|
||||
case ESubGhzChatEvent_KeyMenuGenKey:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_ChatInput);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* switch to password input scene */
|
||||
case ESubGhzChatEvent_KeyMenuPassword:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_PassInput);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* switch to hex key input scene */
|
||||
case ESubGhzChatEvent_KeyMenuHexKey:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_HexKeyInput);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* switch to hex key read scene */
|
||||
case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_KeyReadPopup);
|
||||
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 key menu scene. */
|
||||
void scene_on_exit_key_menu(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_menu");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
menu_reset(state->menu);
|
||||
}
|
||||
|
||||
251
applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c
vendored
Normal file
251
applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
typedef enum {
|
||||
KeyReadPopupState_Idle,
|
||||
KeyReadPopupState_Detecting,
|
||||
KeyReadPopupState_Reading,
|
||||
KeyReadPopupState_Fail,
|
||||
KeyReadPopupState_Success,
|
||||
} KeyReadPopupState;
|
||||
|
||||
static bool read_worker_cb(NfcWorkerEvent event, void* context)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher, event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void key_read_popup_timeout_cb(void* context)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
uint32_t cur_state = scene_manager_get_scene_state(
|
||||
state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
||||
|
||||
/* done displaying our failure */
|
||||
if (cur_state == KeyReadPopupState_Fail) {
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyReadPopupFailed);
|
||||
/* done displaying our success, enter chat */
|
||||
} else if (cur_state == KeyReadPopupState_Success) {
|
||||
enter_chat(state);
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
ESubGhzChatEvent_KeyReadPopupSucceeded);
|
||||
}
|
||||
}
|
||||
|
||||
static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
|
||||
{
|
||||
NfcDeviceData *dev_data = state->nfc_dev_data;
|
||||
|
||||
if (dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* initiate the crypto context */
|
||||
bool ret = crypto_ctx_set_key(state->crypto_ctx,
|
||||
dev_data->mf_ul_data.data, state->name_prefix,
|
||||
furi_get_tick());
|
||||
|
||||
/* cleanup */
|
||||
crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
|
||||
|
||||
if (!ret) {
|
||||
crypto_ctx_clear(state->crypto_ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set encrypted flag */
|
||||
state->encrypted = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void key_read_popup_set_state(ESubGhzChatState *state, KeyReadPopupState
|
||||
new_state)
|
||||
{
|
||||
uint32_t cur_state = scene_manager_get_scene_state(
|
||||
state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
||||
if (cur_state == new_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_state == KeyReadPopupState_Detecting) {
|
||||
popup_reset(state->nfc_popup);
|
||||
popup_disable_timeout(state->nfc_popup);
|
||||
popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97,
|
||||
24, AlignCenter, AlignTop);
|
||||
popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
|
||||
notification_message(state->notification,
|
||||
&sequence_blink_start_cyan);
|
||||
} else if (new_state == KeyReadPopupState_Reading) {
|
||||
popup_reset(state->nfc_popup);
|
||||
popup_disable_timeout(state->nfc_popup);
|
||||
popup_set_header(state->nfc_popup, "Reading key\nDon't "
|
||||
"move...", 85, 24, AlignCenter, AlignTop);
|
||||
popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
|
||||
notification_message(state->notification,
|
||||
&sequence_blink_start_yellow);
|
||||
} else if (new_state == KeyReadPopupState_Fail) {
|
||||
nfc_worker_stop(state->nfc_worker);
|
||||
|
||||
popup_reset(state->nfc_popup);
|
||||
popup_set_header(state->nfc_popup, "Failure!", 64, 2,
|
||||
AlignCenter, AlignTop);
|
||||
popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78,
|
||||
16, AlignLeft, AlignTop);
|
||||
popup_set_icon(state->nfc_popup, 21, 13, &I_Cry_dolph_55x52);
|
||||
|
||||
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
||||
popup_set_context(state->nfc_popup, state);
|
||||
popup_set_callback(state->nfc_popup,
|
||||
key_read_popup_timeout_cb);
|
||||
popup_enable_timeout(state->nfc_popup);
|
||||
|
||||
notification_message(state->notification,
|
||||
&sequence_blink_stop);
|
||||
} else if (new_state == KeyReadPopupState_Success) {
|
||||
nfc_worker_stop(state->nfc_worker);
|
||||
|
||||
popup_reset(state->nfc_popup);
|
||||
popup_set_header(state->nfc_popup, "Key\nread!", 13, 22,
|
||||
AlignLeft, AlignBottom);
|
||||
popup_set_icon(state->nfc_popup, 32, 5, &I_DolphinNice_96x59);
|
||||
|
||||
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
||||
popup_set_context(state->nfc_popup, state);
|
||||
popup_set_callback(state->nfc_popup,
|
||||
key_read_popup_timeout_cb);
|
||||
popup_enable_timeout(state->nfc_popup);
|
||||
|
||||
notification_message(state->notification, &sequence_success);
|
||||
notification_message(state->notification,
|
||||
&sequence_blink_stop);
|
||||
}
|
||||
|
||||
scene_manager_set_scene_state(state->scene_manager,
|
||||
ESubGhzChatScene_KeyReadPopup, new_state);
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
||||
ESubGhzChatView_NfcPopup);
|
||||
}
|
||||
|
||||
/* Prepares the key share read scene. */
|
||||
void scene_on_enter_key_read_popup(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
|
||||
|
||||
state->nfc_dev_data->parsed_data = furi_string_alloc();
|
||||
if (state->nfc_dev_data->parsed_data == NULL) {
|
||||
/* can't do anything here, crash */
|
||||
furi_check(0);
|
||||
}
|
||||
|
||||
nfc_worker_start(state->nfc_worker, NfcWorkerStateRead,
|
||||
state->nfc_dev_data, read_worker_cb, state);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the key read popup scene. */
|
||||
bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
switch(event.type) {
|
||||
case SceneManagerEventTypeCustom:
|
||||
switch(event.event) {
|
||||
/* card detected */
|
||||
case NfcWorkerEventCardDetected:
|
||||
key_read_popup_set_state(state,
|
||||
KeyReadPopupState_Reading);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* no card detected */
|
||||
case NfcWorkerEventNoCardDetected:
|
||||
key_read_popup_set_state(state,
|
||||
KeyReadPopupState_Detecting);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* key probably read */
|
||||
case NfcWorkerEventReadMfUltralight:
|
||||
if (key_read_popup_handle_key_read(state)) {
|
||||
key_read_popup_set_state(state,
|
||||
KeyReadPopupState_Success);
|
||||
} else {
|
||||
key_read_popup_set_state(state,
|
||||
KeyReadPopupState_Fail);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* close the popup and go back */
|
||||
case ESubGhzChatEvent_KeyReadPopupFailed:
|
||||
if (!scene_manager_previous_scene(
|
||||
state->scene_manager)) {
|
||||
view_dispatcher_stop(state->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* success, go to chat input */
|
||||
case ESubGhzChatEvent_KeyReadPopupSucceeded:
|
||||
scene_manager_next_scene(state->scene_manager,
|
||||
ESubGhzChatScene_ChatInput);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
/* something else happend, treat as failure */
|
||||
default:
|
||||
key_read_popup_set_state(state,
|
||||
KeyReadPopupState_Fail);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* Cleans up the key read popup scene. */
|
||||
void scene_on_exit_key_read_popup(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
popup_reset(state->nfc_popup);
|
||||
scene_manager_set_scene_state(state->scene_manager,
|
||||
ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
|
||||
|
||||
notification_message(state->notification, &sequence_blink_stop);
|
||||
|
||||
nfc_worker_stop(state->nfc_worker);
|
||||
|
||||
crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
|
||||
if (state->nfc_dev_data->parsed_data != NULL) {
|
||||
furi_string_free(state->nfc_dev_data->parsed_data);
|
||||
}
|
||||
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
||||
}
|
||||
88
applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c
vendored
Normal file
88
applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
static void prepare_nfc_dev_data(ESubGhzChatState *state)
|
||||
{
|
||||
NfcDeviceData *dev_data = state->nfc_dev_data;
|
||||
|
||||
dev_data->protocol = NfcDeviceProtocolMifareUl;
|
||||
furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7);
|
||||
dev_data->nfc_data.uid_len = 7;
|
||||
dev_data->nfc_data.atqa[0] = 0x44;
|
||||
dev_data->nfc_data.atqa[1] = 0x00;
|
||||
dev_data->nfc_data.sak = 0x00;
|
||||
|
||||
dev_data->mf_ul_data.type = MfUltralightTypeNTAG215;
|
||||
dev_data->mf_ul_data.version.header = 0x00;
|
||||
dev_data->mf_ul_data.version.vendor_id = 0x04;
|
||||
dev_data->mf_ul_data.version.prod_type = 0x04;
|
||||
dev_data->mf_ul_data.version.prod_subtype = 0x02;
|
||||
dev_data->mf_ul_data.version.prod_ver_major = 0x01;
|
||||
dev_data->mf_ul_data.version.prod_ver_minor = 0x00;
|
||||
dev_data->mf_ul_data.version.storage_size = 0x11;
|
||||
dev_data->mf_ul_data.version.protocol_type = 0x03;
|
||||
|
||||
/* Add 16 to the size for config pages */
|
||||
dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + 16;
|
||||
crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data);
|
||||
}
|
||||
|
||||
/* Prepares the key share popup scene. */
|
||||
void scene_on_enter_key_share_popup(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
popup_reset(state->nfc_popup);
|
||||
|
||||
popup_disable_timeout(state->nfc_popup);
|
||||
|
||||
popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft,
|
||||
AlignTop);
|
||||
popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_47x61);
|
||||
popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28,
|
||||
AlignCenter, AlignTop);
|
||||
|
||||
prepare_nfc_dev_data(state);
|
||||
nfc_worker_start(state->nfc_worker, NfcWorkerStateMfUltralightEmulate,
|
||||
state->nfc_dev_data, NULL, NULL);
|
||||
|
||||
notification_message(state->notification,
|
||||
&sequence_blink_start_magenta);
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
||||
ESubGhzChatView_NfcPopup);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the key share popup scene. */
|
||||
bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
UNUSED(state);
|
||||
UNUSED(event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Cleans up the key share popup scene. */
|
||||
void scene_on_exit_key_share_popup(void* context)
|
||||
{
|
||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup");
|
||||
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
popup_reset(state->nfc_popup);
|
||||
|
||||
notification_message(state->notification, &sequence_blink_stop);
|
||||
|
||||
nfc_worker_stop(state->nfc_worker);
|
||||
|
||||
crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
|
||||
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
||||
}
|
||||
127
applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c
vendored
Normal file
127
applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "../esubghz_chat_i.h"
|
||||
|
||||
/* Sends PassEntered event to scene manager and enters the chat. */
|
||||
static void pass_input_cb(void *context)
|
||||
{
|
||||
furi_assert(context);
|
||||
ESubGhzChatState* state = context;
|
||||
|
||||
crypto_explicit_bzero(state->text_input_store,
|
||||
sizeof(state->text_input_store));
|
||||
|
||||
enter_chat(state);
|
||||
|
||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
||||
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;
|
||||
|
||||
if (strlen(text) == 0) {
|
||||
furi_string_printf(error, "Enter a\npassword!");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char key[KEY_BITS / 8];
|
||||
|
||||
/* derive a key from the password */
|
||||
sha256((unsigned char *) text, strlen(text), key);
|
||||
|
||||
/* initiate the crypto context */
|
||||
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
|
||||
state->name_prefix, furi_get_tick());
|
||||
|
||||
/* cleanup */
|
||||
crypto_explicit_bzero(key, sizeof(key));
|
||||
|
||||
if (!ret) {
|
||||
crypto_ctx_clear(state->crypto_ctx);
|
||||
furi_string_printf(error, "Failed to\nset key!");
|
||||
return false;
|
||||
}
|
||||
|
||||
state->encrypted = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Prepares the password input scene. */
|
||||
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,
|
||||
"Password");
|
||||
|
||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||
}
|
||||
|
||||
/* Handles scene manager events for the password input scene. */
|
||||
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;
|
||||
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* Cleans up the password input scene. */
|
||||
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);
|
||||
crypto_explicit_bzero(state->text_input_store,
|
||||
sizeof(state->text_input_store));
|
||||
}
|
||||
30
applications/external/esubghz_chat/scenes/esubghz_chat_scene.c
vendored
Normal file
30
applications/external/esubghz_chat/scenes/esubghz_chat_scene.c
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "esubghz_chat_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) scene_on_enter_##name,
|
||||
void (*const esubghz_chat_scene_on_enter_handlers[])(void*) = {
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) scene_on_event_##name,
|
||||
bool (*const esubghz_chat_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) scene_on_exit_##name,
|
||||
void (*const esubghz_chat_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
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,
|
||||
};
|
||||
29
applications/external/esubghz_chat/scenes/esubghz_chat_scene.h
vendored
Normal file
29
applications/external/esubghz_chat/scenes/esubghz_chat_scene.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) ESubGhzChatScene_##id,
|
||||
typedef enum {
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
ESubGhzChatScene_MAX
|
||||
} ESubGhzChatScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers esubghz_chat_scene_event_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void scene_on_enter_##name(void*);
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool scene_on_event_##name(void* context, SceneManagerEvent event);
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void scene_on_exit_##name(void* context);
|
||||
#include "esubghz_chat_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
9
applications/external/esubghz_chat/scenes/esubghz_chat_scene_config.h
vendored
Normal file
9
applications/external/esubghz_chat/scenes/esubghz_chat_scene_config.h
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
ADD_SCENE(esubghz_chat, freq_input, FreqInput)
|
||||
ADD_SCENE(esubghz_chat, key_menu, KeyMenu)
|
||||
ADD_SCENE(esubghz_chat, pass_input, PassInput)
|
||||
ADD_SCENE(esubghz_chat, hex_key_input, HexKeyInput)
|
||||
ADD_SCENE(esubghz_chat, key_read_popup, KeyReadPopup)
|
||||
ADD_SCENE(esubghz_chat, chat_input, ChatInput)
|
||||
ADD_SCENE(esubghz_chat, chat_box, ChatBox)
|
||||
ADD_SCENE(esubghz_chat, key_display, KeyDisplay)
|
||||
ADD_SCENE(esubghz_chat, key_share_popup, KeySharePopup)
|
||||
Reference in New Issue
Block a user