This commit is contained in:
Willy-JL
2023-03-08 22:16:39 +00:00
86 changed files with 1236 additions and 866 deletions

View File

@@ -11,6 +11,7 @@ typedef struct {
uint16_t left; uint16_t left;
uint16_t right; uint16_t right;
uint16_t ok; uint16_t ok;
FuriMutex* mutex;
} KeypadTestState; } KeypadTestState;
static void keypad_test_reset_state(KeypadTestState* state) { static void keypad_test_reset_state(KeypadTestState* state) {
@@ -22,7 +23,8 @@ static void keypad_test_reset_state(KeypadTestState* state) {
} }
static void keypad_test_render_callback(Canvas* canvas, void* ctx) { static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
KeypadTestState* state = (KeypadTestState*)acquire_mutex((ValueMutex*)ctx, 25); KeypadTestState* state = ctx;
furi_mutex_acquire(state->mutex, FuriWaitForever);
canvas_clear(canvas); canvas_clear(canvas);
char strings[5][20]; char strings[5][20];
@@ -51,7 +53,7 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit"); canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit");
release_mutex((ValueMutex*)ctx, state); furi_mutex_release(state->mutex);
} }
static void keypad_test_input_callback(InputEvent* input_event, void* ctx) { static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
@@ -64,17 +66,17 @@ int32_t keypad_test_app(void* p) {
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
furi_check(event_queue); furi_check(event_queue);
KeypadTestState _state = {{false, false, false, false, false}, 0, 0, 0, 0, 0}; KeypadTestState state = {{false, false, false, false, false}, 0, 0, 0, 0, 0, NULL};
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
ValueMutex state_mutex; if(!state.mutex) {
if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) {
FURI_LOG_E(TAG, "cannot create mutex"); FURI_LOG_E(TAG, "cannot create mutex");
return 0; return 0;
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state_mutex); view_port_draw_callback_set(view_port, keypad_test_render_callback, &state);
view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue); view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -83,7 +85,7 @@ int32_t keypad_test_app(void* p) {
InputEvent event; InputEvent event;
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) { while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
KeypadTestState* state = (KeypadTestState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(state.mutex, FuriWaitForever);
FURI_LOG_I( FURI_LOG_I(
TAG, TAG,
"key: %s type: %s", "key: %s type: %s",
@@ -92,54 +94,54 @@ int32_t keypad_test_app(void* p) {
if(event.key == InputKeyRight) { if(event.key == InputKeyRight) {
if(event.type == InputTypePress) { if(event.type == InputTypePress) {
state->press[0] = true; state.press[0] = true;
} else if(event.type == InputTypeRelease) { } else if(event.type == InputTypeRelease) {
state->press[0] = false; state.press[0] = false;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
++state->right; ++state.right;
} }
} else if(event.key == InputKeyLeft) { } else if(event.key == InputKeyLeft) {
if(event.type == InputTypePress) { if(event.type == InputTypePress) {
state->press[1] = true; state.press[1] = true;
} else if(event.type == InputTypeRelease) { } else if(event.type == InputTypeRelease) {
state->press[1] = false; state.press[1] = false;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
++state->left; ++state.left;
} }
} else if(event.key == InputKeyUp) { } else if(event.key == InputKeyUp) {
if(event.type == InputTypePress) { if(event.type == InputTypePress) {
state->press[2] = true; state.press[2] = true;
} else if(event.type == InputTypeRelease) { } else if(event.type == InputTypeRelease) {
state->press[2] = false; state.press[2] = false;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
++state->up; ++state.up;
} }
} else if(event.key == InputKeyDown) { } else if(event.key == InputKeyDown) {
if(event.type == InputTypePress) { if(event.type == InputTypePress) {
state->press[3] = true; state.press[3] = true;
} else if(event.type == InputTypeRelease) { } else if(event.type == InputTypeRelease) {
state->press[3] = false; state.press[3] = false;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
++state->down; ++state.down;
} }
} else if(event.key == InputKeyOk) { } else if(event.key == InputKeyOk) {
if(event.type == InputTypePress) { if(event.type == InputTypePress) {
state->press[4] = true; state.press[4] = true;
} else if(event.type == InputTypeRelease) { } else if(event.type == InputTypeRelease) {
state->press[4] = false; state.press[4] = false;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
++state->ok; ++state.ok;
} }
} else if(event.key == InputKeyBack) { } else if(event.key == InputKeyBack) {
if(event.type == InputTypeLong) { if(event.type == InputTypeLong) {
release_mutex(&state_mutex, state); furi_mutex_release(state.mutex);
break; break;
} else if(event.type == InputTypeShort) { } else if(event.type == InputTypeShort) {
keypad_test_reset_state(state); keypad_test_reset_state(&state);
} }
} }
release_mutex(&state_mutex, state); furi_mutex_release(state.mutex);
view_port_update(view_port); view_port_update(view_port);
} }
@@ -147,7 +149,7 @@ int32_t keypad_test_app(void* p) {
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(state.mutex);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);

View File

@@ -53,15 +53,17 @@ static void (*text_box_test_render[])(Canvas* canvas) = {
typedef struct { typedef struct {
uint32_t idx; uint32_t idx;
FuriMutex* mutex;
} TextBoxTestState; } TextBoxTestState;
static void text_box_test_render_callback(Canvas* canvas, void* ctx) { static void text_box_test_render_callback(Canvas* canvas, void* ctx) {
TextBoxTestState* state = acquire_mutex((ValueMutex*)ctx, 25); TextBoxTestState* state = ctx;
furi_mutex_acquire(state->mutex, FuriWaitForever);
canvas_clear(canvas); canvas_clear(canvas);
text_box_test_render[state->idx](canvas); text_box_test_render[state->idx](canvas);
release_mutex((ValueMutex*)ctx, state); furi_mutex_release(state->mutex);
} }
static void text_box_test_input_callback(InputEvent* input_event, void* ctx) { static void text_box_test_input_callback(InputEvent* input_event, void* ctx) {
@@ -74,17 +76,17 @@ int32_t text_box_test_app(void* p) {
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
furi_check(event_queue); furi_check(event_queue);
TextBoxTestState _state = {.idx = 0}; TextBoxTestState state = {.idx = 0, .mutex = NULL};
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
ValueMutex state_mutex; if(!state.mutex) {
if(!init_mutex(&state_mutex, &_state, sizeof(TextBoxTestState))) {
FURI_LOG_E(TAG, "Cannot create mutex"); FURI_LOG_E(TAG, "Cannot create mutex");
return 0; return 0;
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state_mutex); view_port_draw_callback_set(view_port, text_box_test_render_callback, &state);
view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue); view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -94,24 +96,24 @@ int32_t text_box_test_app(void* p) {
uint32_t test_renders_num = COUNT_OF(text_box_test_render); uint32_t test_renders_num = COUNT_OF(text_box_test_render);
InputEvent event; InputEvent event;
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) { while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
TextBoxTestState* state = acquire_mutex_block(&state_mutex); furi_mutex_acquire(state.mutex, FuriWaitForever);
if(event.type == InputTypeShort) { if(event.type == InputTypeShort) {
if(event.key == InputKeyRight) { if(event.key == InputKeyRight) {
if(state->idx < test_renders_num - 1) { if(state.idx < test_renders_num - 1) {
state->idx++; state.idx++;
} }
} else if(event.key == InputKeyLeft) { } else if(event.key == InputKeyLeft) {
if(state->idx > 0) { if(state.idx > 0) {
state->idx--; state.idx--;
} }
} else if(event.key == InputKeyBack) { } else if(event.key == InputKeyBack) {
release_mutex(&state_mutex, state); furi_mutex_release(state.mutex);
break; break;
} }
} }
release_mutex(&state_mutex, state); furi_mutex_release(state.mutex);
view_port_update(view_port); view_port_update(view_port);
} }
@@ -119,7 +121,7 @@ int32_t text_box_test_app(void* p) {
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(state.mutex);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);

View File

@@ -5,7 +5,6 @@
// v2 tests // v2 tests
void test_furi_create_open(); void test_furi_create_open();
void test_furi_valuemutex();
void test_furi_concurrent_access(); void test_furi_concurrent_access();
void test_furi_pubsub(); void test_furi_pubsub();
@@ -30,10 +29,6 @@ MU_TEST(mu_test_furi_create_open) {
test_furi_create_open(); test_furi_create_open();
} }
MU_TEST(mu_test_furi_valuemutex) {
test_furi_valuemutex();
}
MU_TEST(mu_test_furi_pubsub) { MU_TEST(mu_test_furi_pubsub) {
test_furi_pubsub(); test_furi_pubsub();
} }
@@ -51,7 +46,6 @@ MU_TEST_SUITE(test_suite) {
// v2 tests // v2 tests
MU_RUN_TEST(mu_test_furi_create_open); MU_RUN_TEST(mu_test_furi_create_open);
MU_RUN_TEST(mu_test_furi_valuemutex);
MU_RUN_TEST(mu_test_furi_pubsub); MU_RUN_TEST(mu_test_furi_pubsub);
MU_RUN_TEST(mu_test_furi_memmgr); MU_RUN_TEST(mu_test_furi_memmgr);
} }

View File

@@ -1,41 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <furi.h>
#include "../minunit.h"
void test_furi_valuemutex() {
const int init_value = 0xdeadbeef;
const int changed_value = 0x12345678;
int value = init_value;
bool result;
ValueMutex valuemutex;
// init mutex case
result = init_mutex(&valuemutex, &value, sizeof(value));
mu_assert(result, "init mutex failed");
// acquire mutex case
int* value_pointer = acquire_mutex(&valuemutex, 100);
mu_assert_pointers_eq(value_pointer, &value);
// second acquire mutex case
int* value_pointer_second = acquire_mutex(&valuemutex, 100);
mu_assert_pointers_eq(value_pointer_second, NULL);
// change value case
*value_pointer = changed_value;
mu_assert_int_eq(value, changed_value);
// release mutex case
result = release_mutex(&valuemutex, &value);
mu_assert(result, "release mutex failed");
// TODO
//acquire mutex blocking case
//write mutex blocking case
//read mutex blocking case
mu_check(delete_mutex(&valuemutex));
}

View File

@@ -19,7 +19,7 @@ void ibutton_scene_exit_confirm_on_enter(void* context) {
widget_add_button_element( widget_add_button_element(
widget, GuiButtonTypeRight, "Stay", ibutton_scene_exit_confirm_widget_callback, ibutton); widget, GuiButtonTypeRight, "Stay", ibutton_scene_exit_confirm_widget_callback, ibutton);
widget_add_string_element( widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu?"); widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton Menu?");
widget_add_string_element( widget_add_string_element(
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");

View File

@@ -14,7 +14,7 @@ void ibutton_scene_read_on_enter(void* context) {
iButtonWorker* worker = ibutton->worker; iButtonWorker* worker = ibutton->worker;
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); popup_set_text(popup, "Apply key to\nFlipper's back", 95, 30, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 5, XTREME_ASSETS()->I_DolphinWait_61x59); popup_set_icon(popup, 0, 5, XTREME_ASSETS()->I_DolphinWait_61x59);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);

View File

@@ -19,7 +19,7 @@ void ibutton_scene_retry_confirm_on_enter(void* context) {
widget_add_button_element( widget_add_button_element(
widget, GuiButtonTypeRight, "Stay", ibutton_scene_retry_confirm_widget_callback, ibutton); widget, GuiButtonTypeRight, "Stay", ibutton_scene_retry_confirm_widget_callback, ibutton);
widget_add_string_element( widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?"); widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Retry Reading?");
widget_add_string_element( widget_add_string_element(
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");

View File

@@ -10,13 +10,13 @@ void infrared_scene_ask_back_on_enter(void* context) {
DialogEx* dialog_ex = infrared->dialog_ex; DialogEx* dialog_ex = infrared->dialog_ex;
if(infrared->app_state.is_learning_new_remote) { if(infrared->app_state.is_learning_new_remote) {
dialog_ex_set_header(dialog_ex, "Exit to Infrared Menu?", 64, 0, AlignCenter, AlignTop); dialog_ex_set_header(dialog_ex, "Exit to Infrared Menu?", 64, 11, AlignCenter, AlignTop);
} else { } else {
dialog_ex_set_header(dialog_ex, "Exit to Remote Menu?", 64, 0, AlignCenter, AlignTop); dialog_ex_set_header(dialog_ex, "Exit to Remote Menu?", 64, 11, AlignCenter, AlignTop);
} }
dialog_ex_set_text( dialog_ex_set_text(
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter); dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL); dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, "Exit"); dialog_ex_set_left_button_text(dialog_ex, "Exit");
dialog_ex_set_center_button_text(dialog_ex, NULL); dialog_ex_set_center_button_text(dialog_ex, NULL);

View File

@@ -9,9 +9,9 @@ void infrared_scene_ask_retry_on_enter(void* context) {
Infrared* infrared = context; Infrared* infrared = context;
DialogEx* dialog_ex = infrared->dialog_ex; DialogEx* dialog_ex = infrared->dialog_ex;
dialog_ex_set_header(dialog_ex, "Return to Reading?", 64, 0, AlignCenter, AlignTop); dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_text( dialog_ex_set_text(
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter); dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL); dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, "Exit"); dialog_ex_set_left_button_text(dialog_ex, "Exit");
dialog_ex_set_center_button_text(dialog_ex, NULL); dialog_ex_set_center_button_text(dialog_ex, NULL);

View File

@@ -7,7 +7,7 @@ void lfrfid_scene_retry_confirm_on_enter(void* context) {
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app);
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app);
widget_add_string_element( widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?"); widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Retry Reading?");
widget_add_string_element( widget_add_string_element(
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");

View File

@@ -25,7 +25,7 @@ void nfc_scene_mf_classic_menu_on_enter(void* context) {
if(!mf_classic_is_card_read(&nfc->dev->dev_data.mf_classic_data)) { if(!mf_classic_is_card_read(&nfc->dev->dev_data.mf_classic_data)) {
submenu_add_item( submenu_add_item(
submenu, submenu,
"Detect reader", "Detect Reader",
SubmenuIndexDetectReader, SubmenuIndexDetectReader,
nfc_scene_mf_classic_menu_submenu_callback, nfc_scene_mf_classic_menu_submenu_callback,
nfc); nfc);

View File

@@ -14,7 +14,7 @@ void nfc_scene_retry_confirm_on_enter(void* context) {
dialog_ex_set_right_button_text(dialog_ex, "Stay"); dialog_ex_set_right_button_text(dialog_ex, "Stay");
dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop); dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_text( dialog_ex_set_text(
dialog_ex, "All unsaved data will be\nlost!", 64, 25, AlignCenter, AlignTop); dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
dialog_ex_set_context(dialog_ex, nfc); dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback); dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback);

View File

@@ -52,20 +52,20 @@ void nfc_scene_saved_menu_on_enter(void* context) {
if(!mf_classic_is_card_read(&nfc->dev->dev_data.mf_classic_data)) { if(!mf_classic_is_card_read(&nfc->dev->dev_data.mf_classic_data)) {
submenu_add_item( submenu_add_item(
submenu, submenu,
"Detect reader", "Detect Reader",
SubmenuIndexDetectReader, SubmenuIndexDetectReader,
nfc_scene_saved_menu_submenu_callback, nfc_scene_saved_menu_submenu_callback,
nfc); nfc);
} }
submenu_add_item( submenu_add_item(
submenu, submenu,
"Write To Initial Card", "Write to Initial Card",
SubmenuIndexWrite, SubmenuIndexWrite,
nfc_scene_saved_menu_submenu_callback, nfc_scene_saved_menu_submenu_callback,
nfc); nfc);
submenu_add_item( submenu_add_item(
submenu, submenu,
"Update From Initial Card", "Update from Initial Card",
SubmenuIndexUpdate, SubmenuIndexUpdate,
nfc_scene_saved_menu_submenu_callback, nfc_scene_saved_menu_submenu_callback,
nfc); nfc);
@@ -76,13 +76,13 @@ void nfc_scene_saved_menu_on_enter(void* context) {
!mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) { !mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) {
submenu_add_item( submenu_add_item(
submenu, submenu,
"Unlock With Reader", "Unlock with Reader",
SubmenuIndexMfUlUnlockByReader, SubmenuIndexMfUlUnlockByReader,
nfc_scene_saved_menu_submenu_callback, nfc_scene_saved_menu_submenu_callback,
nfc); nfc);
submenu_add_item( submenu_add_item(
submenu, submenu,
"Unlock With Password", "Unlock with Password",
SubmenuIndexMfUlUnlockByPassword, SubmenuIndexMfUlUnlockByPassword,
nfc_scene_saved_menu_submenu_callback, nfc_scene_saved_menu_submenu_callback,
nfc); nfc);

View File

@@ -146,6 +146,8 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent
// Set selected radio module // Set selected radio module
furi_hal_subghz_set_radio_type(value_index_exm); furi_hal_subghz_set_radio_type(value_index_exm);
furi_hal_subghz_enable_ext_power();
// Check if module is present, if no -> show error // Check if module is present, if no -> show error
if(!furi_hal_subghz_check_radio()) { if(!furi_hal_subghz_check_radio()) {
value_index_exm = 0; value_index_exm = 0;

View File

@@ -16,7 +16,7 @@ void subghz_scene_need_saving_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
widget_add_string_multiline_element( widget_add_string_multiline_element(
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-GHz menu?"); subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-GHz Menu?");
widget_add_string_multiline_element( widget_add_string_multiline_element(
subghz->widget, subghz->widget,
64, 64,
@@ -24,7 +24,7 @@ void subghz_scene_need_saving_on_enter(void* context) {
AlignCenter, AlignCenter,
AlignCenter, AlignCenter,
FontSecondary, FontSecondary,
"All unsaved will be\nlost."); "All unsaved data\nwill be lost!");
widget_add_button_element( widget_add_button_element(
subghz->widget, GuiButtonTypeRight, "Stay", subghz_scene_need_saving_callback, subghz); subghz->widget, GuiButtonTypeRight, "Stay", subghz_scene_need_saving_callback, subghz);

View File

@@ -75,43 +75,46 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexExtSettings); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexExtSettings);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneExtModuleSettings); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneExtModuleSettings);
return true; return true;
} else if(!furi_hal_subghz_check_radio()) {
furi_string_set(subghz->error_str, "Please connect\nexternal radio");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
return true;
} else if(event.event == SubmenuIndexReadRAW) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
return true;
} else if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
return true;
} else if(event.event == SubmenuIndexSaved) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexSaved);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
return true;
} else if(event.event == SubmenuIndexAddManually) { } else if(event.event == SubmenuIndexAddManually) {
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManually); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType);
return true; return true;
} else if(event.event == SubmenuIndexFrequencyAnalyzer) { } else {
scene_manager_set_scene_state( furi_hal_subghz_enable_ext_power();
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer); if(!furi_hal_subghz_check_radio()) {
DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer); furi_string_set(subghz->error_str, "Please connect\nexternal radio");
return true; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
} else if(event.event == SubmenuIndexTest) { return true;
scene_manager_set_scene_state( } else if(event.event == SubmenuIndexReadRAW) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); scene_manager_set_scene_state(
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW);
return true; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
return true;
} else if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
return true;
} else if(event.event == SubmenuIndexSaved) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexSaved);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
return true;
} else if(event.event == SubmenuIndexFrequencyAnalyzer) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer);
return true;
} else if(event.event == SubmenuIndexTest) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest);
return true;
}
} }
} }
return false; return false;

View File

@@ -421,6 +421,9 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
// The rest // The rest
free(subghz); free(subghz);
// Disable power for External CC1101 if it was enabled and module is connected
furi_hal_subghz_disable_ext_power();
} }
int32_t subghz_app(void* p) { int32_t subghz_app(void* p) {

View File

@@ -37,6 +37,7 @@ typedef struct {
} BallState; } BallState;
typedef struct { typedef struct {
FuriMutex* mutex;
BallState ball_state; BallState ball_state;
BrickState brick_state; BrickState brick_state;
NotificationApp* notify; NotificationApp* notify;
@@ -309,10 +310,9 @@ static void arkanoid_state_init(ArkanoidState* arkanoid_state) {
} }
static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) { static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
ArkanoidState* arkanoid_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(arkanoid_state == NULL) { ArkanoidState* arkanoid_state = ctx;
return; furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever);
}
//Initial level draw //Initial level draw
if(!arkanoid_state->initialDraw) { if(!arkanoid_state->initialDraw) {
@@ -351,7 +351,7 @@ static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
arkanoid_state->score = 0; arkanoid_state->score = 0;
} }
release_mutex((ValueMutex*)ctx, arkanoid_state); furi_mutex_release(arkanoid_state->mutex);
} }
static void arkanoid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void arkanoid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -377,8 +377,8 @@ int32_t arkanoid_game_app(void* p) {
ArkanoidState* arkanoid_state = malloc(sizeof(ArkanoidState)); ArkanoidState* arkanoid_state = malloc(sizeof(ArkanoidState));
arkanoid_state_init(arkanoid_state); arkanoid_state_init(arkanoid_state);
ValueMutex state_mutex; arkanoid_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, arkanoid_state, sizeof(ArkanoidState))) { if(!arkanoid_state->mutex) {
FURI_LOG_E(TAG, "Cannot create mutex\r\n"); FURI_LOG_E(TAG, "Cannot create mutex\r\n");
return_code = 255; return_code = 255;
goto free_and_exit; goto free_and_exit;
@@ -386,7 +386,7 @@ int32_t arkanoid_game_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, arkanoid_draw_callback, &state_mutex); view_port_draw_callback_set(view_port, arkanoid_draw_callback, arkanoid_state);
view_port_input_callback_set(view_port, arkanoid_input_callback, event_queue); view_port_input_callback_set(view_port, arkanoid_input_callback, event_queue);
FuriTimer* timer = FuriTimer* timer =
@@ -400,7 +400,7 @@ int32_t arkanoid_game_app(void* p) {
GameEvent event; GameEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
ArkanoidState* arkanoid_state = (ArkanoidState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// Key events // Key events
@@ -457,7 +457,7 @@ int32_t arkanoid_game_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, arkanoid_state); furi_mutex_release(arkanoid_state->mutex);
} }
furi_timer_free(timer); furi_timer_free(timer);
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
@@ -465,7 +465,7 @@ int32_t arkanoid_game_app(void* p) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port); view_port_free(view_port);
delete_mutex(&state_mutex); furi_mutex_free(arkanoid_state->mutex);
free_and_exit: free_and_exit:
free(arkanoid_state); free(arkanoid_state);

View File

@@ -130,10 +130,9 @@ int calculate_check_digit(PluginState* plugin_state, BarcodeType* type) {
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(plugin_state == NULL) { PluginState* plugin_state = ctx;
return; furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
}
if(plugin_state->mode == MenuMode) { if(plugin_state->mode == MenuMode) {
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
@@ -239,7 +238,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_box(canvas, (endSafetyPosition + 2), BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); canvas_draw_box(canvas, (endSafetyPosition + 2), BARCODE_Y_START, 1, BARCODE_HEIGHT + 2);
} }
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -387,8 +386,9 @@ int32_t barcode_generator_app(void* p) {
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
barcode_generator_state_init(plugin_state); barcode_generator_state_init(plugin_state);
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!plugin_state->mutex) {
FURI_LOG_E("barcode_generator", "cannot create mutex\r\n"); FURI_LOG_E("barcode_generator", "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(plugin_state); free(plugin_state);
@@ -397,7 +397,7 @@ int32_t barcode_generator_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -407,7 +407,7 @@ int32_t barcode_generator_app(void* p) {
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -430,7 +430,7 @@ int32_t barcode_generator_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
@@ -438,6 +438,7 @@ int32_t barcode_generator_app(void* p) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_mutex_free(plugin_state->mutex);
// save settings // save settings
SAVE_BARCODE_SETTINGS(&plugin_state->barcode_state); SAVE_BARCODE_SETTINGS(&plugin_state->barcode_state);
free(plugin_state); free(plugin_state);

View File

@@ -81,6 +81,7 @@ typedef struct {
} BarcodeState; } BarcodeState;
typedef struct { typedef struct {
FuriMutex* mutex;
BarcodeState barcode_state; BarcodeState barcode_state;
int editingIndex; //The index of the editing symbol int editingIndex; //The index of the editing symbol
int menuIndex; //The index of the menu cursor int menuIndex; //The index of the menu cursor

View File

@@ -32,11 +32,9 @@ static void draw_ui(Canvas* const canvas, const GameState* game_state) {
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
const GameState* game_state = ctx;
if(game_state == NULL) { furi_mutex_acquire(game_state->mutex, FuriWaitForever);
return;
}
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -59,7 +57,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
settings_page(canvas, game_state); settings_page(canvas, game_state);
} }
release_mutex((ValueMutex*)ctx, game_state); furi_mutex_release(game_state->mutex);
} }
//region card draw //region card draw
@@ -551,68 +549,65 @@ int32_t blackjack_app(void* p) {
game_state->state = GameStateStart; game_state->state = GameStateStart;
ValueMutex state_mutex; game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) { if(!game_state->mutex) {
FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
return_code = 255; return_code = 255;
goto free_and_exit; goto free_and_exit;
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, game_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue); FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25);
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
AppEvent event; AppEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
GameState* localstate = (GameState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(game_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
if(event.input.type == InputTypePress) { if(event.input.type == InputTypePress) {
switch(event.input.key) { switch(event.input.key) {
case InputKeyUp: case InputKeyUp:
localstate->selectDirection = DirectionUp; game_state->selectDirection = DirectionUp;
break; break;
case InputKeyDown: case InputKeyDown:
localstate->selectDirection = DirectionDown; game_state->selectDirection = DirectionDown;
break; break;
case InputKeyRight: case InputKeyRight:
localstate->selectDirection = DirectionRight; game_state->selectDirection = DirectionRight;
break; break;
case InputKeyLeft: case InputKeyLeft:
localstate->selectDirection = DirectionLeft; game_state->selectDirection = DirectionLeft;
break; break;
case InputKeyBack: case InputKeyBack:
if(localstate->state == GameStateSettings) { if(game_state->state == GameStateSettings) {
localstate->state = GameStateStart; game_state->state = GameStateStart;
save_settings(localstate->settings); save_settings(game_state->settings);
} else } else
processing = false; processing = false;
break; break;
case InputKeyOk: case InputKeyOk:
localstate->selectDirection = Select; game_state->selectDirection = Select;
break; break;
default: default:
break; break;
} }
} }
} else if(event.type == EventTypeTick) { } else if(event.type == EventTypeTick) {
tick(localstate); tick(game_state);
processing = localstate->processing; processing = game_state->processing;
} }
} else {
//FURI_LOG_D(APP_NAME, "osMessageQueue: event timeout");
// event timeout
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, localstate); furi_mutex_release(game_state->mutex);
} }
furi_timer_free(timer); furi_timer_free(timer);
@@ -620,7 +615,7 @@ int32_t blackjack_app(void* p) {
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
delete_mutex(&state_mutex); furi_mutex_free(game_state->mutex);
free_and_exit: free_and_exit:
free(game_state->deck.cards); free(game_state->deck.cards);

View File

@@ -54,6 +54,7 @@ typedef enum {
} Direction; } Direction;
typedef struct { typedef struct {
FuriMutex* mutex;
Card player_cards[21]; Card player_cards[21];
Card dealer_cards[21]; Card dealer_cards[21];
uint8_t player_card_count; uint8_t player_card_count;

View File

@@ -37,6 +37,7 @@ typedef struct {
} PluginEvent; } PluginEvent;
typedef struct { typedef struct {
FuriMutex* mutex;
Player player; Player player;
Entity entity[MAX_ENTITIES]; Entity entity[MAX_ENTITIES];
StaticEntity static_entity[MAX_STATIC_ENTITIES]; StaticEntity static_entity[MAX_STATIC_ENTITIES];
@@ -770,10 +771,9 @@ void loopIntro(Canvas* const canvas) {
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(plugin_state == NULL) { PluginState* plugin_state = ctx;
return; furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
}
if(plugin_state->init) setupDisplay(canvas); if(plugin_state->init) setupDisplay(canvas);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
@@ -797,7 +797,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
break; break;
} }
} }
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -967,8 +967,8 @@ int32_t doom_app() {
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
doom_state_init(plugin_state); doom_state_init(plugin_state);
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
FURI_LOG_E("Doom_game", "cannot create mutex\r\n"); FURI_LOG_E("Doom_game", "cannot create mutex\r\n");
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
@@ -980,11 +980,11 @@ int32_t doom_app() {
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 12); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 12);
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
////////////////////////////////// //////////////////////////////////
@@ -997,7 +997,7 @@ int32_t doom_app() {
#endif #endif
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
#ifdef SOUND #ifdef SOUND
furi_check( furi_check(
furi_mutex_acquire(plugin_state->music_instance->model_mutex, FuriWaitForever) == furi_mutex_acquire(plugin_state->music_instance->model_mutex, FuriWaitForever) ==
@@ -1087,7 +1087,7 @@ int32_t doom_app() {
furi_mutex_release(plugin_state->music_instance->model_mutex); furi_mutex_release(plugin_state->music_instance->model_mutex);
#endif #endif
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
#ifdef SOUND #ifdef SOUND
music_player_worker_free(plugin_state->music_instance->worker); music_player_worker_free(plugin_state->music_instance->worker);
@@ -1099,8 +1099,9 @@ int32_t doom_app() {
furi_timer_free(timer); furi_timer_free(timer);
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_mutex_free(plugin_state->mutex);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(plugin_state); free(plugin_state);
return 0; return 0;

View File

@@ -59,6 +59,7 @@ typedef struct {
PILAR pilars[FLAPPY_PILAR_MAX]; PILAR pilars[FLAPPY_PILAR_MAX];
bool debug; bool debug;
State state; State state;
FuriMutex* mutex;
} GameState; } GameState;
typedef struct { typedef struct {
@@ -174,10 +175,9 @@ static void flappy_game_flap(GameState* const game_state) {
} }
static void flappy_game_render_callback(Canvas* const canvas, void* ctx) { static void flappy_game_render_callback(Canvas* const canvas, void* ctx) {
const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(game_state == NULL) { const GameState* game_state = ctx;
return; furi_mutex_acquire(game_state->mutex, FuriWaitForever);
}
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -261,7 +261,7 @@ static void flappy_game_render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer);
} }
release_mutex((ValueMutex*)ctx, game_state); furi_mutex_release(game_state->mutex);
} }
static void flappy_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void flappy_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -287,8 +287,8 @@ int32_t flappy_game_app(void* p) {
GameState* game_state = malloc(sizeof(GameState)); GameState* game_state = malloc(sizeof(GameState));
flappy_game_state_init(game_state); flappy_game_state_init(game_state);
ValueMutex state_mutex; game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) { if(!game_state->mutex) {
FURI_LOG_E(TAG, "cannot create mutex\r\n"); FURI_LOG_E(TAG, "cannot create mutex\r\n");
return_code = 255; return_code = 255;
goto free_and_exit; goto free_and_exit;
@@ -296,7 +296,7 @@ int32_t flappy_game_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, flappy_game_render_callback, &state_mutex); view_port_draw_callback_set(view_port, flappy_game_render_callback, game_state);
view_port_input_callback_set(view_port, flappy_game_input_callback, event_queue); view_port_input_callback_set(view_port, flappy_game_input_callback, event_queue);
FuriTimer* timer = FuriTimer* timer =
@@ -310,7 +310,7 @@ int32_t flappy_game_app(void* p) {
GameEvent event; GameEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(game_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -352,7 +352,7 @@ int32_t flappy_game_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, game_state); furi_mutex_release(game_state->mutex);
} }
furi_timer_free(timer); furi_timer_free(timer);
@@ -360,7 +360,7 @@ int32_t flappy_game_app(void* p) {
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
delete_mutex(&state_mutex); furi_mutex_free(game_state->mutex);
free_and_exit: free_and_exit:
flappy_game_state_free(game_state); flappy_game_state_free(game_state);

View File

@@ -9,11 +9,9 @@
#define RFIDFUZZER_APP_FOLDER "/ext/lrfid/rfidfuzzer" #define RFIDFUZZER_APP_FOLDER "/ext/lrfid/rfidfuzzer"
static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) { static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
FlipFridState* flipfrid_state = (FlipFridState*)acquire_mutex((ValueMutex*)ctx, 100); furi_assert(ctx);
FlipFridState* flipfrid_state = ctx;
if(flipfrid_state == NULL) { furi_mutex_acquire(flipfrid_state->mutex, FuriWaitForever);
return;
}
// Draw correct Canvas // Draw correct Canvas
switch(flipfrid_state->current_scene) { switch(flipfrid_state->current_scene) {
@@ -37,7 +35,7 @@ static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
break; break;
} }
release_mutex((ValueMutex*)ctx, flipfrid_state); furi_mutex_release(flipfrid_state->mutex);
} }
void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -118,11 +116,9 @@ int32_t flipfrid_start(void* p) {
FURI_LOG_I(TAG, "Initializing input"); FURI_LOG_I(TAG, "Initializing input");
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
FlipFridState* flipfrid_state = flipfrid_alloc(); FlipFridState* flipfrid_state = flipfrid_alloc();
ValueMutex flipfrid_state_mutex;
// Mutex flipfrid_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_LOG_I(TAG, "Initializing flipfrid mutex"); if(!flipfrid_state->mutex) {
if(!init_mutex(&flipfrid_state_mutex, flipfrid_state, sizeof(FlipFridState))) {
FURI_LOG_E(TAG, "cannot create mutex\r\n"); FURI_LOG_E(TAG, "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
@@ -139,7 +135,7 @@ int32_t flipfrid_start(void* p) {
// Configure view port // Configure view port
FURI_LOG_I(TAG, "Initializing viewport"); FURI_LOG_I(TAG, "Initializing viewport");
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, flipfrid_draw_callback, &flipfrid_state_mutex); view_port_draw_callback_set(view_port, flipfrid_draw_callback, flipfrid_state);
view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue); view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue);
// Configure timer // Configure timer
@@ -268,6 +264,7 @@ int32_t flipfrid_start(void* p) {
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
furi_mutex_free(flipfrid_state->mutex);
flipfrid_free(flipfrid_state); flipfrid_free(flipfrid_state);
return 0; return 0;

View File

@@ -58,6 +58,7 @@ typedef struct {
// STRUCTS // STRUCTS
typedef struct { typedef struct {
FuriMutex* mutex;
bool is_running; bool is_running;
bool is_attacking; bool is_attacking;
FlipFridScene current_scene; FlipFridScene current_scene;

View File

@@ -1,7 +1,9 @@
#include "i2ctools_i.h" #include "i2ctools_i.h"
void i2ctools_draw_callback(Canvas* canvas, void* ctx) { void i2ctools_draw_callback(Canvas* canvas, void* ctx) {
i2cTools* i2ctools = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
i2cTools* i2ctools = ctx;
furi_mutex_acquire(i2ctools->mutex, FuriWaitForever);
switch(i2ctools->main_view->current_view) { switch(i2ctools->main_view->current_view) {
case MAIN_VIEW: case MAIN_VIEW:
@@ -23,7 +25,7 @@ void i2ctools_draw_callback(Canvas* canvas, void* ctx) {
default: default:
break; break;
} }
release_mutex((ValueMutex*)ctx, i2ctools); furi_mutex_release(i2ctools->mutex);
} }
void i2ctools_input_callback(InputEvent* input_event, void* ctx) { void i2ctools_input_callback(InputEvent* input_event, void* ctx) {
@@ -38,8 +40,8 @@ int32_t i2ctools_app(void* p) {
// Alloc i2ctools // Alloc i2ctools
i2cTools* i2ctools = malloc(sizeof(i2cTools)); i2cTools* i2ctools = malloc(sizeof(i2cTools));
ValueMutex i2ctools_mutex; i2ctools->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&i2ctools_mutex, i2ctools, sizeof(i2cTools))) { if(!i2ctools->mutex) {
FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
free(i2ctools); free(i2ctools);
return -1; return -1;
@@ -47,7 +49,7 @@ int32_t i2ctools_app(void* p) {
// Alloc viewport // Alloc viewport
i2ctools->view_port = view_port_alloc(); i2ctools->view_port = view_port_alloc();
view_port_draw_callback_set(i2ctools->view_port, i2ctools_draw_callback, &i2ctools_mutex); view_port_draw_callback_set(i2ctools->view_port, i2ctools_draw_callback, i2ctools);
view_port_input_callback_set(i2ctools->view_port, i2ctools_input_callback, event_queue); view_port_input_callback_set(i2ctools->view_port, i2ctools_input_callback, event_queue);
// Register view port in GUI // Register view port in GUI
@@ -216,6 +218,7 @@ int32_t i2ctools_app(void* p) {
i2c_scanner_free(i2ctools->scanner); i2c_scanner_free(i2ctools->scanner);
i2c_sender_free(i2ctools->sender); i2c_sender_free(i2ctools->sender);
i2c_main_view_free(i2ctools->main_view); i2c_main_view_free(i2ctools->main_view);
furi_mutex_free(i2ctools->mutex);
free(i2ctools); free(i2ctools);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
return 0; return 0;

View File

@@ -13,6 +13,7 @@
// App datas // App datas
typedef struct { typedef struct {
FuriMutex* mutex;
ViewPort* view_port; ViewPort* view_port;
i2cMainView* main_view; i2cMainView* main_view;

View File

@@ -33,6 +33,7 @@ typedef enum {
} State; } State;
typedef struct { typedef struct {
FuriMutex* mutex;
State state; State state;
uint8_t table[CELLS_COUNT][CELLS_COUNT]; uint8_t table[CELLS_COUNT][CELLS_COUNT];
uint32_t score; uint32_t score;
@@ -103,8 +104,9 @@ static void gray_canvas(Canvas* const canvas) {
} }
static void draw_callback(Canvas* const canvas, void* ctx) { static void draw_callback(Canvas* const canvas, void* ctx) {
const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(game_state == NULL) return; const GameState* game_state = ctx;
furi_mutex_acquire(game_state->mutex, FuriWaitForever);
canvas_clear(canvas); canvas_clear(canvas);
@@ -180,7 +182,7 @@ static void draw_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignBottom, buf); canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignBottom, buf);
} }
release_mutex((ValueMutex*)ctx, game_state); furi_mutex_release(game_state->mutex);
} }
void calculate_move_to_left(uint8_t arr[], MoveResult* const move_result) { void calculate_move_to_left(uint8_t arr[], MoveResult* const move_result) {
@@ -380,8 +382,8 @@ int32_t game_2048_app() {
MoveResult* move_result = malloc(sizeof(MoveResult)); MoveResult* move_result = malloc(sizeof(MoveResult));
ValueMutex state_mutex; game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) { if(!game_state->mutex) {
FURI_LOG_E("2048Game", "cannot create mutex\r\n"); FURI_LOG_E("2048Game", "cannot create mutex\r\n");
free(game_state); free(game_state);
return 255; return 255;
@@ -391,7 +393,7 @@ int32_t game_2048_app() {
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, draw_callback, &state_mutex); view_port_draw_callback_set(view_port, draw_callback, game_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
Gui* gui = furi_record_open(RECORD_GUI); Gui* gui = furi_record_open(RECORD_GUI);
@@ -404,7 +406,7 @@ int32_t game_2048_app() {
// handle only press event, ignore repeat/release events // handle only press event, ignore repeat/release events
if(input.type != InputTypePress) continue; if(input.type != InputTypePress) continue;
GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(game_state->mutex, FuriWaitForever);
switch(game_state->state) { switch(game_state->state) {
case GameStateMenu: case GameStateMenu:
@@ -489,7 +491,7 @@ int32_t game_2048_app() {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, game_state); furi_mutex_release(game_state->mutex);
} }
} }
@@ -500,7 +502,7 @@ int32_t game_2048_app() {
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(game_state->mutex);
free(game_state); free(game_state);
free(move_result); free(move_result);

View File

@@ -15,10 +15,9 @@ typedef struct {
} PluginEvent; } PluginEvent;
static void render_callback(Canvas* const canvas, void* context) { static void render_callback(Canvas* const canvas, void* context) {
const GpsUart* gps_uart = acquire_mutex((ValueMutex*)context, 25); furi_assert(context);
if(gps_uart == NULL) { const GpsUart* gps_uart = context;
return; furi_mutex_acquire(gps_uart->mutex, FuriWaitForever);
}
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 32, 8, AlignCenter, AlignBottom, "Latitude"); canvas_draw_str_aligned(canvas, 32, 8, AlignCenter, AlignBottom, "Latitude");
@@ -57,7 +56,7 @@ static void render_callback(Canvas* const canvas, void* context) {
gps_uart->status.time_seconds); gps_uart->status.time_seconds);
canvas_draw_str_aligned(canvas, 96, 62, AlignCenter, AlignBottom, buffer); canvas_draw_str_aligned(canvas, 96, 62, AlignCenter, AlignBottom, buffer);
release_mutex((ValueMutex*)context, gps_uart); furi_mutex_release(gps_uart->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -74,8 +73,8 @@ int32_t gps_app(void* p) {
GpsUart* gps_uart = gps_uart_enable(); GpsUart* gps_uart = gps_uart_enable();
ValueMutex gps_uart_mutex; gps_uart->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&gps_uart_mutex, gps_uart, sizeof(GpsUart))) { if(!gps_uart->mutex) {
FURI_LOG_E("GPS", "cannot create mutex\r\n"); FURI_LOG_E("GPS", "cannot create mutex\r\n");
free(gps_uart); free(gps_uart);
return 255; return 255;
@@ -83,18 +82,18 @@ int32_t gps_app(void* p) {
// set system callbacks // set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &gps_uart_mutex); view_port_draw_callback_set(view_port, render_callback, gps_uart);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// open GUI and register view_port // open GUI and register view_port
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
GpsUart* gps_uart = (GpsUart*)acquire_mutex_block(&gps_uart_mutex); furi_mutex_acquire(gps_uart->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -118,15 +117,15 @@ int32_t gps_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&gps_uart_mutex, gps_uart); furi_mutex_release(gps_uart->mutex);
} }
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&gps_uart_mutex); furi_mutex_free(gps_uart->mutex);
gps_uart_disable(gps_uart); gps_uart_disable(gps_uart);
return 0; return 0;

View File

@@ -22,6 +22,7 @@ typedef struct {
} GpsStatus; } GpsStatus;
typedef struct { typedef struct {
FuriMutex* mutex;
FuriThread* thread; FuriThread* thread;
FuriStreamBuffer* rx_stream; FuriStreamBuffer* rx_stream;
uint8_t rx_buf[RX_BUF_SIZE]; uint8_t rx_buf[RX_BUF_SIZE];

View File

@@ -24,6 +24,7 @@ typedef struct {
} PluginEvent; } PluginEvent;
typedef struct { typedef struct {
FuriMutex* mutex;
NotificationApp* notification; NotificationApp* notification;
bool have_5v; bool have_5v;
bool measurement_made; bool measurement_made;
@@ -41,10 +42,10 @@ const NotificationSequence sequence_done = {
}; };
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(plugin_state == NULL) { const PluginState* plugin_state = ctx;
return; furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
}
// border around the edge of the screen // border around the edge of the screen
// canvas_draw_frame(canvas, 0, 0, 128, 64); // canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -85,7 +86,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
} }
} }
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -184,8 +185,8 @@ int32_t hc_sr04_app() {
furi_hal_console_disable(); furi_hal_console_disable();
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
FURI_LOG_E("hc_sr04", "cannot create mutex\r\n"); FURI_LOG_E("hc_sr04", "cannot create mutex\r\n");
if(furi_hal_power_is_otg_enabled()) { if(furi_hal_power_is_otg_enabled()) {
furi_hal_power_disable_otg(); furi_hal_power_disable_otg();
@@ -201,7 +202,7 @@ int32_t hc_sr04_app() {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -212,7 +213,7 @@ int32_t hc_sr04_app() {
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -238,7 +239,7 @@ int32_t hc_sr04_app() {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
if(furi_hal_power_is_otg_enabled()) { if(furi_hal_power_is_otg_enabled()) {
@@ -267,7 +268,8 @@ int32_t hc_sr04_app() {
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(plugin_state->mutex);
free(plugin_state);
return 0; return 0;
} }

View File

@@ -86,6 +86,7 @@ typedef struct {
Person* person; Person* person;
Animations animation; Animations animation;
GameStatuses game_status; GameStatuses game_status;
FuriMutex* mutex;
} GameState; } GameState;
typedef Box** Field; typedef Box** Field;
@@ -432,15 +433,15 @@ static void draw_box(Canvas* canvas, Box* box, int x, int y) {
static void heap_defense_render_callback(Canvas* const canvas, void* mutex) { static void heap_defense_render_callback(Canvas* const canvas, void* mutex) {
furi_assert(mutex); furi_assert(mutex);
const GameState* game = mutex;
const GameState* game = acquire_mutex((ValueMutex*)mutex, 25); furi_mutex_acquire(game->mutex, FuriWaitForever);
///Draw GameOver or Pause ///Draw GameOver or Pause
if(!(game->game_status & GameStatusInProgress)) { if(!(game->game_status & GameStatusInProgress)) {
FURI_LOG_W(TAG, "[DAED_DRAW]func: [%s] line: %d ", __FUNCTION__, __LINE__); FURI_LOG_W(TAG, "[DAED_DRAW]func: [%s] line: %d ", __FUNCTION__, __LINE__);
canvas_draw_icon_animation(canvas, 0, 0, animations[game->animation]); canvas_draw_icon_animation(canvas, 0, 0, animations[game->animation]);
release_mutex((ValueMutex*)mutex, game); furi_mutex_release(game->mutex);
return; return;
} }
@@ -480,7 +481,7 @@ static void heap_defense_render_callback(Canvas* const canvas, void* mutex) {
} }
} }
release_mutex((ValueMutex*)mutex, game); furi_mutex_release(game->mutex);
} }
static void heap_defense_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void heap_defense_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -505,25 +506,25 @@ int32_t heap_defence_app(void* p) {
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent));
GameState* game = allocGameState(); GameState* game = allocGameState();
ValueMutex state_mutex; game->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, game, sizeof(GameState))) { if(!game->mutex) {
game_destroy(game); game_destroy(game);
return 1; return 1;
} }
assets_load(); assets_load();
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, heap_defense_render_callback, &state_mutex); view_port_draw_callback_set(view_port, heap_defense_render_callback, game);
view_port_input_callback_set(view_port, heap_defense_input_callback, event_queue); view_port_input_callback_set(view_port, heap_defense_input_callback, event_queue);
FuriTimer* timer = FuriTimer* timer =
furi_timer_alloc(heap_defense_timer_callback, FuriTimerTypePeriodic, event_queue); furi_timer_alloc(heap_defense_timer_callback, FuriTimerTypePeriodic, event_queue);
furi_timer_start(timer, furi_kernel_get_tick_frequency() / TIMER_UPDATE_FREQ); furi_timer_start(timer, furi_kernel_get_tick_frequency() / TIMER_UPDATE_FREQ);
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
NotificationApp* notification = furi_record_open("notification"); NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
memset(game->field[Y_LAST], 128, ROW_BYTE_SIZE); memset(game->field[Y_LAST], 128, ROW_BYTE_SIZE);
game->person->p.y -= 2; game->person->p.y -= 2;
@@ -536,7 +537,7 @@ int32_t heap_defence_app(void* p) {
continue; continue;
} }
game = (GameState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(game->mutex, FuriWaitForever);
//unset vibration //unset vibration
if(game->game_status & GameStatusVibro) { if(game->game_status & GameStatusVibro) {
@@ -573,7 +574,7 @@ int32_t heap_defence_app(void* p) {
notification_message(notification, &sequence_error); notification_message(notification, &sequence_error);
} }
} }
release_mutex(&state_mutex, game); furi_mutex_release(game->mutex);
view_port_update(view_port); view_port_update(view_port);
} }
@@ -581,11 +582,11 @@ int32_t heap_defence_app(void* p) {
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
view_port_free(view_port); view_port_free(view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
furi_record_close("notification"); furi_record_close(RECORD_NOTIFICATION);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
assets_clear(); assets_clear();
delete_mutex(&state_mutex); furi_mutex_free(game->mutex);
game_destroy(game); game_destroy(game);
return 0; return 0;

View File

@@ -9,11 +9,9 @@
#define IBTNFUZZER_APP_FOLDER "/ext/ibtnfuzzer" #define IBTNFUZZER_APP_FOLDER "/ext/ibtnfuzzer"
static void ibtnfuzzer_draw_callback(Canvas* const canvas, void* ctx) { static void ibtnfuzzer_draw_callback(Canvas* const canvas, void* ctx) {
iBtnFuzzerState* ibtnfuzzer_state = (iBtnFuzzerState*)acquire_mutex((ValueMutex*)ctx, 100); furi_assert(ctx);
iBtnFuzzerState* ibtnfuzzer_state = ctx;
if(ibtnfuzzer_state == NULL) { furi_mutex_acquire(ibtnfuzzer_state->mutex, FuriWaitForever);
return;
}
// Draw correct Canvas // Draw correct Canvas
switch(ibtnfuzzer_state->current_scene) { switch(ibtnfuzzer_state->current_scene) {
@@ -35,7 +33,7 @@ static void ibtnfuzzer_draw_callback(Canvas* const canvas, void* ctx) {
break; break;
} }
release_mutex((ValueMutex*)ctx, ibtnfuzzer_state); furi_mutex_release(ibtnfuzzer_state->mutex);
} }
void ibtnfuzzer_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { void ibtnfuzzer_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -120,11 +118,9 @@ int32_t ibtnfuzzer_start(void* p) {
FURI_LOG_I(TAG, "Initializing input"); FURI_LOG_I(TAG, "Initializing input");
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(iBtnFuzzerEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(iBtnFuzzerEvent));
iBtnFuzzerState* ibtnfuzzer_state = ibtnfuzzer_alloc(); iBtnFuzzerState* ibtnfuzzer_state = ibtnfuzzer_alloc();
ValueMutex ibtnfuzzer_state_mutex;
// Mutex ibtnfuzzer_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_LOG_I(TAG, "Initializing ibtnfuzzer mutex"); if(!ibtnfuzzer_state->mutex) {
if(!init_mutex(&ibtnfuzzer_state_mutex, ibtnfuzzer_state, sizeof(iBtnFuzzerState))) {
FURI_LOG_E(TAG, "cannot create mutex\r\n"); FURI_LOG_E(TAG, "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
@@ -141,7 +137,7 @@ int32_t ibtnfuzzer_start(void* p) {
// Configure view port // Configure view port
FURI_LOG_I(TAG, "Initializing viewport"); FURI_LOG_I(TAG, "Initializing viewport");
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, ibtnfuzzer_draw_callback, &ibtnfuzzer_state_mutex); view_port_draw_callback_set(view_port, ibtnfuzzer_draw_callback, ibtnfuzzer_state);
view_port_input_callback_set(view_port, ibtnfuzzer_input_callback, event_queue); view_port_input_callback_set(view_port, ibtnfuzzer_input_callback, event_queue);
// Configure timer // Configure timer
@@ -160,6 +156,7 @@ int32_t ibtnfuzzer_start(void* p) {
while(ibtnfuzzer_state->is_running) { while(ibtnfuzzer_state->is_running) {
// Get next event // Get next event
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
//furi_mutex_acquire(ibtnfuzzer_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.evt_type == EventTypeKey) { if(event.evt_type == EventTypeKey) {
//Handle event key //Handle event key
@@ -250,6 +247,7 @@ int32_t ibtnfuzzer_start(void* p) {
view_port_update(view_port); view_port_update(view_port);
} }
} }
//furi_mutex_release(ibtnfuzzer_state->mutex);
} }
// Cleanup // Cleanup
@@ -262,6 +260,7 @@ int32_t ibtnfuzzer_start(void* p) {
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
furi_mutex_free(ibtnfuzzer_state->mutex);
ibtnfuzzer_free(ibtnfuzzer_state); ibtnfuzzer_free(ibtnfuzzer_state);
return 0; return 0;

View File

@@ -56,6 +56,7 @@ typedef struct {
// STRUCTS // STRUCTS
typedef struct { typedef struct {
FuriMutex* mutex;
bool is_running; bool is_running;
bool is_attacking; bool is_attacking;
iBtnFuzzerScene current_scene; iBtnFuzzerScene current_scene;

View File

@@ -1,7 +1,6 @@
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <input/input.h> #include <input/input.h>
#include <m-string.h>
#include <stdlib.h> #include <stdlib.h>
#include <gui/gui.h> #include <gui/gui.h>
@@ -50,31 +49,33 @@ typedef struct {
enum OutputMode output_mode; enum OutputMode output_mode;
FuriTimer* timer; FuriTimer* timer;
NotificationApp* notifications; NotificationApp* notifications;
FuriMutex* mutex;
} MetronomeState; } MetronomeState;
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(metronome_state == NULL) { const MetronomeState* metronome_state = ctx;
return; furi_mutex_acquire(metronome_state->mutex, FuriWaitForever);
}
string_t tempStr; FuriString* tempStr = furi_string_alloc();
string_init(tempStr);
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
// draw bars/beat // draw bars/beat
string_printf(tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length); furi_string_printf(
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, string_get_cstr(tempStr)); tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length);
string_reset(tempStr); canvas_draw_str_aligned(
canvas, 64, 8, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr));
furi_string_reset(tempStr);
// draw BPM value // draw BPM value
string_printf(tempStr, "%.2f", metronome_state->bpm); furi_string_printf(tempStr, "%.2f", metronome_state->bpm);
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignCenter, string_get_cstr(tempStr)); canvas_draw_str_aligned(
string_reset(tempStr); canvas, 64, 24, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr));
furi_string_reset(tempStr);
// draw volume indicator // draw volume indicator
// always draw first waves // always draw first waves
@@ -126,8 +127,8 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas, 8, 36, 112, (float)metronome_state->current_beat / metronome_state->beats_per_bar); canvas, 8, 36, 112, (float)metronome_state->current_beat / metronome_state->beats_per_bar);
// cleanup // cleanup
string_clear(tempStr); furi_string_free(tempStr);
release_mutex((ValueMutex*)ctx, metronome_state); furi_mutex_release(metronome_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -139,7 +140,10 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
static void timer_callback(void* ctx) { static void timer_callback(void* ctx) {
// this is where we go BEEP! // this is where we go BEEP!
MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
MetronomeState* metronome_state = ctx;
furi_mutex_acquire(metronome_state->mutex, FuriWaitForever);
metronome_state->current_beat++; metronome_state->current_beat++;
if(metronome_state->current_beat > metronome_state->beats_per_bar) { if(metronome_state->current_beat > metronome_state->beats_per_bar) {
metronome_state->current_beat = 1; metronome_state->current_beat = 1;
@@ -200,7 +204,7 @@ static void timer_callback(void* ctx) {
} }
notification_message(metronome_state->notifications, &sequence_reset_rgb); notification_message(metronome_state->notifications, &sequence_reset_rgb);
release_mutex((ValueMutex*)ctx, metronome_state); furi_mutex_release(metronome_state->mutex);
} }
static uint32_t state_to_sleep_ticks(MetronomeState* metronome_state) { static uint32_t state_to_sleep_ticks(MetronomeState* metronome_state) {
@@ -273,8 +277,8 @@ int32_t metronome_app() {
MetronomeState* metronome_state = malloc(sizeof(MetronomeState)); MetronomeState* metronome_state = malloc(sizeof(MetronomeState));
metronome_state_init(metronome_state); metronome_state_init(metronome_state);
ValueMutex state_mutex; metronome_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, metronome_state, sizeof(MetronomeState))) { if(!metronome_state->mutex) {
FURI_LOG_E("Metronome", "cannot create mutex\r\n"); FURI_LOG_E("Metronome", "cannot create mutex\r\n");
free(metronome_state); free(metronome_state);
return 255; return 255;
@@ -282,19 +286,20 @@ int32_t metronome_app() {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, metronome_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
metronome_state->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, &state_mutex); metronome_state->timer =
furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, metronome_state);
// Open GUI and register view_port // Open GUI and register view_port
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
MetronomeState* metronome_state = (MetronomeState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(metronome_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
@@ -373,21 +378,18 @@ int32_t metronome_app() {
} }
} }
} }
} else {
FURI_LOG_D("Metronome", "FuriMessageQueue: event timeout");
// event timeout
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, metronome_state); furi_mutex_release(metronome_state->mutex);
} }
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(metronome_state->mutex);
furi_timer_free(metronome_state->timer); furi_timer_free(metronome_state->timer);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
free(metronome_state); free(metronome_state);

View File

@@ -55,6 +55,7 @@ typedef struct {
int flags_set; int flags_set;
bool game_started; bool game_started;
uint32_t game_started_tick; uint32_t game_started_tick;
FuriMutex* mutex;
} Minesweeper; } Minesweeper;
static void timer_callback(void* ctx) { static void timer_callback(void* ctx) {
@@ -72,10 +73,10 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const Minesweeper* minesweeper_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(minesweeper_state == NULL) { const Minesweeper* minesweeper_state = ctx;
return; furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever);
}
FuriString* mineStr; FuriString* mineStr;
FuriString* timeStr; FuriString* timeStr;
mineStr = furi_string_alloc(); mineStr = furi_string_alloc();
@@ -160,7 +161,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
furi_string_free(mineStr); furi_string_free(mineStr);
furi_string_free(timeStr); furi_string_free(timeStr);
release_mutex((ValueMutex*)ctx, minesweeper_state); furi_mutex_release(minesweeper_state->mutex);
} }
static void setup_playfield(Minesweeper* minesweeper_state) { static void setup_playfield(Minesweeper* minesweeper_state) {
@@ -387,8 +388,8 @@ int32_t minesweeper_app(void* p) {
// setup // setup
minesweeper_state_init(minesweeper_state); minesweeper_state_init(minesweeper_state);
ValueMutex state_mutex; minesweeper_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, minesweeper_state, sizeof(minesweeper_state))) { if(!minesweeper_state->mutex) {
FURI_LOG_E("Minesweeper", "cannot create mutex\r\n"); FURI_LOG_E("Minesweeper", "cannot create mutex\r\n");
free(minesweeper_state); free(minesweeper_state);
return 255; return 255;
@@ -397,18 +398,19 @@ int32_t minesweeper_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, minesweeper_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
minesweeper_state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, &state_mutex); minesweeper_state->timer =
furi_timer_alloc(timer_callback, FuriTimerTypeOnce, minesweeper_state);
// Open GUI and register view_port // Open GUI and register view_port
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
Minesweeper* minesweeper_state = (Minesweeper*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
@@ -496,19 +498,16 @@ int32_t minesweeper_app(void* p) {
} }
} }
} }
} else {
// event timeout
;
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, minesweeper_state); furi_mutex_release(minesweeper_state->mutex);
} }
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(minesweeper_state->mutex);
furi_timer_free(minesweeper_state->timer); furi_timer_free(minesweeper_state->timer);
free(minesweeper_state); free(minesweeper_state);

View File

@@ -41,10 +41,10 @@ char target_address_str[12] = "None";
char target_text[30]; char target_text[30];
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(plugin_state == NULL) { const PluginState* plugin_state = ctx;
return; furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
}
// border around the edge of the screen // border around the edge of the screen
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -83,7 +83,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "to exit"); canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "to exit");
} }
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -291,8 +291,8 @@ int32_t mousejacker_app(void* p) {
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
mousejacker_state_init(plugin_state); mousejacker_state_init(plugin_state);
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
FURI_LOG_E("mousejacker", "cannot create mutex\r\n"); FURI_LOG_E("mousejacker", "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(plugin_state); free(plugin_state);
@@ -301,7 +301,7 @@ int32_t mousejacker_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -332,7 +332,7 @@ int32_t mousejacker_app(void* p) {
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -382,7 +382,7 @@ int32_t mousejacker_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
furi_thread_free(plugin_state->mjthread); furi_thread_free(plugin_state->mjthread);
@@ -393,6 +393,7 @@ int32_t mousejacker_app(void* p) {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_mutex_free(plugin_state->mutex);
free(plugin_state); free(plugin_state);
return 0; return 0;

View File

@@ -21,6 +21,7 @@ typedef struct {
} MJDuckyKey; } MJDuckyKey;
typedef struct { typedef struct {
FuriMutex* mutex;
bool ducky_err; bool ducky_err;
bool addr_err; bool addr_err;
bool is_thread_running; bool is_thread_running;

View File

@@ -8,10 +8,9 @@
#include "multi_converter_mode_select.h" #include "multi_converter_mode_select.h"
static void multi_converter_render_callback(Canvas* const canvas, void* ctx) { static void multi_converter_render_callback(Canvas* const canvas, void* ctx) {
const MultiConverterState* multi_converter_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(multi_converter_state == NULL) { const MultiConverterState* multi_converter_state = ctx;
return; furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever);
}
if(multi_converter_state->mode == ModeDisplay) { if(multi_converter_state->mode == ModeDisplay) {
multi_converter_mode_display_draw(canvas, multi_converter_state); multi_converter_mode_display_draw(canvas, multi_converter_state);
@@ -19,7 +18,7 @@ static void multi_converter_render_callback(Canvas* const canvas, void* ctx) {
multi_converter_mode_select_draw(canvas, multi_converter_state); multi_converter_mode_select_draw(canvas, multi_converter_state);
} }
release_mutex((ValueMutex*)ctx, multi_converter_state); furi_mutex_release(multi_converter_state->mutex);
} }
static void static void
@@ -62,8 +61,8 @@ int32_t multi_converter_app(void* p) {
MultiConverterState* multi_converter_state = malloc(sizeof(MultiConverterState)); MultiConverterState* multi_converter_state = malloc(sizeof(MultiConverterState));
// set mutex for plugin state (different threads can access it) // set mutex for plugin state (different threads can access it)
ValueMutex state_mutex; multi_converter_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, multi_converter_state, sizeof(multi_converter_state))) { if(!multi_converter_state->mutex) {
FURI_LOG_E("MultiConverter", "cannot create mutex\r\n"); FURI_LOG_E("MultiConverter", "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(multi_converter_state); free(multi_converter_state);
@@ -72,11 +71,11 @@ int32_t multi_converter_app(void* p) {
// register callbacks for drawing and input processing // register callbacks for drawing and input processing
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, multi_converter_render_callback, &state_mutex); view_port_draw_callback_set(view_port, multi_converter_render_callback, multi_converter_state);
view_port_input_callback_set(view_port, multi_converter_input_callback, event_queue); view_port_input_callback_set(view_port, multi_converter_input_callback, event_queue);
// open GUI and register view_port // open GUI and register view_port
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
multi_converter_init(multi_converter_state); multi_converter_init(multi_converter_state);
@@ -85,8 +84,7 @@ int32_t multi_converter_app(void* p) {
MultiConverterEvent event; MultiConverterEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
MultiConverterState* multi_converter_state = furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever);
(MultiConverterState*)acquire_mutex_block(&state_mutex);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -148,20 +146,18 @@ int32_t multi_converter_app(void* p) {
} else if(multi_converter_state->keyboard_lock) { } else if(multi_converter_state->keyboard_lock) {
multi_converter_state->keyboard_lock = 0; multi_converter_state->keyboard_lock = 0;
} }
} else {
// event timeout
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, multi_converter_state); furi_mutex_release(multi_converter_state->mutex);
} }
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close("gui"); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(multi_converter_state->mutex);
free(multi_converter_state); free(multi_converter_state);
return 0; return 0;

View File

@@ -70,6 +70,7 @@ struct MultiConverterUnit {
}; };
struct MultiConverterState { struct MultiConverterState {
FuriMutex* mutex;
char buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS + 1]; char buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS + 1];
char buffer_dest[MULTI_CONVERTER_NUMBER_DIGITS + 1]; char buffer_dest[MULTI_CONVERTER_NUMBER_DIGITS + 1];
MultiConverterUnitType unit_type_orig; MultiConverterUnitType unit_type_orig;

View File

@@ -11,6 +11,10 @@ void nfc_magic_scene_file_select_on_enter(void* context) {
// Process file_select return // Process file_select return
nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic);
if(!furi_string_size(nfc_magic->nfc_dev->load_path)) {
furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER);
}
if(nfc_file_select(nfc_magic->nfc_dev)) { if(nfc_file_select(nfc_magic->nfc_dev)) {
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);

View File

@@ -29,8 +29,7 @@ typedef struct {
} PluginEvent; } PluginEvent;
typedef struct { typedef struct {
int x; FuriMutex* mutex;
int y;
} PluginState; } PluginState;
char rate_text_fmt[] = "Transfer rate: %dMbps"; char rate_text_fmt[] = "Transfer rate: %dMbps";
@@ -96,13 +95,13 @@ static void insert_addr(uint8_t* addr, uint8_t addr_size) {
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
furi_assert(ctx);
const PluginState* plugin_state = ctx;
furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
uint8_t rate = 2; uint8_t rate = 2;
char sniffing[] = "Yes"; char sniffing[] = "Yes";
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25);
if(plugin_state == NULL) {
return;
}
// border around the edge of the screen // border around the edge of the screen
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
@@ -126,7 +125,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text); canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text);
canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address); canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address);
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -321,8 +320,8 @@ int32_t nrfsniff_app(void* p) {
hexlify(address, 5, top_address); hexlify(address, 5, top_address);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
FURI_LOG_E(TAG, "cannot create mutex\r\n"); FURI_LOG_E(TAG, "cannot create mutex\r\n");
free(plugin_state); free(plugin_state);
@@ -333,7 +332,7 @@ int32_t nrfsniff_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -348,7 +347,7 @@ int32_t nrfsniff_app(void* p) {
PluginEvent event; PluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -439,7 +438,7 @@ int32_t nrfsniff_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
clear_cache(); clear_cache();
@@ -454,6 +453,8 @@ int32_t nrfsniff_app(void* p) {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
furi_mutex_free(plugin_state->mutex);
free(plugin_state);
return 0; return 0;
} }

View File

@@ -0,0 +1,8 @@
#include "picopass_keys.h"
const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78};
const uint8_t picopass_factory_credit_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00};
const uint8_t picopass_factory_debit_key[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
const uint8_t picopass_xice_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88};
const uint8_t picopass_xicl_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88};
const uint8_t picopass_xics_key[] = {0x66, 0x66, 0x20, 0x20, 0x66, 0x66, 0x88, 0x88};

View File

@@ -0,0 +1,10 @@
#pragma once
#include "picopass_device.h"
extern const uint8_t picopass_iclass_key[PICOPASS_BLOCK_LEN];
extern const uint8_t picopass_factory_credit_key[PICOPASS_BLOCK_LEN];
extern const uint8_t picopass_factory_debit_key[PICOPASS_BLOCK_LEN];
extern const uint8_t picopass_xice_key[PICOPASS_BLOCK_LEN];
extern const uint8_t picopass_xicl_key[PICOPASS_BLOCK_LEN];
extern const uint8_t picopass_xics_key[PICOPASS_BLOCK_LEN];

View File

@@ -4,13 +4,6 @@
#define TAG "PicopassWorker" #define TAG "PicopassWorker"
const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78};
const uint8_t picopass_factory_credit_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00};
const uint8_t picopass_factory_debit_key[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
const uint8_t picopass_xice_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88};
const uint8_t picopass_xicl_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88};
const uint8_t picopass_xics_key[] = {0x66, 0x66, 0x20, 0x20, 0x66, 0x66, 0x88, 0x88};
static void picopass_worker_enable_field() { static void picopass_worker_enable_field() {
furi_hal_nfc_ll_txrx_on(); furi_hal_nfc_ll_txrx_on();
furi_hal_nfc_exit_sleep(); furi_hal_nfc_exit_sleep();
@@ -179,50 +172,6 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) {
return ERR_NONE; return ERR_NONE;
} }
static ReturnCode picopass_auth_standard(uint8_t* csn, uint8_t* div_key) {
rfalPicoPassReadCheckRes rcRes;
rfalPicoPassCheckRes chkRes;
ReturnCode err;
uint8_t mac[4] = {0};
uint8_t ccnr[12] = {0};
err = rfalPicoPassPollerReadCheck(&rcRes);
if(err != ERR_NONE) {
FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err);
return err;
}
memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
loclass_iclass_calc_div_key(csn, (uint8_t*)picopass_iclass_key, div_key, false);
loclass_opt_doReaderMAC(ccnr, div_key, mac);
return rfalPicoPassPollerCheck(mac, &chkRes);
}
static ReturnCode picopass_auth_factory(uint8_t* csn, uint8_t* div_key) {
rfalPicoPassReadCheckRes rcRes;
rfalPicoPassCheckRes chkRes;
ReturnCode err;
uint8_t mac[4] = {0};
uint8_t ccnr[12] = {0};
err = rfalPicoPassPollerReadCheck(&rcRes);
if(err != ERR_NONE) {
FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err);
return err;
}
memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
loclass_iclass_calc_div_key(csn, (uint8_t*)picopass_factory_debit_key, div_key, false);
loclass_opt_doReaderMAC(ccnr, div_key, mac);
return rfalPicoPassPollerCheck(mac, &chkRes);
}
static ReturnCode picopass_auth_dict( static ReturnCode picopass_auth_dict(
uint8_t* csn, uint8_t* csn,
PicopassPacs* pacs, PicopassPacs* pacs,
@@ -291,19 +240,14 @@ static ReturnCode picopass_auth_dict(
ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) {
ReturnCode err; ReturnCode err;
FURI_LOG_I(TAG, "Trying standard legacy key"); FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]");
err = picopass_auth_standard( err = picopass_auth_dict(
AA1[PICOPASS_CSN_BLOCK_INDEX].data, AA1[PICOPASS_KD_BLOCK_INDEX].data); AA1[PICOPASS_CSN_BLOCK_INDEX].data,
pacs,
AA1[PICOPASS_KD_BLOCK_INDEX].data,
IclassEliteDictTypeFlipper,
false);
if(err == ERR_NONE) { if(err == ERR_NONE) {
memcpy(pacs->key, picopass_iclass_key, PICOPASS_BLOCK_LEN);
return ERR_NONE;
}
FURI_LOG_I(TAG, "Trying factory default key");
err = picopass_auth_factory(
AA1[PICOPASS_CSN_BLOCK_INDEX].data, AA1[PICOPASS_KD_BLOCK_INDEX].data);
if(err == ERR_NONE) {
memcpy(pacs->key, picopass_factory_debit_key, PICOPASS_BLOCK_LEN);
return ERR_NONE; return ERR_NONE;
} }
@@ -329,17 +273,6 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) {
return ERR_NONE; return ERR_NONE;
} }
FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]");
err = picopass_auth_dict(
AA1[PICOPASS_CSN_BLOCK_INDEX].data,
pacs,
AA1[PICOPASS_KD_BLOCK_INDEX].data,
IclassEliteDictTypeFlipper,
false);
if(err == ERR_NONE) {
return ERR_NONE;
}
return err; return err;
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "picopass_device.h" #include "picopass_device.h"
#include "picopass_keys.h"
typedef struct PicopassWorker PicopassWorker; typedef struct PicopassWorker PicopassWorker;

View File

@@ -1,4 +1,5 @@
#include "../picopass_i.h" #include "../picopass_i.h"
#include "../picopass_keys.h"
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexWriteStandard, SubmenuIndexWriteStandard,
@@ -8,11 +9,6 @@ enum SubmenuIndex {
SubmenuIndexWriteCustom, //TODO: user input of key SubmenuIndexWriteCustom, //TODO: user input of key
}; };
extern const uint8_t picopass_xice_key[];
extern const uint8_t picopass_xicl_key[];
extern const uint8_t picopass_xics_key[];
extern const uint8_t picopass_iclass_key[];
void picopass_scene_key_menu_submenu_callback(void* context, uint32_t index) { void picopass_scene_key_menu_submenu_callback(void* context, uint32_t index) {
Picopass* picopass = context; Picopass* picopass = context;

View File

@@ -1,7 +1,6 @@
#include "../picopass_i.h" #include "../picopass_i.h"
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include "../picopass_keys.h"
extern const uint8_t picopass_factory_debit_key[];
void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) { void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) {
UNUSED(event); UNUSED(event);

View File

@@ -1,7 +1,6 @@
#include "../picopass_i.h" #include "../picopass_i.h"
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include "../picopass_keys.h"
extern const uint8_t picopass_iclass_key[];
void picopass_scene_read_factory_success_widget_callback( void picopass_scene_read_factory_success_widget_callback(
GuiButtonType result, GuiButtonType result,

View File

@@ -7,6 +7,7 @@
typedef struct { typedef struct {
uint8_t status; uint8_t status;
FuriMutex* mutex;
} SentryState; } SentryState;
typedef enum { typedef enum {
@@ -22,10 +23,9 @@ typedef struct {
const char* status_texts[3] = {"[Press OK to open safe]", "Sending...", "Done !"}; const char* status_texts[3] = {"[Press OK to open safe]", "Sending...", "Done !"};
static void sentry_safe_render_callback(Canvas* const canvas, void* ctx) { static void sentry_safe_render_callback(Canvas* const canvas, void* ctx) {
const SentryState* sentry_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(sentry_state == NULL) { const SentryState* sentry_state = ctx;
return; furi_mutex_acquire(sentry_state->mutex, FuriWaitForever);
}
// Before the function is called, the state is set with the canvas_reset(canvas) // Before the function is called, the state is set with the canvas_reset(canvas)
@@ -41,7 +41,7 @@ static void sentry_safe_render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 64, 50, AlignCenter, AlignBottom, status_texts[sentry_state->status]); canvas, 64, 50, AlignCenter, AlignBottom, status_texts[sentry_state->status]);
release_mutex((ValueMutex*)ctx, sentry_state); furi_mutex_release(sentry_state->mutex);
} }
static void sentry_safe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void sentry_safe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -89,8 +89,8 @@ int32_t sentry_safe_app(void* p) {
sentry_state->status = 0; sentry_state->status = 0;
ValueMutex state_mutex; sentry_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, sentry_state, sizeof(SentryState))) { if(!sentry_state->mutex) {
FURI_LOG_E("SentrySafe", "cannot create mutex\r\n"); FURI_LOG_E("SentrySafe", "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(sentry_state); free(sentry_state);
@@ -98,7 +98,7 @@ int32_t sentry_safe_app(void* p) {
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, sentry_safe_render_callback, &state_mutex); view_port_draw_callback_set(view_port, sentry_safe_render_callback, sentry_state);
view_port_input_callback_set(view_port, sentry_safe_input_callback, event_queue); view_port_input_callback_set(view_port, sentry_safe_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -109,7 +109,7 @@ int32_t sentry_safe_app(void* p) {
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
SentryState* sentry_state = (SentryState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(sentry_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -151,7 +151,7 @@ int32_t sentry_safe_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, sentry_state); furi_mutex_release(sentry_state->mutex);
} }
// Reset GPIO pins to default state // Reset GPIO pins to default state
@@ -162,7 +162,7 @@ int32_t sentry_safe_app(void* p) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(sentry_state->mutex);
free(sentry_state); free(sentry_state);
return 0; return 0;

View File

@@ -49,6 +49,7 @@ typedef struct {
Direction nextMovement; // if backward of currentMovement, ignore Direction nextMovement; // if backward of currentMovement, ignore
Point fruit; Point fruit;
GameState state; GameState state;
FuriMutex* mutex;
} SnakeState; } SnakeState;
typedef enum { typedef enum {
@@ -91,12 +92,10 @@ const NotificationSequence sequence_eat = {
}; };
static void snake_game_render_callback(Canvas* const canvas, void* ctx) { static void snake_game_render_callback(Canvas* const canvas, void* ctx) {
const SnakeState* snake_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(snake_state == NULL) { const SnakeState* snake_state = ctx;
return;
}
// Before the function is called, the state is set with the canvas_reset(canvas) furi_mutex_acquire(snake_state->mutex, FuriWaitForever);
// Frame // Frame
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -133,7 +132,7 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer);
} }
release_mutex((ValueMutex*)ctx, snake_state); furi_mutex_release(snake_state->mutex);
} }
static void snake_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void snake_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -323,15 +322,16 @@ int32_t snake_game_app(void* p) {
SnakeState* snake_state = malloc(sizeof(SnakeState)); SnakeState* snake_state = malloc(sizeof(SnakeState));
snake_game_init_game(snake_state); snake_game_init_game(snake_state);
ValueMutex state_mutex; snake_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) {
if(!snake_state->mutex) {
FURI_LOG_E("SnakeGame", "cannot create mutex\r\n"); FURI_LOG_E("SnakeGame", "cannot create mutex\r\n");
free(snake_state); free(snake_state);
return 255; return 255;
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, snake_game_render_callback, &state_mutex); view_port_draw_callback_set(view_port, snake_game_render_callback, snake_state);
view_port_input_callback_set(view_port, snake_game_input_callback, event_queue); view_port_input_callback_set(view_port, snake_game_input_callback, event_queue);
FuriTimer* timer = FuriTimer* timer =
@@ -349,7 +349,7 @@ int32_t snake_game_app(void* p) {
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
SnakeState* snake_state = (SnakeState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(snake_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// press events // press events
@@ -388,7 +388,7 @@ int32_t snake_game_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, snake_state); furi_mutex_release(snake_state->mutex);
} }
// Return backlight to normal state // Return backlight to normal state
@@ -401,7 +401,7 @@ int32_t snake_game_app(void* p) {
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(snake_state->mutex);
free(snake_state); free(snake_state);
return 0; return 0;

View File

@@ -53,4 +53,5 @@ typedef struct {
int8_t selected_card; int8_t selected_card;
CardAnimation animation; CardAnimation animation;
uint8_t* buffer; uint8_t* buffer;
FuriMutex* mutex;
} GameState; } GameState;

View File

@@ -154,10 +154,9 @@ static void draw_animation(Canvas* const canvas, const GameState* game_state) {
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(game_state == NULL) { const GameState* game_state = ctx;
return; furi_mutex_acquire(game_state->mutex, FuriWaitForever);
}
switch(game_state->state) { switch(game_state->state) {
case GameStateAnimate: case GameStateAnimate:
@@ -173,7 +172,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
break; break;
} }
release_mutex((ValueMutex*)ctx, game_state); furi_mutex_release(game_state->mutex);
} }
void remove_drag(GameState* game_state) { void remove_drag(GameState* game_state) {
@@ -468,8 +467,8 @@ int32_t solitaire_app(void* p) {
game_state->state = GameStateStart; game_state->state = GameStateStart;
game_state->processing = true; game_state->processing = true;
ValueMutex state_mutex; game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) { if(!game_state->mutex) {
FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
return_code = 255; return_code = 255;
goto free_and_exit; goto free_and_exit;
@@ -479,20 +478,20 @@ int32_t solitaire_app(void* p) {
notification_message_block(notification, &sequence_display_backlight_enforce_on); notification_message_block(notification, &sequence_display_backlight_enforce_on);
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, game_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue); FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30);
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
AppEvent event; AppEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150);
GameState* localstate = (GameState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(game_state->mutex, FuriWaitForever);
bool hadChange = false; bool hadChange = false;
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
@@ -504,7 +503,7 @@ int32_t solitaire_app(void* p) {
case InputKeyRight: case InputKeyRight:
case InputKeyLeft: case InputKeyLeft:
case InputKeyOk: case InputKeyOk:
localstate->input = event.input.key; game_state->input = event.input.key;
break; break;
case InputKeyBack: case InputKeyBack:
processing = false; processing = false;
@@ -520,12 +519,12 @@ int32_t solitaire_app(void* p) {
case InputKeyRight: case InputKeyRight:
case InputKeyLeft: case InputKeyLeft:
case InputKeyOk: case InputKeyOk:
if(event.input.key == InputKeyOk && localstate->state == GameStateStart) { if(event.input.key == InputKeyOk && game_state->state == GameStateStart) {
localstate->state = GameStatePlay; game_state->state = GameStatePlay;
init(game_state); init(game_state);
} else { } else {
hadChange = true; hadChange = true;
localstate->input = event.input.key; game_state->input = event.input.key;
} }
break; break;
case InputKeyBack: case InputKeyBack:
@@ -538,16 +537,16 @@ int32_t solitaire_app(void* p) {
} }
} }
} else if(event.type == EventTypeTick) { } else if(event.type == EventTypeTick) {
tick(localstate, notification); tick(game_state, notification);
processing = localstate->processing; processing = game_state->processing;
localstate->input = InputKeyMAX; game_state->input = InputKeyMAX;
} }
} else { } else {
//FURI_LOG_W(APP_NAME, "osMessageQueue: event timeout"); //FURI_LOG_W(APP_NAME, "osMessageQueue: event timeout");
// event timeout // event timeout
} }
if(hadChange || game_state->state == GameStateAnimate) view_port_update(view_port); if(hadChange || game_state->state == GameStateAnimate) view_port_update(view_port);
release_mutex(&state_mutex, localstate); furi_mutex_release(game_state->mutex);
} }
notification_message_block(notification, &sequence_display_backlight_enforce_auto); notification_message_block(notification, &sequence_display_backlight_enforce_auto);
@@ -557,7 +556,7 @@ int32_t solitaire_app(void* p) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port); view_port_free(view_port);
delete_mutex(&state_mutex); furi_mutex_free(game_state->mutex);
free_and_exit: free_and_exit:
free(game_state->animation.buffer); free(game_state->animation.buffer);

View File

@@ -61,6 +61,8 @@ typedef struct {
bool ctl_request_exit; // can be set to true if the worker should exit bool ctl_request_exit; // can be set to true if the worker should exit
bool ctl_pause; // can be set to true if the worker should pause bool ctl_pause; // can be set to true if the worker should pause
bool ctl_request_skip; // can be set to true if the worker should skip the current file
bool ctl_request_prev; // can be set to true if the worker should go to the previous file
bool is_running; // indicates if the worker is running bool is_running; // indicates if the worker is running
} PlaylistWorker; } PlaylistWorker;
@@ -185,6 +187,18 @@ static int playlist_worker_process(
status = 1; status = 1;
break; break;
} }
if(worker->ctl_request_skip) {
worker->ctl_request_skip = false;
FURI_LOG_D(TAG, " (TX) Requested to skip. Cancelling and resending...");
status = 0;
break;
}
if(worker->ctl_request_prev) {
worker->ctl_request_prev = false;
FURI_LOG_D(TAG, " (TX) Requested to prev. Cancelling and resending...");
status = 3;
break;
}
furi_delay_ms(50); furi_delay_ms(50);
} }
@@ -213,6 +227,22 @@ static bool playlist_worker_wait_pause(PlaylistWorker* worker) {
return true; return true;
} }
void updatePlayListView(PlaylistWorker* worker, const char* str) {
furi_string_reset(worker->meta->prev_3_path);
furi_string_set(worker->meta->prev_3_path, furi_string_get_cstr(worker->meta->prev_2_path));
furi_string_reset(worker->meta->prev_2_path);
furi_string_set(worker->meta->prev_2_path, furi_string_get_cstr(worker->meta->prev_1_path));
furi_string_reset(worker->meta->prev_1_path);
furi_string_set(worker->meta->prev_1_path, furi_string_get_cstr(worker->meta->prev_0_path));
furi_string_reset(worker->meta->prev_0_path);
furi_string_set(worker->meta->prev_0_path, str);
view_port_update(worker->meta->view_port);
}
static bool playlist_worker_play_playlist_once( static bool playlist_worker_play_playlist_once(
PlaylistWorker* worker, PlaylistWorker* worker,
Storage* storage, Storage* storage,
@@ -226,6 +256,7 @@ static bool playlist_worker_play_playlist_once(
FURI_LOG_E(TAG, "Failed to rewind file"); FURI_LOG_E(TAG, "Failed to rewind file");
return false; return false;
} }
while(flipper_format_read_string(fff_head, "sub", data)) { while(flipper_format_read_string(fff_head, "sub", data)) {
if(!playlist_worker_wait_pause(worker)) { if(!playlist_worker_wait_pause(worker)) {
break; break;
@@ -238,18 +269,7 @@ static bool playlist_worker_play_playlist_once(
const char* str = furi_string_get_cstr(data); const char* str = furi_string_get_cstr(data);
// it's not fancy, but it works for now :) // it's not fancy, but it works for now :)
furi_string_reset(worker->meta->prev_3_path); updatePlayListView(worker, str);
furi_string_set(
worker->meta->prev_3_path, furi_string_get_cstr(worker->meta->prev_2_path));
furi_string_reset(worker->meta->prev_2_path);
furi_string_set(
worker->meta->prev_2_path, furi_string_get_cstr(worker->meta->prev_1_path));
furi_string_reset(worker->meta->prev_1_path);
furi_string_set(
worker->meta->prev_1_path, furi_string_get_cstr(worker->meta->prev_0_path));
furi_string_reset(worker->meta->prev_0_path);
furi_string_set(worker->meta->prev_0_path, str);
view_port_update(worker->meta->view_port);
for(int i = 0; i < 1; i++) { for(int i = 0; i < 1; i++) {
if(!playlist_worker_wait_pause(worker)) { if(!playlist_worker_wait_pause(worker)) {
@@ -279,6 +299,23 @@ static bool playlist_worker_play_playlist_once(
// exited, exit loop // exited, exit loop
} else if(status == 2) { } else if(status == 2) {
return false; return false;
} else if(status == 3) {
//aqui rebobinamos y avanzamos de nuevo el fichero n-1 veces
//decrementamos el contador de ficheros enviados
worker->meta->current_count--;
if(worker->meta->current_count > 0) {
worker->meta->current_count--;
}
//rebobinamos el fichero
if(!flipper_format_rewind(fff_head)) {
FURI_LOG_E(TAG, "Failed to rewind file");
return false;
}
//avanzamos el fichero n-1 veces
for(int j = 0; j < worker->meta->current_count; j++) {
flipper_format_read_string(fff_head, "sub", data);
}
break;
} }
} }
} // end of loop } // end of loop
@@ -591,6 +628,8 @@ static void render_callback(Canvas* canvas, void* ctx) {
} }
} }
break; break;
default:
break;
} }
furi_string_free(temp_str); furi_string_free(temp_str);
@@ -711,6 +750,10 @@ int32_t playlist_app(void* p) {
if(input.type == InputTypeShort && app->meta->playlist_repetitions > 0) { if(input.type == InputTypeShort && app->meta->playlist_repetitions > 0) {
--app->meta->playlist_repetitions; --app->meta->playlist_repetitions;
} }
} else if(app->meta->state == STATE_SENDING) {
if(input.type == InputTypeShort) {
app->worker->ctl_request_prev = true;
}
} }
break; break;
@@ -719,6 +762,10 @@ int32_t playlist_app(void* p) {
if(input.type == InputTypeShort) { if(input.type == InputTypeShort) {
++app->meta->playlist_repetitions; ++app->meta->playlist_repetitions;
} }
} else if(app->meta->state == STATE_SENDING) {
if(input.type == InputTypeShort) {
app->worker->ctl_request_skip = true;
}
} }
break; break;

View File

@@ -0,0 +1,17 @@
# ARM SWD (Single Wire Debug) Probe
Modern microcontrollers have support for the two wire debug interface SWD, which makes wiring a lot simpler.
When reverse engineering, finding these two pins is a los easier than with JTAG, where you had to wire up twice or more pins. However, finding the two pins is still a bit of work, which gets simplified even more with this application.
This application tries to detect a valid SWD response on the wires you have picked and beeps when you have found the correct pins, showing the detected ID register and, more important, the SWD pinout. It doesn't matter which two pins you choose, just pick any two from the GPIOs on the breakout header.
To achieve this, the application sends packets and scans the response on all pins and elaborates the pins within a few retries. Using some kind of bisect pattern reduces this number to a hand full of tries, yielding in a seemingly instant detection.
For the user it is as simple as a continuity tester - wire up your two test needles (or accupuncture needles), connect the obvious GND pin and probe all test pads.
Now it depends on your bisect capabilities finding all pad combinations, how long it will take this time.
https://cdn.discordapp.com/attachments/954430078882816021/1071603366741938176/20230205_022641.mp4
https://cdn.discordapp.com/attachments/1071712925171056690/1072306469057347594/qFlipper_2023-02-07_01-01-24.mp4
Discussion thread: https://discord.com/channels/740930220399525928/1071712925171056690

View File

@@ -471,7 +471,10 @@ uint8_t swd_read_memory(AppFSM* const ctx, uint8_t ap, uint32_t address, uint32_
ret |= swd_read_ap(ctx, ap, MEMAP_DRW, data); ret |= swd_read_ap(ctx, ap, MEMAP_DRW, data);
if(ret != 1) { if(ret != 1) {
DBG("read from 0x%08lX failed", address);
swd_abort(ctx); swd_abort(ctx);
} else {
DBG("read 0x%08lX from 0x%08lX", *data, address);
} }
return ret; return ret;
} }
@@ -705,7 +708,9 @@ static void swd_script_log(ScriptContext* ctx, FuriLogLevel level, const char* f
size_t pos = strlen(buffer); size_t pos = strlen(buffer);
vsnprintf(&buffer[pos], sizeof(buffer) - pos - 2, format, argp); vsnprintf(&buffer[pos], sizeof(buffer) - pos - 2, format, argp);
strcat(buffer, "\n"); strcat(buffer, "\n");
usb_uart_tx_data(ctx->app->uart, (uint8_t*)buffer, strlen(buffer)); if(!usb_uart_tx_data(ctx->app->uart, (uint8_t*)buffer, strlen(buffer))) {
DBGS("Sending via USB failed");
}
} else { } else {
LOG(buffer); LOG(buffer);
} }
@@ -1379,9 +1384,10 @@ static bool swd_scriptfunc_mem_write(ScriptContext* ctx) {
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
access_ok = swd_write_memory(ctx->app, ctx->selected_ap, address, data) == 1; access_ok = swd_write_memory(ctx->app, ctx->selected_ap, address, data) == 1;
furi_mutex_release(ctx->app->swd_mutex);
access_ok |= ctx->errors_ignore; access_ok |= ctx->errors_ignore;
swd_read_memory(ctx->app, ctx->selected_ap, address, &data); swd_read_memory(ctx->app, ctx->selected_ap, address, &data);
furi_mutex_release(ctx->app->swd_mutex);
DBG("read %08lX from %08lX", data, address); DBG("read %08lX from %08lX", data, address);
if(!access_ok) { if(!access_ok) {
@@ -1406,6 +1412,60 @@ static bool swd_scriptfunc_mem_write(ScriptContext* ctx) {
return success; return success;
} }
static bool swd_scriptfunc_mem_read(ScriptContext* ctx) {
uint32_t address = 0;
bool success = true;
/* get file */
if(!swd_script_skip_whitespace(ctx)) {
swd_script_log(ctx, FuriLogLevelError, "missing whitespace");
return false;
}
/* get address */
if(!swd_script_get_number(ctx, &address)) {
swd_script_log(ctx, FuriLogLevelError, "failed to parse address");
return false;
}
DBG("read from %08lX", address);
uint32_t data = 0;
bool access_ok = false;
for(uint32_t tries = 0; tries < ctx->max_tries; tries++) {
if(ctx->abort) {
DBGS("aborting");
break;
}
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
access_ok = swd_read_memory(ctx->app, ctx->selected_ap, address, &data) == 1;
furi_mutex_release(ctx->app->swd_mutex);
if(!access_ok) {
swd_script_log(ctx, FuriLogLevelError, "Failed to read from %08lX", address);
snprintf(
ctx->app->state_string,
sizeof(ctx->app->state_string),
"Failed read 0x%08lX",
address);
swd_script_gui_refresh(ctx);
} else {
swd_script_log(ctx, FuriLogLevelDefault, "%08lX", data);
break;
}
}
if(!access_ok) {
notification_message_block(ctx->app->notification, &seq_error);
success = false;
}
swd_script_seek_newline(ctx);
return success;
}
static bool swd_scriptfunc_mem_ldmst(ScriptContext* ctx) { static bool swd_scriptfunc_mem_ldmst(ScriptContext* ctx) {
uint32_t address = 0; uint32_t address = 0;
uint32_t data = 0; uint32_t data = 0;
@@ -1633,6 +1693,275 @@ static bool swd_scriptfunc_ap_read(ScriptContext* ctx) {
return success; return success;
} }
static bool swd_scriptfunc_core_halt(ScriptContext* ctx) {
bool succ = false;
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
uint32_t reg_dhcsr = SCS_DHCSR_KEY | SCS_DHCSR_C_HALT | SCS_DHCSR_C_DEBUGEN;
succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, reg_dhcsr) == 1;
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed");
} else {
swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &reg_dhcsr);
if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core did not halt");
succ = false;
} else {
swd_script_log(ctx, FuriLogLevelDefault, "Core halted");
}
}
furi_mutex_release(ctx->app->swd_mutex);
swd_script_seek_newline(ctx);
return succ;
}
static bool swd_scriptfunc_core_continue(ScriptContext* ctx) {
bool succ = false;
uint32_t data = 0;
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &data) == 1;
if(!(data & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state");
succ = false;
} else {
succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, SCS_DHCSR_KEY) == 1;
furi_mutex_release(ctx->app->swd_mutex);
}
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed");
} else {
swd_script_log(ctx, FuriLogLevelDefault, "Core continued");
}
swd_script_seek_newline(ctx);
return succ;
}
static bool swd_scriptfunc_core_step(ScriptContext* ctx) {
bool succ = false;
uint32_t data = 0;
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &data) == 1;
if(!(data & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state");
succ = false;
} else {
succ = swd_write_memory(
ctx->app,
ctx->selected_ap,
SCS_DHCSR,
SCS_DHCSR_KEY | SCS_DHCSR_C_STEP | SCS_DHCSR_C_MASKINTS |
SCS_DHCSR_C_DEBUGEN) == 1;
}
furi_mutex_release(ctx->app->swd_mutex);
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed");
} else {
swd_script_log(ctx, FuriLogLevelDefault, "Core stepped");
}
swd_script_seek_newline(ctx);
return succ;
}
static struct cpu_regs_type {
uint8_t regsel;
const char* desc;
} cpu_regs[] = {
{0x00, "R00"}, {0x01, "R01"}, {0x02, "R02"}, {0x03, "R03"}, {0x04, "R04"},
{0x05, "R05"}, {0x06, "R06"}, {0x07, "R07"}, {0x08, "R08"}, {0x09, "R09"},
{0x0A, "R10"}, {0x0B, "R11"}, {0x0C, "R12"}, {0x0D, "SP/R13"}, {0x0E, "LR/R14"},
{0x0F, "PC/R15"}, {0x10, "xPSR"}, {0x11, "MSP"}, {0x12, "PSP"}, {0x14, "Flags"},
{0x21, "FPCSR"}, {0x40, "FP S00"}, {0x41, "FP S01"}, {0x42, "FP S02"}, {0x43, "FP S03"},
{0x44, "FP S04"}, {0x45, "FP S05"}, {0x46, "FP S06"}, {0x47, "FP S07"}, {0x48, "FP S08"},
{0x49, "FP S09"}, {0x4A, "FP S10"}, {0x4B, "FP S11"}, {0x4C, "FP S12"}, {0x4D, "FP S13"},
{0x4E, "FP S14"}, {0x4F, "FP S15"}, {0x50, "FP S16"}, {0x51, "FP S17"}, {0x52, "FP S18"},
{0x53, "FP S19"}, {0x54, "FP S20"}, {0x55, "FP S21"}, {0x56, "FP S22"}, {0x57, "FP S23"},
{0x58, "FP S24"}, {0x59, "FP S25"}, {0x5A, "FP S26"}, {0x5B, "FP S27"}, {0x5C, "FP S28"},
{0x5D, "FP S29"}, {0x5E, "FP S30"}, {0x5F, "FP S31"}};
static bool swd_scriptfunc_core_regs(ScriptContext* ctx) {
bool succ = false;
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
uint32_t reg_dhcsr = 0;
uint32_t reg_cpacr = 0;
swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &reg_dhcsr);
swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, &reg_cpacr);
/* when FPU is enabled/available, CP10 and CP11 are implemented */
bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0;
if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state");
succ = false;
} else {
for(size_t pos = 0; pos < COUNT(cpu_regs); pos++) {
if(!has_fpu && (cpu_regs[pos].regsel >= 0x20)) {
continue;
}
uint32_t core_data = 0;
succ =
swd_write_memory(
ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_RD | cpu_regs[pos].regsel) ==
1;
succ &= swd_read_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, &core_data) == 1;
if(!succ) {
swd_script_log(ctx, FuriLogLevelDefault, "%08s ----------", cpu_regs[pos].desc);
} else {
swd_script_log(
ctx, FuriLogLevelDefault, "%06s 0x%08X", cpu_regs[pos].desc, core_data);
}
}
}
furi_mutex_release(ctx->app->swd_mutex);
swd_script_seek_newline(ctx);
return true;
}
static bool swd_scriptfunc_core_reg_get(ScriptContext* ctx) {
uint32_t core_reg = 0;
uint32_t core_data = 0;
bool succ = false;
if(!swd_script_skip_whitespace(ctx)) {
swd_script_log(ctx, FuriLogLevelError, "missing whitespace");
return false;
}
if(!swd_script_get_number(ctx, &core_reg)) {
swd_script_log(ctx, FuriLogLevelError, "failed to parse register");
return false;
}
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
uint32_t reg_dhcsr = 0;
uint32_t reg_cpacr = 0;
swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &reg_dhcsr);
swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, &reg_cpacr);
/* when FPU is enabled/available, CP10 and CP11 are implemented */
bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0;
if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state");
succ = false;
} else {
if(!has_fpu && (core_reg >= 0x20)) {
swd_script_log(ctx, FuriLogLevelError, "Core has no FP extensions");
succ = false;
} else {
succ = swd_write_memory(
ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_RD | core_reg) == 1;
succ &= swd_read_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, &core_data) == 1;
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed");
}
}
}
furi_mutex_release(ctx->app->swd_mutex);
if(succ) {
swd_script_log(ctx, FuriLogLevelDefault, "0x%08X", core_data);
}
swd_script_seek_newline(ctx);
return succ;
}
static bool swd_scriptfunc_core_reg_set(ScriptContext* ctx) {
uint32_t core_reg = 0;
uint32_t core_data = 0;
bool succ = false;
if(!swd_script_skip_whitespace(ctx)) {
swd_script_log(ctx, FuriLogLevelError, "missing whitespace");
return false;
}
if(!swd_script_get_number(ctx, &core_reg)) {
swd_script_log(ctx, FuriLogLevelError, "failed to parse register");
return false;
}
if(!swd_script_skip_whitespace(ctx)) {
swd_script_log(ctx, FuriLogLevelError, "missing whitespace");
return false;
}
if(!swd_script_get_number(ctx, &core_data)) {
swd_script_log(ctx, FuriLogLevelError, "failed to parse data");
return false;
}
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
uint32_t reg_dhcsr = 0;
uint32_t reg_cpacr = 0;
swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &reg_dhcsr);
swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, &reg_cpacr);
/* when FPU is enabled/available, CP10 and CP11 are implemented */
bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0;
if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) {
swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state");
succ = false;
} else {
if(!has_fpu && (core_reg >= 0x20)) {
swd_script_log(ctx, FuriLogLevelError, "Core has no FP extensions");
succ = false;
} else {
succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, core_data) == 1;
succ &= swd_write_memory(
ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_WR | core_reg) == 1;
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed");
}
}
}
furi_mutex_release(ctx->app->swd_mutex);
swd_script_seek_newline(ctx);
return succ;
}
static bool swd_scriptfunc_core_cpuid(ScriptContext* ctx) {
bool succ = false;
uint32_t reg_cpuid = 0;
furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever);
succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPUID, &reg_cpuid) == 1;
furi_mutex_release(ctx->app->swd_mutex);
if(!succ) {
swd_script_log(ctx, FuriLogLevelError, "swd_read_memory failed");
} else {
swd_script_log(ctx, FuriLogLevelDefault, "0x%08X", reg_cpuid);
}
swd_script_seek_newline(ctx);
return succ;
}
static const ScriptFunctionInfo script_funcs[] = { static const ScriptFunctionInfo script_funcs[] = {
{"#", &swd_scriptfunc_comment}, {"#", &swd_scriptfunc_comment},
{".label", &swd_scriptfunc_label}, {".label", &swd_scriptfunc_label},
@@ -1650,12 +1979,20 @@ static const ScriptFunctionInfo script_funcs[] = {
{"mem_dump", &swd_scriptfunc_mem_dump}, {"mem_dump", &swd_scriptfunc_mem_dump},
{"mem_ldmst", &swd_scriptfunc_mem_ldmst}, {"mem_ldmst", &swd_scriptfunc_mem_ldmst},
{"mem_write", &swd_scriptfunc_mem_write}, {"mem_write", &swd_scriptfunc_mem_write},
{"mem_read", &swd_scriptfunc_mem_read},
{"dp_write", &swd_scriptfunc_dp_write}, {"dp_write", &swd_scriptfunc_dp_write},
{"dp_read", &swd_scriptfunc_dp_read}, {"dp_read", &swd_scriptfunc_dp_read},
{"ap_scan", &swd_scriptfunc_apscan}, {"ap_scan", &swd_scriptfunc_apscan},
{"ap_select", &swd_scriptfunc_apselect}, {"ap_select", &swd_scriptfunc_apselect},
{"ap_read", &swd_scriptfunc_ap_read}, {"ap_read", &swd_scriptfunc_ap_read},
{"ap_write", &swd_scriptfunc_ap_write}}; {"ap_write", &swd_scriptfunc_ap_write},
{"core_halt", &swd_scriptfunc_core_halt},
{"core_step", &swd_scriptfunc_core_step},
{"core_continue", &swd_scriptfunc_core_continue},
{"core_regs", &swd_scriptfunc_core_regs},
{"core_reg_get", &swd_scriptfunc_core_reg_get},
{"core_reg_set", &swd_scriptfunc_core_reg_set},
{"core_cpuid", &swd_scriptfunc_core_cpuid}};
/************************** script main code **************************/ /************************** script main code **************************/
@@ -2487,7 +2824,6 @@ static void swd_main_loop(AppFSM* ctx) {
} }
case ModePageDPRegs: case ModePageDPRegs:
case ModePageDPID:
case ModePageAPID: { case ModePageAPID: {
furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever);
/* set debug enable request */ /* set debug enable request */
@@ -2532,6 +2868,7 @@ static void swd_main_loop(AppFSM* ctx) {
break; break;
} }
case ModePageDPID:
case ModePageCoresight: case ModePageCoresight:
furi_delay_ms(50); furi_delay_ms(50);
break; break;

View File

@@ -87,6 +87,21 @@ typedef enum {
#define AP_IDR 0xFC #define AP_IDR 0xFC
#define AP_BASE 0xF8 #define AP_BASE 0xF8
#define SCS_CPUID 0xE000ED00u
#define SCS_CPACR 0xE000ED88u
#define SCS_DHCSR 0xE000EDF0u
#define SCS_DHCSR_S_HALT (1u << 17)
#define SCS_DHCSR_C_MASKINTS (1u << 3)
#define SCS_DHCSR_C_STEP (1u << 2)
#define SCS_DHCSR_C_HALT (1u << 1)
#define SCS_DHCSR_C_DEBUGEN (1u << 0)
#define SCS_DHCSR_KEY 0xA05F0000u
#define SCS_DCRSR 0xE000EDF4u
#define SCS_DCRSR_RD 0x00000000u
#define SCS_DCRSR_WR 0x00010000u
#define SCS_DCRDR 0xE000EDF8u
#define SCS_DEMCR 0xE000EDFCu
typedef enum { KeyNone, KeyUp, KeyRight, KeyDown, KeyLeft, KeyOK } KeyCode; typedef enum { KeyNone, KeyUp, KeyRight, KeyDown, KeyLeft, KeyOK } KeyCode;
typedef enum { typedef enum {

View File

@@ -76,7 +76,7 @@ static void usb_uart_vcp_deinit(UsbUart* usb_uart, uint8_t vcp_ch) {
} }
} }
void usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length) { bool usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length) {
uint32_t pos = 0; uint32_t pos = 0;
while(pos < length) { while(pos < length) {
size_t pkt_size = length - pos; size_t pkt_size = length - pos;
@@ -85,14 +85,19 @@ void usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length) {
pkt_size = USB_CDC_PKT_LEN; pkt_size = USB_CDC_PKT_LEN;
} }
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) { if(furi_semaphore_acquire(usb_uart->tx_sem, 100) != FuriStatusOk) {
furi_check(furi_mutex_acquire(usb_uart->usb_mutex, FuriWaitForever) == FuriStatusOk); return false;
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, &data[pos], pkt_size);
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
usb_uart->st.tx_cnt += pkt_size;
pos += pkt_size;
} }
if(furi_mutex_acquire(usb_uart->usb_mutex, 100) != FuriStatusOk) {
furi_semaphore_release(usb_uart->tx_sem);
return false;
}
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, &data[pos], pkt_size);
furi_mutex_release(usb_uart->usb_mutex);
usb_uart->st.tx_cnt += pkt_size;
pos += pkt_size;
} }
return true;
} }
static int32_t usb_uart_worker(void* context) { static int32_t usb_uart_worker(void* context) {
@@ -118,10 +123,11 @@ static int32_t usb_uart_worker(void* context) {
} }
if(events & WorkerEvtCdcRx) { if(events & WorkerEvtCdcRx) {
furi_check(furi_mutex_acquire(usb_uart->usb_mutex, FuriWaitForever) == FuriStatusOk); size_t len = 0;
size_t len = if(furi_mutex_acquire(usb_uart->usb_mutex, 100) == FuriStatusOk) {
furi_hal_cdc_receive(usb_uart->cfg.vcp_ch, &data[remain], USB_CDC_PKT_LEN); len = furi_hal_cdc_receive(usb_uart->cfg.vcp_ch, &data[remain], USB_CDC_PKT_LEN);
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk); furi_mutex_release(usb_uart->usb_mutex);
}
if(len > 0) { if(len > 0) {
usb_uart->st.rx_cnt += len; usb_uart->st.rx_cnt += len;

View File

@@ -26,4 +26,4 @@ void usb_uart_get_config(UsbUart* usb_uart, UsbUartConfig* cfg);
void usb_uart_get_state(UsbUart* usb_uart, UsbUartState* st); void usb_uart_get_state(UsbUart* usb_uart, UsbUartState* st);
void usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length); bool usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length);

View File

@@ -70,6 +70,7 @@ typedef struct {
uint16_t fallSpeed; uint16_t fallSpeed;
GameState gameState; GameState gameState;
FuriTimer* timer; FuriTimer* timer;
FuriMutex* mutex;
} TetrisState; } TetrisState;
typedef enum { typedef enum {
@@ -126,11 +127,9 @@ static void tetris_game_draw_playfield(Canvas* const canvas, const TetrisState*
} }
static void tetris_game_render_callback(Canvas* const canvas, void* ctx) { static void tetris_game_render_callback(Canvas* const canvas, void* ctx) {
const TetrisState* tetris_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(tetris_state == NULL) { const TetrisState* tetris_state = ctx;
FURI_LOG_E("TetrisGame", "it null"); furi_mutex_acquire(tetris_state->mutex, FuriWaitForever);
return;
}
tetris_game_draw_border(canvas); tetris_game_draw_border(canvas);
tetris_game_draw_playfield(canvas, tetris_state); tetris_game_draw_playfield(canvas, tetris_state);
@@ -158,7 +157,7 @@ static void tetris_game_render_callback(Canvas* const canvas, void* ctx) {
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 32, 73, AlignCenter, AlignBottom, buffer); canvas_draw_str_aligned(canvas, 32, 73, AlignCenter, AlignBottom, buffer);
} }
release_mutex((ValueMutex*)ctx, tetris_state); furi_mutex_release(tetris_state->mutex);
} }
static void tetris_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void tetris_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -357,8 +356,8 @@ int32_t tetris_game_app() {
TetrisState* tetris_state = malloc(sizeof(TetrisState)); TetrisState* tetris_state = malloc(sizeof(TetrisState));
ValueMutex state_mutex; tetris_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, tetris_state, sizeof(TetrisState))) { if(!tetris_state->mutex) {
FURI_LOG_E("TetrisGame", "cannot create mutex\r\n"); FURI_LOG_E("TetrisGame", "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(tetris_state); free(tetris_state);
@@ -375,7 +374,7 @@ int32_t tetris_game_app() {
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_set_orientation(view_port, ViewPortOrientationVertical); view_port_set_orientation(view_port, ViewPortOrientationVertical);
view_port_draw_callback_set(view_port, tetris_game_render_callback, &state_mutex); view_port_draw_callback_set(view_port, tetris_game_render_callback, tetris_state);
view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue); view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -395,7 +394,7 @@ int32_t tetris_game_app() {
// This 10U implicitly sets the game loop speed. downRepeatCounter relies on this value // This 10U implicitly sets the game loop speed. downRepeatCounter relies on this value
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 10U); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 10U);
TetrisState* tetris_state = (TetrisState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(tetris_state->mutex, FuriWaitForever);
memcpy(newPiece, &tetris_state->currPiece, sizeof(tetris_state->currPiece)); memcpy(newPiece, &tetris_state->currPiece, sizeof(tetris_state->currPiece));
bool wasDownMove = false; bool wasDownMove = false;
@@ -462,7 +461,7 @@ int32_t tetris_game_app() {
tetris_game_process_step(tetris_state, newPiece, wasDownMove); tetris_game_process_step(tetris_state, newPiece, wasDownMove);
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, tetris_state); furi_mutex_release(tetris_state->mutex);
} }
furi_timer_free(tetris_state->timer); furi_timer_free(tetris_state->timer);
@@ -471,7 +470,7 @@ int32_t tetris_game_app() {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(tetris_state->mutex);
vTaskPrioritySet(timer_task, origTimerPrio); vTaskPrioritySet(timer_task, origTimerPrio);
free(newPiece); free(newPiece);
free(tetris_state); free(tetris_state);

View File

@@ -9,6 +9,7 @@
typedef enum { EventTypeTick, EventTypeKey } EventType; typedef enum { EventTypeTick, EventTypeKey } EventType;
typedef struct { typedef struct {
FuriMutex* mutex;
FuriTimer* timer; FuriTimer* timer;
uint8_t selBoxX; uint8_t selBoxX;
uint8_t selBoxY; uint8_t selBoxY;
@@ -172,10 +173,9 @@ static void tictactoe_state_init(TicTacToeState* tictactoe_state) {
} }
static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) { static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) {
TicTacToeState* ticst = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(ticst == NULL) { TicTacToeState* ticst = ctx;
return; furi_mutex_acquire(ticst->mutex, FuriWaitForever);
}
if(ticst->selX > 3) { if(ticst->selX > 3) {
ticst->selX = 3; ticst->selX = 3;
@@ -284,7 +284,7 @@ static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) {
tictactoe_draw(canvas, ticst); tictactoe_draw(canvas, ticst);
release_mutex((ValueMutex*)ctx, ticst); furi_mutex_release(ticst->mutex);
} }
static void tictactoe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void tictactoe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -307,8 +307,9 @@ int32_t tictactoe_game_app(void* p) {
TicTacToeState* tictactoe_state = malloc(sizeof(TicTacToeState)); TicTacToeState* tictactoe_state = malloc(sizeof(TicTacToeState));
ValueMutex state_mutex; tictactoe_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, tictactoe_state, sizeof(TicTacToeState))) {
if(!tictactoe_state->mutex) {
FURI_LOG_E(TAG, "Cannot create mutex\r\n"); FURI_LOG_E(TAG, "Cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
free(tictactoe_state); free(tictactoe_state);
@@ -317,7 +318,7 @@ int32_t tictactoe_game_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, tictactoe_draw_callback, &state_mutex); view_port_draw_callback_set(view_port, tictactoe_draw_callback, tictactoe_state);
view_port_input_callback_set(view_port, tictactoe_input_callback, event_queue); view_port_input_callback_set(view_port, tictactoe_input_callback, event_queue);
tictactoe_state->timer = tictactoe_state->timer =
@@ -333,7 +334,7 @@ int32_t tictactoe_game_app(void* p) {
GameEvent event; GameEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
TicTacToeState* tictactoe_state = (TicTacToeState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(tictactoe_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
// Key events // Key events
@@ -366,7 +367,7 @@ int32_t tictactoe_game_app(void* p) {
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, tictactoe_state); furi_mutex_release(tictactoe_state->mutex);
} }
furi_timer_free(tictactoe_state->timer); furi_timer_free(tictactoe_state->timer);
@@ -375,7 +376,7 @@ int32_t tictactoe_game_app(void* p) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(tictactoe_state->mutex);
free(tictactoe_state); free(tictactoe_state);
return 0; return 0;

View File

@@ -23,12 +23,14 @@
#define IDLE_TIMEOUT 60000 #define IDLE_TIMEOUT 60000
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
PluginState* plugin_state = ctx;
furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(plugin_state != NULL) { if(plugin_state != NULL) {
totp_scene_director_render(canvas, plugin_state); totp_scene_director_render(canvas, plugin_state);
} }
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -137,8 +139,8 @@ int32_t totp_app() {
return 254; return 254;
} }
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
FURI_LOG_E(LOGGING_TAG, "Cannot create mutex\r\n"); FURI_LOG_E(LOGGING_TAG, "Cannot create mutex\r\n");
totp_plugin_state_free(plugin_state); totp_plugin_state_free(plugin_state);
return 255; return 255;
@@ -157,7 +159,7 @@ int32_t totp_app() {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -169,7 +171,7 @@ int32_t totp_app() {
while(processing) { while(processing) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
@@ -179,16 +181,16 @@ int32_t totp_app() {
if(event.type == EventForceCloseApp) { if(event.type == EventForceCloseApp) {
processing = false; processing = false;
} else { } else {
processing = totp_scene_director_handle_event(&event, plugin_state_m); processing = totp_scene_director_handle_event(&event, plugin_state);
} }
} else if( } else if(
plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication &&
furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) {
totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL); totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state_m); furi_mutex_release(plugin_state->mutex);
} }
totp_cli_unregister_command_handler(cli_context); totp_cli_unregister_command_handler(cli_context);
@@ -199,7 +201,7 @@ int32_t totp_app() {
gui_remove_view_port(plugin_state->gui, view_port); gui_remove_view_port(plugin_state->gui, view_port);
view_port_free(view_port); view_port_free(view_port);
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
delete_mutex(&state_mutex); furi_mutex_free(plugin_state->mutex);
totp_plugin_state_free(plugin_state); totp_plugin_state_free(plugin_state);
return 0; return 0;
} }

View File

@@ -87,4 +87,5 @@ typedef struct {
* @brief Notification method * @brief Notification method
*/ */
NotificationMethod notification_method; NotificationMethod notification_method;
FuriMutex* mutex;
} PluginState; } PluginState;

View File

@@ -57,8 +57,10 @@ static void totp_type_code_worker_type_code(TotpTypeCodeWorkerContext* context)
} }
static int32_t totp_type_code_worker_callback(void* context) { static int32_t totp_type_code_worker_callback(void* context) {
ValueMutex context_mutex; furi_assert(context);
if(!init_mutex(&context_mutex, context, sizeof(TotpTypeCodeWorkerContext))) { TotpTypeCodeWorkerContext* ctxx = context;
ctxx->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!ctxx->mutex) {
return 251; return 251;
} }
@@ -70,15 +72,16 @@ static int32_t totp_type_code_worker_callback(void* context) {
furi_check((flags & FuriFlagError) == 0); //-V562 furi_check((flags & FuriFlagError) == 0); //-V562
if(flags & TotpTypeCodeWorkerEventStop) break; if(flags & TotpTypeCodeWorkerEventStop) break;
TotpTypeCodeWorkerContext* h_context = acquire_mutex_block(&context_mutex); TotpTypeCodeWorkerContext* h_context = context;
furi_mutex_acquire(ctxx->mutex, FuriWaitForever);
if(flags & TotpTypeCodeWorkerEventType) { if(flags & TotpTypeCodeWorkerEventType) {
totp_type_code_worker_type_code(h_context); totp_type_code_worker_type_code(h_context);
} }
release_mutex(&context_mutex, h_context); furi_mutex_release(ctxx->mutex);
} }
delete_mutex(&context_mutex); furi_mutex_free(ctxx->mutex);
return 0; return 0;
} }

View File

@@ -12,6 +12,7 @@ typedef struct {
FuriThread* thread; FuriThread* thread;
FuriMutex* string_sync; FuriMutex* string_sync;
FuriHalUsbInterface* usb_mode_prev; FuriHalUsbInterface* usb_mode_prev;
FuriMutex* mutex;
} TotpTypeCodeWorkerContext; } TotpTypeCodeWorkerContext;
enum TotpTypeCodeWorkerEvents { enum TotpTypeCodeWorkerEvents {

View File

@@ -62,6 +62,7 @@ typedef struct SGpioButtons {
} SGpioButtons; } SGpioButtons;
typedef struct SWiFiDeauthApp { typedef struct SWiFiDeauthApp {
FuriMutex* mutex;
Gui* m_gui; Gui* m_gui;
FuriThread* m_worker_thread; FuriThread* m_worker_thread;
//NotificationApp* m_notification; //NotificationApp* m_notification;
@@ -121,10 +122,9 @@ static void esp8266_deauth_app_init(SWiFiDeauthApp* const app) {
} }
static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ctx) { static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ctx) {
SWiFiDeauthApp* app = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(app == NULL) { SWiFiDeauthApp* app = ctx;
return; furi_mutex_acquire(app->mutex, FuriWaitForever);
}
//if(app->m_needUpdateGUI) //if(app->m_needUpdateGUI)
//{ //{
@@ -206,7 +206,7 @@ static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ct
break; break;
} }
release_mutex((ValueMutex*)ctx, app); furi_mutex_release(app->mutex);
} }
static void static void
@@ -235,14 +235,15 @@ static int32_t uart_worker(void* context) {
furi_assert(context); furi_assert(context);
DEAUTH_APP_LOG_I("[UART] Worker thread init"); DEAUTH_APP_LOG_I("[UART] Worker thread init");
SWiFiDeauthApp* app = acquire_mutex((ValueMutex*)context, 25); SWiFiDeauthApp* app = context;
furi_mutex_acquire(app->mutex, FuriWaitForever);
if(app == NULL) { if(app == NULL) {
return 1; return 1;
} }
FuriStreamBuffer* rx_stream = app->m_rx_stream; FuriStreamBuffer* rx_stream = app->m_rx_stream;
release_mutex((ValueMutex*)context, app); furi_mutex_release(app->mutex);
#if ENABLE_MODULE_POWER #if ENABLE_MODULE_POWER
bool initialized = false; bool initialized = false;
@@ -259,7 +260,8 @@ static int32_t uart_worker(void* context) {
if(events & WorkerEventStop) break; if(events & WorkerEventStop) break;
if(events & WorkerEventRx) { if(events & WorkerEventRx) {
DEAUTH_APP_LOG_I("[UART] Received data"); DEAUTH_APP_LOG_I("[UART] Received data");
SWiFiDeauthApp* app = acquire_mutex((ValueMutex*)context, 25); SWiFiDeauthApp* app = context;
furi_mutex_acquire(app->mutex, FuriWaitForever);
if(app == NULL) { if(app == NULL) {
return 1; return 1;
} }
@@ -307,7 +309,7 @@ static int32_t uart_worker(void* context) {
} }
#endif // ENABLE_MODULE_POWER #endif // ENABLE_MODULE_POWER
release_mutex((ValueMutex*)context, app); furi_mutex_release(app->mutex);
} }
} }
@@ -356,8 +358,8 @@ int32_t esp8266_deauth_app(void* p) {
#endif #endif
#endif // ENABLE_MODULE_DETECTION #endif // ENABLE_MODULE_DETECTION
ValueMutex app_data_mutex; app->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&app_data_mutex, app, sizeof(SWiFiDeauthApp))) { if(!app->mutex) {
DEAUTH_APP_LOG_E("cannot create mutex\r\n"); DEAUTH_APP_LOG_E("cannot create mutex\r\n");
free(app); free(app);
return 255; return 255;
@@ -365,10 +367,10 @@ int32_t esp8266_deauth_app(void* p) {
DEAUTH_APP_LOG_I("Mutex created"); DEAUTH_APP_LOG_I("Mutex created");
//app->m_notification = furi_record_open("notification"); //app->m_notification = furi_record_open(RECORD_NOTIFICATION);
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, esp8266_deauth_module_render_callback, &app_data_mutex); view_port_draw_callback_set(view_port, esp8266_deauth_module_render_callback, app);
view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue); view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -382,7 +384,7 @@ int32_t esp8266_deauth_app(void* p) {
app->m_worker_thread = furi_thread_alloc(); app->m_worker_thread = furi_thread_alloc();
furi_thread_set_name(app->m_worker_thread, "WiFiDeauthModuleUARTWorker"); furi_thread_set_name(app->m_worker_thread, "WiFiDeauthModuleUARTWorker");
furi_thread_set_stack_size(app->m_worker_thread, 1 * 1024); furi_thread_set_stack_size(app->m_worker_thread, 1 * 1024);
furi_thread_set_context(app->m_worker_thread, &app_data_mutex); furi_thread_set_context(app->m_worker_thread, app);
furi_thread_set_callback(app->m_worker_thread, uart_worker); furi_thread_set_callback(app->m_worker_thread, uart_worker);
furi_thread_start(app->m_worker_thread); furi_thread_start(app->m_worker_thread);
DEAUTH_APP_LOG_I("UART thread allocated"); DEAUTH_APP_LOG_I("UART thread allocated");
@@ -398,7 +400,7 @@ int32_t esp8266_deauth_app(void* p) {
SPluginEvent event; SPluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
SWiFiDeauthApp* app = (SWiFiDeauthApp*)acquire_mutex_block(&app_data_mutex); furi_mutex_acquire(app->mutex, FuriWaitForever);
#if ENABLE_MODULE_DETECTION #if ENABLE_MODULE_DETECTION
if(!app->m_wifiDeauthModuleAttached) { if(!app->m_wifiDeauthModuleAttached) {
@@ -484,7 +486,7 @@ int32_t esp8266_deauth_app(void* p) {
#endif #endif
view_port_update(view_port); view_port_update(view_port);
release_mutex(&app_data_mutex, app); furi_mutex_release(app->mutex);
} }
DEAUTH_APP_LOG_I("Start exit app"); DEAUTH_APP_LOG_I("Start exit app");
@@ -514,7 +516,7 @@ int32_t esp8266_deauth_app(void* p) {
// Close gui record // Close gui record
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close("notification"); //furi_record_close(RECORD_NOTIFICATION);
app->m_gui = NULL; app->m_gui = NULL;
view_port_free(view_port); view_port_free(view_port);
@@ -523,7 +525,7 @@ int32_t esp8266_deauth_app(void* p) {
furi_stream_buffer_free(app->m_rx_stream); furi_stream_buffer_free(app->m_rx_stream);
delete_mutex(&app_data_mutex); furi_mutex_free(app->mutex);
// Free rest // Free rest
free(app); free(app);

View File

@@ -83,6 +83,7 @@ typedef enum EWorkerEventFlags {
} EWorkerEventFlags; } EWorkerEventFlags;
typedef struct SWiFiScannerApp { typedef struct SWiFiScannerApp {
FuriMutex* mutex;
Gui* m_gui; Gui* m_gui;
FuriThread* m_worker_thread; FuriThread* m_worker_thread;
NotificationApp* m_notification; NotificationApp* m_notification;
@@ -162,10 +163,9 @@ void DrawSignalStrengthBar(Canvas* canvas, int rssi, int x, int y, int width, in
} }
static void wifi_module_render_callback(Canvas* const canvas, void* ctx) { static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
SWiFiScannerApp* app = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(app == NULL) { SWiFiScannerApp* app = ctx;
return; furi_mutex_acquire(app->mutex, FuriWaitForever);
}
canvas_clear(canvas); canvas_clear(canvas);
@@ -433,7 +433,7 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
break; break;
} }
} }
release_mutex((ValueMutex*)ctx, app); furi_mutex_release(app->mutex);
} }
static void wifi_module_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void wifi_module_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -460,14 +460,15 @@ static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
static int32_t uart_worker(void* context) { static int32_t uart_worker(void* context) {
furi_assert(context); furi_assert(context);
SWiFiScannerApp* app = acquire_mutex((ValueMutex*)context, 25); SWiFiScannerApp* app = context;
furi_mutex_acquire(app->mutex, FuriWaitForever);
if(app == NULL) { if(app == NULL) {
return 1; return 1;
} }
FuriStreamBuffer* rx_stream = app->m_rx_stream; FuriStreamBuffer* rx_stream = app->m_rx_stream;
release_mutex((ValueMutex*)context, app); furi_mutex_release(app->mutex);
while(true) { while(true) {
uint32_t events = furi_thread_flags_wait( uint32_t events = furi_thread_flags_wait(
@@ -527,7 +528,8 @@ static int32_t uart_worker(void* context) {
} while(end < stringSize); } while(end < stringSize);
furi_string_free(chunk); furi_string_free(chunk);
app = acquire_mutex((ValueMutex*)context, 25); app = context;
furi_mutex_acquire(app->mutex, FuriWaitForever);
if(app == NULL) { if(app == NULL) {
return 1; return 1;
} }
@@ -584,7 +586,7 @@ static int32_t uart_worker(void* context) {
} }
} }
release_mutex((ValueMutex*)context, app); furi_mutex_release(app->mutex);
// Clear string array // Clear string array
for(index = 0; index < EChunkArrayData_ENUM_MAX; ++index) { for(index = 0; index < EChunkArrayData_ENUM_MAX; ++index) {
@@ -665,8 +667,9 @@ int32_t wifi_scanner_app(void* p) {
#endif // ENABLE_MODULE_POWER #endif // ENABLE_MODULE_POWER
#endif // ENABLE_MODULE_DETECTION #endif // ENABLE_MODULE_DETECTION
ValueMutex app_data_mutex; app->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&app_data_mutex, app, sizeof(SWiFiScannerApp))) {
if(!app->mutex) {
WIFI_APP_LOG_E("cannot create mutex\r\n"); WIFI_APP_LOG_E("cannot create mutex\r\n");
free(app); free(app);
return 255; return 255;
@@ -674,10 +677,10 @@ int32_t wifi_scanner_app(void* p) {
WIFI_APP_LOG_I("Mutex created"); WIFI_APP_LOG_I("Mutex created");
app->m_notification = furi_record_open("notification"); app->m_notification = furi_record_open(RECORD_NOTIFICATION);
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, wifi_module_render_callback, &app_data_mutex); view_port_draw_callback_set(view_port, wifi_module_render_callback, app);
view_port_input_callback_set(view_port, wifi_module_input_callback, event_queue); view_port_input_callback_set(view_port, wifi_module_input_callback, event_queue);
// Open GUI and register view_port // Open GUI and register view_port
@@ -691,7 +694,7 @@ int32_t wifi_scanner_app(void* p) {
app->m_worker_thread = furi_thread_alloc(); app->m_worker_thread = furi_thread_alloc();
furi_thread_set_name(app->m_worker_thread, "WiFiModuleUARTWorker"); furi_thread_set_name(app->m_worker_thread, "WiFiModuleUARTWorker");
furi_thread_set_stack_size(app->m_worker_thread, 1024); furi_thread_set_stack_size(app->m_worker_thread, 1024);
furi_thread_set_context(app->m_worker_thread, &app_data_mutex); furi_thread_set_context(app->m_worker_thread, app);
furi_thread_set_callback(app->m_worker_thread, uart_worker); furi_thread_set_callback(app->m_worker_thread, uart_worker);
furi_thread_start(app->m_worker_thread); furi_thread_start(app->m_worker_thread);
WIFI_APP_LOG_I("UART thread allocated"); WIFI_APP_LOG_I("UART thread allocated");
@@ -710,7 +713,7 @@ int32_t wifi_scanner_app(void* p) {
SPluginEvent event; SPluginEvent event;
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
SWiFiScannerApp* app = (SWiFiScannerApp*)acquire_mutex_block(&app_data_mutex); furi_mutex_acquire(app->mutex, FuriWaitForever);
#if ENABLE_MODULE_DETECTION #if ENABLE_MODULE_DETECTION
if(!app->m_wifiModuleAttached) { if(!app->m_wifiModuleAttached) {
@@ -807,7 +810,7 @@ int32_t wifi_scanner_app(void* p) {
#endif #endif
view_port_update(view_port); view_port_update(view_port);
release_mutex(&app_data_mutex, app); furi_mutex_release(app->mutex);
} }
WIFI_APP_LOG_I("Start exit app"); WIFI_APP_LOG_I("Start exit app");
@@ -831,7 +834,7 @@ int32_t wifi_scanner_app(void* p) {
// Close gui record // Close gui record
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
furi_record_close("notification"); furi_record_close(RECORD_NOTIFICATION);
app->m_gui = NULL; app->m_gui = NULL;
view_port_free(view_port); view_port_free(view_port);
@@ -840,7 +843,7 @@ int32_t wifi_scanner_app(void* p) {
furi_stream_buffer_free(app->m_rx_stream); furi_stream_buffer_free(app->m_rx_stream);
delete_mutex(&app_data_mutex); furi_mutex_free(app->mutex);
// Free rest // Free rest
free(app); free(app);

View File

@@ -51,6 +51,7 @@ typedef struct {
} Projectile; } Projectile;
typedef struct { typedef struct {
FuriMutex* mutex;
GameState game_state; GameState game_state;
Player player; Player player;
@@ -65,10 +66,9 @@ typedef struct {
} PluginState; } PluginState;
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); furi_assert(ctx);
if(plugin_state == NULL) { const PluginState* plugin_state = ctx;
return; furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
}
canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 0, 128, 64);
@@ -180,7 +180,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
//canvas_draw_str_aligned(canvas, 32, 16, AlignLeft, AlignBottom, info); //canvas_draw_str_aligned(canvas, 32, 16, AlignLeft, AlignBottom, info);
//free(info); //free(info);
release_mutex((ValueMutex*)ctx, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -294,8 +294,8 @@ int32_t zombiez_game_app(void* p) {
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
zombiez_state_init(plugin_state); zombiez_state_init(plugin_state);
ValueMutex state_mutex; plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!plugin_state->mutex) {
FURI_LOG_E("Zombiez", "cannot create mutex\r\n"); FURI_LOG_E("Zombiez", "cannot create mutex\r\n");
return_code = 255; return_code = 255;
goto free_and_exit; goto free_and_exit;
@@ -303,7 +303,7 @@ int32_t zombiez_game_app(void* p) {
// Set system callbacks // Set system callbacks
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex); view_port_draw_callback_set(view_port, render_callback, plugin_state);
view_port_input_callback_set(view_port, input_callback, event_queue); view_port_input_callback_set(view_port, input_callback, event_queue);
FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue); FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
@@ -317,7 +317,7 @@ int32_t zombiez_game_app(void* p) {
bool isRunning = true; bool isRunning = true;
while(isRunning) { while(isRunning) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
if(event.input.type == InputTypePress) { if(event.input.type == InputTypePress) {
@@ -377,12 +377,10 @@ int32_t zombiez_game_app(void* p) {
} else if(event.type == EventTypeTick) { } else if(event.type == EventTypeTick) {
tick(plugin_state); tick(plugin_state);
} }
} else {
// event timeout
} }
view_port_update(view_port); view_port_update(view_port);
release_mutex(&state_mutex, plugin_state); furi_mutex_release(plugin_state->mutex);
} }
furi_timer_free(timer); furi_timer_free(timer);
@@ -390,7 +388,7 @@ int32_t zombiez_game_app(void* p) {
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
view_port_free(view_port); view_port_free(view_port);
delete_mutex(&state_mutex); furi_mutex_free(plugin_state->mutex);
free_and_exit: free_and_exit:
free(plugin_state); free(plugin_state);

View File

@@ -45,3 +45,5 @@ C1B74D7478053AE2
# default iCLASS RFIDeas # default iCLASS RFIDeas
6B65797374726B72 6B65797374726B72
5C100DF7042EAE64

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 21st Feb, 2023 # Last Updated 07th Mar, 2023
# Last Checked 21st Feb, 2023 # Last Checked 07th Mar, 2023
# #
name: POWER name: POWER
type: raw type: raw
@@ -1091,6 +1091,18 @@ type: raw
frequency: 38000 frequency: 38000
duty_cycle: 0.330000 duty_cycle: 0.330000
data: 270 18152 3021 8955 523 499 495 1497 492 504 500 468 526 496 498 498 496 499 495 501 493 502 492 1499 500 496 498 524 470 1521 498 497 497 499 495 1496 492 1499 500 1491 497 1494 494 1497 502 494 500 495 499 497 497 498 496 500 494 528 466 530 464 531 473 522 493 503 491 504 500 495 499 497 497 498 496 500 494 501 493 503 491 504 500 495 499 496 498 498 496 499 495 501 493 529 465 531 473 522 472 523 492 504 490 505 499 496 498 498 496 499 495 1496 492 1499 500 1492 496 1494 525 2947 2999 8953 525 1519 469 499 516 507 497 498 496 500 494 501 493 503 491 504 500 495 499 1492 496 499 495 501 493 1498 501 495 499 1492 496 1522 466 1524 496 1496 492 1499 500 1492 496 499 495 500 494 502 492 504 500 495 499 496 498 498 496 499 495 500 494 502 492 530 474 521 473 523 523 472 522 474 489 506 498 497 497 499 495 500 494 502 492 503 501 494 500 496 498 497 497 499 495 500 494 502 492 503 501 521 473 523 471 524 522 474 520 475 498 497 497 499 495 500 494 2978 2999 8952 525 1492 496 499 495 501 493 503 491 504 500 495 499 497 497 525 469 526 468 1524 516 479 494 501 493 503 491 504 500 495 499 497 497 1494 494 1497 492 1500 499 1492 496 499 495 1497 491 531 473 1518 522 1469 499 496 498 498 496 500 494 1497 491 1500 499 1492 496 499 495 501 493 502 492 504 500 495 499 523 471 525 469 526 520 1472 516 1475 493 502 492 504 500 495 499 1492 496 499 495 501 493 502 492 504 500 495 499 496 498 498 496 1522 466 1525 525 1466 491 1500 499 data: 270 18152 3021 8955 523 499 495 1497 492 504 500 468 526 496 498 498 496 499 495 501 493 502 492 1499 500 496 498 524 470 1521 498 497 497 499 495 1496 492 1499 500 1491 497 1494 494 1497 502 494 500 495 499 497 497 498 496 500 494 528 466 530 464 531 473 522 493 503 491 504 500 495 499 497 497 498 496 500 494 501 493 503 491 504 500 495 499 496 498 498 496 499 495 501 493 529 465 531 473 522 472 523 492 504 490 505 499 496 498 498 496 499 495 1496 492 1499 500 1492 496 1494 525 2947 2999 8953 525 1519 469 499 516 507 497 498 496 500 494 501 493 503 491 504 500 495 499 1492 496 499 495 501 493 1498 501 495 499 1492 496 1522 466 1524 496 1496 492 1499 500 1492 496 499 495 500 494 502 492 504 500 495 499 496 498 498 496 499 495 500 494 502 492 530 474 521 473 523 523 472 522 474 489 506 498 497 497 499 495 500 494 502 492 503 501 494 500 496 498 497 497 499 495 500 494 502 492 503 501 521 473 523 471 524 522 474 520 475 498 497 497 499 495 500 494 2978 2999 8952 525 1492 496 499 495 501 493 503 491 504 500 495 499 497 497 525 469 526 468 1524 516 479 494 501 493 503 491 504 500 495 499 497 497 1494 494 1497 492 1500 499 1492 496 499 495 1497 491 531 473 1518 522 1469 499 496 498 498 496 500 494 1497 491 1500 499 1492 496 499 495 501 493 502 492 504 500 495 499 523 471 525 469 526 520 1472 516 1475 493 502 492 504 500 495 499 1492 496 499 495 501 493 502 492 504 500 495 499 496 498 498 496 1522 466 1525 525 1466 491 1500 499
# POWER_ON
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4455 4310 587 1553 587 481 588 1552 587 1553 587 482 587 483 586 1553 585 483 586 483 587 1553 586 483 586 483 585 1553 586 1553 586 483 586 1553 586 1553 586 483 586 483 585 1553 586 1553 587 1552 586 1553 585 1554 585 483 586 1552 588 1552 585 483 586 483 586 483 586 483 585 484 585 484 585 483 586 483 586 483 585 484 586 483 586 483 586 483 586 1553 585 1553 585 1554 585 1553 585 1554 585 1553 586 1553 585 1554 584 5128 4426 4312 584 1554 585 484 585 1553 585 1554 585 483 586 483 585 1554 584 484 585 484 584 1553 584 485 584 484 585 1554 584 1555 583 485 584 1552 586 1553 585 484 585 483 585 1553 583 1554 585 1553 584 1554 583 1554 584 485 584 1554 584 1554 583 484 585 484 585 484 584 484 584 485 584 484 585 484 584 485 583 485 583 484 585 484 585 484 584 485 583 1555 584 1554 584 1553 584 1553 585 1553 584 1553 585 1553 584 1555 583
# POWER_ON
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 530 374 30128 50095 3452 1625 471 1229 471 459 471 459 471 459 444 459 471 459 470 459 471 459 471 459 471 459 444 460 470 459 471 1230 470 459 470 460 443 460 470 460 469 460 470 460 470 460 443 1231 470 1230 470 460 470 460 470 460 443 487 443 460 469 460 470 461 468 461 469 1232 442 461 469 1232 468 1232 442 1232 468 1232 468 1232 468 1232 441 461 469 1232 468 1232 442 488 442 461 469 462 468 463 466 463 467 485 418 488 442 485 444 1234 467 1256 418 1256 444 1256 444 1256 444 1256 418 1256 444 1256 444 485 444 486 417 486 444 1256 444 485 444 485 444 486 417 486 444 1257 443 486 444 485 444 1257 417 486 444 486 443 486 444 1257 417 1257 443 486 444 486 444 486 443 486 417 513 416 487 443 487 442 486 444 1257 416 1257 443 487 442 486 444 486 443 487 416 513 416 487 443 486 443 487 443 487 442 487 416 514 415 1258 442 487 442 487 443 487 416 514 416 488 442 487 443 488 442 488 442 1258 415 1258 442 488 442 488 441 488 442 488 415 488 441 488 442 488 442 1259 441 1259 415 489 440 489 441 488 442 489 440 488 415 1259 441 1260 440 1260 414 516 414 489 439 491 440 489 440 490 439 490 414 516 413 490 438 491 438 492 438 491 415 539 389 517 413 514 391 516 414 539 414 516 390 539 388 542 363 540 390 1311 389 540 389 540 363 567 363 540 390 540 389 540 390 540 390 540 363 567 363 541 389 540 390 540 389 540 390 541 362 567 363 541 389 541 389 541 389 541 389 541 362 568 361 541 389 541 389 542 388 541 389 541 362 542 388 542 387 542 388 542 388 543 387 567 335 567 363 567 363 567 363 567 363 567 336 594 335 568 362 567 362 568 361 568 362 567 336 595 335 568 362 568 361 568 362 1338 362 1339 334 569 361 569 360 569 361 569 360 569 334 570 360 570 360 595 334 595 334 1366 307 1366 334 595 335 595 335 595 335 596 306 623 307 596 334 596 333 597 333 622 307 597 306 597 333 623 306 623 306 624 306 624 306 624 278 1395 305 1395 305 650 279 651 360
# #
name: TEMP+ name: TEMP+
type: raw type: raw
@@ -1572,3 +1584,99 @@ type: raw
frequency: 38000 frequency: 38000
duty_cycle: 0.330000 duty_cycle: 0.330000
data: 8362 4223 595 1983 1116 1480 592 1987 1081 1567 1070 1524 550 2029 1043 1540 1042 1568 1043 1532 549 2030 1042 1540 1042 1568 1042 1532 1042 1532 549 2022 549 2065 1043 1528 1043 1532 1043 1524 1042 1576 1042 1532 1042 1525 548 2030 549 2082 1042 1524 1042 1533 1042 1525 1042 1576 1042 1533 1042 1525 1041 1533 1042 1569 1042 1533 1042 1533 1042 1525 1041 1577 1041 1533 1042 1525 1041 1534 1041 1569 1042 1533 1041 1534 1040 1526 1041 1578 1041 1534 1041 1526 1040 1534 1041 1570 1041 1534 1015 1560 1015 1552 1015 1604 1040 1535 1040 1527 1039 1535 1014 1597 1013 1561 1014 1561 1013 1554 519 2129 987 1554 544 2036 518 2093 987 data: 8362 4223 595 1983 1116 1480 592 1987 1081 1567 1070 1524 550 2029 1043 1540 1042 1568 1043 1532 549 2030 1042 1540 1042 1568 1042 1532 1042 1532 549 2022 549 2065 1043 1528 1043 1532 1043 1524 1042 1576 1042 1532 1042 1525 548 2030 549 2082 1042 1524 1042 1533 1042 1525 1042 1576 1042 1533 1042 1525 1041 1533 1042 1569 1042 1533 1042 1533 1042 1525 1041 1577 1041 1533 1042 1525 1041 1534 1041 1569 1042 1533 1041 1534 1040 1526 1041 1578 1041 1534 1041 1526 1040 1534 1041 1570 1041 1534 1015 1560 1015 1552 1015 1604 1040 1535 1040 1527 1039 1535 1014 1597 1013 1561 1014 1561 1013 1554 519 2129 987 1554 544 2036 518 2093 987
# POWER_OFF
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4453 4313 586 1554 585 483 586 1554 587 1552 587 483 587 484 586 1552 587 482 588 483 586 1553 586 483 587 483 586 1554 586 1553 585 484 587 1553 586 484 587 1553 586 1554 586 1553 586 1554 586 483 586 1553 586 1553 586 1555 585 483 586 482 588 483 585 484 585 1554 586 483 587 484 585 1553 587 1554 584 1554 585 484 586 484 586 483 586 483 586 484 586 482 588 483 584 484 586 1553 585 1555 584 1555 586 1553 586 1554 585 5129 4428 4312 585 1553 586 483 586 1555 584 1553 586 484 583 486 584 1555 585 484 585 483 586 1554 585 483 586 484 585 1554 585 1554 585 484 585 1554 585 484 584 1554 585 1554 584 1554 585 1554 586 483 585 1554 585 1555 584 1553 584 484 586 483 586 483 585 484 586 1554 583 484 586 483 585 1553 585 1553 585 1553 585 484 584 485 585 485 584 484 585 484 585 485 584 484 585 483 586 1554 585 1553 585 1554 584 1553 585 1553 585
# TEMP_17
name: TEMP-
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4459 4311 588 1552 588 482 588 1552 589 1552 588 481 589 481 589 1552 588 482 587 483 587 1553 587 482 588 481 589 1553 588 1552 588 482 587 1554 586 483 587 1553 587 482 588 1552 588 1553 587 1553 588 1552 588 1552 588 1553 587 482 587 1553 588 481 589 482 587 482 587 483 587 482 587 483 588 482 587 483 587 482 587 483 587 482 587 483 586 483 587 1553 587 1553 587 1553 587 1554 586 1553 588 1553 587 1554 587 1553 587 5130 4431 4314 586 1553 588 482 588 1553 586 1554 587 483 587 483 587 1553 587 483 587 483 586 1554 587 483 586 483 587 1553 587 1553 587 482 588 1553 587 482 587 1553 587 483 587 1553 587 1554 586 1554 586 1554 586 1553 587 1554 587 482 588 1553 587 483 586 484 586 483 586 483 587 483 587 483 587 483 586 483 586 483 587 483 586 484 586 483 587 483 586 1554 586 1554 586 1554 586 1554 586 1554 586 1554 586 1555 586 1554 586
# TEMP_30
name: TEMP+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4489 4254 647 1493 645 425 619 1521 619 1521 619 452 617 453 616 1526 613 478 591 479 590 1551 589 481 588 481 589 1552 588 1552 588 482 588 1552 588 482 588 1552 588 482 588 1552 588 1553 587 1553 587 1552 588 1553 588 1552 588 482 588 1553 587 482 588 482 588 482 588 482 588 482 588 1552 588 482 588 1552 588 1552 588 482 588 482 588 482 588 482 588 482 588 1553 587 482 588 482 588 1553 587 1553 587 1553 587 1553 587 5130 4432 4313 587 1553 587 483 587 1553 587 1553 587 483 587 483 587 1553 587 483 587 483 587 1553 587 483 587 483 587 1553 587 1554 586 483 586 1553 587 483 587 1553 587 483 587 1553 587 1553 587 1554 586 1554 586 1554 586 1554 587 483 587 1553 587 483 587 483 587 483 587 483 587 483 587 1554 586 483 587 1554 586 1554 586 483 587 483 587 483 587 483 586 484 586 1554 586 484 586 483 587 1554 586 1554 586 1554 586 1554 586
# POWER_OFF
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 479 397 30131 50087 3427 1674 447 1253 447 483 446 483 446 483 420 483 447 483 447 483 447 483 447 483 420 510 419 483 447 483 446 1254 446 483 420 510 419 484 446 483 447 484 445 483 446 484 419 1255 445 1254 446 484 445 484 445 484 419 484 446 484 446 484 445 484 446 484 445 1255 418 484 446 1255 445 1255 418 1255 445 1255 445 1254 446 1255 419 484 446 1255 445 1255 418 511 418 485 445 484 445 484 446 484 445 485 418 511 418 484 446 1255 445 1255 418 1255 445 1255 444 1256 444 1256 417 1256 445 1255 443 487 418 511 419 485 444 1255 445 485 445 485 420 509 418 485 445 1255 445 485 444 485 445 1256 417 512 418 485 444 485 445 1256 417 1256 444 485 444 485 420 509 444 486 418 511 418 485 445 485 444 1256 444 486 418 512 417 485 420 509 445 485 445 485 445 485 417 1256 444 486 444 485 445 1256 417 1256 443 486 444 485 444 486 444 485 444 485 418 485 444 485 444 485 444 486 443 486 417 1257 420 509 420 510 444 485 444 486 444 485 418 485 445 485 443 487 444 1256 444 1256 417 485 442 487 420 510 444 485 444 486 417 1256 420 1280 443 1257 417 512 393 510 444 486 442 487 443 486 419 510 417 513 419 484 419 510 444 486 419 510 419 510 393 537 415 488 420 510 418 510 419 510 419 510 392 537 392 511 445 484 419 511 418 511 418 511 392 538 391 511 419 511 419 511 418 511 418 511 391 511 419 512 418 511 418 511 419 511 418 512 391 512 418 512 417 512 417 512 418 512 417 512 391 512 418 512 417 512 417 512 417 512 391 539 390 513 416 513 417 512 417 513 417 537 366 564 365 514 416 537 392 537 392 538 392 538 365 564 365 538 392 538 392 538 391 538 391 538 365 564 365 538 392 538 391 1309 391 1308 365 538 391 538 392 538 391 538 392 538 365 565 364 538 392 538 391 539 391 1309 364 1309 391 538 391 539 391 538 391 538 391 539 364 538 392 539 390 539 391 539 390 539 364 565 364 539 391 539 390 1309 391 539 390 1309 364 539 391 539 390 539 391 539 498
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 479 396 30132 50085 3427 1674 446 1254 446 483 446 483 446 483 420 483 446 483 447 483 446 483 446 483 420 510 419 483 446 483 446 1254 446 483 420 510 419 483 446 484 446 483 446 484 446 483 420 1254 446 1254 446 484 445 484 446 483 420 484 446 484 445 484 446 484 445 484 419 1255 445 484 445 1254 446 1255 418 1255 446 1255 445 1255 445 1254 419 484 446 1255 445 1255 418 511 419 484 446 484 445 484 445 484 445 485 418 511 418 484 446 1255 445 1255 418 1255 445 1255 445 1255 446 1255 418 1256 445 1255 445 484 419 511 418 485 444 1256 444 485 445 484 445 485 417 485 445 1256 444 485 444 485 445 1256 417 485 445 485 444 486 443 1256 417 1283 417 1256 444 485 420 509 445 485 417 485 445 485 443 486 443 1257 443 487 417 485 420 510 444 485 443 487 419 510 416 513 417 1256 442 487 420 510 419 1281 392 1281 419 510 443 486 420 510 443 487 416 513 417 486 443 486 443 486 444 486 419 510 417 1257 419 511 443 487 418 511 418 511 392 511 419 511 419 511 418 511 443 1258 391 1282 443 487 418 511 418 511 418 512 391 538 418 1256 417 1282 418 1282 391 512 417 512 417 512 417 512 417 513 417 512 391 513 416 536 393 536 393 536 393 537 366 563 367 537 393 536 393 536 393 537 393 537 366 564 366 537 393 537 393 1308 392 537 366 563 366 537 393 537 393 537 392 537 393 537 366 564 366 537 393 537 392 537 393 537 392 537 366 564 365 537 393 537 392 537 392 537 392 537 366 564 366 537 392 537 392 537 393 537 392 537 366 564 365 538 392 538 392 538 391 538 392 538 365 538 392 537 392 538 391 538 391 538 391 538 365 565 364 538 392 538 391 538 392 538 391 538 365 538 391 538 392 538 391 538 391 1309 364 1310 390 539 391 539 390 539 390 539 364 566 363 539 391 539 390 539 390 539 390 1310 363 1310 391 539 390 539 390 540 363 567 362 540 390 539 390 540 390 541 388 564 338 568 362 565 364 565 364 565 365 1335 338 1336 364 565 364 565 364 565 364 566 364 1309 391
#
name: TEMP+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 531 372 30125 50084 3425 1651 471 1229 471 458 471 458 445 485 445 458 472 458 472 458 471 458 471 458 445 485 444 459 471 458 472 1229 471 458 445 485 444 459 470 459 471 459 471 459 470 459 444 1230 470 1230 470 459 471 459 470 459 444 459 470 459 471 459 470 459 470 460 470 1204 469 459 470 1230 470 1231 442 1231 469 1231 469 1231 469 1231 443 460 469 1231 469 1231 442 487 443 461 468 461 468 461 468 461 469 462 441 489 441 461 468 1255 445 1255 418 1282 418 1282 418 1256 444 1256 418 1256 444 1256 444 485 445 485 418 485 445 1256 444 485 444 485 444 485 418 485 444 1256 444 485 444 485 444 1256 417 485 445 485 444 485 444 485 444 485 418 512 417 1256 444 485 444 485 445 485 418 512 417 485 444 1256 444 486 443 486 416 513 417 486 444 486 443 486 443 486 444 486 417 1257 443 486 444 1257 443 1257 416 486 444 486 443 486 443 487 442 487 416 513 416 487 418 511 443 487 442 487 418 1282 440 462 442 487 442 488 442 487 443 487 416 514 415 487 418 512 442 1258 442 1258 414 489 418 512 417 512 417 512 440 490 440 1260 413 1260 417 1283 441 488 391 539 390 512 441 488 417 512 417 513 416 512 391 539 390 513 438 491 417 513 416 513 416 513 389 540 390 514 415 513 417 513 416 513 416 514 388 541 388 1285 415 538 391 514 415 538 365 541 389 538 391 538 391 538 391 538 391 539 364 565 364 538 392 538 391 538 391 539 390 539 364 539 390 538 391 539 390 539 390 539 391 539 363 539 390 539 390 539 390 539 390 539 390 539 363 540 390 539 390 539 390 539 391 539 364 566 363 540 390 540 390 540 390 539 390 540 362 566 363 540 390 540 389 540 389 540 390 540 362 567 362 540 390 540 389 1311 389 1311 362 566 363 541 389 566 363 566 363 566 363 566 337 566 363 566 363 566 363 1337 336 1363 337 566 363 566 363 566 363 566 363 566 363 540 363 567 362 567 362 567 362 567 336 594 335 567 363 1337 363 1338 362 568 334 594 335 568 362 568 362 568 361 1364 496
#
name: TEMP-
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 479 398 30129 50086 3427 1675 446 1254 446 483 446 483 420 510 420 483 446 483 447 483 446 483 446 483 420 510 419 483 447 483 446 1254 446 484 419 510 420 484 446 483 446 484 446 484 445 484 419 1254 446 1254 446 484 445 484 445 484 419 484 446 484 446 484 445 484 446 484 419 1281 419 484 446 1255 445 1254 419 1254 446 1255 445 1255 445 1255 418 484 446 1255 445 1255 445 484 419 485 445 484 445 484 445 484 445 484 418 511 419 484 445 1255 445 1255 418 1282 418 1255 445 1255 445 1255 418 1282 418 1256 444 485 444 485 418 485 444 1256 443 486 444 485 445 485 418 485 444 1256 444 485 444 485 420 1281 418 485 443 486 444 485 420 1280 444 485 418 485 420 1280 444 486 443 487 417 512 416 487 420 510 444 1256 444 485 417 513 416 487 443 486 420 510 419 510 420 510 417 1257 443 486 419 510 419 1281 417 1257 419 510 420 510 420 509 419 511 418 511 392 511 419 510 443 486 419 511 418 510 393 1308 392 511 419 510 419 510 419 511 418 511 391 511 419 511 418 511 418 1281 419 1281 416 487 418 511 418 511 418 511 419 511 392 1281 419 1282 418 1282 392 537 392 511 418 511 419 511 419 511 419 511 392 538 392 512 418 511 419 511 418 512 418 512 391 538 391 512 418 512 417 512 418 512 417 512 391 539 390 512 417 1283 417 512 417 512 391 539 390 513 416 513 417 513 416 513 416 537 366 540 390 537 393 537 392 537 392 537 392 537 366 564 365 537 393 537 392 537 392 537 392 537 366 564 365 538 392 537 392 537 392 538 391 537 366 538 392 538 391 538 392 538 392 538 391 538 365 538 392 538 392 538 391 538 391 538 391 538 365 538 392 538 391 538 392 538 391 538 364 565 364 538 391 538 392 538 391 1309 364 1336 364 538 392 538 391 538 391 538 391 538 364 539 391 538 391 539 390 539 391 1309 364 1309 391 538 391 539 391 539 390 539 363 566 363 539 391 539 390 539 390 539 390 539 363 566 364 539 391 539 391 539 390 1310 363 566 364 539 391 539 390 540 389 1310 497
#
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 454 414 452 413 453 413 453 413 453 412 454 25103 3488 1708 454 1278 454 413 453 413 453 413 453 1278 454 413 453 413 453 412 453 413 453 1278 479 388 478 1254 478 1255 477 389 476 1257 475 1283 449 1283 449 1284 448 1284 448 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 418 448 417 449 418 448 417 449 418 448 418 448 1284 448 418 448 1284 448 418 448 418 448 418 448 1284 448 1284 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 447 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 1284 448 1285 447 418 448 418 448 1285 447 1285 447 1285 447 35478 3510 1713 449 1284 448 418 448 418 448 417 449 1284 448 418 448 418 448 418 448 418 448 1284 448 418 448 1284 448 1284 448 417 449 1284 448 1284 448 1284 448 1284 448 1284 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 447 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 1285 447 418 448 418 447 418 448 418 448 418 448 418 448 418 448 418 448 418 447 418 448 418 448 419 447 419 447 1285 447 418 448 418 448 418 448 418 448 418 448 1285 447 419 447 418 448 1285 447 1285 447 418 448 35479 3509 1713 449 1284 448 417 449 417 449 417 449 1284 448 418 448 418 448 418 448 418 448 1284 448 418 448 1284 448 1284 448 418 448 1284 448 1284 448 1284 448 1284 448 1284 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 447 418 448 418 448 1285 447 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 418 448 1285 447 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 419 447 418 448 418 448 1285 447 419 447 1285 447 418 448 418 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 1285 447 1286 446 419 447 419 447 419 447 419 447 419 447 419 447 419 447 420 446 419 446 420 446 1286 446 1286 446 420 446 420 446 419 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 1287 445 420 446 420 446 420 446 420 446 421 445 1287 445 1287 445 421 445 421 445 421 445 421 445 421 445 421 445 421 445 1288 444 421 445 421 445 421 445 422 444 421 445 422 444 421 445 422 444 422 444 1288 444 1288 444 422 444 422 444 422 444 422 444 1289 443
#
name: TEMP+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 453 414 452 413 453 412 454 414 452 413 453 25102 3490 1707 455 1278 483 384 482 383 482 383 482 1249 483 384 481 384 481 385 480 385 480 1251 481 387 478 1252 480 1253 478 414 451 1281 450 1282 449 1283 448 1283 449 1284 448 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 418 448 417 449 417 449 417 449 417 449 417 449 1284 448 417 449 1284 448 417 449 417 449 417 449 1284 448 1284 448 417 449 417 449 417 449 418 448 1284 448 418 448 417 449 418 448 418 448 417 449 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 1284 448 1284 448 418 448 418 448 1284 448 1284 448 1284 448 35479 3509 1713 449 1284 448 418 448 417 449 418 448 1284 448 417 449 418 448 417 449 418 448 1284 448 418 448 1284 448 1284 448 418 448 1284 448 1284 448 1284 448 1284 448 1284 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 447 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 447 418 448 1285 447 418 448 418 448 1285 447 1284 448 418 448 35478 3510 1713 449 1284 448 417 449 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 1284 448 418 448 1284 448 1284 448 417 449 1284 448 1284 448 1284 448 1284 448 1284 448 418 448 417 449 1284 448 418 448 418 448 418 448 418 448 418 448 417 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 447 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 447 418 448 1284 448 1285 447 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 419 447 418 447 419 447 418 448 418 448 418 448 418 448 1285 447 1285 447 419 447 1285 447 419 447 418 448 419 447 419 447 419 447 418 448 419 447 419 447 419 447 419 447 419 447 419 446 419 447 419 447 419 447 419 447 419 447 1285 447 1286 446 419 447 419 447 419 447 419 447 419 447 420 446 419 447 419 447 419 447 419 447 1286 446 1286 446 419 447 1286 446 419 447 420 446 419 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 445 1286 446 420 446 420 446 420 446 420 446 420 446 1287 445 1287 445 420 446 420 446 420 446 421 445 420 446 421 445 421 445 1287 445 421 445 420 446 421 445 421 445 421 445 421 445 421 445 421 445 1287 445 421 445 421 445 1287 445 1287 445 421 445 421 445 1287 445
#
name: TEMP-
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 454 414 451 413 453 413 453 413 453 413 453 25102 3489 1708 454 1277 455 413 452 413 453 413 453 1278 454 412 454 412 454 412 454 412 453 1278 454 413 478 1253 479 1254 477 389 476 1257 475 1283 448 1284 448 1284 448 1284 448 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 418 448 418 448 418 448 418 448 418 448 417 448 1284 448 417 449 1284 448 418 448 418 448 418 448 1284 448 1284 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 419 447 1285 447 1285 447 1285 447 419 447 419 447 1285 447 1285 447 1285 447 35505 3483 1713 449 1284 448 417 449 417 449 418 448 1284 448 417 449 417 449 417 449 418 448 1284 448 418 448 1284 448 1284 448 418 448 1284 448 1284 448 1284 448 1284 448 1284 448 417 449 418 448 1284 448 417 449 418 448 418 448 418 448 418 448 418 448 418 448 418 447 418 448 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 1285 447 418 447 418 448 1284 448 1285 447 418 448 35481 3508 1713 448 1284 448 417 449 418 448 418 448 1284 448 418 448 418 448 417 449 418 448 1284 448 418 448 1284 448 1284 448 418 448 1284 448 1284 448 1284 448 1284 448 1284 448 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 418 448 419 447 418 448 418 448 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 446 419 447 419 447 419 447 1286 446 419 447 419 447 419 446 419 447 419 447 419 447 1286 446 419 447 419 447 1286 446 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 446 419 447 419 447 419 447 419 447 419 447 1286 446 1286 446 420 446 1286 446 420 446 420 446 419 446 420 446 420 446 420 446 420 446 420 446 420 446 420 445 420 446 421 445 420 446 421 445 421 445 420 446 421 445 1287 445 1287 445 421 445 421 445 422 444 446 420 446 420 423 443 446 420 446 420 446 420 446 420 1312 420 1312 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 419 446 420 446 420 1313 419 446 420 446 420 447 419 447 419 446 420 1313 419 1313 419 447 419 447 419 446 420 447 419 446 420 447 419 447 419 1313 419 447 419 446 420 447 419 447 419 447 419 447 419 447 419 447 419 1313 419 447 419 1313 419 447 419 1313 419 447 419 447 419 1313 419
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 484 410 456 385 481 385 481 384 482 385 481 25074 3521 1676 483 1249 483 410 484 382 485 381 485 1247 485 381 484 381 485 381 484 382 483 1248 484 383 482 1249 482 1250 481 385 480 1253 478 1254 478 1255 477 1256 476 1256 476 389 477 389 477 1256 476 390 476 390 476 390 476 389 477 390 476 390 476 390 476 390 476 390 476 389 476 1256 476 390 476 1256 476 390 476 390 476 390 476 1256 476 1256 476 390 476 390 476 390 476 390 476 1257 475 390 476 390 476 390 476 390 476 390 476 390 476 390 476 390 475 391 475 391 475 390 476 1257 475 1257 475 1257 475 391 475 391 475 1257 475 1258 474 1258 474 35476 3516 1682 476 1256 476 390 476 389 477 389 477 1256 476 389 477 389 477 389 477 389 477 1256 476 389 477 1256 476 1256 476 390 476 1256 476 1256 476 1256 476 1256 476 1256 476 390 476 390 476 1256 476 390 476 390 476 390 476 390 476 390 476 390 476 390 476 390 476 390 476 390 476 390 476 1256 476 390 476 390 476 390 476 390 476 1257 475 390 476 390 476 390 475 391 475 390 476 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 1257 475 391 475 391 475 391 475 391 475 391 475 1258 474 392 474 392 474 1258 474 1259 473 416 450 35476 3516 1682 477 1257 475 390 476 390 476 390 476 1256 476 390 476 390 476 390 476 390 476 1257 475 390 476 1257 475 1257 475 390 476 1257 475 1257 475 1257 475 1257 475 1258 474 391 475 391 475 1258 474 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 391 475 392 474 391 475 391 475 391 475 392 474 392 474 391 475 392 474 1282 450 416 450 1283 449 416 450 416 450 416 450 416 450 393 473 416 449 416 450 416 450 1283 449 1283 449 417 449 417 449 416 449 417 449 416 450 416 450 417 449 416 450 416 450 417 449 416 450 417 449 417 449 1283 449 417 449 1283 449 417 449 417 449 417 449 417 449 417 449 417 449 417 448 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 1284 448 1283 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 1284 448 1284 448 417 449 418 448 417 449 418 448 418 448 418 448 418 448 418 448 418 448 418 448 417 449 418 447 418 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 1284 448 1285 447 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1285 447 418 448 418 448 418 448 418 448 418 448 419 447 418 448 418 448 1285 447 418 447 419 447 419 447 418 448 419 447 1285 447 419 447
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 536 335 510 363 509 363 509 335 565 311 505 25378 3540 1697 455 1317 427 418 455 417 455 417 455 1289 456 390 455 417 455 417 455 417 428 1317 454 392 480 1265 480 1265 480 393 479 1268 476 1269 476 1269 476 1269 476 1269 476 397 475 369 476 1269 476 396 476 397 476 396 449 397 476 396 476 397 448 396 476 397 475 397 476 370 475 1270 475 397 475 1270 475 397 475 397 448 397 475 1271 474 1271 474 398 474 398 474 371 474 398 475 398 474 398 447 398 475 398 474 398 447 399 474 400 472 423 449 371 474 399 473 399 473 423 422 1324 421 1324 421 1324 421 423 450 1296 449 423 449 1297 448 1297 448 34986 3534 1704 476 1269 476 396 476 369 476 396 476 1270 475 396 476 369 476 397 476 396 476 1270 475 397 448 1297 448 1297 449 397 476 1270 475 1270 475 1270 475 1270 475 1270 476 397 475 397 475 1270 475 370 475 397 476 397 475 397 448 398 474 397 475 397 476 370 475 398 474 397 475 398 447 1298 447 398 475 398 474 398 447 398 474 1272 473 399 473 398 474 372 473 399 473 399 474 423 422 399 474 423 449 423 449 396 449 423 450 423 449 1296 449 1296 449 423 422 424 449 423 449 423 422 423 449 1297 448 1297 448 424 448 1297 448 1297 448 423 450 34986 3535 1703 476 1269 476 369 476 396 476 396 477 1269 476 396 449 396 477 396 476 396 476 1270 475 369 476 1270 475 1270 475 397 476 1270 475 1270 475 1270 475 1270 475 1270 475 397 476 370 475 1270 475 397 476 397 475 397 448 397 475 397 476 397 475 370 475 398 474 398 475 398 447 398 474 398 474 398 474 371 474 398 474 399 473 371 474 422 451 1272 473 423 449 422 423 1323 422 423 450 1296 449 423 449 423 449 395 450 423 449 423 449 423 422 423 449 423 449 1296 450 1296 449 423 449 396 449 423 449 423 449 423 422 423 449 424 448 424 421 1324 421 1324 421 1324 421 1324 421 424 449 1297 448 424 448 1297 448 1297 448 1297 448 1297 448 1297 448 424 448 397 448 424 448 424 448 424 421 424 449 424 448 424 448 397 448 424 448 424 448 425 420 425 448 1298 447 1298 447 425 447 425 420 425 447 425 447 425 448 397 448 425 447 425 448 425 420 425 448 1298 447 1298 447 425 448 425 447 398 447 425 448 425 447 425 420 425 447 425 448 425 420 425 447 425 447 425 447 398 447 426 446 426 446 426 419 426 446 1299 446 426 446 426 447 398 447 426 446 426 446 1299 446 1299 446 426 419 426 446 426 446 426 447 399 446 427 446 426 446 1300 445 400 445 427 445 427 446 427 418 427 446 427 445 428 444 400 445 453 419 453 419 453 392 453 419 453 420 1326 419 1326 419 453 419
# SWING_WIDE
name: SWING
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 484 362 510 363 482 390 454 391 457 416 456 25430 3517 1720 457 1287 458 416 484 387 486 387 458 1286 458 387 485 387 457 414 431 414 458 1286 457 415 459 1286 457 1288 457 415 458 1288 456 1290 455 1290 480 1267 478 1292 453 392 453 420 453 1293 451 421 452 420 425 420 452 420 452 420 452 392 453 420 453 420 452 420 425 420 453 1293 452 421 452 1293 452 421 452 393 452 420 452 1293 452 1294 451 421 452 393 452 420 452 420 452 420 425 420 453 420 452 420 452 393 452 420 452 420 452 420 425 420 452 420 453 420 452 393 452 1293 451 1294 452 1294 451 421 451 1294 451 421 452 1294 451 1294 451 34985 3537 1726 452 1294 451 393 452 420 453 420 452 1293 452 421 424 420 453 420 452 420 452 1293 452 393 453 1293 452 1294 451 421 452 1293 452 1294 451 1294 451 1294 451 1294 451 421 452 421 424 1321 424 421 452 421 452 420 425 421 452 420 452 421 451 393 452 421 452 420 452 421 424 421 452 1294 451 421 452 421 451 394 451 421 451 1294 451 421 452 421 424 421 452 421 451 421 424 421 451 421 451 421 451 394 451 421 451 421 451 421 424 1321 424 1322 423 422 451 421 452 421 451 394 451 421 451 1294 451 1295 450 422 451 1294 451 1295 450 422 423 34985 3536 1726 452 1293 452 420 452 420 453 420 425 1320 425 421 452 420 452 420 452 393 452 1293 451 421 452 1293 451 1294 451 421 452 1293 452 1294 451 1294 451 1294 451 1294 451 421 424 421 452 1293 452 421 452 420 452 393 452 420 452 420 452 420 425 420 452 420 453 420 425 421 452 420 452 420 452 393 452 421 452 420 452 420 425 421 452 420 452 1294 451 421 452 394 451 1294 450 421 452 421 452 421 424 421 451 421 452 421 424 1322 423 421 452 421 451 1294 451 421 452 394 451 421 452 421 451 421 424 421 452 421 451 421 451 394 451 421 451 421 451 421 424 421 452 421 451 1294 451 1295 450 422 423 422 452 1294 450 1295 451 1295 450 1295 450 422 450 422 451 394 451 421 452 421 452 421 424 422 451 421 451 421 451 394 451 421 451 421 452 421 424 1322 423 1323 422 422 451 422 451 421 451 394 451 421 451 422 450 394 451 421 451 422 450 422 423 1322 422 1323 422 423 450 1295 450 423 450 422 450 395 450 422 450 422 450 422 423 422 451 422 450 422 450 395 450 422 451 422 450 395 450 422 450 422 451 1295 449 423 422 422 451 422 450 422 450 395 450 1295 449 1295 450 423 450 422 451 422 423 422 451 422 450 422 450 395 450 1295 449 423 450 422 451 395 450 422 450 422 450 422 423 422 451 422 450 422 451 1295 449 1296 449 396 449 423 450 1296 448 423 450 423 422
#
name: TEMP+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 511 362 483 363 509 362 483 391 454 391 457 25457 3518 1719 457 1287 458 389 456 415 457 415 457 1287 485 389 456 388 457 415 457 415 457 1286 459 387 458 1286 459 1287 458 415 483 1262 483 1263 482 1264 481 1265 480 1291 454 419 453 420 425 1320 425 420 453 420 452 420 453 392 453 420 452 420 452 393 452 420 453 420 452 420 425 1320 425 420 453 1293 452 420 453 420 452 393 452 1293 452 1293 452 420 453 420 452 420 425 420 453 420 453 420 452 393 452 420 452 420 452 420 425 420 453 420 452 420 425 420 452 420 452 420 452 1293 452 1293 452 1293 452 393 452 1293 452 420 453 1293 452 1293 452 34983 3540 1724 452 1293 452 420 452 420 425 420 452 1293 452 420 453 420 453 392 453 420 452 1293 452 420 452 1293 452 1293 452 393 452 1293 452 1293 452 1293 452 1293 452 1294 451 420 452 421 452 1293 452 421 424 420 452 420 452 420 452 393 452 420 452 420 452 420 425 421 452 420 453 420 452 1293 452 394 451 421 451 421 451 393 452 1294 451 421 451 421 451 421 424 421 451 421 451 421 452 393 452 421 452 421 451 421 424 421 452 421 451 421 451 1294 451 394 451 421 452 421 451 394 451 421 451 1294 451 421 452 421 424 1322 423 1322 423 422 451 34985 3539 1724 452 1293 452 420 452 420 453 393 452 1293 452 421 452 420 452 420 425 420 452 1293 452 421 452 1293 452 1294 451 421 424 1321 424 1322 424 1321 424 1321 424 1321 424 421 451 421 452 1294 451 421 452 393 452 421 451 421 452 420 425 421 452 420 452 421 451 393 452 420 452 421 452 421 424 421 451 421 452 421 451 393 452 421 451 421 451 1294 451 394 452 421 451 1294 451 421 452 421 424 421 452 421 451 421 451 1294 451 1295 451 394 451 422 451 1294 450 422 451 421 424 421 451 421 451 421 452 394 451 422 451 422 450 394 451 421 451 421 451 421 424 422 451 422 450 1295 450 1295 450 422 450 395 450 422 450 422 450 422 423 422 450 422 450 422 451 394 451 422 450 422 450 395 450 422 450 422 450 422 423 422 451 422 450 422 450 395 450 1295 449 1296 449 423 449 423 450 423 422 423 450 422 450 423 449 396 449 423 450 423 449 423 422 1324 420 1324 422 424 449 1297 448 424 449 423 422 423 450 424 448 424 448 396 449 423 449 423 449 424 421 424 449 424 449 423 449 396 449 423 449 424 449 1297 447 425 420 425 448 424 449 424 421 425 448 1297 447 1298 447 425 447 425 448 397 448 425 447 424 448 425 420 426 447 1322 423 450 423 449 423 422 423 450 422 450 423 450 395 450 422 450 422 1323 421 451 395 450 423 1323 421 1324 421 451 421 451 422 423 422
#
name: TEMP-
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 538 335 510 362 510 362 510 338 507 338 534 25377 3593 1642 510 1235 510 363 537 335 509 363 509 1209 537 335 510 361 511 362 510 362 483 1262 483 363 508 1236 508 1237 507 366 478 1268 477 1269 476 1269 476 1270 475 1270 475 397 475 370 475 1270 475 397 475 397 475 397 448 397 476 397 475 397 476 369 476 397 475 397 475 370 475 1270 475 397 475 1270 475 397 475 397 448 397 475 1271 474 1270 475 397 475 397 475 370 475 398 474 398 474 397 448 398 475 398 474 397 475 370 475 398 474 398 475 370 475 398 475 398 474 398 447 1299 447 1299 446 1299 446 398 474 1271 474 399 474 1271 474 1272 473 34986 3534 1703 476 1269 476 396 476 369 476 396 476 1269 476 396 476 397 448 397 476 396 477 1269 476 397 448 1297 448 1297 448 396 476 1270 475 1270 475 1270 475 1270 475 1270 475 397 475 397 475 1270 475 370 475 397 475 397 475 397 448 397 475 397 475 397 475 370 475 397 475 397 475 397 448 1298 447 398 475 398 475 398 447 398 474 1271 474 398 474 398 474 395 450 422 450 422 450 422 423 422 450 422 450 423 450 395 450 422 451 422 450 423 422 1323 422 423 449 423 449 422 450 395 450 423 449 1296 450 422 450 395 450 1296 449 1296 449 423 449 34986 3535 1703 476 1269 476 396 476 396 449 397 475 1270 475 396 477 396 476 369 476 397 476 1269 476 397 475 1270 476 1270 475 397 448 1298 447 1298 447 1297 448 1298 447 1298 448 398 474 398 474 1295 450 398 447 398 474 422 450 422 451 395 450 422 450 422 450 422 423 422 451 422 450 422 450 395 450 422 450 422 451 422 423 422 450 422 451 422 423 1323 423 422 450 422 451 1295 450 422 450 395 450 422 450 422 451 422 423 423 450 1295 450 422 450 422 451 1295 450 395 450 422 450 423 449 422 423 423 449 423 450 422 423 423 449 423 450 422 450 396 449 423 449 423 449 423 422 1324 421 1323 422 423 450 423 449 423 449 396 449 423 449 423 449 423 422 423 450 423 450 423 449 396 449 423 449 423 450 396 449 424 448 424 449 423 422 424 449 424 448 1297 448 1297 448 424 448 397 448 424 449 424 448 424 421 424 448 424 449 424 449 396 449 424 448 1297 448 1297 448 424 448 1297 448 397 448 424 448 424 449 424 421 425 448 424 448 424 448 398 447 424 448 424 448 425 420 425 447 425 447 425 448 397 448 1298 447 425 447 425 447 398 448 425 447 425 447 1298 447 1298 447 425 420 425 447 425 448 425 447 398 447 425 447 426 446 1299 446 426 419 426 447 425 447 426 446 399 446 426 446 426 447 426 419 1326 419 1327 418 1327 419 426 446 1300 445 426 446 426 419 427 446
# SWING_WIDE
name: SWING
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 454 413 453 412 454 412 454 412 454 413 453 25102 3490 1707 483 1249 484 383 483 383 482 383 509 1222 483 383 482 384 481 385 480 385 480 1250 482 386 479 1252 479 1254 477 414 451 1281 450 1282 449 1283 449 1283 449 1284 448 417 448 417 449 1284 448 417 449 417 449 418 448 417 449 417 449 417 449 417 449 417 449 417 449 417 449 1284 448 418 448 1284 448 418 448 418 448 418 448 1284 448 1284 448 418 448 418 448 417 448 418 448 1284 448 417 449 417 448 418 448 417 449 417 449 417 449 418 448 417 449 418 448 418 448 418 448 1284 448 1284 448 1284 449 417 449 418 448 1284 448 1284 448 1284 448 35505 3485 1712 449 1283 449 417 449 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 1284 448 417 449 1284 448 1284 448 417 449 1284 448 1284 448 1284 448 1283 449 1284 448 417 449 417 449 1284 448 417 449 417 449 417 449 417 449 417 449 417 449 417 449 417 449 418 448 418 448 417 449 1284 448 417 449 417 449 417 449 417 449 1284 448 417 448 418 448 418 448 417 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 418 448 418 448 418 448 1284 448 418 448 418 448 1285 447 1285 447 418 448 35504 3486 1712 449 1283 449 417 449 417 448 417 449 1284 448 417 449 417 449 417 449 417 448 1284 448 417 449 1284 448 1284 448 417 449 1283 449 1284 448 1284 448 1284 448 1284 449 417 449 417 449 1284 448 417 449 417 449 418 448 417 449 417 449 417 449 418 448 417 449 417 449 418 448 418 448 418 448 417 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1284 448 1284 448 1284 448 418 448 418 448 418 448 1284 448 418 448 418 448 1284 448 1284 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 418 448 1285 447 1285 447 418 448 1285 447 1285 447 1285 447 1285 447 1285 447 419 447 418 448 419 447 418 448 418 448 418 448 419 447 419 447 418 448 418 448 419 447 419 447 419 447 1285 447 1285 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 1286 446 1285 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 419 447 1286 446 420 446 420 446 420 446 420 446 419 447 1286 446 1286 446 419 447 420 446 420 446 420 446 420 446 420 446 420 446 1286 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 420 446 1286 446 420 446 420 446 420 446 1287 445 1287 445 1287 445

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 21st Feb, 2023 # Last Updated 07th Mar, 2023
# Last Checked 21st Feb, 2023 # Last Checked 07th Mar, 2023
# #
name: POWER name: POWER
type: parsed type: parsed
@@ -2092,3 +2092,9 @@ type: parsed
protocol: NECext protocol: NECext
address: 30 FC 00 00 address: 30 FC 00 00
command: 17 E8 00 00 command: 17 E8 00 00
#
name: POWER
type: parsed
protocol: NEC
address: 00 00 00 00
command: 04 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 15th Feb, 2023 # Last Updated 15th Feb, 2023
# Last Checked 21st Feb, 2023 # Last Checked 07th Mar, 2023
# #
name: POWER name: POWER
type: raw type: raw

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 21st Feb, 2023 # Last Updated 07th Mar, 2023
# Last Checked 21st Feb, 2023 # Last Checked 07th Mar, 2023
# #
# ON # ON
name: POWER name: POWER
@@ -844,3 +844,33 @@ type: raw
frequency: 38000 frequency: 38000
duty_cycle: 0.330000 duty_cycle: 0.330000
data: 8811 4222 530 1580 531 1579 531 507 531 507 531 507 531 508 531 508 530 1582 528 1583 527 535 503 1608 502 536 501 1609 501 537 501 1610 500 538 500 1611 499 538 500 539 500 538 500 1611 500 539 499 538 500 1611 499 539 499 1611 499 1611 500 1611 499 539 499 1611 500 1611 500 539 499 35437 8784 4252 500 1611 500 1612 500 539 500 539 500 539 500 539 500 539 500 1611 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 539 500 539 499 1612 499 540 499 539 500 1612 499 539 500 1612 499 1613 499 1612 499 539 500 1612 500 1612 500 539 500 data: 8811 4222 530 1580 531 1579 531 507 531 507 531 507 531 508 531 508 530 1582 528 1583 527 535 503 1608 502 536 501 1609 501 537 501 1610 500 538 500 1611 499 538 500 539 500 538 500 1611 500 539 499 538 500 1611 499 539 499 1611 499 1611 500 1611 499 539 499 1611 500 1611 500 539 499 35437 8784 4252 500 1611 500 1612 500 539 500 539 500 539 500 539 500 539 500 1611 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 539 500 539 499 1612 499 540 499 539 500 1612 499 539 500 1612 499 1613 499 1612 499 539 500 1612 500 1612 500 539 500
#
name: VOL+
type: parsed
protocol: NEC
address: 01 00 00 00
command: 06 00 00 00
#
name: VOL-
type: parsed
protocol: NEC
address: 01 00 00 00
command: 09 00 00 00
#
name: MUTE
type: parsed
protocol: NEC
address: 01 00 00 00
command: 1A 00 00 00
#
name: POWER
type: parsed
protocol: NEC
address: 01 00 00 00
command: 00 00 00 00
#
name: MUTE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9035 4437 563 548 563 548 563 522 594 1645 591 1639 592 518 593 548 563 552 563 1640 592 548 563 553 562 1668 564 524 592 1642 594 1674 562 1673 563 1639 593 548 563 552 564 1669 562 548 563 520 615 529 586 1645 587 529 587 1650 586 1646 586 529 586 1650 586 1649 587 1646 586 524 587 524 587 524 587 524 587 525 643 467 644 440 671 467 644 472 643 1592 644 1593 643 1593 642 1594 641 1594 587 1649 585 1651 563 1682 562 14430 9008 2205 562

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 15th Feb, 2023 # Last Updated 07th Mar, 2023
# Last Checked 21st Feb, 2023 # Last Checked 07th Mar, 2023
# #
name: POWER name: POWER
type: parsed type: parsed
@@ -1863,3 +1863,39 @@ type: parsed
protocol: RC5 protocol: RC5
address: 00 00 00 00 address: 00 00 00 00
command: 17 00 00 00 command: 17 00 00 00
#
name: POWER
type: parsed
protocol: NEC
address: 80 00 00 00
command: 12 00 00 00
#
name: VOL+
type: parsed
protocol: NEC
address: 80 00 00 00
command: 1A 00 00 00
#
name: VOL-
type: parsed
protocol: NEC
address: 80 00 00 00
command: 1E 00 00 00
#
name: MUTE
type: parsed
protocol: NEC
address: 80 00 00 00
command: 10 00 00 00
#
name: CH+
type: parsed
protocol: SIRC20
address: 10 01 00 00
command: 34 00 00 00
#
name: CH-
type: parsed
protocol: SIRC20
address: 10 01 00 00
command: 33 00 00 00

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,17.0,, Version,+,18.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@@ -156,6 +156,7 @@ Header,+,lib/toolbox/manchester_decoder.h,,
Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/manchester_encoder.h,,
Header,+,lib/toolbox/md5.h,, Header,+,lib/toolbox/md5.h,,
Header,+,lib/toolbox/path.h,, Header,+,lib/toolbox/path.h,,
Header,+,lib/toolbox/pretty_format.h,,
Header,+,lib/toolbox/protocols/protocol_dict.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,,
Header,+,lib/toolbox/random_name.h,, Header,+,lib/toolbox/random_name.h,,
Header,+,lib/toolbox/saved_struct.h,, Header,+,lib/toolbox/saved_struct.h,,
@@ -439,7 +440,6 @@ Function,-,_wctomb_r,int,"_reent*, char*, wchar_t, _mbstate_t*"
Function,-,a64l,long,const char* Function,-,a64l,long,const char*
Function,+,abort,void, Function,+,abort,void,
Function,-,abs,int,int Function,-,abs,int,int
Function,+,acquire_mutex,void*,"ValueMutex*, uint32_t"
Function,-,aligned_alloc,void*,"size_t, size_t" Function,-,aligned_alloc,void*,"size_t, size_t"
Function,+,aligned_free,void,void* Function,+,aligned_free,void,void*
Function,+,aligned_malloc,void*,"size_t, size_t" Function,+,aligned_malloc,void*,"size_t, size_t"
@@ -573,7 +573,6 @@ Function,-,ctermid,char*,char*
Function,-,ctime,char*,const time_t* Function,-,ctime,char*,const time_t*
Function,-,ctime_r,char*,"const time_t*, char*" Function,-,ctime_r,char*,"const time_t*, char*"
Function,-,cuserid,char*,char* Function,-,cuserid,char*,char*
Function,+,delete_mutex,_Bool,ValueMutex*
Function,+,dialog_ex_alloc,DialogEx*, Function,+,dialog_ex_alloc,DialogEx*,
Function,+,dialog_ex_disable_extended_events,void,DialogEx* Function,+,dialog_ex_disable_extended_events,void,DialogEx*
Function,+,dialog_ex_enable_extended_events,void,DialogEx* Function,+,dialog_ex_enable_extended_events,void,DialogEx*
@@ -684,6 +683,7 @@ Function,+,file_browser_worker_set_folder_callback,void,"BrowserWorker*, Browser
Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback" Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback"
Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback" Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback"
Function,+,file_browser_worker_set_long_load_callback,void,"BrowserWorker*, BrowserWorkerLongLoadCallback" Function,+,file_browser_worker_set_long_load_callback,void,"BrowserWorker*, BrowserWorkerLongLoadCallback"
Function,+,file_info_is_dir,_Bool,const FileInfo*
Function,+,file_stream_alloc,Stream*,Storage* Function,+,file_stream_alloc,Stream*,Storage*
Function,+,file_stream_close,_Bool,Stream* Function,+,file_stream_close,_Bool,Stream*
Function,+,file_stream_get_error,FS_Error,Stream* Function,+,file_stream_get_error,FS_Error,Stream*
@@ -707,6 +707,7 @@ Function,-,flipper_application_preload_status_to_string,const char*,FlipperAppli
Function,+,flipper_application_spawn,FuriThread*,"FlipperApplication*, void*" Function,+,flipper_application_spawn,FuriThread*,"FlipperApplication*, void*"
Function,+,flipper_format_buffered_file_alloc,FlipperFormat*,Storage* Function,+,flipper_format_buffered_file_alloc,FlipperFormat*,Storage*
Function,+,flipper_format_buffered_file_close,_Bool,FlipperFormat* Function,+,flipper_format_buffered_file_close,_Bool,FlipperFormat*
Function,+,flipper_format_buffered_file_open_always,_Bool,"FlipperFormat*, const char*"
Function,+,flipper_format_buffered_file_open_existing,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_buffered_file_open_existing,_Bool,"FlipperFormat*, const char*"
Function,+,flipper_format_delete_key,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_delete_key,_Bool,"FlipperFormat*, const char*"
Function,+,flipper_format_file_alloc,FlipperFormat*,Storage* Function,+,flipper_format_file_alloc,FlipperFormat*,Storage*
@@ -1234,6 +1235,7 @@ Function,+,furi_thread_flags_get,uint32_t,
Function,+,furi_thread_flags_set,uint32_t,"FuriThreadId, uint32_t" Function,+,furi_thread_flags_set,uint32_t,"FuriThreadId, uint32_t"
Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t" Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t"
Function,+,furi_thread_free,void,FuriThread* Function,+,furi_thread_free,void,FuriThread*
Function,+,furi_thread_get_appid,const char*,FuriThreadId
Function,+,furi_thread_get_current,FuriThread*, Function,+,furi_thread_get_current,FuriThread*,
Function,+,furi_thread_get_current_id,FuriThreadId, Function,+,furi_thread_get_current_id,FuriThreadId,
Function,+,furi_thread_get_current_priority,FuriThreadPriority, Function,+,furi_thread_get_current_priority,FuriThreadPriority,
@@ -1248,6 +1250,7 @@ Function,+,furi_thread_is_suspended,_Bool,FuriThreadId
Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_join,_Bool,FuriThread*
Function,+,furi_thread_mark_as_service,void,FuriThread* Function,+,furi_thread_mark_as_service,void,FuriThread*
Function,+,furi_thread_resume,void,FuriThreadId Function,+,furi_thread_resume,void,FuriThreadId
Function,+,furi_thread_set_appid,void,"FuriThread*, const char*"
Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback"
Function,+,furi_thread_set_context,void,"FuriThread*, void*" Function,+,furi_thread_set_context,void,"FuriThread*, void*"
Function,+,furi_thread_set_current_priority,void,FuriThreadPriority Function,+,furi_thread_set_current_priority,void,FuriThreadPriority
@@ -1312,7 +1315,6 @@ Function,+,icon_get_data,const uint8_t*,const Icon*
Function,+,icon_get_height,uint8_t,const Icon* Function,+,icon_get_height,uint8_t,const Icon*
Function,+,icon_get_width,uint8_t,const Icon* Function,+,icon_get_width,uint8_t,const Icon*
Function,-,index,char*,"const char*, int" Function,-,index,char*,"const char*, int"
Function,+,init_mutex,_Bool,"ValueMutex*, void*, size_t"
Function,-,initstate,char*,"unsigned, char*, size_t" Function,-,initstate,char*,"unsigned, char*, size_t"
Function,+,input_get_key_name,const char*,InputKey Function,+,input_get_key_name,const char*,InputKey
Function,+,input_get_type_name,const char*,InputType Function,+,input_get_type_name,const char*,InputType
@@ -1491,6 +1493,7 @@ Function,+,power_get_pubsub,FuriPubSub*,Power*
Function,+,power_is_battery_healthy,_Bool,Power* Function,+,power_is_battery_healthy,_Bool,Power*
Function,+,power_off,void,Power* Function,+,power_off,void,Power*
Function,+,power_reboot,void,PowerBootMode Function,+,power_reboot,void,PowerBootMode
Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t"
Function,-,printf,int,"const char*, ..." Function,-,printf,int,"const char*, ..."
Function,+,property_value_out,void,"PropertyValueContext*, const char*, unsigned int, ..." Function,+,property_value_out,void,"PropertyValueContext*, const char*, unsigned int, ..."
Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t" Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t"
@@ -1534,12 +1537,10 @@ Function,+,rand,int,
Function,-,rand_r,int,unsigned* Function,-,rand_r,int,unsigned*
Function,+,random,long, Function,+,random,long,
Function,-,rawmemchr,void*,"const void*, int" Function,-,rawmemchr,void*,"const void*, int"
Function,-,read_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
Function,+,realloc,void*,"void*, size_t" Function,+,realloc,void*,"void*, size_t"
Function,-,reallocarray,void*,"void*, size_t, size_t" Function,-,reallocarray,void*,"void*, size_t, size_t"
Function,-,reallocf,void*,"void*, size_t" Function,-,reallocf,void*,"void*, size_t"
Function,-,realpath,char*,"const char*, char*" Function,-,realpath,char*,"const char*, char*"
Function,+,release_mutex,_Bool,"ValueMutex*, const void*"
Function,-,remove,int,const char* Function,-,remove,int,const char*
Function,-,rename,int,"const char*, const char*" Function,-,rename,int,"const char*, const char*"
Function,-,renameat,int,"int, const char*, int, const char*" Function,-,renameat,int,"int, const char*, int, const char*"
@@ -1617,14 +1618,18 @@ Function,-,srand48,void,long
Function,-,srandom,void,unsigned Function,-,srandom,void,unsigned
Function,+,sscanf,int,"const char*, const char*, ..." Function,+,sscanf,int,"const char*, const char*, ..."
Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_exists,_Bool,"Storage*, const char*"
Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*" Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*"
Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_migrate,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*" Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*"
Function,+,storage_common_remove,FS_Error,"Storage*, const char*" Function,+,storage_common_remove,FS_Error,"Storage*, const char*"
Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_resolve_path_and_ensure_app_directory,void,"Storage*, FuriString*"
Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*" Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*"
Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*" Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*"
Function,+,storage_dir_close,_Bool,File* Function,+,storage_dir_close,_Bool,File*
Function,+,storage_dir_exists,_Bool,"Storage*, const char*"
Function,+,storage_dir_open,_Bool,"File*, const char*" Function,+,storage_dir_open,_Bool,"File*, const char*"
Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t" Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t"
Function,-,storage_dir_rewind,_Bool,File* Function,-,storage_dir_rewind,_Bool,File*
@@ -1995,7 +2000,6 @@ Function,+,widget_alloc,Widget*,
Function,+,widget_free,void,Widget* Function,+,widget_free,void,Widget*
Function,+,widget_get_view,View*,Widget* Function,+,widget_get_view,View*,Widget*
Function,+,widget_reset,void,Widget* Function,+,widget_reset,void,Widget*
Function,-,write_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
Function,-,xPortGetFreeHeapSize,size_t, Function,-,xPortGetFreeHeapSize,size_t,
Function,-,xPortGetMinimumEverFreeHeapSize,size_t, Function,-,xPortGetMinimumEverFreeHeapSize,size_t,
Function,-,xPortStartScheduler,BaseType_t, Function,-,xPortStartScheduler,BaseType_t,
1 entry status name type params
2 Version + 17.0 18.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
156 Header + lib/toolbox/manchester_encoder.h
157 Header + lib/toolbox/md5.h
158 Header + lib/toolbox/path.h
159 Header + lib/toolbox/pretty_format.h
160 Header + lib/toolbox/protocols/protocol_dict.h
161 Header + lib/toolbox/random_name.h
162 Header + lib/toolbox/saved_struct.h
440 Function - a64l long const char*
441 Function + abort void
442 Function - abs int int
Function + acquire_mutex void* ValueMutex*, uint32_t
443 Function - aligned_alloc void* size_t, size_t
444 Function + aligned_free void void*
445 Function + aligned_malloc void* size_t, size_t
573 Function - ctime char* const time_t*
574 Function - ctime_r char* const time_t*, char*
575 Function - cuserid char* char*
Function + delete_mutex _Bool ValueMutex*
576 Function + dialog_ex_alloc DialogEx*
577 Function + dialog_ex_disable_extended_events void DialogEx*
578 Function + dialog_ex_enable_extended_events void DialogEx*
683 Function + file_browser_worker_set_item_callback void BrowserWorker*, BrowserWorkerListItemCallback
684 Function + file_browser_worker_set_list_callback void BrowserWorker*, BrowserWorkerListLoadCallback
685 Function + file_browser_worker_set_long_load_callback void BrowserWorker*, BrowserWorkerLongLoadCallback
686 Function + file_info_is_dir _Bool const FileInfo*
687 Function + file_stream_alloc Stream* Storage*
688 Function + file_stream_close _Bool Stream*
689 Function + file_stream_get_error FS_Error Stream*
707 Function + flipper_application_spawn FuriThread* FlipperApplication*, void*
708 Function + flipper_format_buffered_file_alloc FlipperFormat* Storage*
709 Function + flipper_format_buffered_file_close _Bool FlipperFormat*
710 Function + flipper_format_buffered_file_open_always _Bool FlipperFormat*, const char*
711 Function + flipper_format_buffered_file_open_existing _Bool FlipperFormat*, const char*
712 Function + flipper_format_delete_key _Bool FlipperFormat*, const char*
713 Function + flipper_format_file_alloc FlipperFormat* Storage*
1235 Function + furi_thread_flags_set uint32_t FuriThreadId, uint32_t
1236 Function + furi_thread_flags_wait uint32_t uint32_t, uint32_t, uint32_t
1237 Function + furi_thread_free void FuriThread*
1238 Function + furi_thread_get_appid const char* FuriThreadId
1239 Function + furi_thread_get_current FuriThread*
1240 Function + furi_thread_get_current_id FuriThreadId
1241 Function + furi_thread_get_current_priority FuriThreadPriority
1250 Function + furi_thread_join _Bool FuriThread*
1251 Function + furi_thread_mark_as_service void FuriThread*
1252 Function + furi_thread_resume void FuriThreadId
1253 Function + furi_thread_set_appid void FuriThread*, const char*
1254 Function + furi_thread_set_callback void FuriThread*, FuriThreadCallback
1255 Function + furi_thread_set_context void FuriThread*, void*
1256 Function + furi_thread_set_current_priority void FuriThreadPriority
1315 Function + icon_get_height uint8_t const Icon*
1316 Function + icon_get_width uint8_t const Icon*
1317 Function - index char* const char*, int
Function + init_mutex _Bool ValueMutex*, void*, size_t
1318 Function - initstate char* unsigned, char*, size_t
1319 Function + input_get_key_name const char* InputKey
1320 Function + input_get_type_name const char* InputType
1493 Function + power_is_battery_healthy _Bool Power*
1494 Function + power_off void Power*
1495 Function + power_reboot void PowerBootMode
1496 Function + pretty_format_bytes_hex_canonical void FuriString*, size_t, const char*, const uint8_t*, size_t
1497 Function - printf int const char*, ...
1498 Function + property_value_out void PropertyValueContext*, const char*, unsigned int, ...
1499 Function + protocol_dict_alloc ProtocolDict* const ProtocolBase**, size_t
1537 Function - rand_r int unsigned*
1538 Function + random long
1539 Function - rawmemchr void* const void*, int
Function - read_mutex _Bool ValueMutex*, void*, size_t, uint32_t
1540 Function + realloc void* void*, size_t
1541 Function - reallocarray void* void*, size_t, size_t
1542 Function - reallocf void* void*, size_t
1543 Function - realpath char* const char*, char*
Function + release_mutex _Bool ValueMutex*, const void*
1544 Function - remove int const char*
1545 Function - rename int const char*, const char*
1546 Function - renameat int int, const char*, int, const char*
1618 Function - srandom void unsigned
1619 Function + sscanf int const char*, const char*, ...
1620 Function + storage_common_copy FS_Error Storage*, const char*, const char*
1621 Function + storage_common_exists _Bool Storage*, const char*
1622 Function + storage_common_fs_info FS_Error Storage*, const char*, uint64_t*, uint64_t*
1623 Function + storage_common_merge FS_Error Storage*, const char*, const char*
1624 Function + storage_common_migrate FS_Error Storage*, const char*, const char*
1625 Function + storage_common_mkdir FS_Error Storage*, const char*
1626 Function + storage_common_remove FS_Error Storage*, const char*
1627 Function + storage_common_rename FS_Error Storage*, const char*, const char*
1628 Function + storage_common_resolve_path_and_ensure_app_directory void Storage*, FuriString*
1629 Function + storage_common_stat FS_Error Storage*, const char*, FileInfo*
1630 Function + storage_common_timestamp FS_Error Storage*, const char*, uint32_t*
1631 Function + storage_dir_close _Bool File*
1632 Function + storage_dir_exists _Bool Storage*, const char*
1633 Function + storage_dir_open _Bool File*, const char*
1634 Function + storage_dir_read _Bool File*, FileInfo*, char*, uint16_t
1635 Function - storage_dir_rewind _Bool File*
2000 Function + widget_free void Widget*
2001 Function + widget_get_view View* Widget*
2002 Function + widget_reset void Widget*
Function - write_mutex _Bool ValueMutex*, void*, size_t, uint32_t
2003 Function - xPortGetFreeHeapSize size_t
2004 Function - xPortGetMinimumEverFreeHeapSize size_t
2005 Function - xPortStartScheduler BaseType_t

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,17.0,, Version,+,18.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@@ -504,7 +504,6 @@ Function,-,acosh,double,double
Function,-,acoshf,float,float Function,-,acoshf,float,float
Function,-,acoshl,long double,long double Function,-,acoshl,long double,long double
Function,-,acosl,long double,long double Function,-,acosl,long double,long double
Function,+,acquire_mutex,void*,"ValueMutex*, uint32_t"
Function,-,aligned_alloc,void*,"size_t, size_t" Function,-,aligned_alloc,void*,"size_t, size_t"
Function,+,aligned_free,void,void* Function,+,aligned_free,void,void*
Function,+,aligned_malloc,void*,"size_t, size_t" Function,+,aligned_malloc,void*,"size_t, size_t"
@@ -740,7 +739,6 @@ Function,-,ctermid,char*,char*
Function,-,ctime,char*,const time_t* Function,-,ctime,char*,const time_t*
Function,-,ctime_r,char*,"const time_t*, char*" Function,-,ctime_r,char*,"const time_t*, char*"
Function,-,cuserid,char*,char* Function,-,cuserid,char*,char*
Function,+,delete_mutex,_Bool,ValueMutex*
Function,+,dialog_ex_alloc,DialogEx*, Function,+,dialog_ex_alloc,DialogEx*,
Function,+,dialog_ex_disable_extended_events,void,DialogEx* Function,+,dialog_ex_disable_extended_events,void,DialogEx*
Function,+,dialog_ex_enable_extended_events,void,DialogEx* Function,+,dialog_ex_enable_extended_events,void,DialogEx*
@@ -1406,7 +1404,7 @@ Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle*
Function,+,furi_hal_subghz_check_radio,_Bool, Function,+,furi_hal_subghz_check_radio,_Bool,
Function,+,furi_hal_subghz_disable_ext_power,void, Function,+,furi_hal_subghz_disable_ext_power,void,
Function,-,furi_hal_subghz_dump_state,void, Function,-,furi_hal_subghz_dump_state,void,
Function,+,furi_hal_subghz_enable_ext_power,void, Function,+,furi_hal_subghz_enable_ext_power,_Bool,
Function,+,furi_hal_subghz_flush_rx,void, Function,+,furi_hal_subghz_flush_rx,void,
Function,+,furi_hal_subghz_flush_tx,void, Function,+,furi_hal_subghz_flush_tx,void,
Function,+,furi_hal_subghz_get_extend_settings,void,"_Bool*, _Bool*" Function,+,furi_hal_subghz_get_extend_settings,void,"_Bool*, _Bool*"
@@ -1778,7 +1776,6 @@ Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, Inf
Function,+,infrared_worker_tx_set_signal_sent_callback,void,"InfraredWorker*, InfraredWorkerMessageSentCallback, void*" Function,+,infrared_worker_tx_set_signal_sent_callback,void,"InfraredWorker*, InfraredWorkerMessageSentCallback, void*"
Function,+,infrared_worker_tx_start,void,InfraredWorker* Function,+,infrared_worker_tx_start,void,InfraredWorker*
Function,+,infrared_worker_tx_stop,void,InfraredWorker* Function,+,infrared_worker_tx_stop,void,InfraredWorker*
Function,+,init_mutex,_Bool,"ValueMutex*, void*, size_t"
Function,-,initstate,char*,"unsigned, char*, size_t" Function,-,initstate,char*,"unsigned, char*, size_t"
Function,+,input_get_key_name,const char*,InputKey Function,+,input_get_key_name,const char*,InputKey
Function,+,input_get_type_name,const char*,InputType Function,+,input_get_type_name,const char*,InputType
@@ -1989,7 +1986,7 @@ Function,+,menu_free,void,Menu*
Function,+,menu_get_view,View*,Menu* Function,+,menu_get_view,View*,Menu*
Function,+,menu_reset,void,Menu* Function,+,menu_reset,void,Menu*
Function,+,menu_set_selected_item,void,"Menu*, uint32_t" Function,+,menu_set_selected_item,void,"Menu*, uint32_t"
Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t" Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, MfClassicAuthContext*, uint64_t"
Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t" Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t"
Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t" Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t"
Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey" Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey"
@@ -2310,12 +2307,10 @@ Function,+,rand,int,
Function,-,rand_r,int,unsigned* Function,-,rand_r,int,unsigned*
Function,+,random,long, Function,+,random,long,
Function,-,rawmemchr,void*,"const void*, int" Function,-,rawmemchr,void*,"const void*, int"
Function,-,read_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
Function,+,realloc,void*,"void*, size_t" Function,+,realloc,void*,"void*, size_t"
Function,-,reallocarray,void*,"void*, size_t, size_t" Function,-,reallocarray,void*,"void*, size_t, size_t"
Function,-,reallocf,void*,"void*, size_t" Function,-,reallocf,void*,"void*, size_t"
Function,-,realpath,char*,"const char*, char*" Function,-,realpath,char*,"const char*, char*"
Function,+,release_mutex,_Bool,"ValueMutex*, const void*"
Function,-,remainder,double,"double, double" Function,-,remainder,double,"double, double"
Function,-,remainderf,float,"float, float" Function,-,remainderf,float,"float, float"
Function,-,remainderl,long double,"long double, long double" Function,-,remainderl,long double,"long double, long double"
@@ -4714,7 +4709,6 @@ Function,+,widget_alloc,Widget*,
Function,+,widget_free,void,Widget* Function,+,widget_free,void,Widget*
Function,+,widget_get_view,View*,Widget* Function,+,widget_get_view,View*,Widget*
Function,+,widget_reset,void,Widget* Function,+,widget_reset,void,Widget*
Function,-,write_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
Function,-,xPortGetFreeHeapSize,size_t, Function,-,xPortGetFreeHeapSize,size_t,
Function,-,xPortGetMinimumEverFreeHeapSize,size_t, Function,-,xPortGetMinimumEverFreeHeapSize,size_t,
Function,-,xPortStartScheduler,BaseType_t, Function,-,xPortStartScheduler,BaseType_t,
1 entry status name type params
2 Version + 17.0 18.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
504 Function - acoshf float float
505 Function - acoshl long double long double
506 Function - acosl long double long double
Function + acquire_mutex void* ValueMutex*, uint32_t
507 Function - aligned_alloc void* size_t, size_t
508 Function + aligned_free void void*
509 Function + aligned_malloc void* size_t, size_t
739 Function - ctime char* const time_t*
740 Function - ctime_r char* const time_t*, char*
741 Function - cuserid char* char*
Function + delete_mutex _Bool ValueMutex*
742 Function + dialog_ex_alloc DialogEx*
743 Function + dialog_ex_disable_extended_events void DialogEx*
744 Function + dialog_ex_enable_extended_events void DialogEx*
1404 Function + furi_hal_subghz_check_radio _Bool
1405 Function + furi_hal_subghz_disable_ext_power void
1406 Function - furi_hal_subghz_dump_state void
1407 Function + furi_hal_subghz_enable_ext_power void _Bool
1408 Function + furi_hal_subghz_flush_rx void
1409 Function + furi_hal_subghz_flush_tx void
1410 Function + furi_hal_subghz_get_extend_settings void _Bool*, _Bool*
1776 Function + infrared_worker_tx_set_signal_sent_callback void InfraredWorker*, InfraredWorkerMessageSentCallback, void*
1777 Function + infrared_worker_tx_start void InfraredWorker*
1778 Function + infrared_worker_tx_stop void InfraredWorker*
Function + init_mutex _Bool ValueMutex*, void*, size_t
1779 Function - initstate char* unsigned, char*, size_t
1780 Function + input_get_key_name const char* InputKey
1781 Function + input_get_type_name const char* InputType
1986 Function + menu_get_view View* Menu*
1987 Function + menu_reset void Menu*
1988 Function + menu_set_selected_item void Menu*, uint32_t
1989 Function - mf_classic_auth_attempt _Bool FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t FuriHalNfcTxRxContext*, Crypto1*, MfClassicAuthContext*, uint64_t
1990 Function - mf_classic_auth_init_context void MfClassicAuthContext*, uint8_t
1991 Function - mf_classic_auth_write_block _Bool FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t
1992 Function - mf_classic_authenticate _Bool FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey
2307 Function - rand_r int unsigned*
2308 Function + random long
2309 Function - rawmemchr void* const void*, int
Function - read_mutex _Bool ValueMutex*, void*, size_t, uint32_t
2310 Function + realloc void* void*, size_t
2311 Function - reallocarray void* void*, size_t, size_t
2312 Function - reallocf void* void*, size_t
2313 Function - realpath char* const char*, char*
Function + release_mutex _Bool ValueMutex*, const void*
2314 Function - remainder double double, double
2315 Function - remainderf float float, float
2316 Function - remainderl long double long double, long double
4709 Function + widget_free void Widget*
4710 Function + widget_get_view View* Widget*
4711 Function + widget_reset void Widget*
Function - write_mutex _Bool ValueMutex*, void*, size_t, uint32_t
4712 Function - xPortGetFreeHeapSize size_t
4713 Function - xPortGetMinimumEverFreeHeapSize size_t
4714 Function - xPortStartScheduler BaseType_t

View File

@@ -21,8 +21,6 @@
#define INIT_TIMEOUT 10 #define INIT_TIMEOUT 10
static uint32_t furi_hal_subghz_debug_gpio_buff[2]; static uint32_t furi_hal_subghz_debug_gpio_buff[2];
static bool last_OTG_state = false;
static bool ext_power_is_enabled_already = false;
/* DMA Channels definition */ /* DMA Channels definition */
#define SUBGHZ_DMA DMA2 #define SUBGHZ_DMA DMA2
@@ -80,18 +78,20 @@ void furi_hal_subghz_init(void) {
furi_hal_subghz_init_check(); furi_hal_subghz_init_check();
} }
void furi_hal_subghz_enable_ext_power(void) { bool furi_hal_subghz_enable_ext_power(void) {
if(ext_power_is_enabled_already && furi_hal_power_is_otg_enabled()) return; if(furi_hal_subghz.radio_type != SubGhzRadioInternal) {
ext_power_is_enabled_already = true; uint8_t attempts = 0;
last_OTG_state = furi_hal_power_is_otg_enabled(); while(!furi_hal_power_is_otg_enabled() && attempts++ < 2) {
if(furi_hal_subghz.radio_type != SubGhzRadioInternal && !furi_hal_power_is_otg_enabled()) { furi_hal_power_enable_otg();
furi_hal_power_enable_otg(); //CC1101 power-up time
furi_delay_ms(5);
}
} }
return furi_hal_power_is_otg_enabled();
} }
void furi_hal_subghz_disable_ext_power(void) { void furi_hal_subghz_disable_ext_power(void) {
ext_power_is_enabled_already = false; if(furi_hal_subghz.radio_type != SubGhzRadioInternal) {
if(furi_hal_subghz.radio_type != SubGhzRadioInternal && !last_OTG_state) {
furi_hal_power_disable_otg(); furi_hal_power_disable_otg();
} }
} }
@@ -99,8 +99,6 @@ void furi_hal_subghz_disable_ext_power(void) {
bool furi_hal_subghz_check_radio(void) { bool furi_hal_subghz_check_radio(void) {
bool result = true; bool result = true;
furi_hal_subghz_enable_ext_power();
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
uint8_t ver = cc1101_get_version(furi_hal_subghz.spi_bus_handle); uint8_t ver = cc1101_get_version(furi_hal_subghz.spi_bus_handle);
@@ -113,7 +111,6 @@ bool furi_hal_subghz_check_radio(void) {
result = false; result = false;
} }
furi_hal_subghz_disable_ext_power();
return result; return result;
} }
@@ -124,7 +121,6 @@ bool furi_hal_subghz_init_check(void) {
furi_hal_subghz.state = SubGhzStateIdle; furi_hal_subghz.state = SubGhzStateIdle;
furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE;
furi_hal_subghz_enable_ext_power();
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
#ifdef FURI_HAL_SUBGHZ_TX_GPIO #ifdef FURI_HAL_SUBGHZ_TX_GPIO
@@ -176,7 +172,6 @@ bool furi_hal_subghz_init_check(void) {
} else { } else {
FURI_LOG_E(TAG, "Failed to initialization"); FURI_LOG_E(TAG, "Failed to initialization");
} }
furi_hal_subghz_disable_ext_power();
return result; return result;
} }
@@ -193,8 +188,6 @@ void furi_hal_subghz_sleep() {
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
furi_hal_subghz_disable_ext_power();
furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE;
} }
@@ -339,7 +332,6 @@ void furi_hal_subghz_shutdown() {
// Reset and shutdown // Reset and shutdown
cc1101_shutdown(furi_hal_subghz.spi_bus_handle); cc1101_shutdown(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
furi_hal_subghz_disable_ext_power();
} }
void furi_hal_subghz_reset() { void furi_hal_subghz_reset() {
@@ -352,7 +344,6 @@ void furi_hal_subghz_reset() {
} }
void furi_hal_subghz_idle() { void furi_hal_subghz_idle() {
furi_hal_subghz_enable_ext_power();
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);

View File

@@ -317,8 +317,9 @@ SubGhzRadioType furi_hal_subghz_get_radio_type(void);
bool furi_hal_subghz_check_radio(void); bool furi_hal_subghz_check_radio(void);
/** Turn on the power of the external radio module /** Turn on the power of the external radio module
* @return true if power-up is successful
*/ */
void furi_hal_subghz_enable_ext_power(void); bool furi_hal_subghz_enable_ext_power(void);
/** Turn off the power of the external radio module /** Turn off the power of the external radio module
*/ */

View File

@@ -1,59 +0,0 @@
#include "valuemutex.h"
#include <string.h>
bool init_mutex(ValueMutex* valuemutex, void* value, size_t size) {
// mutex without name,
// no attributes (unfortunately robust mutex is not supported by FreeRTOS),
// with dynamic memory allocation
valuemutex->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(valuemutex->mutex == NULL) return false;
valuemutex->value = value;
valuemutex->size = size;
return true;
}
bool delete_mutex(ValueMutex* valuemutex) {
if(furi_mutex_acquire(valuemutex->mutex, FuriWaitForever) == FuriStatusOk) {
furi_mutex_free(valuemutex->mutex);
return true;
} else {
return false;
}
}
void* acquire_mutex(ValueMutex* valuemutex, uint32_t timeout) {
if(furi_mutex_acquire(valuemutex->mutex, timeout) == FuriStatusOk) {
return valuemutex->value;
} else {
return NULL;
}
}
bool release_mutex(ValueMutex* valuemutex, const void* value) {
if(value != valuemutex->value) return false;
if(furi_mutex_release(valuemutex->mutex) != FuriStatusOk) return false;
return true;
}
bool read_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout) {
void* value = acquire_mutex(valuemutex, timeout);
if(value == NULL || len > valuemutex->size) return false;
memcpy(data, value, len > 0 ? len : valuemutex->size);
if(!release_mutex(valuemutex, value)) return false;
return true;
}
bool write_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout) {
void* value = acquire_mutex(valuemutex, timeout);
if(value == NULL || len > valuemutex->size) return false;
memcpy(value, data, len > 0 ? len : valuemutex->size);
if(!release_mutex(valuemutex, value)) return false;
return true;
}

View File

@@ -1,149 +0,0 @@
#pragma once
#include <stdbool.h>
#include "mutex.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* == ValueMutex ==
* The most simple concept is ValueMutex.
* It is wrapper around mutex and value pointer.
* You can take and give mutex to work with value and read and write value.
*/
typedef struct {
void* value;
size_t size;
FuriMutex* mutex;
} ValueMutex;
/**
* Creates ValueMutex.
*/
bool init_mutex(ValueMutex* valuemutex, void* value, size_t size);
/**
* Free resources allocated by `init_mutex`.
* This function doesn't free the memory occupied by `ValueMutex` itself.
*/
bool delete_mutex(ValueMutex* valuemutex);
/**
* Call for work with data stored in mutex.
* @return pointer to data if success, NULL otherwise.
*/
void* acquire_mutex(ValueMutex* valuemutex, uint32_t timeout);
/**
* Helper: infinitely wait for mutex
*/
static inline void* acquire_mutex_block(ValueMutex* valuemutex) {
return acquire_mutex(valuemutex, FuriWaitForever);
}
/**
* With statement for value mutex, acts as lambda
* @param name a resource name, const char*
* @param function_body a (){} lambda declaration,
* executed within you parent function context.
*/
#define with_value_mutex(value_mutex, function_body) \
{ \
void* p = acquire_mutex_block(value_mutex); \
furi_check(p); \
({ void __fn__ function_body __fn__; })(p); \
release_mutex(value_mutex, p); \
}
/**
* Release mutex after end of work with data.
* Call `release_mutex` and pass ValueData instance and pointer to data.
*/
bool release_mutex(ValueMutex* valuemutex, const void* value);
/**
* Instead of take-access-give sequence you can use `read_mutex` and `write_mutex` functions.
* Both functions return true in case of success, false otherwise.
*/
bool read_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
bool write_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
inline static bool write_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
return write_mutex(valuemutex, data, len, FuriWaitForever);
}
inline static bool read_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
return read_mutex(valuemutex, data, len, FuriWaitForever);
}
#ifdef __cplusplus
}
#endif
/*
Usage example
```C
// MANIFEST
// name="example-provider-app"
// stack=128
void provider_app(void* _p) {
// create record with mutex
uint32_t example_value = 0;
ValueMutex example_mutex;
// call `init_mutex`.
if(!init_mutex(&example_mutex, (void*)&example_value, sizeof(uint32_t))) {
printf("critical error\n");
flapp_exit(NULL);
}
furi_record_create("provider/example", (void*)&example_mutex);
// we are ready to provide record to other apps
flapp_ready();
// get value and increment it
while(1) {
uint32_t* value = acquire_mutex(&example_mutex, OsWaitForever);
if(value != NULL) {
value++;
}
release_mutex(&example_mutex, value);
furi_delay_ms(100);
}
}
// MANIFEST
// name="example-consumer-app"
// stack=128
// require="example-provider-app"
void consumer_app(void* _p) {
// this app run after flapp_ready call in all requirements app
// open mutex value
ValueMutex* counter_mutex = furi_record_open("provider/example");
if(counter_mutex == NULL) {
printf("critical error\n");
flapp_exit(NULL);
}
// continuously read value every 1s
uint32_t counter;
while(1) {
if(read_mutex(counter_mutex, &counter, sizeof(counter), OsWaitForever)) {
printf("counter value: %d\n", counter);
}
furi_delay_ms(1000);
}
}
```
*/

View File

@@ -16,7 +16,6 @@
#include "core/semaphore.h" #include "core/semaphore.h"
#include "core/thread.h" #include "core/thread.h"
#include "core/timer.h" #include "core/timer.h"
#include "core/valuemutex.h"
#include "core/string.h" #include "core/string.h"
#include "core/stream_buffer.h" #include "core/stream_buffer.h"

View File

@@ -902,6 +902,32 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
} }
} }
static bool nfc_worker_mf_get_b_key_from_sector_trailer(
FuriHalNfcTxRxContext* tx_rx,
uint16_t sector,
uint64_t key,
uint64_t* found_key) {
// Some access conditions allow reading B key via A key
uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector);
Crypto1 crypto = {};
MfClassicBlock block_tmp = {};
MfClassicAuthContext auth_context = {.sector = sector, .key_a = MF_CLASSIC_NO_KEY, .key_b = 0};
furi_hal_nfc_sleep();
if(mf_classic_auth_attempt(tx_rx, &crypto, &auth_context, key)) {
if(mf_classic_read_block(tx_rx, &crypto, block, &block_tmp)) {
*found_key = nfc_util_bytes2num(&block_tmp.value[10], sizeof(uint8_t) * 6);
return *found_key;
}
}
return false;
}
static void nfc_worker_mf_classic_key_attack( static void nfc_worker_mf_classic_key_attack(
NfcWorker* nfc_worker, NfcWorker* nfc_worker,
uint64_t key, uint64_t key,
@@ -947,6 +973,16 @@ static void nfc_worker_mf_classic_key_attack(
mf_classic_set_key_found(data, i, MfClassicKeyA, key); mf_classic_set_key_found(data, i, MfClassicKeyA, key);
FURI_LOG_D(TAG, "Key found"); FURI_LOG_D(TAG, "Key found");
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
uint64_t found_key;
if(nfc_worker_mf_get_b_key_from_sector_trailer(tx_rx, i, key, &found_key)) {
FURI_LOG_D(TAG, "Found B key via reading sector %d", i);
mf_classic_set_key_found(data, i, MfClassicKeyB, found_key);
if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
}
}
} }
} }
if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
@@ -1038,6 +1074,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
mf_classic_set_key_found(data, i, MfClassicKeyA, key); mf_classic_set_key_found(data, i, MfClassicKeyA, key);
FURI_LOG_D(TAG, "Key found"); FURI_LOG_D(TAG, "Key found");
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
uint64_t found_key;
if(nfc_worker_mf_get_b_key_from_sector_trailer(
&tx_rx, i, key, &found_key)) {
FURI_LOG_D(TAG, "Found B key via reading sector %d", i);
mf_classic_set_key_found(data, i, MfClassicKeyB, found_key);
if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
}
nfc_worker_mf_classic_key_attack(nfc_worker, found_key, &tx_rx, i + 1);
}
nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
deactivated = true; deactivated = true;
} }

View File

@@ -541,6 +541,7 @@ bool mf_classic_authenticate_skip_activate(
bool mf_classic_auth_attempt( bool mf_classic_auth_attempt(
FuriHalNfcTxRxContext* tx_rx, FuriHalNfcTxRxContext* tx_rx,
Crypto1* crypto,
MfClassicAuthContext* auth_ctx, MfClassicAuthContext* auth_ctx,
uint64_t key) { uint64_t key) {
furi_assert(tx_rx); furi_assert(tx_rx);
@@ -549,15 +550,14 @@ bool mf_classic_auth_attempt(
bool need_halt = (auth_ctx->key_a == MF_CLASSIC_NO_KEY) && bool need_halt = (auth_ctx->key_a == MF_CLASSIC_NO_KEY) &&
(auth_ctx->key_b == MF_CLASSIC_NO_KEY); (auth_ctx->key_b == MF_CLASSIC_NO_KEY);
Crypto1 crypto;
if(auth_ctx->key_a == MF_CLASSIC_NO_KEY) { if(auth_ctx->key_a == MF_CLASSIC_NO_KEY) {
// Try AUTH with key A // Try AUTH with key A
if(mf_classic_auth( if(mf_classic_auth(
tx_rx, tx_rx,
mf_classic_get_first_block_num_of_sector(auth_ctx->sector), mf_classic_get_sector_trailer_block_num_by_sector(auth_ctx->sector),
key, key,
MfClassicKeyA, MfClassicKeyA,
&crypto, crypto,
false, false,
0)) { 0)) {
auth_ctx->key_a = key; auth_ctx->key_a = key;
@@ -573,10 +573,10 @@ bool mf_classic_auth_attempt(
// Try AUTH with key B // Try AUTH with key B
if(mf_classic_auth( if(mf_classic_auth(
tx_rx, tx_rx,
mf_classic_get_first_block_num_of_sector(auth_ctx->sector), mf_classic_get_sector_trailer_block_num_by_sector(auth_ctx->sector),
key, key,
MfClassicKeyB, MfClassicKeyB,
&crypto, crypto,
false, false,
0)) { 0)) {
auth_ctx->key_b = key; auth_ctx->key_b = key;
@@ -672,6 +672,9 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
do { do {
if(blocks_read == total_blocks) break; if(blocks_read == total_blocks) break;
if(!key_b_found) break; if(!key_b_found) break;
if(key_a_found) {
furi_hal_nfc_sleep();
}
FURI_LOG_D(TAG, "Try to read blocks with key B"); FURI_LOG_D(TAG, "Try to read blocks with key B");
key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b)); key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b));
if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break; if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break;

View File

@@ -175,6 +175,7 @@ bool mf_classic_authenticate_skip_activate(
bool mf_classic_auth_attempt( bool mf_classic_auth_attempt(
FuriHalNfcTxRxContext* tx_rx, FuriHalNfcTxRxContext* tx_rx,
Crypto1* crypto,
MfClassicAuthContext* auth_ctx, MfClassicAuthContext* auth_ctx,
uint64_t key); uint64_t key);