mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 17:08:35 -07:00
Merge branch 'dev' into ntag-auto-pwd-capture
This commit is contained in:
1
.github/workflows/pvs_studio.yml
vendored
1
.github/workflows/pvs_studio.yml
vendored
@@ -65,6 +65,7 @@ jobs:
|
|||||||
pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }}
|
pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }}
|
||||||
pvs-studio-analyzer analyze \
|
pvs-studio-analyzer analyze \
|
||||||
@.pvsoptions \
|
@.pvsoptions \
|
||||||
|
--disableLicenseExpirationCheck \
|
||||||
-j$(grep -c processor /proc/cpuinfo) \
|
-j$(grep -c processor /proc/cpuinfo) \
|
||||||
-f build/f7-firmware-DC/compile_commands.json \
|
-f build/f7-firmware-DC/compile_commands.json \
|
||||||
-o PVS-Studio.log
|
-o PVS-Studio.log
|
||||||
|
|||||||
@@ -154,7 +154,9 @@ static bool bt_test_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
void bt_test_process_up(BtTest* bt_test) {
|
void bt_test_process_up(BtTest* bt_test) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
uint8_t params_on_screen = 3;
|
uint8_t params_on_screen = 3;
|
||||||
if(model->position > 0) {
|
if(model->position > 0) {
|
||||||
model->position--;
|
model->position--;
|
||||||
@@ -168,13 +170,15 @@ void bt_test_process_up(BtTest* bt_test) {
|
|||||||
model->window_position = model->position - (params_on_screen - 1);
|
model->window_position = model->position - (params_on_screen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_process_down(BtTest* bt_test) {
|
void bt_test_process_down(BtTest* bt_test) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
uint8_t params_on_screen = 3;
|
uint8_t params_on_screen = 3;
|
||||||
if(model->position < (BtTestParamArray_size(model->params) - 1)) {
|
if(model->position < (BtTestParamArray_size(model->params) - 1)) {
|
||||||
model->position++;
|
model->position++;
|
||||||
@@ -187,8 +191,8 @@ void bt_test_process_down(BtTest* bt_test) {
|
|||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BtTestParam* bt_test_get_selected_param(BtTestModel* model) {
|
BtTestParam* bt_test_get_selected_param(BtTestModel* model) {
|
||||||
@@ -213,7 +217,9 @@ BtTestParam* bt_test_get_selected_param(BtTestModel* model) {
|
|||||||
void bt_test_process_left(BtTest* bt_test) {
|
void bt_test_process_left(BtTest* bt_test) {
|
||||||
BtTestParam* param;
|
BtTestParam* param;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
param = bt_test_get_selected_param(model);
|
param = bt_test_get_selected_param(model);
|
||||||
if(param->current_value_index > 0) {
|
if(param->current_value_index > 0) {
|
||||||
param->current_value_index--;
|
param->current_value_index--;
|
||||||
@@ -225,8 +231,8 @@ void bt_test_process_left(BtTest* bt_test) {
|
|||||||
model->packets_num_tx = 0;
|
model->packets_num_tx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
if(param->change_callback) {
|
if(param->change_callback) {
|
||||||
param->change_callback(param);
|
param->change_callback(param);
|
||||||
}
|
}
|
||||||
@@ -235,7 +241,9 @@ void bt_test_process_left(BtTest* bt_test) {
|
|||||||
void bt_test_process_right(BtTest* bt_test) {
|
void bt_test_process_right(BtTest* bt_test) {
|
||||||
BtTestParam* param;
|
BtTestParam* param;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
param = bt_test_get_selected_param(model);
|
param = bt_test_get_selected_param(model);
|
||||||
if(param->current_value_index < (param->values_count - 1)) {
|
if(param->current_value_index < (param->values_count - 1)) {
|
||||||
param->current_value_index++;
|
param->current_value_index++;
|
||||||
@@ -247,8 +255,8 @@ void bt_test_process_right(BtTest* bt_test) {
|
|||||||
model->packets_num_tx = 0;
|
model->packets_num_tx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
if(param->change_callback) {
|
if(param->change_callback) {
|
||||||
param->change_callback(param);
|
param->change_callback(param);
|
||||||
}
|
}
|
||||||
@@ -257,7 +265,9 @@ void bt_test_process_right(BtTest* bt_test) {
|
|||||||
void bt_test_process_ok(BtTest* bt_test) {
|
void bt_test_process_ok(BtTest* bt_test) {
|
||||||
BtTestState state;
|
BtTestState state;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
if(model->state == BtTestStateStarted) {
|
if(model->state == BtTestStateStarted) {
|
||||||
model->state = BtTestStateStopped;
|
model->state = BtTestStateStopped;
|
||||||
model->message = BT_TEST_START_MESSAGE;
|
model->message = BT_TEST_START_MESSAGE;
|
||||||
@@ -269,8 +279,8 @@ void bt_test_process_ok(BtTest* bt_test) {
|
|||||||
model->message = BT_TEST_STOP_MESSAGE;
|
model->message = BT_TEST_STOP_MESSAGE;
|
||||||
}
|
}
|
||||||
state = model->state;
|
state = model->state;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
if(bt_test->change_state_callback) {
|
if(bt_test->change_state_callback) {
|
||||||
bt_test->change_state_callback(state, bt_test->context);
|
bt_test->change_state_callback(state, bt_test->context);
|
||||||
}
|
}
|
||||||
@@ -278,13 +288,15 @@ void bt_test_process_ok(BtTest* bt_test) {
|
|||||||
|
|
||||||
void bt_test_process_back(BtTest* bt_test) {
|
void bt_test_process_back(BtTest* bt_test) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
model->state = BtTestStateStopped;
|
model->state = BtTestStateStopped;
|
||||||
model->rssi = 0.0f;
|
model->rssi = 0.0f;
|
||||||
model->packets_num_rx = 0;
|
model->packets_num_rx = 0;
|
||||||
model->packets_num_tx = 0;
|
model->packets_num_tx = 0;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
if(bt_test->back_callback) {
|
if(bt_test->back_callback) {
|
||||||
bt_test->back_callback(bt_test->context);
|
bt_test->back_callback(bt_test->context);
|
||||||
}
|
}
|
||||||
@@ -299,7 +311,9 @@ BtTest* bt_test_alloc() {
|
|||||||
view_set_input_callback(bt_test->view, bt_test_input_callback);
|
view_set_input_callback(bt_test->view, bt_test_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
model->state = BtTestStateStopped;
|
model->state = BtTestStateStopped;
|
||||||
model->message = "Ok - Start";
|
model->message = "Ok - Start";
|
||||||
BtTestParamArray_init(model->params);
|
BtTestParamArray_init(model->params);
|
||||||
@@ -308,8 +322,8 @@ BtTest* bt_test_alloc() {
|
|||||||
model->rssi = 0.0f;
|
model->rssi = 0.0f;
|
||||||
model->packets_num_tx = 0;
|
model->packets_num_tx = 0;
|
||||||
model->packets_num_rx = 0;
|
model->packets_num_rx = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return bt_test;
|
return bt_test;
|
||||||
}
|
}
|
||||||
@@ -318,15 +332,17 @@ void bt_test_free(BtTest* bt_test) {
|
|||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
BtTestParamArray_it_t it;
|
BtTestParamArray_it_t it;
|
||||||
for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it);
|
for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it);
|
||||||
BtTestParamArray_next(it)) {
|
BtTestParamArray_next(it)) {
|
||||||
furi_string_free(BtTestParamArray_ref(it)->current_value_text);
|
furi_string_free(BtTestParamArray_ref(it)->current_value_text);
|
||||||
}
|
}
|
||||||
BtTestParamArray_clear(model->params);
|
BtTestParamArray_clear(model->params);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
view_free(bt_test->view);
|
view_free(bt_test->view);
|
||||||
free(bt_test);
|
free(bt_test);
|
||||||
}
|
}
|
||||||
@@ -347,7 +363,9 @@ BtTestParam* bt_test_param_add(
|
|||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view,
|
||||||
|
BtTestModel * model,
|
||||||
|
{
|
||||||
param = BtTestParamArray_push_new(model->params);
|
param = BtTestParamArray_push_new(model->params);
|
||||||
param->label = label;
|
param->label = label;
|
||||||
param->values_count = values_count;
|
param->values_count = values_count;
|
||||||
@@ -355,8 +373,8 @@ BtTestParam* bt_test_param_add(
|
|||||||
param->context = context;
|
param->context = context;
|
||||||
param->current_value_index = 0;
|
param->current_value_index = 0;
|
||||||
param->current_value_text = furi_string_alloc();
|
param->current_value_text = furi_string_alloc();
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
@@ -364,28 +382,19 @@ BtTestParam* bt_test_param_add(
|
|||||||
void bt_test_set_rssi(BtTest* bt_test, float rssi) {
|
void bt_test_set_rssi(BtTest* bt_test, float rssi) {
|
||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
|
||||||
model->rssi = rssi;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
|
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
|
||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view, BtTestModel * model, { model->packets_num_tx = packets_num; }, true);
|
||||||
model->packets_num_tx = packets_num;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) {
|
void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) {
|
||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_test->view, (BtTestModel * model) {
|
bt_test->view, BtTestModel * model, { model->packets_num_rx = packets_num; }, true);
|
||||||
model->packets_num_rx = packets_num;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback) {
|
void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback) {
|
||||||
|
|||||||
@@ -110,7 +110,9 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) {
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (ViewDisplayTestModel * model) {
|
instance->view,
|
||||||
|
ViewDisplayTestModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyLeft && model->test > 0) {
|
if(event->key == InputKeyLeft && model->test > 0) {
|
||||||
model->test--;
|
model->test--;
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@@ -129,8 +131,8 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) {
|
|||||||
model->flip_flop = !model->flip_flop;
|
model->flip_flop = !model->flip_flop;
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
return consumed;
|
},
|
||||||
});
|
consumed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
@@ -149,10 +151,7 @@ static void view_display_test_exit(void* context) {
|
|||||||
static void view_display_test_timer_callback(void* context) {
|
static void view_display_test_timer_callback(void* context) {
|
||||||
ViewDisplayTest* instance = context;
|
ViewDisplayTest* instance = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (ViewDisplayTestModel * model) {
|
instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
|
||||||
model->counter++;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewDisplayTest* view_display_test_alloc() {
|
ViewDisplayTest* view_display_test_alloc() {
|
||||||
|
|||||||
@@ -52,23 +52,29 @@ static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
static void lfrfid_debug_view_tune_button_up(LfRfidTuneView* tune_view) {
|
static void lfrfid_debug_view_tune_button_up(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
if(model->pos > 0) model->pos--;
|
if(model->pos > 0) model->pos--;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) {
|
static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
if(model->pos < 1) model->pos++;
|
if(model->pos < 1) model->pos++;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) {
|
static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
if(model->pos == 0) {
|
if(model->pos == 0) {
|
||||||
if(model->fine) {
|
if(model->fine) {
|
||||||
model->ARR -= 1;
|
model->ARR -= 1;
|
||||||
@@ -84,13 +90,15 @@ static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model->dirty = true;
|
model->dirty = true;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) {
|
static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
if(model->pos == 0) {
|
if(model->pos == 0) {
|
||||||
if(model->fine) {
|
if(model->fine) {
|
||||||
model->ARR += 1;
|
model->ARR += 1;
|
||||||
@@ -106,16 +114,13 @@ static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model->dirty = true;
|
model->dirty = true;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) {
|
static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view, LfRfidTuneViewModel * model, { model->fine = !model->fine; }, true);
|
||||||
model->fine = !model->fine;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* context) {
|
static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -158,14 +163,16 @@ LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
|
|||||||
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
model->dirty = true;
|
model->dirty = true;
|
||||||
model->fine = false;
|
model->fine = false;
|
||||||
model->ARR = 511;
|
model->ARR = 511;
|
||||||
model->CCR = 255;
|
model->CCR = 255;
|
||||||
model->pos = 0;
|
model->pos = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
||||||
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
||||||
@@ -184,24 +191,28 @@ View* lfrfid_debug_view_tune_get_view(LfRfidTuneView* tune_view) {
|
|||||||
|
|
||||||
void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
|
void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
model->dirty = true;
|
model->dirty = true;
|
||||||
model->fine = false;
|
model->fine = false;
|
||||||
model->ARR = 511;
|
model->ARR = 511;
|
||||||
model->CCR = 255;
|
model->CCR = 255;
|
||||||
model->pos = 0;
|
model->pos = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
|
bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
result = model->dirty;
|
result = model->dirty;
|
||||||
model->dirty = false;
|
model->dirty = false;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -209,10 +220,7 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
|
|||||||
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
|
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
|
||||||
uint32_t result = false;
|
uint32_t result = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
|
||||||
result = model->ARR;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -220,10 +228,7 @@ uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
|
|||||||
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
||||||
uint32_t result = false;
|
uint32_t result = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
tune_view->view, (LfRfidTuneViewModel * model) {
|
tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
|
||||||
result = model->CCR;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <notification/notification.h>
|
#include <notification/notification.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi_hal_uart.h>
|
#include <furi_hal_uart.h>
|
||||||
#include <furi_hal_console.h>
|
#include <furi_hal_console.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
@@ -20,7 +19,7 @@ typedef struct {
|
|||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
View* view;
|
View* view;
|
||||||
FuriThread* worker_thread;
|
FuriThread* worker_thread;
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
} UartEchoApp;
|
} UartEchoApp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -92,13 +91,11 @@ static uint32_t uart_echo_exit(void* context) {
|
|||||||
|
|
||||||
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
UartEchoApp* app = context;
|
UartEchoApp* app = context;
|
||||||
|
|
||||||
if(ev == UartIrqEventRXNE) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,25 +155,24 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
do {
|
do {
|
||||||
uint8_t data[64];
|
uint8_t data[64];
|
||||||
length = xStreamBufferReceive(app->rx_stream, data, 64, 0);
|
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
||||||
if(length > 0) {
|
if(length > 0) {
|
||||||
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->view, (UartDumpModel * model) {
|
app->view,
|
||||||
|
UartDumpModel * model,
|
||||||
|
{
|
||||||
for(size_t i = 0; i < length; i++) {
|
for(size_t i = 0; i < length; i++) {
|
||||||
uart_echo_push_to_list(model, data[i]);
|
uart_echo_push_to_list(model, data[i]);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
} while(length > 0);
|
} while(length > 0);
|
||||||
|
|
||||||
notification_message(app->notification, &sequence_notification);
|
notification_message(app->notification, &sequence_notification);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->view, (UartDumpModel * model) {
|
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
||||||
UNUSED(model);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +182,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
static UartEchoApp* uart_echo_app_alloc() {
|
static UartEchoApp* uart_echo_app_alloc() {
|
||||||
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
||||||
|
|
||||||
app->rx_stream = xStreamBufferCreate(2048, 1);
|
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
app->gui = furi_record_open(RECORD_GUI);
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
@@ -203,15 +199,17 @@ static UartEchoApp* uart_echo_app_alloc() {
|
|||||||
view_set_input_callback(app->view, uart_echo_view_input_callback);
|
view_set_input_callback(app->view, uart_echo_view_input_callback);
|
||||||
view_allocate_model(app->view, ViewModelTypeLocking, sizeof(UartDumpModel));
|
view_allocate_model(app->view, ViewModelTypeLocking, sizeof(UartDumpModel));
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->view, (UartDumpModel * model) {
|
app->view,
|
||||||
|
UartDumpModel * model,
|
||||||
|
{
|
||||||
for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
|
for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
|
||||||
model->line = 0;
|
model->line = 0;
|
||||||
model->escape = false;
|
model->escape = false;
|
||||||
model->list[i] = malloc(sizeof(ListElement));
|
model->list[i] = malloc(sizeof(ListElement));
|
||||||
model->list[i]->text = furi_string_alloc();
|
model->list[i]->text = furi_string_alloc();
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
view_set_previous_callback(app->view, uart_echo_exit);
|
view_set_previous_callback(app->view, uart_echo_exit);
|
||||||
view_dispatcher_add_view(app->view_dispatcher, 0, app->view);
|
view_dispatcher_add_view(app->view_dispatcher, 0, app->view);
|
||||||
@@ -245,13 +243,15 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
|||||||
view_dispatcher_remove_view(app->view_dispatcher, 0);
|
view_dispatcher_remove_view(app->view_dispatcher, 0);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->view, (UartDumpModel * model) {
|
app->view,
|
||||||
|
UartDumpModel * model,
|
||||||
|
{
|
||||||
for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
|
for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
|
||||||
furi_string_free(model->list[i]->text);
|
furi_string_free(model->list[i]->text);
|
||||||
free(model->list[i]);
|
free(model->list[i]);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
view_free(app->view);
|
view_free(app->view);
|
||||||
view_dispatcher_free(app->view_dispatcher);
|
view_dispatcher_free(app->view_dispatcher);
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
|||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
app->gui = NULL;
|
app->gui = NULL;
|
||||||
|
|
||||||
vStreamBufferDelete(app->rx_stream);
|
furi_stream_buffer_free(app->rx_stream);
|
||||||
|
|
||||||
// Free rest
|
// Free rest
|
||||||
free(app);
|
free(app);
|
||||||
|
|||||||
@@ -221,13 +221,13 @@ static void infrared_test_run_encoder(InfraredProtocol protocol, uint32_t test_i
|
|||||||
const char* protocol_name = infrared_get_protocol_name(protocol);
|
const char* protocol_name = infrared_get_protocol_name(protocol);
|
||||||
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
||||||
|
|
||||||
furi_string_printf(buf, "encoder_input%d", test_index);
|
furi_string_printf(buf, "encoder_input%ld", test_index);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
infrared_test_load_messages(
|
infrared_test_load_messages(
|
||||||
test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
|
test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
|
||||||
"Failed to load messages from file");
|
"Failed to load messages from file");
|
||||||
|
|
||||||
furi_string_printf(buf, "encoder_expected%d", test_index);
|
furi_string_printf(buf, "encoder_expected%ld", test_index);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
infrared_test_load_raw_signal(
|
infrared_test_load_raw_signal(
|
||||||
test->ff, furi_string_get_cstr(buf), &expected_timings, &expected_timings_count),
|
test->ff, furi_string_get_cstr(buf), &expected_timings, &expected_timings_count),
|
||||||
@@ -277,7 +277,7 @@ static void infrared_test_run_encoder_decoder(InfraredProtocol protocol, uint32_
|
|||||||
const char* protocol_name = infrared_get_protocol_name(protocol);
|
const char* protocol_name = infrared_get_protocol_name(protocol);
|
||||||
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
||||||
|
|
||||||
furi_string_printf(buf, "encoder_decoder_input%d", test_index);
|
furi_string_printf(buf, "encoder_decoder_input%ld", test_index);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
infrared_test_load_messages(
|
infrared_test_load_messages(
|
||||||
test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
|
test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
|
||||||
@@ -336,13 +336,13 @@ static void infrared_test_run_decoder(InfraredProtocol protocol, uint32_t test_i
|
|||||||
infrared_test_prepare_file(infrared_get_protocol_name(protocol)),
|
infrared_test_prepare_file(infrared_get_protocol_name(protocol)),
|
||||||
"Failed to prepare test file");
|
"Failed to prepare test file");
|
||||||
|
|
||||||
furi_string_printf(buf, "decoder_input%d", test_index);
|
furi_string_printf(buf, "decoder_input%ld", test_index);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
infrared_test_load_raw_signal(
|
infrared_test_load_raw_signal(
|
||||||
test->ff, furi_string_get_cstr(buf), &timings, &timings_count),
|
test->ff, furi_string_get_cstr(buf), &timings, &timings_count),
|
||||||
"Failed to load raw signal from file");
|
"Failed to load raw signal from file");
|
||||||
|
|
||||||
furi_string_printf(buf, "decoder_expected%d", test_index);
|
furi_string_printf(buf, "decoder_expected%ld", test_index);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
infrared_test_load_messages(
|
infrared_test_load_messages(
|
||||||
test->ff, furi_string_get_cstr(buf), &messages, &messages_count),
|
test->ff, furi_string_get_cstr(buf), &messages, &messages_count),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
// Check timings
|
// Check timings
|
||||||
if(time > encode_max_time) {
|
if(time > encode_max_time) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "Encoding time: %d us while accepted value: %d us", time, encode_max_time);
|
TAG, "Encoding time: %ld us while accepted value: %ld us", time, encode_max_time);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
ref_timings_sum += ref[i];
|
ref_timings_sum += ref[i];
|
||||||
if(timings_diff > timing_tolerance) {
|
if(timings_diff > timing_tolerance) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "Too big differece in %d timings. Ref: %d, DUT: %d", i, ref[i], dut[i]);
|
TAG, "Too big differece in %d timings. Ref: %ld, DUT: %ld", i, ref[i], dut[i]);
|
||||||
timing_check_success = false;
|
timing_check_success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -143,16 +143,16 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
if(sum_diff > timings_sum_tolerance) {
|
if(sum_diff > timings_sum_tolerance) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Too big difference in timings sum. Ref: %d, DUT: %d",
|
"Too big difference in timings sum. Ref: %ld, DUT: %ld",
|
||||||
ref_timings_sum,
|
ref_timings_sum,
|
||||||
dut_timings_sum);
|
dut_timings_sum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Encoding time: %d us. Acceptable time: %d us", time, encode_max_time);
|
FURI_LOG_I(TAG, "Encoding time: %ld us. Acceptable time: %ld us", time, encode_max_time);
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
"Timings sum difference: %d [1/64MHZ]. Acceptable difference: %d [1/64MHz]",
|
"Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]",
|
||||||
sum_diff,
|
sum_diff,
|
||||||
timings_sum_tolerance);
|
timings_sum_tolerance);
|
||||||
success = true;
|
success = true;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <pb.h>
|
#include <pb.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
@@ -34,7 +33,7 @@ static uint32_t command_id = 0;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RpcSession* session;
|
RpcSession* session;
|
||||||
StreamBufferHandle_t output_stream;
|
FuriStreamBuffer* output_stream;
|
||||||
SemaphoreHandle_t close_session_semaphore;
|
SemaphoreHandle_t close_session_semaphore;
|
||||||
SemaphoreHandle_t terminate_semaphore;
|
SemaphoreHandle_t terminate_semaphore;
|
||||||
TickType_t timeout;
|
TickType_t timeout;
|
||||||
@@ -90,7 +89,7 @@ static void test_rpc_setup(void) {
|
|||||||
}
|
}
|
||||||
furi_check(rpc_session[0].session);
|
furi_check(rpc_session[0].session);
|
||||||
|
|
||||||
rpc_session[0].output_stream = xStreamBufferCreate(1000, 1);
|
rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
|
||||||
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
||||||
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
||||||
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
||||||
@@ -110,7 +109,7 @@ static void test_rpc_setup_second_session(void) {
|
|||||||
}
|
}
|
||||||
furi_check(rpc_session[1].session);
|
furi_check(rpc_session[1].session);
|
||||||
|
|
||||||
rpc_session[1].output_stream = xStreamBufferCreate(1000, 1);
|
rpc_session[1].output_stream = furi_stream_buffer_alloc(1000, 1);
|
||||||
rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback);
|
rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback);
|
||||||
rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary();
|
rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary();
|
||||||
rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary();
|
rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary();
|
||||||
@@ -126,7 +125,7 @@ static void test_rpc_teardown(void) {
|
|||||||
rpc_session_close(rpc_session[0].session);
|
rpc_session_close(rpc_session[0].session);
|
||||||
furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY));
|
furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY));
|
||||||
furi_record_close(RECORD_RPC);
|
furi_record_close(RECORD_RPC);
|
||||||
vStreamBufferDelete(rpc_session[0].output_stream);
|
furi_stream_buffer_free(rpc_session[0].output_stream);
|
||||||
vSemaphoreDelete(rpc_session[0].close_session_semaphore);
|
vSemaphoreDelete(rpc_session[0].close_session_semaphore);
|
||||||
vSemaphoreDelete(rpc_session[0].terminate_semaphore);
|
vSemaphoreDelete(rpc_session[0].terminate_semaphore);
|
||||||
++command_id;
|
++command_id;
|
||||||
@@ -141,7 +140,7 @@ static void test_rpc_teardown_second_session(void) {
|
|||||||
xSemaphoreTake(rpc_session[1].terminate_semaphore, 0);
|
xSemaphoreTake(rpc_session[1].terminate_semaphore, 0);
|
||||||
rpc_session_close(rpc_session[1].session);
|
rpc_session_close(rpc_session[1].session);
|
||||||
furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY));
|
furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY));
|
||||||
vStreamBufferDelete(rpc_session[1].output_stream);
|
furi_stream_buffer_free(rpc_session[1].output_stream);
|
||||||
vSemaphoreDelete(rpc_session[1].close_session_semaphore);
|
vSemaphoreDelete(rpc_session[1].close_session_semaphore);
|
||||||
vSemaphoreDelete(rpc_session[1].terminate_semaphore);
|
vSemaphoreDelete(rpc_session[1].terminate_semaphore);
|
||||||
++command_id;
|
++command_id;
|
||||||
@@ -268,8 +267,8 @@ static PB_CommandStatus test_rpc_storage_get_file_error(File* file) {
|
|||||||
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) {
|
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) {
|
||||||
RpcSessionContext* callbacks_context = ctx;
|
RpcSessionContext* callbacks_context = ctx;
|
||||||
|
|
||||||
size_t bytes_sent =
|
size_t bytes_sent = furi_stream_buffer_send(
|
||||||
xStreamBufferSend(callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever);
|
callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever);
|
||||||
(void)bytes_sent;
|
(void)bytes_sent;
|
||||||
furi_check(bytes_sent == got_size);
|
furi_check(bytes_sent == got_size);
|
||||||
}
|
}
|
||||||
@@ -534,7 +533,8 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_
|
|||||||
TickType_t now = xTaskGetTickCount();
|
TickType_t now = xTaskGetTickCount();
|
||||||
int32_t time_left = session_context->timeout - now;
|
int32_t time_left = session_context->timeout - now;
|
||||||
time_left = MAX(time_left, 0);
|
time_left = MAX(time_left, 0);
|
||||||
bytes_received = xStreamBufferReceive(session_context->output_stream, buf, count, time_left);
|
bytes_received =
|
||||||
|
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
|
||||||
return (count == bytes_received);
|
return (count == bytes_received);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ static void
|
|||||||
archive_switch_tab(browser, browser->last_tab_switch_dir);
|
archive_switch_tab(browser, browser->last_tab_switch_dir);
|
||||||
} else if(!furi_string_start_with_str(browser->path, "/app:")) {
|
} else if(!furi_string_start_with_str(browser->path, "/app:")) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
files_array_reset(model->files);
|
files_array_reset(model->files);
|
||||||
model->item_cnt = item_cnt;
|
model->item_cnt = item_cnt;
|
||||||
model->item_idx = (file_idx > 0) ? file_idx : 0;
|
model->item_idx = (file_idx > 0) ? file_idx : 0;
|
||||||
@@ -31,8 +33,8 @@ static void
|
|||||||
model->list_offset = 0;
|
model->list_offset = 0;
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
model->folder_loading = false;
|
model->folder_loading = false;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
|
|
||||||
file_browser_worker_load(browser->worker, load_offset, FILE_LIST_BUF_LEN);
|
file_browser_worker_load(browser->worker, load_offset, FILE_LIST_BUF_LEN);
|
||||||
@@ -44,11 +46,13 @@ static void archive_list_load_cb(void* context, uint32_t list_load_offset) {
|
|||||||
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
|
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
files_array_reset(model->files);
|
files_array_reset(model->files);
|
||||||
model->array_offset = list_load_offset;
|
model->array_offset = list_load_offset;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -60,10 +64,7 @@ static void
|
|||||||
archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
|
archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true);
|
||||||
model->list_loading = false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +73,7 @@ static void archive_long_load_cb(void* context) {
|
|||||||
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
|
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { model->folder_loading = true; }, true);
|
||||||
model->folder_loading = true;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void archive_file_browser_set_path(
|
static void archive_file_browser_set_path(
|
||||||
@@ -113,7 +111,9 @@ void archive_update_offset(ArchiveBrowserView* browser) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt;
|
uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt;
|
||||||
|
|
||||||
if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) {
|
if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) {
|
||||||
@@ -125,9 +125,8 @@ void archive_update_offset(ArchiveBrowserView* browser) {
|
|||||||
model->list_offset =
|
model->list_offset =
|
||||||
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
|
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
||||||
@@ -140,7 +139,9 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
|||||||
archive_switch_tab(browser, TAB_RIGHT);
|
archive_switch_tab(browser, TAB_RIGHT);
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
uint16_t idx = 0;
|
uint16_t idx = 0;
|
||||||
while(idx < files_array_size(model->files)) {
|
while(idx < files_array_size(model->files)) {
|
||||||
ArchiveFile_t* current = files_array_get(model->files, idx);
|
ArchiveFile_t* current = files_array_get(model->files, idx);
|
||||||
@@ -150,8 +151,8 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
|||||||
}
|
}
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
}
|
}
|
||||||
@@ -162,10 +163,10 @@ size_t archive_file_get_array_size(ArchiveBrowserView* browser) {
|
|||||||
|
|
||||||
uint16_t size = 0;
|
uint16_t size = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
size = files_array_size(model->files);
|
ArchiveBrowserViewModel * model,
|
||||||
return false;
|
{ size = files_array_size(model->files); },
|
||||||
});
|
false);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +174,13 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
model->item_cnt = count;
|
model->item_cnt = count;
|
||||||
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
|
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +189,9 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
|
|||||||
uint32_t items_cnt = 0;
|
uint32_t items_cnt = 0;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
files_array_remove_v(
|
files_array_remove_v(
|
||||||
model->files,
|
model->files,
|
||||||
model->item_idx - model->array_offset,
|
model->item_idx - model->array_offset,
|
||||||
@@ -194,8 +199,8 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
|
|||||||
model->item_cnt--;
|
model->item_cnt--;
|
||||||
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
|
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
|
||||||
items_cnt = model->item_cnt;
|
items_cnt = model->item_cnt;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
if((items_cnt == 0) && (archive_is_home(browser))) {
|
if((items_cnt == 0) && (archive_is_home(browser))) {
|
||||||
archive_switch_tab(browser, TAB_RIGHT);
|
archive_switch_tab(browser, TAB_RIGHT);
|
||||||
@@ -208,7 +213,9 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
ArchiveFile_t temp;
|
ArchiveFile_t temp;
|
||||||
size_t array_size = files_array_size(model->files) - 1;
|
size_t array_size = files_array_size(model->files) - 1;
|
||||||
uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u);
|
uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u);
|
||||||
@@ -226,18 +233,18 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) {
|
|||||||
} else {
|
} else {
|
||||||
files_array_swap_at(model->files, model->item_idx, swap_idx);
|
files_array_swap_at(model->files, model->item_idx, swap_idx);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_file_array_rm_all(ArchiveBrowserView* browser) {
|
void archive_file_array_rm_all(ArchiveBrowserView* browser) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
files_array_reset(model->files);
|
ArchiveBrowserViewModel * model,
|
||||||
return false;
|
{ files_array_reset(model->files); },
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
|
void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
|
||||||
@@ -246,7 +253,9 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
|
|||||||
int32_t offset_new = 0;
|
int32_t offset_new = 0;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
if(model->item_cnt > FILE_LIST_BUF_LEN) {
|
if(model->item_cnt > FILE_LIST_BUF_LEN) {
|
||||||
if(dir < 0) {
|
if(dir < 0) {
|
||||||
offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 3;
|
offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 3;
|
||||||
@@ -262,8 +271,8 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
|
|||||||
offset_new = 0;
|
offset_new = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
file_browser_worker_load(browser->worker, offset_new, FILE_LIST_BUF_LEN);
|
file_browser_worker_load(browser->worker, offset_new, FILE_LIST_BUF_LEN);
|
||||||
}
|
}
|
||||||
@@ -273,12 +282,14 @@ ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) {
|
|||||||
|
|
||||||
ArchiveFile_t* selected = NULL;
|
ArchiveFile_t* selected = NULL;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
selected = files_array_size(model->files) ?
|
selected = files_array_size(model->files) ?
|
||||||
files_array_get(model->files, model->item_idx - model->array_offset) :
|
files_array_get(model->files, model->item_idx - model->array_offset) :
|
||||||
NULL;
|
NULL;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,11 +299,13 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) {
|
|||||||
ArchiveFile_t* selected = NULL;
|
ArchiveFile_t* selected = NULL;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u);
|
idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u);
|
||||||
selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL;
|
selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,10 +314,7 @@ ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) {
|
|||||||
|
|
||||||
ArchiveTabEnum tab_id = 0;
|
ArchiveTabEnum tab_id = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { tab_id = model->tab_idx; }, false);
|
||||||
tab_id = model->tab_idx;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
return tab_id;
|
return tab_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,10 +338,7 @@ void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { model->tab_idx = tab; }, false);
|
||||||
model->tab_idx = tab;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
|
void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
|
||||||
@@ -344,11 +351,13 @@ void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
|
|||||||
archive_set_file_type(&item, name, false, true);
|
archive_set_file_type(&item, name, false, true);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
files_array_push_back(model->files, item);
|
files_array_push_back(model->files, item);
|
||||||
model->item_cnt = files_array_size(model->files);
|
model->item_cnt = files_array_size(model->files);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
ArchiveFile_t_clear(&item);
|
ArchiveFile_t_clear(&item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,17 +388,19 @@ void archive_add_file_item(ArchiveBrowserView* browser, bool is_folder, const ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
files_array_push_back(model->files, item);
|
ArchiveBrowserViewModel * model,
|
||||||
return false;
|
{ files_array_push_back(model->files, item); },
|
||||||
});
|
false);
|
||||||
ArchiveFile_t_clear(&item);
|
ArchiveFile_t_clear(&item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_show_file_menu(ArchiveBrowserView* browser, bool show) {
|
void archive_show_file_menu(ArchiveBrowserView* browser, bool show) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
if(show) {
|
if(show) {
|
||||||
if(archive_is_item_in_array(model, model->item_idx)) {
|
if(archive_is_item_in_array(model, model->item_idx)) {
|
||||||
model->menu = true;
|
model->menu = true;
|
||||||
@@ -403,19 +414,15 @@ void archive_show_file_menu(ArchiveBrowserView* browser, bool show) {
|
|||||||
model->menu = false;
|
model->menu = false;
|
||||||
model->menu_idx = 0;
|
model->menu_idx = 0;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
|
void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { model->move_fav = active; }, true);
|
||||||
model->move_fav = active;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool archive_is_dir_exists(FuriString* path) {
|
static bool archive_is_dir_exists(FuriString* path) {
|
||||||
@@ -476,11 +483,13 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
|
|||||||
archive_switch_tab(browser, key);
|
archive_switch_tab(browser, key);
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
model->item_idx = 0;
|
model->item_idx = 0;
|
||||||
model->array_offset = 0;
|
model->array_offset = 0;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
}
|
}
|
||||||
@@ -493,10 +502,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, FuriString* path) {
|
|||||||
int32_t idx_temp = 0;
|
int32_t idx_temp = 0;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
|
||||||
idx_temp = model->item_idx;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
furi_string_set(browser->path, path);
|
furi_string_set(browser->path, path);
|
||||||
file_browser_worker_folder_enter(browser->worker, path, idx_temp);
|
file_browser_worker_folder_enter(browser->worker, path, idx_temp);
|
||||||
@@ -514,9 +520,6 @@ void archive_refresh_dir(ArchiveBrowserView* browser) {
|
|||||||
int32_t idx_temp = 0;
|
int32_t idx_temp = 0;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
|
||||||
idx_temp = model->item_idx;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
file_browser_worker_folder_refresh(browser->worker, idx_temp);
|
file_browser_worker_folder_refresh(browser->worker, idx_temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
uint16_t archive_favorites_count(void* context);
|
uint16_t archive_favorites_count(void* context);
|
||||||
bool archive_favorites_read(void* context);
|
bool archive_favorites_read(void* context);
|
||||||
bool archive_favorites_delete(const char* format, ...);
|
bool archive_favorites_delete(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
|
||||||
bool archive_is_favorite(const char* format, ...);
|
bool archive_is_favorite(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
|
||||||
bool archive_favorites_rename(const char* src, const char* dst);
|
bool archive_favorites_rename(const char* src, const char* dst);
|
||||||
void archive_add_to_favorites(const char* file_path);
|
void archive_add_to_favorites(const char* file_path);
|
||||||
void archive_favorites_save(void* context);
|
void archive_favorites_save(void* context);
|
||||||
|
|||||||
@@ -86,5 +86,7 @@ ARRAY_DEF(
|
|||||||
|
|
||||||
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
|
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
|
||||||
bool archive_get_items(void* context, const char* path);
|
bool archive_get_items(void* context, const char* path);
|
||||||
void archive_file_append(const char* path, const char* format, ...);
|
void archive_file_append(const char* path, const char* format, ...)
|
||||||
void archive_delete_file(void* context, const char* format, ...);
|
_ATTRIBUTE((__format__(__printf__, 2, 3)));
|
||||||
|
void archive_delete_file(void* context, const char* format, ...)
|
||||||
|
_ATTRIBUTE((__format__(__printf__, 2, 3)));
|
||||||
|
|||||||
@@ -263,33 +263,37 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
bool in_menu;
|
bool in_menu;
|
||||||
bool move_fav_mode;
|
bool move_fav_mode;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
in_menu = model->menu;
|
in_menu = model->menu;
|
||||||
move_fav_mode = model->move_fav;
|
move_fav_mode = model->move_fav;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
if(in_menu) {
|
if(in_menu) {
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
if(event->key == InputKeyUp || event->key == InputKeyDown) {
|
if(event->key == InputKeyUp || event->key == InputKeyDown) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->menu_idx = ((model->menu_idx - 1) + MENU_ITEMS) % MENU_ITEMS;
|
model->menu_idx = ((model->menu_idx - 1) + MENU_ITEMS) % MENU_ITEMS;
|
||||||
} else if(event->key == InputKeyDown) {
|
} else if(event->key == InputKeyDown) {
|
||||||
model->menu_idx = (model->menu_idx + 1) % MENU_ITEMS;
|
model->menu_idx = (model->menu_idx + 1) % MENU_ITEMS;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event->key == InputKeyOk) {
|
if(event->key == InputKeyOk) {
|
||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
idx = model->menu_idx;
|
ArchiveBrowserViewModel * model,
|
||||||
return false;
|
{ idx = model->menu_idx; },
|
||||||
});
|
false);
|
||||||
browser->callback(file_menu_actions[idx], browser->context);
|
browser->callback(file_menu_actions[idx], browser->context);
|
||||||
} else if(event->key == InputKeyBack) {
|
} else if(event->key == InputKeyBack) {
|
||||||
browser->callback(ArchiveBrowserEventFileMenuClose, browser->context);
|
browser->callback(ArchiveBrowserEventFileMenuClose, browser->context);
|
||||||
@@ -313,7 +317,9 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
if((event->key == InputKeyUp || event->key == InputKeyDown) &&
|
if((event->key == InputKeyUp || event->key == InputKeyDown) &&
|
||||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->item_idx =
|
model->item_idx =
|
||||||
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
||||||
@@ -334,9 +340,8 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
|
browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,11 +389,13 @@ ArchiveBrowserView* browser_alloc() {
|
|||||||
browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
|
browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{
|
||||||
files_array_init(model->files);
|
files_array_init(model->files);
|
||||||
model->tab_idx = TAB_DEFAULT;
|
model->tab_idx = TAB_DEFAULT;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
@@ -401,10 +408,10 @@ void browser_free(ArchiveBrowserView* browser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (ArchiveBrowserViewModel * model) {
|
browser->view,
|
||||||
files_array_clear(model->files);
|
ArchiveBrowserViewModel * model,
|
||||||
return false;
|
{ files_array_clear(model->files); },
|
||||||
});
|
false);
|
||||||
|
|
||||||
furi_string_free(browser->path);
|
furi_string_free(browser->path);
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ static const char ducky_cmd_string[] = {"STRING "};
|
|||||||
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
|
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
|
||||||
static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
|
static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
|
||||||
static const char ducky_cmd_repeat[] = {"REPEAT "};
|
static const char ducky_cmd_repeat[] = {"REPEAT "};
|
||||||
|
static const char ducky_cmd_sysrq[] = {"SYSRQ "};
|
||||||
|
|
||||||
static const char ducky_cmd_altchar[] = {"ALTCHAR "};
|
static const char ducky_cmd_altchar[] = {"ALTCHAR "};
|
||||||
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
|
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
|
||||||
@@ -292,6 +293,14 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
|
|||||||
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
|
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
|
||||||
state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt);
|
state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt);
|
||||||
return (state) ? (0) : SCRIPT_STATE_ERROR;
|
return (state) ? (0) : SCRIPT_STATE_ERROR;
|
||||||
|
} else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) {
|
||||||
|
// SYSRQ
|
||||||
|
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
|
||||||
|
uint16_t key = ducky_get_keycode(line_tmp, true);
|
||||||
|
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
|
||||||
|
furi_hal_hid_kb_press(key);
|
||||||
|
furi_hal_hid_kb_release_all();
|
||||||
|
return (0);
|
||||||
} else {
|
} else {
|
||||||
// Special keys + modifiers
|
// Special keys + modifiers
|
||||||
uint16_t key = ducky_get_keycode(line_tmp, false);
|
uint16_t key = ducky_get_keycode(line_tmp, false);
|
||||||
@@ -323,7 +332,7 @@ static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
|
|||||||
}
|
}
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
WORKER_TAG,
|
WORKER_TAG,
|
||||||
"set id: %04X:%04X mfr:%s product:%s",
|
"set id: %04lX:%04lX mfr:%s product:%s",
|
||||||
bad_usb->hid_cfg.vid,
|
bad_usb->hid_cfg.vid,
|
||||||
bad_usb->hid_cfg.pid,
|
bad_usb->hid_cfg.pid,
|
||||||
bad_usb->hid_cfg.manuf,
|
bad_usb->hid_cfg.manuf,
|
||||||
@@ -388,7 +397,7 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
|||||||
return 0;
|
return 0;
|
||||||
} else if(delay_val < 0) { // Script error
|
} else if(delay_val < 0) { // Script error
|
||||||
bad_usb->st.error_line = bad_usb->st.line_cur - 1;
|
bad_usb->st.error_line = bad_usb->st.line_cur - 1;
|
||||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", bad_usb->st.line_cur - 1);
|
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur - 1);
|
||||||
return SCRIPT_STATE_ERROR;
|
return SCRIPT_STATE_ERROR;
|
||||||
} else {
|
} else {
|
||||||
return (delay_val + bad_usb->defdelay);
|
return (delay_val + bad_usb->defdelay);
|
||||||
@@ -420,7 +429,7 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
|||||||
delay_val = ducky_parse_line(bad_usb, bad_usb->line);
|
delay_val = ducky_parse_line(bad_usb, bad_usb->line);
|
||||||
if(delay_val < 0) {
|
if(delay_val < 0) {
|
||||||
bad_usb->st.error_line = bad_usb->st.line_cur;
|
bad_usb->st.error_line = bad_usb->st.line_cur;
|
||||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", bad_usb->st.line_cur);
|
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur);
|
||||||
return SCRIPT_STATE_ERROR;
|
return SCRIPT_STATE_ERROR;
|
||||||
} else {
|
} else {
|
||||||
return (delay_val + bad_usb->defdelay);
|
return (delay_val + bad_usb->defdelay);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
furi_string_reset(disp_str);
|
furi_string_reset(disp_str);
|
||||||
canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14);
|
canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14);
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
furi_string_printf(disp_str, "delay %us", model->state.delay_remain);
|
furi_string_printf(disp_str, "delay %lus", model->state.delay_remain);
|
||||||
canvas_draw_str_aligned(
|
canvas_draw_str_aligned(
|
||||||
canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||||
furi_string_reset(disp_str);
|
furi_string_reset(disp_str);
|
||||||
@@ -145,29 +145,33 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c
|
|||||||
furi_assert(bad_usb);
|
furi_assert(bad_usb);
|
||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bad_usb->view, (BadUsbModel * model) {
|
bad_usb->view,
|
||||||
|
BadUsbModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
bad_usb->callback = callback;
|
bad_usb->callback = callback;
|
||||||
bad_usb->context = context;
|
bad_usb->context = context;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) {
|
void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) {
|
||||||
furi_assert(name);
|
furi_assert(name);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bad_usb->view, (BadUsbModel * model) {
|
bad_usb->view,
|
||||||
strlcpy(model->file_name, name, MAX_NAME_LEN);
|
BadUsbModel * model,
|
||||||
return true;
|
{ strlcpy(model->file_name, name, MAX_NAME_LEN); },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) {
|
void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) {
|
||||||
furi_assert(st);
|
furi_assert(st);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bad_usb->view, (BadUsbModel * model) {
|
bad_usb->view,
|
||||||
|
BadUsbModel * model,
|
||||||
|
{
|
||||||
memcpy(&(model->state), st, sizeof(BadUsbState));
|
memcpy(&(model->state), st, sizeof(BadUsbState));
|
||||||
model->anim_frame ^= 1;
|
model->anim_frame ^= 1;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address) {
|
|||||||
|
|
||||||
auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key);
|
auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key);
|
||||||
if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) {
|
if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) {
|
||||||
FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %x)!", name, gnu_sym_hash);
|
FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %lx)!", name, gnu_sym_hash);
|
||||||
result = false;
|
result = false;
|
||||||
} else {
|
} else {
|
||||||
result = true;
|
result = true;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
|
|||||||
do {
|
do {
|
||||||
file_selected = true;
|
file_selected = true;
|
||||||
loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
|
loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
|
||||||
|
size_t start = furi_get_tick();
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "FAP Loader is loading %s", furi_string_get_cstr(loader->fap_path));
|
FURI_LOG_I(TAG, "FAP Loader is loading %s", furi_string_get_cstr(loader->fap_path));
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start));
|
||||||
FURI_LOG_I(TAG, "FAP Loader is staring app");
|
FURI_LOG_I(TAG, "FAP Loader is staring app");
|
||||||
|
|
||||||
FuriThread* thread = flipper_application_spawn(loader->app, NULL);
|
FuriThread* thread = flipper_application_spawn(loader->app, NULL);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "usb_uart_bridge.h"
|
#include "usb_uart_bridge.h"
|
||||||
#include "furi_hal.h"
|
#include "furi_hal.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi_hal_usb_cdc.h>
|
#include <furi_hal_usb_cdc.h>
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
#include "cli/cli_vcp.h"
|
#include "cli/cli_vcp.h"
|
||||||
@@ -43,7 +42,7 @@ struct UsbUartBridge {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
FuriThread* tx_thread;
|
FuriThread* tx_thread;
|
||||||
|
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
|
|
||||||
FuriMutex* usb_mutex;
|
FuriMutex* usb_mutex;
|
||||||
|
|
||||||
@@ -74,12 +73,10 @@ static int32_t usb_uart_tx_thread(void* context);
|
|||||||
|
|
||||||
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
if(ev == UartIrqEventRXNE) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
|
||||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +153,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
|
|
||||||
memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig));
|
memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig));
|
||||||
|
|
||||||
usb_uart->rx_stream = xStreamBufferCreate(USB_UART_RX_BUF_SIZE, 1);
|
usb_uart->rx_stream = furi_stream_buffer_alloc(USB_UART_RX_BUF_SIZE, 1);
|
||||||
|
|
||||||
usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
|
usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
|
||||||
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
@@ -189,8 +186,8 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_check((events & FuriFlagError) == 0);
|
furi_check((events & FuriFlagError) == 0);
|
||||||
if(events & WorkerEvtStop) break;
|
if(events & WorkerEvtStop) break;
|
||||||
if(events & WorkerEvtRxDone) {
|
if(events & WorkerEvtRxDone) {
|
||||||
size_t len =
|
size_t len = furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) {
|
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) {
|
||||||
usb_uart->st.rx_cnt += len;
|
usb_uart->st.rx_cnt += len;
|
||||||
@@ -199,7 +196,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len);
|
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len);
|
||||||
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
|
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
|
||||||
} else {
|
} else {
|
||||||
xStreamBufferReset(usb_uart->rx_stream);
|
furi_stream_buffer_reset(usb_uart->rx_stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,7 +267,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_thread_join(usb_uart->tx_thread);
|
furi_thread_join(usb_uart->tx_thread);
|
||||||
furi_thread_free(usb_uart->tx_thread);
|
furi_thread_free(usb_uart->tx_thread);
|
||||||
|
|
||||||
vStreamBufferDelete(usb_uart->rx_stream);
|
furi_stream_buffer_free(usb_uart->rx_stream);
|
||||||
furi_mutex_free(usb_uart->usb_mutex);
|
furi_mutex_free(usb_uart->usb_mutex);
|
||||||
furi_semaphore_free(usb_uart->tx_sem);
|
furi_semaphore_free(usb_uart->tx_sem);
|
||||||
|
|
||||||
|
|||||||
@@ -48,23 +48,27 @@ static bool gpio_test_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
static bool gpio_test_process_left(GpioTest* gpio_test) {
|
static bool gpio_test_process_left(GpioTest* gpio_test) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
gpio_test->view, (GpioTestModel * model) {
|
gpio_test->view,
|
||||||
|
GpioTestModel * model,
|
||||||
|
{
|
||||||
if(model->pin_idx) {
|
if(model->pin_idx) {
|
||||||
model->pin_idx--;
|
model->pin_idx--;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gpio_test_process_right(GpioTest* gpio_test) {
|
static bool gpio_test_process_right(GpioTest* gpio_test) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
gpio_test->view, (GpioTestModel * model) {
|
gpio_test->view,
|
||||||
|
GpioTestModel * model,
|
||||||
|
{
|
||||||
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
||||||
model->pin_idx++;
|
model->pin_idx++;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +76,9 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
gpio_test->view, (GpioTestModel * model) {
|
gpio_test->view,
|
||||||
|
GpioTestModel * model,
|
||||||
|
{
|
||||||
if(event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
||||||
gpio_item_set_pin(model->pin_idx, true);
|
gpio_item_set_pin(model->pin_idx, true);
|
||||||
@@ -89,8 +95,8 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
gpio_test->callback(event->type, gpio_test->context);
|
gpio_test->callback(event->type, gpio_test->context);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
@@ -122,10 +128,12 @@ void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback,
|
|||||||
furi_assert(gpio_test);
|
furi_assert(gpio_test);
|
||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
gpio_test->view, (GpioTestModel * model) {
|
gpio_test->view,
|
||||||
|
GpioTestModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
gpio_test->callback = callback;
|
gpio_test->callback = callback;
|
||||||
gpio_test->context = context;
|
gpio_test->context = context;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
canvas_draw_str_aligned(canvas, 116, 24, AlignRight, AlignBottom, temp_str);
|
canvas_draw_str_aligned(canvas, 116, 24, AlignRight, AlignBottom, temp_str);
|
||||||
} else {
|
} else {
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "KB.");
|
canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "KiB.");
|
||||||
canvas_set_font(canvas, FontKeyboard);
|
canvas_set_font(canvas, FontKeyboard);
|
||||||
snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024);
|
snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024);
|
||||||
canvas_draw_str_aligned(canvas, 111, 24, AlignRight, AlignBottom, temp_str);
|
canvas_draw_str_aligned(canvas, 111, 24, AlignRight, AlignBottom, temp_str);
|
||||||
@@ -68,7 +68,7 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
canvas_draw_str_aligned(canvas, 116, 41, AlignRight, AlignBottom, temp_str);
|
canvas_draw_str_aligned(canvas, 116, 41, AlignRight, AlignBottom, temp_str);
|
||||||
} else {
|
} else {
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "KB.");
|
canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "KiB.");
|
||||||
canvas_set_font(canvas, FontKeyboard);
|
canvas_set_font(canvas, FontKeyboard);
|
||||||
snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024);
|
snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024);
|
||||||
canvas_draw_str_aligned(canvas, 111, 41, AlignRight, AlignBottom, temp_str);
|
canvas_draw_str_aligned(canvas, 111, 41, AlignRight, AlignBottom, temp_str);
|
||||||
@@ -129,12 +129,14 @@ void gpio_usb_uart_set_callback(GpioUsbUart* usb_uart, GpioUsbUartCallback callb
|
|||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
usb_uart->view, (GpioUsbUartModel * model) {
|
usb_uart->view,
|
||||||
|
GpioUsbUartModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
usb_uart->callback = callback;
|
usb_uart->callback = callback;
|
||||||
usb_uart->context = context;
|
usb_uart->context = context;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUartState* st) {
|
void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUartState* st) {
|
||||||
@@ -143,7 +145,9 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa
|
|||||||
furi_assert(st);
|
furi_assert(st);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (GpioUsbUartModel * model) {
|
instance->view,
|
||||||
|
GpioUsbUartModel * model,
|
||||||
|
{
|
||||||
model->baudrate = st->baudrate_cur;
|
model->baudrate = st->baudrate_cur;
|
||||||
model->vcp_port = cfg->vcp_ch;
|
model->vcp_port = cfg->vcp_ch;
|
||||||
model->tx_pin = (cfg->uart_ch == 0) ? (13) : (15);
|
model->tx_pin = (cfg->uart_ch == 0) ? (13) : (15);
|
||||||
@@ -152,6 +156,6 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa
|
|||||||
model->rx_active = (model->rx_cnt != st->rx_cnt);
|
model->rx_active = (model->rx_cnt != st->rx_cnt);
|
||||||
model->tx_cnt = st->tx_cnt;
|
model->tx_cnt = st->tx_cnt;
|
||||||
model->rx_cnt = st->rx_cnt;
|
model->rx_cnt = st->rx_cnt;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,14 +92,14 @@ static void infrared_find_vacant_remote_name(FuriString* name, const char* path)
|
|||||||
uint32_t i = 1;
|
uint32_t i = 1;
|
||||||
do {
|
do {
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
path_temp, "%s%u%s", furi_string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION);
|
path_temp, "%s%lu%s", furi_string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION);
|
||||||
status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL);
|
status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL);
|
||||||
} while(status == FSE_OK);
|
} while(status == FSE_OK);
|
||||||
|
|
||||||
furi_string_free(path_temp);
|
furi_string_free(path_temp);
|
||||||
|
|
||||||
if(status == FSE_NOT_EXIST) {
|
if(status == FSE_NOT_EXIST) {
|
||||||
furi_string_cat_printf(name, "%u", i);
|
furi_string_cat_printf(name, "%lu", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) {
|
|||||||
if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
|
if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Frequency is out of range (%lX - %lX): %lX",
|
"Frequency is out of range (%X - %X): %lX",
|
||||||
INFRARED_MIN_FREQUENCY,
|
INFRARED_MIN_FREQUENCY,
|
||||||
INFRARED_MAX_FREQUENCY,
|
INFRARED_MAX_FREQUENCY,
|
||||||
raw->frequency);
|
raw->frequency);
|
||||||
@@ -74,7 +74,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) {
|
|||||||
} else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
|
} else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Timings amount is out of range (0 - %lX): %lX",
|
"Timings amount is out of range (0 - %X): %X",
|
||||||
MAX_TIMINGS_AMOUNT,
|
MAX_TIMINGS_AMOUNT,
|
||||||
raw->timings_size);
|
raw->timings_size);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -9,14 +9,11 @@ void lfrfid_scene_save_data_on_enter(void* context) {
|
|||||||
|
|
||||||
bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData);
|
bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData);
|
||||||
|
|
||||||
if(need_restore) {
|
if(!need_restore) {
|
||||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
|
||||||
} else {
|
|
||||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||||
|
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
|
|
||||||
|
|
||||||
byte_input_set_header_text(byte_input, "Enter the data in hex");
|
byte_input_set_header_text(byte_input, "Enter the data in hex");
|
||||||
|
|
||||||
byte_input_set_result_callback(
|
byte_input_set_result_callback(
|
||||||
@@ -41,6 +38,8 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
||||||
|
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||||
|
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ void lfrfid_scene_save_success_on_enter(void* context) {
|
|||||||
LfRfid* app = context;
|
LfRfid* app = context;
|
||||||
Popup* popup = app->popup;
|
Popup* popup = app->popup;
|
||||||
|
|
||||||
|
// Clear state of data enter scene
|
||||||
|
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0);
|
||||||
|
|
||||||
DOLPHIN_DEED(DolphinDeedRfidSave);
|
DOLPHIN_DEED(DolphinDeedRfidSave);
|
||||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||||
|
|||||||
@@ -56,19 +56,13 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
void lfrfid_view_read_enter(void* context) {
|
void lfrfid_view_read_enter(void* context) {
|
||||||
LfRfidReadView* read_view = context;
|
LfRfidReadView* read_view = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
read_view->view, (LfRfidReadViewModel * model) {
|
read_view->view, LfRfidReadViewModel * model, { icon_animation_start(model->icon); }, true);
|
||||||
icon_animation_start(model->icon);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lfrfid_view_read_exit(void* context) {
|
void lfrfid_view_read_exit(void* context) {
|
||||||
LfRfidReadView* read_view = context;
|
LfRfidReadView* read_view = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
read_view->view, (LfRfidReadViewModel * model) {
|
read_view->view, LfRfidReadViewModel * model, { icon_animation_stop(model->icon); }, false);
|
||||||
icon_animation_stop(model->icon);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LfRfidReadView* lfrfid_view_read_alloc() {
|
LfRfidReadView* lfrfid_view_read_alloc() {
|
||||||
@@ -78,11 +72,13 @@ LfRfidReadView* lfrfid_view_read_alloc() {
|
|||||||
view_allocate_model(read_view->view, ViewModelTypeLocking, sizeof(LfRfidReadViewModel));
|
view_allocate_model(read_view->view, ViewModelTypeLocking, sizeof(LfRfidReadViewModel));
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
read_view->view, (LfRfidReadViewModel * model) {
|
read_view->view,
|
||||||
|
LfRfidReadViewModel * model,
|
||||||
|
{
|
||||||
model->icon = icon_animation_alloc(&A_Round_loader_8x8);
|
model->icon = icon_animation_alloc(&A_Round_loader_8x8);
|
||||||
view_tie_icon_animation(read_view->view, model->icon);
|
view_tie_icon_animation(read_view->view, model->icon);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
view_set_draw_callback(read_view->view, lfrfid_view_read_draw_callback);
|
view_set_draw_callback(read_view->view, lfrfid_view_read_draw_callback);
|
||||||
view_set_enter_callback(read_view->view, lfrfid_view_read_enter);
|
view_set_enter_callback(read_view->view, lfrfid_view_read_enter);
|
||||||
@@ -93,10 +89,7 @@ LfRfidReadView* lfrfid_view_read_alloc() {
|
|||||||
|
|
||||||
void lfrfid_view_read_free(LfRfidReadView* read_view) {
|
void lfrfid_view_read_free(LfRfidReadView* read_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
read_view->view, (LfRfidReadViewModel * model) {
|
read_view->view, LfRfidReadViewModel * model, { icon_animation_free(model->icon); }, false);
|
||||||
icon_animation_free(model->icon);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
view_free(read_view->view);
|
view_free(read_view->view);
|
||||||
free(read_view);
|
free(read_view);
|
||||||
@@ -108,10 +101,12 @@ View* lfrfid_view_read_get_view(LfRfidReadView* read_view) {
|
|||||||
|
|
||||||
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode) {
|
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
read_view->view, (LfRfidReadViewModel * model) {
|
read_view->view,
|
||||||
|
LfRfidReadViewModel * model,
|
||||||
|
{
|
||||||
icon_animation_stop(model->icon);
|
icon_animation_stop(model->icon);
|
||||||
icon_animation_start(model->icon);
|
icon_animation_start(model->icon);
|
||||||
model->read_mode = mode;
|
model->read_mode = mode;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) {
|
|||||||
char* current_key = (char*)malloc(sizeof(char) * 13);
|
char* current_key = (char*)malloc(sizeof(char) * 13);
|
||||||
strncpy(current_key, furi_string_get_cstr(temp_key), 12);
|
strncpy(current_key, furi_string_get_cstr(temp_key), 12);
|
||||||
MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
|
MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
|
||||||
FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
|
FURI_LOG_D("ListKeys", "Key %ld: %s", index, current_key);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc);
|
submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
|
|||||||
|
|
||||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||||
furi_string_cat_printf(temp_str, "\n%d", bytes_total);
|
furi_string_cat_printf(temp_str, "\n%ld", bytes_total);
|
||||||
if(data->version.sw_storage & 1) {
|
if(data->version.sw_storage & 1) {
|
||||||
furi_string_push_back(temp_str, '+');
|
furi_string_push_back(temp_str, '+');
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free);
|
||||||
|
|
||||||
uint16_t n_apps = 0;
|
uint16_t n_apps = 0;
|
||||||
uint16_t n_files = 0;
|
uint16_t n_files = 0;
|
||||||
|
|||||||
@@ -59,11 +59,11 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
MifareDesfireData* data = &dev_data->mf_df_data;
|
MifareDesfireData* data = &dev_data->mf_df_data;
|
||||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||||
furi_string_cat_printf(temp_str, "\n%d", bytes_total);
|
furi_string_cat_printf(temp_str, "\n%ld", bytes_total);
|
||||||
if(data->version.sw_storage & 1) {
|
if(data->version.sw_storage & 1) {
|
||||||
furi_string_push_back(temp_str, '+');
|
furi_string_push_back(temp_str, '+');
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free);
|
||||||
|
|
||||||
uint16_t n_apps = 0;
|
uint16_t n_apps = 0;
|
||||||
uint16_t n_files = 0;
|
uint16_t n_files = 0;
|
||||||
|
|||||||
@@ -64,10 +64,7 @@ static bool detect_reader_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
uint8_t nonces = 0;
|
uint8_t nonces = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
detect_reader->view, (DetectReaderViewModel * model) {
|
detect_reader->view, DetectReaderViewModel * model, { nonces = model->nonces; }, false);
|
||||||
nonces = model->nonces;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
if(event->key == InputKeyOk) {
|
if(event->key == InputKeyOk) {
|
||||||
@@ -103,12 +100,14 @@ void detect_reader_reset(DetectReader* detect_reader) {
|
|||||||
furi_assert(detect_reader);
|
furi_assert(detect_reader);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
detect_reader->view, (DetectReaderViewModel * model) {
|
detect_reader->view,
|
||||||
|
DetectReaderViewModel * model,
|
||||||
|
{
|
||||||
model->nonces = 0;
|
model->nonces = 0;
|
||||||
model->nonces_max = 0;
|
model->nonces_max = 0;
|
||||||
model->state = DetectReaderStateStart;
|
model->state = DetectReaderStateStart;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* detect_reader_get_view(DetectReader* detect_reader) {
|
View* detect_reader_get_view(DetectReader* detect_reader) {
|
||||||
@@ -132,27 +131,24 @@ void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_m
|
|||||||
furi_assert(detect_reader);
|
furi_assert(detect_reader);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
detect_reader->view, (DetectReaderViewModel * model) {
|
detect_reader->view,
|
||||||
model->nonces_max = nonces_max;
|
DetectReaderViewModel * model,
|
||||||
return false;
|
{ model->nonces_max = nonces_max; },
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) {
|
void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) {
|
||||||
furi_assert(detect_reader);
|
furi_assert(detect_reader);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
detect_reader->view, (DetectReaderViewModel * model) {
|
detect_reader->view,
|
||||||
model->nonces = nonces_collected;
|
DetectReaderViewModel * model,
|
||||||
return false;
|
{ model->nonces = nonces_collected; },
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) {
|
void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) {
|
||||||
furi_assert(detect_reader);
|
furi_assert(detect_reader);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
detect_reader->view, (DetectReaderViewModel * model) {
|
detect_reader->view, DetectReaderViewModel * model, { model->state = state; }, true);
|
||||||
model->state = state;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,20 +80,20 @@ DictAttack* dict_attack_alloc() {
|
|||||||
view_set_input_callback(dict_attack->view, dict_attack_input_callback);
|
view_set_input_callback(dict_attack->view, dict_attack_input_callback);
|
||||||
view_set_context(dict_attack->view, dict_attack);
|
view_set_context(dict_attack->view, dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
model->header = furi_string_alloc();
|
DictAttackViewModel * model,
|
||||||
return false;
|
{ model->header = furi_string_alloc(); },
|
||||||
});
|
false);
|
||||||
return dict_attack;
|
return dict_attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_free(DictAttack* dict_attack) {
|
void dict_attack_free(DictAttack* dict_attack) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
furi_string_free(model->header);
|
DictAttackViewModel * model,
|
||||||
return false;
|
{ furi_string_free(model->header); },
|
||||||
});
|
false);
|
||||||
view_free(dict_attack->view);
|
view_free(dict_attack->view);
|
||||||
free(dict_attack);
|
free(dict_attack);
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,9 @@ void dict_attack_free(DictAttack* dict_attack) {
|
|||||||
void dict_attack_reset(DictAttack* dict_attack) {
|
void dict_attack_reset(DictAttack* dict_attack) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
model->state = DictAttackStateRead;
|
model->state = DictAttackStateRead;
|
||||||
model->type = MfClassicType1k;
|
model->type = MfClassicType1k;
|
||||||
model->sectors_total = 0;
|
model->sectors_total = 0;
|
||||||
@@ -112,8 +114,8 @@ void dict_attack_reset(DictAttack* dict_attack) {
|
|||||||
model->dict_keys_total = 0;
|
model->dict_keys_total = 0;
|
||||||
model->dict_keys_current = 0;
|
model->dict_keys_current = 0;
|
||||||
furi_string_reset(model->header);
|
furi_string_reset(model->header);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* dict_attack_get_view(DictAttack* dict_attack) {
|
View* dict_attack_get_view(DictAttack* dict_attack) {
|
||||||
@@ -133,99 +135,103 @@ void dict_attack_set_header(DictAttack* dict_attack, const char* header) {
|
|||||||
furi_assert(header);
|
furi_assert(header);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
furi_string_set(model->header, header);
|
DictAttackViewModel * model,
|
||||||
return true;
|
{ furi_string_set(model->header, header); },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type) {
|
void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
model->state = DictAttackStateRead;
|
model->state = DictAttackStateRead;
|
||||||
model->sectors_total = mf_classic_get_total_sectors_num(type);
|
model->sectors_total = mf_classic_get_total_sectors_num(type);
|
||||||
model->keys_total = model->sectors_total * 2;
|
model->keys_total = model->sectors_total * 2;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_card_removed(DictAttack* dict_attack) {
|
void dict_attack_set_card_removed(DictAttack* dict_attack) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
model->state = DictAttackStateCardRemoved;
|
DictAttackViewModel * model,
|
||||||
return true;
|
{ model->state = DictAttackStateCardRemoved; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) {
|
void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view, DictAttackViewModel * model, { model->sectors_read = sec_read; }, true);
|
||||||
model->sectors_read = sec_read;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found) {
|
void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view, DictAttackViewModel * model, { model->keys_found = keys_found; }, true);
|
||||||
model->keys_found = keys_found;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) {
|
void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
model->sector_current = curr_sec;
|
model->sector_current = curr_sec;
|
||||||
model->dict_keys_current = 0;
|
model->dict_keys_current = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_inc_current_sector(DictAttack* dict_attack) {
|
void dict_attack_inc_current_sector(DictAttack* dict_attack) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
if(model->sector_current < model->sectors_total) {
|
if(model->sector_current < model->sectors_total) {
|
||||||
model->sector_current++;
|
model->sector_current++;
|
||||||
model->dict_keys_current = 0;
|
model->dict_keys_current = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_inc_keys_found(DictAttack* dict_attack) {
|
void dict_attack_inc_keys_found(DictAttack* dict_attack) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
if(model->keys_found < model->keys_total) {
|
if(model->keys_found < model->keys_total) {
|
||||||
model->keys_found++;
|
model->keys_found++;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) {
|
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
model->dict_keys_total = dict_keys_total;
|
DictAttackViewModel * model,
|
||||||
return true;
|
{ model->dict_keys_total = dict_keys_total; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) {
|
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) {
|
||||||
furi_assert(dict_attack);
|
furi_assert(dict_attack);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dict_attack->view, (DictAttackViewModel * model) {
|
dict_attack->view,
|
||||||
|
DictAttackViewModel * model,
|
||||||
|
{
|
||||||
if(model->dict_keys_current + keys_tried < model->dict_keys_total) {
|
if(model->dict_keys_current + keys_tried < model->dict_keys_total) {
|
||||||
model->dict_keys_current += keys_tried;
|
model->dict_keys_current += keys_tried;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
|||||||
|
|
||||||
FURI_LOG_T(
|
FURI_LOG_T(
|
||||||
TAG,
|
TAG,
|
||||||
"RSSI: avg %f, max %f at %u, min %f",
|
"RSSI: avg %f, max %f at %lu, min %f",
|
||||||
(double)(rssi_avg / rssi_avg_samples),
|
(double)(rssi_avg / rssi_avg_samples),
|
||||||
(double)frequency_rssi.rssi_coarse,
|
(double)frequency_rssi.rssi_coarse,
|
||||||
frequency_rssi.frequency_coarse,
|
frequency_rssi.frequency_coarse,
|
||||||
@@ -180,7 +180,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
|||||||
|
|
||||||
rssi = furi_hal_subghz_get_rssi();
|
rssi = furi_hal_subghz_get_rssi();
|
||||||
|
|
||||||
FURI_LOG_T(TAG, "#:%u:%f", frequency, (double)rssi);
|
FURI_LOG_T(TAG, "#:%lu:%f", frequency, (double)rssi);
|
||||||
|
|
||||||
if(frequency_rssi.rssi_fine < rssi) {
|
if(frequency_rssi.rssi_fine < rssi) {
|
||||||
frequency_rssi.rssi_fine = rssi;
|
frequency_rssi.rssi_fine = rssi;
|
||||||
@@ -193,7 +193,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
|||||||
// Deliver results fine
|
// Deliver results fine
|
||||||
if(frequency_rssi.rssi_fine > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) {
|
if(frequency_rssi.rssi_fine > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) {
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG, "=:%u:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine);
|
TAG, "=:%lu:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine);
|
||||||
|
|
||||||
instance->sample_hold_counter = 20;
|
instance->sample_hold_counter = 20;
|
||||||
rssi_temp = frequency_rssi.rssi_fine;
|
rssi_temp = frequency_rssi.rssi_fine;
|
||||||
@@ -217,7 +217,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
|||||||
(instance->sample_hold_counter < 10)) {
|
(instance->sample_hold_counter < 10)) {
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"~:%u:%f",
|
"~:%lu:%f",
|
||||||
frequency_rssi.frequency_coarse,
|
frequency_rssi.frequency_coarse,
|
||||||
(double)frequency_rssi.rssi_coarse);
|
(double)frequency_rssi.rssi_coarse);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
#include <lib/subghz/subghz_keystore.h>
|
#include <lib/subghz/subghz_keystore.h>
|
||||||
@@ -152,8 +151,8 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) {
|
|||||||
"Protocol: Princeton\n"
|
"Protocol: Princeton\n"
|
||||||
"Bit: 24\n"
|
"Bit: 24\n"
|
||||||
"Key: 00 00 00 00 00 %02X %02X %02X\n"
|
"Key: 00 00 00 00 00 %02X %02X %02X\n"
|
||||||
"TE: %d\n"
|
"TE: %ld\n"
|
||||||
"Repeat: %d\n",
|
"Repeat: %ld\n",
|
||||||
(uint8_t)((key >> 16) & 0xFF),
|
(uint8_t)((key >> 16) & 0xFF),
|
||||||
(uint8_t)((key >> 8) & 0xFF),
|
(uint8_t)((key >> 8) & 0xFF),
|
||||||
(uint8_t)(key & 0xFF),
|
(uint8_t)(key & 0xFF),
|
||||||
@@ -194,23 +193,21 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile bool overrun;
|
volatile bool overrun;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
size_t packet_count;
|
size_t packet_count;
|
||||||
} SubGhzCliCommandRx;
|
} SubGhzCliCommandRx;
|
||||||
|
|
||||||
static void subghz_cli_command_rx_capture_callback(bool level, uint32_t duration, void* context) {
|
static void subghz_cli_command_rx_capture_callback(bool level, uint32_t duration, void* context) {
|
||||||
SubGhzCliCommandRx* instance = context;
|
SubGhzCliCommandRx* instance = context;
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
LevelDuration level_duration = level_duration_make(level, duration);
|
LevelDuration level_duration = level_duration_make(level, duration);
|
||||||
if(instance->overrun) {
|
if(instance->overrun) {
|
||||||
instance->overrun = false;
|
instance->overrun = false;
|
||||||
level_duration = level_duration_reset();
|
level_duration = level_duration_reset();
|
||||||
}
|
}
|
||||||
size_t ret = xStreamBufferSendFromISR(
|
size_t ret =
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0);
|
||||||
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_cli_command_rx_callback(
|
static void subghz_cli_command_rx_callback(
|
||||||
@@ -249,7 +246,8 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
// Allocate context and buffers
|
// Allocate context and buffers
|
||||||
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
|
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
|
||||||
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
instance->stream =
|
||||||
|
furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
||||||
furi_check(instance->stream);
|
furi_check(instance->stream);
|
||||||
|
|
||||||
SubGhzEnvironment* environment = subghz_environment_alloc();
|
SubGhzEnvironment* environment = subghz_environment_alloc();
|
||||||
@@ -279,8 +277,8 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
|
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
|
||||||
LevelDuration level_duration;
|
LevelDuration level_duration;
|
||||||
while(!cli_cmd_interrupt_received(cli)) {
|
while(!cli_cmd_interrupt_received(cli)) {
|
||||||
int ret =
|
int ret = furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
||||||
if(ret == sizeof(LevelDuration)) {
|
if(ret == sizeof(LevelDuration)) {
|
||||||
if(level_duration_is_reset(level_duration)) {
|
if(level_duration_is_reset(level_duration)) {
|
||||||
printf(".");
|
printf(".");
|
||||||
@@ -304,7 +302,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
// Cleanup
|
// Cleanup
|
||||||
subghz_receiver_free(receiver);
|
subghz_receiver_free(receiver);
|
||||||
subghz_environment_free(environment);
|
subghz_environment_free(environment);
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +794,7 @@ static bool subghz_on_system_start_istream_decode_band(
|
|||||||
|
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
"SubGhzOnStart",
|
"SubGhzOnStart",
|
||||||
"Add allowed band: start %dHz, stop %dHz, power_limit %ddBm, duty_cycle %d%%",
|
"Add allowed band: start %ldHz, stop %ldHz, power_limit %ddBm, duty_cycle %d%%",
|
||||||
band.start,
|
band.start,
|
||||||
band.end,
|
band.end,
|
||||||
band.power_limit,
|
band.power_limit,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void subghz_get_frequency_modulation(SubGhz* subghz, FuriString* frequency, Furi
|
|||||||
subghz->txrx->preset->frequency / 10000 % 100);
|
subghz->txrx->preset->frequency / 10000 % 100);
|
||||||
}
|
}
|
||||||
if(modulation != NULL) {
|
if(modulation != NULL) {
|
||||||
furi_string_printf(modulation, "%0.2s", furi_string_get_cstr(subghz->txrx->preset->name));
|
furi_string_printf(modulation, "%2s", furi_string_get_cstr(subghz->txrx->preset->name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,17 +67,17 @@ void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLo
|
|||||||
if(lock == SubGhzLockOn) {
|
if(lock == SubGhzLockOn) {
|
||||||
subghz_receiver->lock = lock;
|
subghz_receiver->lock = lock;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
model->bar_show = SubGhzViewReceiverBarShowLock;
|
SubGhzViewReceiverModel * model,
|
||||||
return true;
|
{ model->bar_show = SubGhzViewReceiverBarShowLock; },
|
||||||
});
|
true);
|
||||||
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000));
|
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000));
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
model->bar_show = SubGhzViewReceiverBarShowDefault;
|
SubGhzViewReceiverModel * model,
|
||||||
return true;
|
{ model->bar_show = SubGhzViewReceiverBarShowDefault; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,9 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv
|
|||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
size_t history_item = model->history_item;
|
size_t history_item = model->history_item;
|
||||||
uint16_t bounds = history_item > 3 ? 2 : history_item;
|
uint16_t bounds = history_item > 3 ? 2 : history_item;
|
||||||
|
|
||||||
@@ -107,8 +109,8 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv
|
|||||||
} else if(model->list_offset > model->idx - bounds) {
|
} else if(model->list_offset > model->idx - bounds) {
|
||||||
model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0);
|
model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_view_receiver_add_item_to_menu(
|
void subghz_view_receiver_add_item_to_menu(
|
||||||
@@ -117,7 +119,9 @@ void subghz_view_receiver_add_item_to_menu(
|
|||||||
uint8_t type) {
|
uint8_t type) {
|
||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
SubGhzReceiverMenuItem* item_menu =
|
SubGhzReceiverMenuItem* item_menu =
|
||||||
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
|
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
|
||||||
item_menu->item_str = furi_string_alloc_set(name);
|
item_menu->item_str = furi_string_alloc_set(name);
|
||||||
@@ -128,9 +132,8 @@ void subghz_view_receiver_add_item_to_menu(
|
|||||||
} else {
|
} else {
|
||||||
model->history_item++;
|
model->history_item++;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
subghz_view_receiver_update_offset(subghz_receiver);
|
subghz_view_receiver_update_offset(subghz_receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,12 +144,14 @@ void subghz_view_receiver_add_data_statusbar(
|
|||||||
const char* history_stat_str) {
|
const char* history_stat_str) {
|
||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
furi_string_set(model->frequency_str, frequency_str);
|
furi_string_set(model->frequency_str, frequency_str);
|
||||||
furi_string_set(model->preset_str, preset_str);
|
furi_string_set(model->preset_str, preset_str);
|
||||||
furi_string_set(model->history_stat_str, history_stat_str);
|
furi_string_set(model->history_stat_str, history_stat_str);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||||
@@ -240,10 +245,10 @@ static void subghz_view_receiver_timer_callback(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzViewReceiver* subghz_receiver = context;
|
SubGhzViewReceiver* subghz_receiver = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
model->bar_show = SubGhzViewReceiverBarShowDefault;
|
SubGhzViewReceiverModel * model,
|
||||||
return true;
|
{ model->bar_show = SubGhzViewReceiverBarShowDefault; },
|
||||||
});
|
true);
|
||||||
if(subghz_receiver->lock_count < UNLOCK_CNT) {
|
if(subghz_receiver->lock_count < UNLOCK_CNT) {
|
||||||
subghz_receiver->callback(
|
subghz_receiver->callback(
|
||||||
SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context);
|
SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context);
|
||||||
@@ -260,10 +265,10 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
if(subghz_receiver->lock == SubGhzLockOn) {
|
if(subghz_receiver->lock == SubGhzLockOn) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
model->bar_show = SubGhzViewReceiverBarShowToUnlockPress;
|
SubGhzViewReceiverModel * model,
|
||||||
return true;
|
{ model->bar_show = SubGhzViewReceiverBarShowToUnlockPress; },
|
||||||
});
|
true);
|
||||||
if(subghz_receiver->lock_count == 0) {
|
if(subghz_receiver->lock_count == 0) {
|
||||||
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000));
|
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000));
|
||||||
}
|
}
|
||||||
@@ -274,10 +279,10 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
|
|||||||
// subghz_receiver->callback(
|
// subghz_receiver->callback(
|
||||||
// SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context);
|
// SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
model->bar_show = SubGhzViewReceiverBarShowUnlock;
|
SubGhzViewReceiverModel * model,
|
||||||
return true;
|
{ model->bar_show = SubGhzViewReceiverBarShowUnlock; },
|
||||||
});
|
true);
|
||||||
//subghz_receiver->lock = SubGhzLockOff;
|
//subghz_receiver->lock = SubGhzLockOff;
|
||||||
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(650));
|
furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(650));
|
||||||
}
|
}
|
||||||
@@ -291,29 +296,35 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
|
|||||||
event->key == InputKeyUp &&
|
event->key == InputKeyUp &&
|
||||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
if(model->idx != 0) model->idx--;
|
if(model->idx != 0) model->idx--;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
} else if(
|
} else if(
|
||||||
event->key == InputKeyDown &&
|
event->key == InputKeyDown &&
|
||||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
if(model->idx != model->history_item - 1) model->idx++;
|
if(model->idx != model->history_item - 1) model->idx++;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||||
subghz_receiver->callback(SubGhzCustomEventViewReceiverConfig, subghz_receiver->context);
|
subghz_receiver->callback(SubGhzCustomEventViewReceiverConfig, subghz_receiver->context);
|
||||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
if(model->history_item != 0) {
|
if(model->history_item != 0) {
|
||||||
subghz_receiver->callback(
|
subghz_receiver->callback(
|
||||||
SubGhzCustomEventViewReceiverOK, subghz_receiver->context);
|
SubGhzCustomEventViewReceiverOK, subghz_receiver->context);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
subghz_view_receiver_update_offset(subghz_receiver);
|
subghz_view_receiver_update_offset(subghz_receiver);
|
||||||
@@ -329,7 +340,9 @@ void subghz_view_receiver_exit(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzViewReceiver* subghz_receiver = context;
|
SubGhzViewReceiver* subghz_receiver = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
furi_string_reset(model->frequency_str);
|
furi_string_reset(model->frequency_str);
|
||||||
furi_string_reset(model->preset_str);
|
furi_string_reset(model->preset_str);
|
||||||
furi_string_reset(model->history_stat_str);
|
furi_string_reset(model->history_stat_str);
|
||||||
@@ -342,8 +355,8 @@ void subghz_view_receiver_exit(void* context) {
|
|||||||
model->idx = 0;
|
model->idx = 0;
|
||||||
model->list_offset = 0;
|
model->list_offset = 0;
|
||||||
model->history_item = 0;
|
model->history_item = 0;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
furi_timer_stop(subghz_receiver->timer);
|
furi_timer_stop(subghz_receiver->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,15 +377,17 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() {
|
|||||||
view_set_exit_callback(subghz_receiver->view, subghz_view_receiver_exit);
|
view_set_exit_callback(subghz_receiver->view, subghz_view_receiver_exit);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
model->frequency_str = furi_string_alloc();
|
model->frequency_str = furi_string_alloc();
|
||||||
model->preset_str = furi_string_alloc();
|
model->preset_str = furi_string_alloc();
|
||||||
model->history_stat_str = furi_string_alloc();
|
model->history_stat_str = furi_string_alloc();
|
||||||
model->bar_show = SubGhzViewReceiverBarShowDefault;
|
model->bar_show = SubGhzViewReceiverBarShowDefault;
|
||||||
model->history = malloc(sizeof(SubGhzReceiverHistory));
|
model->history = malloc(sizeof(SubGhzReceiverHistory));
|
||||||
SubGhzReceiverMenuItemArray_init(model->history->data);
|
SubGhzReceiverMenuItemArray_init(model->history->data);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
subghz_receiver->timer =
|
subghz_receiver->timer =
|
||||||
furi_timer_alloc(subghz_view_receiver_timer_callback, FuriTimerTypeOnce, subghz_receiver);
|
furi_timer_alloc(subghz_view_receiver_timer_callback, FuriTimerTypeOnce, subghz_receiver);
|
||||||
return subghz_receiver;
|
return subghz_receiver;
|
||||||
@@ -382,7 +397,9 @@ void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) {
|
|||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
furi_string_free(model->frequency_str);
|
furi_string_free(model->frequency_str);
|
||||||
furi_string_free(model->preset_str);
|
furi_string_free(model->preset_str);
|
||||||
furi_string_free(model->history_stat_str);
|
furi_string_free(model->history_stat_str);
|
||||||
@@ -393,8 +410,8 @@ void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) {
|
|||||||
}
|
}
|
||||||
SubGhzReceiverMenuItemArray_clear(model->history->data);
|
SubGhzReceiverMenuItemArray_clear(model->history->data);
|
||||||
free(model->history);
|
free(model->history);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
furi_timer_free(subghz_receiver->timer);
|
furi_timer_free(subghz_receiver->timer);
|
||||||
view_free(subghz_receiver->view);
|
view_free(subghz_receiver->view);
|
||||||
free(subghz_receiver);
|
free(subghz_receiver);
|
||||||
@@ -409,20 +426,19 @@ uint16_t subghz_view_receiver_get_idx_menu(SubGhzViewReceiver* subghz_receiver)
|
|||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view, SubGhzViewReceiverModel * model, { idx = model->idx; }, false);
|
||||||
idx = model->idx;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint16_t idx) {
|
void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint16_t idx) {
|
||||||
furi_assert(subghz_receiver);
|
furi_assert(subghz_receiver);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
|
subghz_receiver->view,
|
||||||
|
SubGhzViewReceiverModel * model,
|
||||||
|
{
|
||||||
model->idx = idx;
|
model->idx = idx;
|
||||||
if(model->idx > 2) model->list_offset = idx - 2;
|
if(model->idx > 2) model->list_offset = idx - 2;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
subghz_view_receiver_update_offset(subghz_receiver);
|
subghz_view_receiver_update_offset(subghz_receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,12 +132,14 @@ void subghz_frequency_analyzer_pair_callback(
|
|||||||
}
|
}
|
||||||
//update history
|
//update history
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
|
instance->view,
|
||||||
|
SubGhzFrequencyAnalyzerModel * model,
|
||||||
|
{
|
||||||
model->history_frequency[2] = model->history_frequency[1];
|
model->history_frequency[2] = model->history_frequency[1];
|
||||||
model->history_frequency[1] = model->history_frequency[0];
|
model->history_frequency[1] = model->history_frequency[0];
|
||||||
model->history_frequency[0] = model->frequency;
|
model->history_frequency[0] = model->frequency;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
} else if((rssi != 0.f) && (!instance->locked)) {
|
} else if((rssi != 0.f) && (!instance->locked)) {
|
||||||
if(instance->callback) {
|
if(instance->callback) {
|
||||||
instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context);
|
instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context);
|
||||||
@@ -146,12 +148,14 @@ void subghz_frequency_analyzer_pair_callback(
|
|||||||
|
|
||||||
instance->locked = (rssi != 0.f);
|
instance->locked = (rssi != 0.f);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
|
instance->view,
|
||||||
|
SubGhzFrequencyAnalyzerModel * model,
|
||||||
|
{
|
||||||
model->rssi = rssi;
|
model->rssi = rssi;
|
||||||
model->frequency = frequency;
|
model->frequency = frequency;
|
||||||
model->signal = signal;
|
model->signal = signal;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_frequency_analyzer_enter(void* context) {
|
void subghz_frequency_analyzer_enter(void* context) {
|
||||||
@@ -169,14 +173,16 @@ void subghz_frequency_analyzer_enter(void* context) {
|
|||||||
subghz_frequency_analyzer_worker_start(instance->worker);
|
subghz_frequency_analyzer_worker_start(instance->worker);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
|
instance->view,
|
||||||
|
SubGhzFrequencyAnalyzerModel * model,
|
||||||
|
{
|
||||||
model->rssi = 0;
|
model->rssi = 0;
|
||||||
model->frequency = 0;
|
model->frequency = 0;
|
||||||
model->history_frequency[2] = 0;
|
model->history_frequency[2] = 0;
|
||||||
model->history_frequency[1] = 0;
|
model->history_frequency[1] = 0;
|
||||||
model->history_frequency[0] = 0;
|
model->history_frequency[0] = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_frequency_analyzer_exit(void* context) {
|
void subghz_frequency_analyzer_exit(void* context) {
|
||||||
@@ -190,10 +196,7 @@ void subghz_frequency_analyzer_exit(void* context) {
|
|||||||
subghz_frequency_analyzer_worker_free(instance->worker);
|
subghz_frequency_analyzer_worker_free(instance->worker);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
|
instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true);
|
||||||
model->rssi = 0;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
|
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
|
||||||
@@ -210,10 +213,7 @@ SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
|
|||||||
view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit);
|
view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
|
instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true);
|
||||||
model->rssi = 0;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,11 +45,13 @@ void subghz_read_raw_add_data_statusbar(
|
|||||||
const char* preset_str) {
|
const char* preset_str) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
furi_string_set(model->frequency_str, frequency_str);
|
furi_string_set(model->frequency_str, frequency_str);
|
||||||
furi_string_set(model->preset_str, preset_str);
|
furi_string_set(model->preset_str, preset_str);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) {
|
void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) {
|
||||||
@@ -63,31 +65,35 @@ void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
model->rssi_history[model->ind_write++] = u_rssi;
|
model->rssi_history[model->ind_write++] = u_rssi;
|
||||||
if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
|
if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
|
||||||
model->rssi_history_end = true;
|
model->rssi_history_end = true;
|
||||||
model->ind_write = 0;
|
model->ind_write = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample) {
|
void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
furi_string_printf(model->sample_write, "%d spl.", sample);
|
SubGhzReadRAWModel * model,
|
||||||
return false;
|
{ furi_string_printf(model->sample_write, "%d spl.", sample); },
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_read_raw_stop_send(SubGhzReadRAW* instance) {
|
void subghz_read_raw_stop_send(SubGhzReadRAW* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
switch(model->status) {
|
switch(model->status) {
|
||||||
case SubGhzReadRAWStatusTXRepeat:
|
case SubGhzReadRAWStatusTXRepeat:
|
||||||
case SubGhzReadRAWStatusLoadKeyTXRepeat:
|
case SubGhzReadRAWStatusLoadKeyTXRepeat:
|
||||||
@@ -105,19 +111,21 @@ void subghz_read_raw_stop_send(SubGhzReadRAW* instance) {
|
|||||||
model->status = SubGhzReadRAWStatusIDLE;
|
model->status = SubGhzReadRAWStatusIDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_read_raw_update_sin(SubGhzReadRAW* instance) {
|
void subghz_read_raw_update_sin(SubGhzReadRAW* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->ind_sin++ > 62) {
|
if(model->ind_sin++ > 62) {
|
||||||
model->ind_sin = 0;
|
model->ind_sin = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t subghz_read_raw_tab_sin(uint8_t x) {
|
static int8_t subghz_read_raw_tab_sin(uint8_t x) {
|
||||||
@@ -286,9 +294,11 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
//further check of events is not needed, we exit
|
//further check of events is not needed, we exit
|
||||||
return false;
|
return false;
|
||||||
} else if(event->key == InputKeyOk && event->type == InputTypePress) {
|
} else if(event->key == InputKeyOk && event->type == InputTypePress) {
|
||||||
|
uint8_t ret = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
uint8_t ret = false;
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
switch(model->status) {
|
switch(model->status) {
|
||||||
case SubGhzReadRAWStatusIDLE:
|
case SubGhzReadRAWStatusIDLE:
|
||||||
// Start TX
|
// Start TX
|
||||||
@@ -314,11 +324,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
},
|
||||||
});
|
ret);
|
||||||
} else if(event->key == InputKeyOk && event->type == InputTypeRelease) {
|
} else if(event->key == InputKeyOk && event->type == InputTypeRelease) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzReadRAWStatusTXRepeat) {
|
if(model->status == SubGhzReadRAWStatusTXRepeat) {
|
||||||
// Stop repeat TX
|
// Stop repeat TX
|
||||||
model->status = SubGhzReadRAWStatusTX;
|
model->status = SubGhzReadRAWStatusTX;
|
||||||
@@ -326,11 +338,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
// Stop repeat TX
|
// Stop repeat TX
|
||||||
model->status = SubGhzReadRAWStatusLoadKeyTX;
|
model->status = SubGhzReadRAWStatusLoadKeyTX;
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
} else if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
switch(model->status) {
|
switch(model->status) {
|
||||||
case SubGhzReadRAWStatusREC:
|
case SubGhzReadRAWStatusREC:
|
||||||
//Stop REC
|
//Stop REC
|
||||||
@@ -357,11 +371,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
instance->callback(SubGhzCustomEventViewReadRAWBack, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWBack, instance->context);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzReadRAWStatusStart) {
|
if(model->status == SubGhzReadRAWStatusStart) {
|
||||||
//Config
|
//Config
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context);
|
||||||
@@ -376,11 +392,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
furi_string_reset(model->file_name);
|
furi_string_reset(model->file_name);
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzReadRAWStatusIDLE) {
|
if(model->status == SubGhzReadRAWStatusIDLE) {
|
||||||
//Save
|
//Save
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context);
|
||||||
@@ -388,11 +406,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
//More
|
//More
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzReadRAWStatusStart) {
|
if(model->status == SubGhzReadRAWStatusStart) {
|
||||||
//Record
|
//Record
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWREC, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWREC, instance->context);
|
||||||
@@ -404,8 +424,8 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
|
|||||||
instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context);
|
||||||
model->status = SubGhzReadRAWStatusIDLE;
|
model->status = SubGhzReadRAWStatusIDLE;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -419,36 +439,42 @@ void subghz_read_raw_set_status(
|
|||||||
switch(status) {
|
switch(status) {
|
||||||
case SubGhzReadRAWStatusStart:
|
case SubGhzReadRAWStatusStart:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
model->status = SubGhzReadRAWStatusStart;
|
model->status = SubGhzReadRAWStatusStart;
|
||||||
model->rssi_history_end = false;
|
model->rssi_history_end = false;
|
||||||
model->ind_write = 0;
|
model->ind_write = 0;
|
||||||
furi_string_reset(model->file_name);
|
furi_string_reset(model->file_name);
|
||||||
furi_string_set(model->sample_write, "0 spl.");
|
furi_string_set(model->sample_write, "0 spl.");
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
break;
|
break;
|
||||||
case SubGhzReadRAWStatusIDLE:
|
case SubGhzReadRAWStatusIDLE:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
model->status = SubGhzReadRAWStatusIDLE;
|
SubGhzReadRAWModel * model,
|
||||||
return true;
|
{ model->status = SubGhzReadRAWStatusIDLE; },
|
||||||
});
|
true);
|
||||||
break;
|
break;
|
||||||
case SubGhzReadRAWStatusLoadKeyTX:
|
case SubGhzReadRAWStatusLoadKeyTX:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
|
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
|
||||||
model->rssi_history_end = false;
|
model->rssi_history_end = false;
|
||||||
model->ind_write = 0;
|
model->ind_write = 0;
|
||||||
furi_string_set(model->file_name, file_name);
|
furi_string_set(model->file_name, file_name);
|
||||||
furi_string_set(model->sample_write, "RAW");
|
furi_string_set(model->sample_write, "RAW");
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
break;
|
break;
|
||||||
case SubGhzReadRAWStatusSaveKey:
|
case SubGhzReadRAWStatusSaveKey:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
|
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
|
||||||
if(!model->ind_write) {
|
if(!model->ind_write) {
|
||||||
furi_string_set(model->file_name, file_name);
|
furi_string_set(model->file_name, file_name);
|
||||||
@@ -456,8 +482,8 @@ void subghz_read_raw_set_status(
|
|||||||
} else {
|
} else {
|
||||||
furi_string_reset(model->file_name);
|
furi_string_reset(model->file_name);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -476,15 +502,17 @@ void subghz_read_raw_exit(void* context) {
|
|||||||
SubGhzReadRAW* instance = context;
|
SubGhzReadRAW* instance = context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
if(model->status != SubGhzReadRAWStatusIDLE &&
|
if(model->status != SubGhzReadRAWStatusIDLE &&
|
||||||
model->status != SubGhzReadRAWStatusStart &&
|
model->status != SubGhzReadRAWStatusStart &&
|
||||||
model->status != SubGhzReadRAWStatusLoadKeyIDLE) {
|
model->status != SubGhzReadRAWStatusLoadKeyIDLE) {
|
||||||
instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context);
|
instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context);
|
||||||
model->status = SubGhzReadRAWStatusStart;
|
model->status = SubGhzReadRAWStatusStart;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzReadRAW* subghz_read_raw_alloc() {
|
SubGhzReadRAW* subghz_read_raw_alloc() {
|
||||||
@@ -500,14 +528,16 @@ SubGhzReadRAW* subghz_read_raw_alloc() {
|
|||||||
view_set_exit_callback(instance->view, subghz_read_raw_exit);
|
view_set_exit_callback(instance->view, subghz_read_raw_exit);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
model->frequency_str = furi_string_alloc();
|
model->frequency_str = furi_string_alloc();
|
||||||
model->preset_str = furi_string_alloc();
|
model->preset_str = furi_string_alloc();
|
||||||
model->sample_write = furi_string_alloc();
|
model->sample_write = furi_string_alloc();
|
||||||
model->file_name = furi_string_alloc();
|
model->file_name = furi_string_alloc();
|
||||||
model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
|
model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -516,14 +546,16 @@ void subghz_read_raw_free(SubGhzReadRAW* instance) {
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzReadRAWModel * model) {
|
instance->view,
|
||||||
|
SubGhzReadRAWModel * model,
|
||||||
|
{
|
||||||
furi_string_free(model->frequency_str);
|
furi_string_free(model->frequency_str);
|
||||||
furi_string_free(model->preset_str);
|
furi_string_free(model->preset_str);
|
||||||
furi_string_free(model->sample_write);
|
furi_string_free(model->sample_write);
|
||||||
furi_string_free(model->file_name);
|
furi_string_free(model->file_name);
|
||||||
free(model->rssi_history);
|
free(model->rssi_history);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
view_free(instance->view);
|
view_free(instance->view);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_test_carrier->view, (SubGhzTestCarrierModel * model) {
|
subghz_test_carrier->view,
|
||||||
|
SubGhzTestCarrierModel * model,
|
||||||
|
{
|
||||||
furi_hal_subghz_idle();
|
furi_hal_subghz_idle();
|
||||||
|
|
||||||
if(event->key == InputKeyLeft) {
|
if(event->key == InputKeyLeft) {
|
||||||
@@ -125,9 +127,8 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
|||||||
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -142,15 +143,17 @@ void subghz_test_carrier_enter(void* context) {
|
|||||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_test_carrier->view, (SubGhzTestCarrierModel * model) {
|
subghz_test_carrier->view,
|
||||||
|
SubGhzTestCarrierModel * model,
|
||||||
|
{
|
||||||
model->frequency = subghz_frequencies_433_92_testing; // 433
|
model->frequency = subghz_frequencies_433_92_testing; // 433
|
||||||
model->real_frequency =
|
model->real_frequency =
|
||||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||||
model->path = FuriHalSubGhzPathIsolate; // isolate
|
model->path = FuriHalSubGhzPathIsolate; // isolate
|
||||||
model->rssi = 0.0f;
|
model->rssi = 0.0f;
|
||||||
model->status = SubGhzTestCarrierModelStatusRx;
|
model->status = SubGhzTestCarrierModelStatusRx;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
furi_hal_subghz_rx();
|
furi_hal_subghz_rx();
|
||||||
|
|
||||||
@@ -172,13 +175,14 @@ void subghz_test_carrier_rssi_timer_callback(void* context) {
|
|||||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_test_carrier->view, (SubGhzTestCarrierModel * model) {
|
subghz_test_carrier->view,
|
||||||
|
SubGhzTestCarrierModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||||
model->rssi = furi_hal_subghz_get_rssi();
|
model->rssi = furi_hal_subghz_get_rssi();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzTestCarrier* subghz_test_carrier_alloc() {
|
SubGhzTestCarrier* subghz_test_carrier_alloc() {
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ static void subghz_test_packet_rssi_timer_callback(void* context) {
|
|||||||
SubGhzTestPacket* instance = context;
|
SubGhzTestPacket* instance = context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestPacketModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestPacketModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzTestPacketModelStatusRx) {
|
if(model->status == SubGhzTestPacketModelStatusRx) {
|
||||||
model->rssi = furi_hal_subghz_get_rssi();
|
model->rssi = furi_hal_subghz_get_rssi();
|
||||||
model->packets = instance->packet_rx;
|
model->packets = instance->packet_rx;
|
||||||
@@ -77,8 +79,8 @@ static void subghz_test_packet_rssi_timer_callback(void* context) {
|
|||||||
SUBGHZ_TEST_PACKET_COUNT -
|
SUBGHZ_TEST_PACKET_COUNT -
|
||||||
subghz_encoder_princeton_for_testing_get_repeat_left(instance->encoder);
|
subghz_encoder_princeton_for_testing_get_repeat_left(instance->encoder);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_test_packet_draw(Canvas* canvas, SubGhzTestPacketModel* model) {
|
static void subghz_test_packet_draw(Canvas* canvas, SubGhzTestPacketModel* model) {
|
||||||
@@ -137,7 +139,9 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestPacketModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestPacketModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzTestPacketModelStatusRx) {
|
if(model->status == SubGhzTestPacketModelStatusRx) {
|
||||||
furi_hal_subghz_stop_async_rx();
|
furi_hal_subghz_stop_async_rx();
|
||||||
} else if(model->status == SubGhzTestPacketModelStatusTx) {
|
} else if(model->status == SubGhzTestPacketModelStatusTx) {
|
||||||
@@ -179,9 +183,8 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) {
|
|||||||
instance->callback(SubGhzTestPacketEventOnlyRx, instance->context);
|
instance->callback(SubGhzTestPacketEventOnlyRx, instance->context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -194,15 +197,17 @@ void subghz_test_packet_enter(void* context) {
|
|||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestPacketModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestPacketModel * model,
|
||||||
|
{
|
||||||
model->frequency = subghz_frequencies_433_92_testing;
|
model->frequency = subghz_frequencies_433_92_testing;
|
||||||
model->real_frequency =
|
model->real_frequency =
|
||||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||||
model->path = FuriHalSubGhzPathIsolate; // isolate
|
model->path = FuriHalSubGhzPathIsolate; // isolate
|
||||||
model->rssi = 0.0f;
|
model->rssi = 0.0f;
|
||||||
model->status = SubGhzTestPacketModelStatusRx;
|
model->status = SubGhzTestPacketModelStatusRx;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
furi_hal_subghz_start_async_rx(subghz_test_packet_rx_callback, instance);
|
furi_hal_subghz_start_async_rx(subghz_test_packet_rx_callback, instance);
|
||||||
|
|
||||||
@@ -217,15 +222,17 @@ void subghz_test_packet_exit(void* context) {
|
|||||||
|
|
||||||
// Reinitialize IC to default state
|
// Reinitialize IC to default state
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestPacketModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestPacketModel * model,
|
||||||
|
{
|
||||||
if(model->status == SubGhzTestPacketModelStatusRx) {
|
if(model->status == SubGhzTestPacketModelStatusRx) {
|
||||||
furi_hal_subghz_stop_async_rx();
|
furi_hal_subghz_stop_async_rx();
|
||||||
} else if(model->status == SubGhzTestPacketModelStatusTx) {
|
} else if(model->status == SubGhzTestPacketModelStatusTx) {
|
||||||
subghz_encoder_princeton_for_testing_stop(instance->encoder, furi_get_tick());
|
subghz_encoder_princeton_for_testing_stop(instance->encoder, furi_get_tick());
|
||||||
furi_hal_subghz_stop_async_tx();
|
furi_hal_subghz_stop_async_tx();
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
furi_hal_subghz_sleep();
|
furi_hal_subghz_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,9 @@ bool subghz_test_static_input(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestStaticModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestStaticModel * model,
|
||||||
|
{
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
if(event->key == InputKeyLeft) {
|
if(event->key == InputKeyLeft) {
|
||||||
if(model->frequency > 0) model->frequency--;
|
if(model->frequency > 0) model->frequency--;
|
||||||
@@ -128,9 +130,8 @@ bool subghz_test_static_input(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -147,13 +148,14 @@ void subghz_test_static_enter(void* context) {
|
|||||||
instance->status_tx = SubGhzTestStaticStatusIDLE;
|
instance->status_tx = SubGhzTestStaticStatusIDLE;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubGhzTestStaticModel * model) {
|
instance->view,
|
||||||
|
SubGhzTestStaticModel * model,
|
||||||
|
{
|
||||||
model->frequency = subghz_frequencies_433_92_testing;
|
model->frequency = subghz_frequencies_433_92_testing;
|
||||||
model->real_frequency = subghz_frequencies_testing[model->frequency];
|
model->real_frequency = subghz_frequencies_testing[model->frequency];
|
||||||
model->button = 0;
|
model->button = 0;
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_test_static_exit(void* context) {
|
void subghz_test_static_exit(void* context) {
|
||||||
|
|||||||
@@ -35,13 +35,15 @@ void subghz_view_transmitter_add_data_to_show(
|
|||||||
uint8_t show_button) {
|
uint8_t show_button) {
|
||||||
furi_assert(subghz_transmitter);
|
furi_assert(subghz_transmitter);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
|
subghz_transmitter->view,
|
||||||
|
SubGhzViewTransmitterModel * model,
|
||||||
|
{
|
||||||
furi_string_set(model->key_str, key_str);
|
furi_string_set(model->key_str, key_str);
|
||||||
furi_string_set(model->frequency_str, frequency_str);
|
furi_string_set(model->frequency_str, frequency_str);
|
||||||
furi_string_set(model->preset_str, preset_str);
|
furi_string_set(model->preset_str, preset_str);
|
||||||
model->show_button = show_button;
|
model->show_button = show_button;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) {
|
static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) {
|
||||||
@@ -95,23 +97,27 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
|
subghz_transmitter->view,
|
||||||
|
SubGhzViewTransmitterModel * model,
|
||||||
|
{
|
||||||
furi_string_reset(model->frequency_str);
|
furi_string_reset(model->frequency_str);
|
||||||
furi_string_reset(model->preset_str);
|
furi_string_reset(model->preset_str);
|
||||||
furi_string_reset(model->key_str);
|
furi_string_reset(model->key_str);
|
||||||
model->show_button = 0;
|
model->show_button = 0;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
|
subghz_transmitter->view,
|
||||||
|
SubGhzViewTransmitterModel * model,
|
||||||
|
{
|
||||||
if(model->show_button) {
|
if(model->show_button) {
|
||||||
can_be_sent = true;
|
can_be_sent = true;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
|
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
|
||||||
subghz_transmitter->callback(
|
subghz_transmitter->callback(
|
||||||
@@ -149,12 +155,14 @@ SubGhzViewTransmitter* subghz_view_transmitter_alloc() {
|
|||||||
view_set_exit_callback(subghz_transmitter->view, subghz_view_transmitter_exit);
|
view_set_exit_callback(subghz_transmitter->view, subghz_view_transmitter_exit);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
|
subghz_transmitter->view,
|
||||||
|
SubGhzViewTransmitterModel * model,
|
||||||
|
{
|
||||||
model->frequency_str = furi_string_alloc();
|
model->frequency_str = furi_string_alloc();
|
||||||
model->preset_str = furi_string_alloc();
|
model->preset_str = furi_string_alloc();
|
||||||
model->key_str = furi_string_alloc();
|
model->key_str = furi_string_alloc();
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
return subghz_transmitter;
|
return subghz_transmitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,12 +170,14 @@ void subghz_view_transmitter_free(SubGhzViewTransmitter* subghz_transmitter) {
|
|||||||
furi_assert(subghz_transmitter);
|
furi_assert(subghz_transmitter);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
|
subghz_transmitter->view,
|
||||||
|
SubGhzViewTransmitterModel * model,
|
||||||
|
{
|
||||||
furi_string_free(model->frequency_str);
|
furi_string_free(model->frequency_str);
|
||||||
furi_string_free(model->preset_str);
|
furi_string_free(model->preset_str);
|
||||||
furi_string_free(model->key_str);
|
furi_string_free(model->key_str);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
view_free(subghz_transmitter->view);
|
view_free(subghz_transmitter->view);
|
||||||
free(subghz_transmitter);
|
free(subghz_transmitter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,18 +85,17 @@ void u2f_view_set_ok_callback(U2fView* u2f, U2fOkCallback callback, void* contex
|
|||||||
furi_assert(u2f);
|
furi_assert(u2f);
|
||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
u2f->view, (U2fModel * model) {
|
u2f->view,
|
||||||
|
U2fModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
u2f->callback = callback;
|
u2f->callback = callback;
|
||||||
u2f->context = context;
|
u2f->context = context;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) {
|
void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
u2f->view, (U2fModel * model) {
|
u2f->view, U2fModel * model, { model->display_msg = msg; }, true);
|
||||||
model->display_msg = msg;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -277,7 +277,9 @@ static void bt_hid_keyboard_get_select_key(BtHidKeyboardModel* model, BtHidKeybo
|
|||||||
|
|
||||||
static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* event) {
|
static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* event) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_keyboard->view, (BtHidKeyboardModel * model) {
|
bt_hid_keyboard->view,
|
||||||
|
BtHidKeyboardModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyOk) {
|
if(event->key == InputKeyOk) {
|
||||||
if(event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
model->ok_pressed = true;
|
model->ok_pressed = true;
|
||||||
@@ -338,8 +340,8 @@ static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent*
|
|||||||
bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 1, .y = 0});
|
bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 1, .y = 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bt_hid_keyboard_input_callback(InputEvent* event, void* context) {
|
static bool bt_hid_keyboard_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -382,8 +384,5 @@ View* bt_hid_keyboard_get_view(BtHidKeyboard* bt_hid_keyboard) {
|
|||||||
void bt_hid_keyboard_set_connected_status(BtHidKeyboard* bt_hid_keyboard, bool connected) {
|
void bt_hid_keyboard_set_connected_status(BtHidKeyboard* bt_hid_keyboard, bool connected) {
|
||||||
furi_assert(bt_hid_keyboard);
|
furi_assert(bt_hid_keyboard);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_keyboard->view, (BtHidKeyboardModel * model) {
|
bt_hid_keyboard->view, BtHidKeyboardModel * model, { model->connected = connected; }, true);
|
||||||
model->connected = connected;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) {
|
|||||||
|
|
||||||
static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* event) {
|
static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* event) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_keynote->view, (BtHidKeynoteModel * model) {
|
bt_hid_keynote->view,
|
||||||
|
BtHidKeynoteModel * model,
|
||||||
|
{
|
||||||
if(event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->up_pressed = true;
|
model->up_pressed = true;
|
||||||
@@ -153,8 +155,8 @@ static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* eve
|
|||||||
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_AC_BACK);
|
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_AC_BACK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bt_hid_keynote_input_callback(InputEvent* event, void* context) {
|
static bool bt_hid_keynote_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -197,8 +199,5 @@ View* bt_hid_keynote_get_view(BtHidKeynote* bt_hid_keynote) {
|
|||||||
void bt_hid_keynote_set_connected_status(BtHidKeynote* bt_hid_keynote, bool connected) {
|
void bt_hid_keynote_set_connected_status(BtHidKeynote* bt_hid_keynote, bool connected) {
|
||||||
furi_assert(bt_hid_keynote);
|
furi_assert(bt_hid_keynote);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_keynote->view, (BtHidKeynoteModel * model) {
|
bt_hid_keynote->view, BtHidKeynoteModel * model, { model->connected = connected; }, true);
|
||||||
model->connected = connected;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,9 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) {
|
|||||||
|
|
||||||
static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* event) {
|
static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* event) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_media->view, (BtHidMediaModel * model) {
|
bt_hid_media->view,
|
||||||
|
BtHidMediaModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->up_pressed = true;
|
model->up_pressed = true;
|
||||||
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT);
|
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT);
|
||||||
@@ -124,13 +126,15 @@ static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* eve
|
|||||||
model->ok_pressed = true;
|
model->ok_pressed = true;
|
||||||
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_PLAY_PAUSE);
|
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_PLAY_PAUSE);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* event) {
|
static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* event) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_media->view, (BtHidMediaModel * model) {
|
bt_hid_media->view,
|
||||||
|
BtHidMediaModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->up_pressed = false;
|
model->up_pressed = false;
|
||||||
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT);
|
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT);
|
||||||
@@ -147,8 +151,8 @@ static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* e
|
|||||||
model->ok_pressed = false;
|
model->ok_pressed = false;
|
||||||
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_PLAY_PAUSE);
|
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_PLAY_PAUSE);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bt_hid_media_input_callback(InputEvent* event, void* context) {
|
static bool bt_hid_media_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -196,8 +200,5 @@ View* bt_hid_media_get_view(BtHidMedia* bt_hid_media) {
|
|||||||
void bt_hid_media_set_connected_status(BtHidMedia* bt_hid_media, bool connected) {
|
void bt_hid_media_set_connected_status(BtHidMedia* bt_hid_media, bool connected) {
|
||||||
furi_assert(bt_hid_media);
|
furi_assert(bt_hid_media);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_media->view, (BtHidMediaModel * model) {
|
bt_hid_media->view, BtHidMediaModel * model, { model->connected = connected; }, true);
|
||||||
model->connected = connected;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
|||||||
|
|
||||||
static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) {
|
static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_mouse->view, (BtHidMouseModel * model) {
|
bt_hid_mouse->view,
|
||||||
|
BtHidMouseModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyBack) {
|
if(event->key == InputKeyBack) {
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
|
furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
|
||||||
@@ -167,8 +169,8 @@ static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) {
|
|||||||
model->up_pressed = false;
|
model->up_pressed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bt_hid_mouse_input_callback(InputEvent* event, void* context) {
|
static bool bt_hid_mouse_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -211,8 +213,5 @@ View* bt_hid_mouse_get_view(BtHidMouse* bt_hid_mouse) {
|
|||||||
void bt_hid_mouse_set_connected_status(BtHidMouse* bt_hid_mouse, bool connected) {
|
void bt_hid_mouse_set_connected_status(BtHidMouse* bt_hid_mouse, bool connected) {
|
||||||
furi_assert(bt_hid_mouse);
|
furi_assert(bt_hid_mouse);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
bt_hid_mouse->view, (BtHidMouseModel * model) {
|
bt_hid_mouse->view, BtHidMouseModel * model, { model->connected = connected; }, true);
|
||||||
model->connected = connected;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,12 +248,16 @@ static void music_player_worker_callback(
|
|||||||
view_port_update(music_player->view_port);
|
view_port_update(music_player->view_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void music_player_clear(MusicPlayer* instance) {
|
||||||
|
memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
||||||
|
memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
||||||
|
music_player_worker_clear(instance->worker);
|
||||||
|
}
|
||||||
|
|
||||||
MusicPlayer* music_player_alloc() {
|
MusicPlayer* music_player_alloc() {
|
||||||
MusicPlayer* instance = malloc(sizeof(MusicPlayer));
|
MusicPlayer* instance = malloc(sizeof(MusicPlayer));
|
||||||
|
|
||||||
instance->model = malloc(sizeof(MusicPlayerModel));
|
instance->model = malloc(sizeof(MusicPlayerModel));
|
||||||
memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
|
||||||
memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
|
||||||
instance->model->volume = 3;
|
instance->model->volume = 3;
|
||||||
|
|
||||||
instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
@@ -265,6 +269,8 @@ MusicPlayer* music_player_alloc() {
|
|||||||
instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]);
|
instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]);
|
||||||
music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance);
|
music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance);
|
||||||
|
|
||||||
|
music_player_clear(instance);
|
||||||
|
|
||||||
instance->view_port = view_port_alloc();
|
instance->view_port = view_port_alloc();
|
||||||
view_port_draw_callback_set(instance->view_port, render_callback, instance);
|
view_port_draw_callback_set(instance->view_port, render_callback, instance);
|
||||||
view_port_input_callback_set(instance->view_port, input_callback, instance);
|
view_port_input_callback_set(instance->view_port, input_callback, instance);
|
||||||
@@ -299,7 +305,7 @@ int32_t music_player_app(void* p) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(p && strlen(p)) {
|
if(p && strlen(p)) {
|
||||||
furi_string_cat(file_path, (const char*)p);
|
furi_string_set(file_path, (const char*)p);
|
||||||
} else {
|
} else {
|
||||||
furi_string_set(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
|
furi_string_set(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
|
||||||
|
|
||||||
@@ -350,7 +356,9 @@ int32_t music_player_app(void* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
music_player_worker_stop(music_player->worker);
|
music_player_worker_stop(music_player->worker);
|
||||||
} while(0);
|
if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg
|
||||||
|
music_player_clear(music_player);
|
||||||
|
} while(1);
|
||||||
|
|
||||||
furi_string_free(file_path);
|
furi_string_free(file_path);
|
||||||
music_player_free(music_player);
|
music_player_free(music_player);
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ MusicPlayerWorker* music_player_worker_alloc() {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void music_player_worker_clear(MusicPlayerWorker* instance) {
|
||||||
|
NoteBlockArray_reset(instance->notes);
|
||||||
|
}
|
||||||
|
|
||||||
void music_player_worker_free(MusicPlayerWorker* instance) {
|
void music_player_worker_free(MusicPlayerWorker* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
@@ -129,6 +133,7 @@ static bool is_space(const char c) {
|
|||||||
|
|
||||||
static size_t extract_number(const char* string, uint32_t* number) {
|
static size_t extract_number(const char* string, uint32_t* number) {
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
|
*number = 0;
|
||||||
while(is_digit(*string)) {
|
while(is_digit(*string)) {
|
||||||
*number *= 10;
|
*number *= 10;
|
||||||
*number += (*string - '0');
|
*number += (*string - '0');
|
||||||
@@ -140,6 +145,7 @@ static size_t extract_number(const char* string, uint32_t* number) {
|
|||||||
|
|
||||||
static size_t extract_dots(const char* string, uint32_t* number) {
|
static size_t extract_dots(const char* string, uint32_t* number) {
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
|
*number = 0;
|
||||||
while(*string == '.') {
|
while(*string == '.') {
|
||||||
*number += 1;
|
*number += 1;
|
||||||
string++;
|
string++;
|
||||||
@@ -258,7 +264,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c
|
|||||||
if(!is_valid) {
|
if(!is_valid) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Invalid note: %u%c%c%u.%u",
|
"Invalid note: %lu%c%c%lu.%lu",
|
||||||
duration,
|
duration,
|
||||||
note_char == '\0' ? '_' : note_char,
|
note_char == '\0' ? '_' : note_char,
|
||||||
sharp_char == '\0' ? '_' : sharp_char,
|
sharp_char == '\0' ? '_' : sharp_char,
|
||||||
@@ -281,7 +287,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c
|
|||||||
if(music_player_worker_add_note(instance, semitone, duration, dots)) {
|
if(music_player_worker_add_note(instance, semitone, duration, dots)) {
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"Added note: %c%c%u.%u = %u %u",
|
"Added note: %c%c%lu.%lu = %u %lu",
|
||||||
note_char == '\0' ? '_' : note_char,
|
note_char == '\0' ? '_' : note_char,
|
||||||
sharp_char == '\0' ? '_' : sharp_char,
|
sharp_char == '\0' ? '_' : sharp_char,
|
||||||
octave,
|
octave,
|
||||||
@@ -291,7 +297,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c
|
|||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Invalid note: %c%c%u.%u = %u %u",
|
"Invalid note: %c%c%lu.%lu = %u %lu",
|
||||||
note_char == '\0' ? '_' : note_char,
|
note_char == '\0' ? '_' : note_char,
|
||||||
sharp_char == '\0' ? '_' : sharp_char,
|
sharp_char == '\0' ? '_' : sharp_char,
|
||||||
octave,
|
octave,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ typedef struct MusicPlayerWorker MusicPlayerWorker;
|
|||||||
|
|
||||||
MusicPlayerWorker* music_player_worker_alloc();
|
MusicPlayerWorker* music_player_worker_alloc();
|
||||||
|
|
||||||
|
void music_player_worker_clear(MusicPlayerWorker* instance);
|
||||||
|
|
||||||
void music_player_worker_free(MusicPlayerWorker* instance);
|
void music_player_worker_free(MusicPlayerWorker* instance);
|
||||||
|
|
||||||
bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path);
|
bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path);
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
#include "../signal_gen_app_i.h"
|
#include "../signal_gen_app_i.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
LineIndexPin,
|
||||||
LineIndexSource,
|
LineIndexSource,
|
||||||
LineIndexDivision,
|
LineIndexDivision,
|
||||||
} LineIndex;
|
} LineIndex;
|
||||||
|
|
||||||
|
static const char* const mco_pin_names[] = {
|
||||||
|
"13(Tx)",
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const mco_source_names[] = {
|
static const char* const mco_source_names[] = {
|
||||||
"32768",
|
"32768Hz",
|
||||||
"64MHz",
|
"64MHz",
|
||||||
"~100K",
|
"~100K",
|
||||||
"~200K",
|
"~200K",
|
||||||
@@ -81,14 +86,22 @@ void signal_gen_scene_mco_on_enter(void* context) {
|
|||||||
|
|
||||||
VariableItem* item;
|
VariableItem* item;
|
||||||
|
|
||||||
|
item = variable_item_list_add(var_item_list, "GPIO Pin", COUNT_OF(mco_pin_names), NULL, NULL);
|
||||||
|
variable_item_set_current_value_index(item, 0);
|
||||||
|
variable_item_set_current_value_text(item, mco_pin_names[0]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
var_item_list, "Source", COUNT_OF(mco_source_names), mco_source_list_change_callback, app);
|
var_item_list,
|
||||||
|
"Frequency",
|
||||||
|
COUNT_OF(mco_source_names),
|
||||||
|
mco_source_list_change_callback,
|
||||||
|
app);
|
||||||
variable_item_set_current_value_index(item, 0);
|
variable_item_set_current_value_index(item, 0);
|
||||||
variable_item_set_current_value_text(item, mco_source_names[0]);
|
variable_item_set_current_value_text(item, mco_source_names[0]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
var_item_list,
|
var_item_list,
|
||||||
"Division",
|
"Freq. divider",
|
||||||
COUNT_OF(mco_divisor_names),
|
COUNT_OF(mco_divisor_names),
|
||||||
mco_divisor_list_change_callback,
|
mco_divisor_list_change_callback,
|
||||||
app);
|
app);
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ void signal_gen_scene_start_on_enter(void* context) {
|
|||||||
Submenu* submenu = app->submenu;
|
Submenu* submenu = app->submenu;
|
||||||
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "PWM", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app);
|
submenu, "PWM Generator", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Clock Output",
|
"Clock Generator",
|
||||||
SubmenuIndexClockOutput,
|
SubmenuIndexClockOutput,
|
||||||
signal_gen_scene_start_submenu_callback,
|
signal_gen_scene_start_submenu_callback,
|
||||||
app);
|
app);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ typedef enum {
|
|||||||
LineIndexTotalCount
|
LineIndexTotalCount
|
||||||
} LineIndex;
|
} LineIndex;
|
||||||
|
|
||||||
static const char* const pwm_ch_names[] = {"TIM1(2)", "LPTIM2(4)"};
|
static const char* const pwm_ch_names[] = {"2(A7)", "4(A4)"};
|
||||||
|
|
||||||
struct SignalGenPwm {
|
struct SignalGenPwm {
|
||||||
View* view;
|
View* view;
|
||||||
@@ -31,8 +31,8 @@ typedef struct {
|
|||||||
#define ITEM_H 64 / 3
|
#define ITEM_H 64 / 3
|
||||||
#define ITEM_W 128
|
#define ITEM_W 128
|
||||||
|
|
||||||
#define VALUE_X 95
|
#define VALUE_X 100
|
||||||
#define VALUE_W 55
|
#define VALUE_W 45
|
||||||
|
|
||||||
#define FREQ_VALUE_X 62
|
#define FREQ_VALUE_X 62
|
||||||
#define FREQ_MAX 1000000UL
|
#define FREQ_MAX 1000000UL
|
||||||
@@ -44,12 +44,14 @@ static void pwm_set_config(SignalGenPwm* pwm) {
|
|||||||
uint8_t duty;
|
uint8_t duty;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
pwm->view, (SignalGenPwmViewModel * model) {
|
pwm->view,
|
||||||
|
SignalGenPwmViewModel * model,
|
||||||
|
{
|
||||||
channel = model->channel_id;
|
channel = model->channel_id;
|
||||||
freq = model->freq;
|
freq = model->freq;
|
||||||
duty = model->duty;
|
duty = model->duty;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
furi_assert(pwm->callback);
|
furi_assert(pwm->callback);
|
||||||
pwm->callback(channel, freq, duty, pwm->context);
|
pwm->callback(channel, freq, duty, pwm->context);
|
||||||
@@ -126,11 +128,11 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
for(uint8_t line = 0; line < LineIndexTotalCount; line++) {
|
for(uint8_t line = 0; line < LineIndexTotalCount; line++) {
|
||||||
if(line == LineIndexChannel) {
|
if(line == LineIndexChannel) {
|
||||||
line_label = "PWM Channel";
|
line_label = "GPIO Pin";
|
||||||
} else if(line == LineIndexFrequency) {
|
} else if(line == LineIndexFrequency) {
|
||||||
line_label = "Frequency";
|
line_label = "Frequency";
|
||||||
} else if(line == LineIndexDuty) {
|
} else if(line == LineIndexDuty) {
|
||||||
line_label = "Duty Cycle";
|
line_label = "Pulse width";
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
@@ -162,9 +164,9 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
|
||||||
if(model->edit_mode) {
|
if(model->edit_mode) {
|
||||||
uint8_t icon_x = (FREQ_VALUE_X - 1) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6;
|
uint8_t icon_x = (FREQ_VALUE_X) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6;
|
||||||
canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_4x7);
|
canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_3x5);
|
||||||
canvas_draw_icon(canvas, icon_x, text_y + 4, &I_SmallArrowDown_4x7);
|
canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_3x5);
|
||||||
}
|
}
|
||||||
} else if(line == LineIndexDuty) {
|
} else if(line == LineIndexDuty) {
|
||||||
snprintf(val_text, sizeof(val_text), "%d%%", model->duty);
|
snprintf(val_text, sizeof(val_text), "%d%%", model->duty);
|
||||||
@@ -188,7 +190,9 @@ static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) {
|
|||||||
bool need_update = false;
|
bool need_update = false;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
pwm->view, (SignalGenPwmViewModel * model) {
|
pwm->view,
|
||||||
|
SignalGenPwmViewModel * model,
|
||||||
|
{
|
||||||
if(model->edit_mode == false) {
|
if(model->edit_mode == false) {
|
||||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
@@ -238,8 +242,8 @@ static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
if(need_update) {
|
if(need_update) {
|
||||||
pwm_set_config(pwm);
|
pwm_set_config(pwm);
|
||||||
@@ -279,22 +283,26 @@ void signal_gen_pwm_set_callback(
|
|||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
pwm->view, (SignalGenPwmViewModel * model) {
|
pwm->view,
|
||||||
|
SignalGenPwmViewModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
pwm->callback = callback;
|
pwm->callback = callback;
|
||||||
pwm->context = context;
|
pwm->context = context;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty) {
|
void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
pwm->view, (SignalGenPwmViewModel * model) {
|
pwm->view,
|
||||||
|
SignalGenPwmViewModel * model,
|
||||||
|
{
|
||||||
model->channel_id = channel_id;
|
model->channel_id = channel_id;
|
||||||
model->freq = freq;
|
model->freq = freq;
|
||||||
model->duty = duty;
|
model->duty = duty;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
furi_assert(pwm->callback);
|
furi_assert(pwm->callback);
|
||||||
pwm->callback(channel_id, freq, duty, pwm->context);
|
pwm->callback(channel_id, freq, duty, pwm->context);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// +-----x
|
// +-----x
|
||||||
@@ -59,6 +61,35 @@ typedef struct {
|
|||||||
InputEvent input;
|
InputEvent input;
|
||||||
} SnakeEvent;
|
} SnakeEvent;
|
||||||
|
|
||||||
|
const NotificationSequence sequence_fail = {
|
||||||
|
&message_vibro_on,
|
||||||
|
|
||||||
|
&message_note_ds4,
|
||||||
|
&message_delay_10,
|
||||||
|
&message_sound_off,
|
||||||
|
&message_delay_10,
|
||||||
|
|
||||||
|
&message_note_ds4,
|
||||||
|
&message_delay_10,
|
||||||
|
&message_sound_off,
|
||||||
|
&message_delay_10,
|
||||||
|
|
||||||
|
&message_note_ds4,
|
||||||
|
&message_delay_10,
|
||||||
|
&message_sound_off,
|
||||||
|
&message_delay_10,
|
||||||
|
|
||||||
|
&message_vibro_off,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationSequence sequence_eat = {
|
||||||
|
&message_note_c7,
|
||||||
|
&message_delay_50,
|
||||||
|
&message_sound_off,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
const SnakeState* snake_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||||
if(snake_state == NULL) {
|
if(snake_state == NULL) {
|
||||||
@@ -230,7 +261,8 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex
|
|||||||
snake_state->points[0] = next_step;
|
snake_state->points[0] = next_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snake_game_process_game_step(SnakeState* const snake_state) {
|
static void
|
||||||
|
snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) {
|
||||||
if(snake_state->state == GameStateGameOver) {
|
if(snake_state->state == GameStateGameOver) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -249,6 +281,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
|
|||||||
return;
|
return;
|
||||||
} else if(snake_state->state == GameStateLastChance) {
|
} else if(snake_state->state == GameStateLastChance) {
|
||||||
snake_state->state = GameStateGameOver;
|
snake_state->state = GameStateGameOver;
|
||||||
|
notification_message_block(notification, &sequence_fail);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -260,6 +293,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
|
|||||||
crush = snake_game_collision_with_tail(snake_state, next_step);
|
crush = snake_game_collision_with_tail(snake_state, next_step);
|
||||||
if(crush) {
|
if(crush) {
|
||||||
snake_state->state = GameStateGameOver;
|
snake_state->state = GameStateGameOver;
|
||||||
|
notification_message_block(notification, &sequence_fail);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +302,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
|
|||||||
snake_state->len++;
|
snake_state->len++;
|
||||||
if(snake_state->len >= MAX_SNAKE_LEN) {
|
if(snake_state->len >= MAX_SNAKE_LEN) {
|
||||||
snake_state->state = GameStateGameOver;
|
snake_state->state = GameStateGameOver;
|
||||||
|
notification_message_block(notification, &sequence_fail);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,6 +311,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
|
|||||||
|
|
||||||
if(eatFruit) {
|
if(eatFruit) {
|
||||||
snake_state->fruit = snake_game_get_new_fruit(snake_state);
|
snake_state->fruit = snake_game_get_new_fruit(snake_state);
|
||||||
|
notification_message(notification, &sequence_eat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,6 +342,9 @@ int32_t snake_game_app(void* p) {
|
|||||||
// Open GUI and register view_port
|
// Open GUI and register view_port
|
||||||
Gui* gui = furi_record_open(RECORD_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(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
notification_message_block(notification, &sequence_display_backlight_enforce_on);
|
||||||
|
|
||||||
SnakeEvent event;
|
SnakeEvent event;
|
||||||
for(bool processing = true; processing;) {
|
for(bool processing = true; processing;) {
|
||||||
@@ -341,7 +380,7 @@ int32_t snake_game_app(void* p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(event.type == EventTypeTick) {
|
} else if(event.type == EventTypeTick) {
|
||||||
snake_game_process_game_step(snake_state);
|
snake_game_process_game_step(snake_state, notification);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// event timeout
|
// event timeout
|
||||||
@@ -351,10 +390,14 @@ int32_t snake_game_app(void* p) {
|
|||||||
release_mutex(&state_mutex, snake_state);
|
release_mutex(&state_mutex, snake_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for all notifications to be played and return backlight to normal state
|
||||||
|
notification_message_block(notification, &sequence_display_backlight_enforce_auto);
|
||||||
|
|
||||||
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(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
|
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);
|
delete_mutex(&state_mutex);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) {
|
|||||||
notification_message(bt->notification, &sequence_display_backlight_on);
|
notification_message(bt->notification, &sequence_display_backlight_on);
|
||||||
FuriString* pin_str;
|
FuriString* pin_str;
|
||||||
dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0);
|
dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0);
|
||||||
pin_str = furi_string_alloc_printf("Verify code\n%06d", pin);
|
pin_str = furi_string_alloc_printf("Verify code\n%06ld", pin);
|
||||||
dialog_message_set_text(
|
dialog_message_set_text(
|
||||||
bt->dialog_message, furi_string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop);
|
bt->dialog_message, furi_string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop);
|
||||||
dialog_message_set_buttons(bt->dialog_message, "Cancel", "OK", NULL);
|
dialog_message_set_buttons(bt->dialog_message, "Cancel", "OK", NULL);
|
||||||
@@ -277,7 +277,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
|
|||||||
static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void* context) {
|
static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
Bt* bt = context;
|
Bt* bt = context;
|
||||||
FURI_LOG_I(TAG, "Changed addr start: %08lX, size changed: %d", addr, size);
|
FURI_LOG_I(TAG, "Changed addr start: %p, size changed: %d", addr, size);
|
||||||
BtMessage message = {.type = BtMessageTypeKeysStorageUpdated};
|
BtMessage message = {.type = BtMessageTypeKeysStorageUpdated};
|
||||||
furi_check(
|
furi_check(
|
||||||
furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
// Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'`
|
// Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'`
|
||||||
#define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d"
|
#define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d"
|
||||||
@@ -140,7 +139,7 @@ void cli_command_date(Cli* cli, FuriString* args, void* context) {
|
|||||||
#define CLI_COMMAND_LOG_BUFFER_SIZE 64
|
#define CLI_COMMAND_LOG_BUFFER_SIZE 64
|
||||||
|
|
||||||
void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* context) {
|
void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* context) {
|
||||||
xStreamBufferSend(context, buffer, size, 0);
|
furi_stream_buffer_send(context, buffer, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_log_level_set_from_string(FuriString* level) {
|
void cli_command_log_level_set_from_string(FuriString* level) {
|
||||||
@@ -165,7 +164,7 @@ void cli_command_log_level_set_from_string(FuriString* level) {
|
|||||||
|
|
||||||
void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1);
|
FuriStreamBuffer* ring = furi_stream_buffer_alloc(CLI_COMMAND_LOG_RING_SIZE, 1);
|
||||||
uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE];
|
uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE];
|
||||||
FuriLogLevel previous_level = furi_log_get_level();
|
FuriLogLevel previous_level = furi_log_get_level();
|
||||||
bool restore_log_level = false;
|
bool restore_log_level = false;
|
||||||
@@ -179,7 +178,7 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
printf("Press CTRL+C to stop...\r\n");
|
printf("Press CTRL+C to stop...\r\n");
|
||||||
while(!cli_cmd_interrupt_received(cli)) {
|
while(!cli_cmd_interrupt_received(cli)) {
|
||||||
size_t ret = xStreamBufferReceive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50);
|
size_t ret = furi_stream_buffer_receive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50);
|
||||||
cli_write(cli, buffer, ret);
|
cli_write(cli, buffer, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +189,7 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||||||
furi_log_set_level(previous_level);
|
furi_log_set_level(previous_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
vStreamBufferDelete(ring);
|
furi_stream_buffer_free(ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_vibro(Cli* cli, FuriString* args, void* context) {
|
void cli_command_vibro(Cli* cli, FuriString* args, void* context) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <furi_hal_usb_cdc.h>
|
#include <furi_hal_usb_cdc.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include "cli_i.h"
|
#include "cli_i.h"
|
||||||
|
|
||||||
#define TAG "CliVcp"
|
#define TAG "CliVcp"
|
||||||
@@ -29,8 +28,8 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
StreamBufferHandle_t tx_stream;
|
FuriStreamBuffer* tx_stream;
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
|
|
||||||
volatile bool connected;
|
volatile bool connected;
|
||||||
volatile bool running;
|
volatile bool running;
|
||||||
@@ -62,8 +61,8 @@ static const uint8_t ascii_eot = 0x04;
|
|||||||
static void cli_vcp_init() {
|
static void cli_vcp_init() {
|
||||||
if(vcp == NULL) {
|
if(vcp == NULL) {
|
||||||
vcp = malloc(sizeof(CliVcp));
|
vcp = malloc(sizeof(CliVcp));
|
||||||
vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1);
|
vcp->tx_stream = furi_stream_buffer_alloc(VCP_TX_BUF_SIZE, 1);
|
||||||
vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
|
vcp->rx_stream = furi_stream_buffer_alloc(VCP_RX_BUF_SIZE, 1);
|
||||||
}
|
}
|
||||||
furi_assert(vcp->thread == NULL);
|
furi_assert(vcp->thread == NULL);
|
||||||
|
|
||||||
@@ -113,7 +112,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#endif
|
#endif
|
||||||
if(vcp->connected == false) {
|
if(vcp->connected == false) {
|
||||||
vcp->connected = true;
|
vcp->connected = true;
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +123,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#endif
|
#endif
|
||||||
if(vcp->connected == true) {
|
if(vcp->connected == true) {
|
||||||
vcp->connected = false;
|
vcp->connected = false;
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +133,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "StreamRx");
|
FURI_LOG_D(TAG, "StreamRx");
|
||||||
#endif
|
#endif
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
flags |= VcpEvtRx;
|
flags |= VcpEvtRx;
|
||||||
missed_rx--;
|
missed_rx--;
|
||||||
}
|
}
|
||||||
@@ -142,14 +141,15 @@ static int32_t vcp_worker(void* context) {
|
|||||||
|
|
||||||
// New data received
|
// New data received
|
||||||
if(flags & VcpEvtRx) {
|
if(flags & VcpEvtRx) {
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Rx %d", len);
|
FURI_LOG_D(TAG, "Rx %d", len);
|
||||||
#endif
|
#endif
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
furi_check(
|
furi_check(
|
||||||
xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) ==
|
furi_stream_buffer_send(
|
||||||
|
vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) ==
|
||||||
(size_t)len);
|
(size_t)len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -173,7 +173,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
// CDC write transfer done
|
// CDC write transfer done
|
||||||
if(flags & VcpEvtTx) {
|
if(flags & VcpEvtTx) {
|
||||||
size_t len =
|
size_t len =
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Tx %d", len);
|
FURI_LOG_D(TAG, "Tx %d", len);
|
||||||
#endif
|
#endif
|
||||||
@@ -202,8 +202,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
|
furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
|
||||||
}
|
}
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) {
|
|||||||
size_t batch_size = size;
|
size_t batch_size = size;
|
||||||
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
||||||
|
|
||||||
size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout);
|
size_t len = furi_stream_buffer_receive(vcp->rx_stream, buffer, batch_size, timeout);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
||||||
#endif
|
#endif
|
||||||
@@ -262,7 +262,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
|
|||||||
size_t batch_size = size;
|
size_t batch_size = size;
|
||||||
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
||||||
|
|
||||||
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, FuriWaitForever);
|
furi_stream_buffer_send(vcp->tx_stream, buffer, batch_size, FuriWaitForever);
|
||||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx);
|
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u", batch_size);
|
FURI_LOG_D(TAG, "tx %u", batch_size);
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ static bool animation_storage_load_frames(
|
|||||||
if(file_info.size > max_filesize) {
|
if(file_info.size > max_filesize) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Filesize %d, max: %d (width %d, height %d)",
|
"Filesize %lld, max: %d (width %d, height %d)",
|
||||||
file_info.size,
|
file_info.size,
|
||||||
max_filesize,
|
max_filesize,
|
||||||
width,
|
width,
|
||||||
@@ -329,7 +329,7 @@ static bool animation_storage_load_frames(
|
|||||||
if(!frames_ok) {
|
if(!frames_ok) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"Load \'%s\' failed, %dx%d, size: %d",
|
"Load \'%s\' failed, %dx%d, size: %lld",
|
||||||
furi_string_get_cstr(filename),
|
furi_string_get_cstr(filename),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|||||||
@@ -124,16 +124,17 @@ bool desktop_debug_input(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
DesktopViewStatsScreens current = 0;
|
DesktopViewStatsScreens current = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
debug_view->view, (DesktopDebugViewModel * model) {
|
debug_view->view,
|
||||||
|
DesktopDebugViewModel * model,
|
||||||
|
{
|
||||||
#ifdef SRV_DOLPHIN_STATE_DEBUG
|
#ifdef SRV_DOLPHIN_STATE_DEBUG
|
||||||
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
|
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
|
||||||
model->screen = !model->screen;
|
model->screen = !model->screen;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
current = model->screen;
|
current = model->screen;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
size_t count = (event->type == InputTypeRepeat) ? 10 : 1;
|
size_t count = (event->type == InputTypeRepeat) ? 10 : 1;
|
||||||
if(current == DesktopViewStatsMeta) {
|
if(current == DesktopViewStatsMeta) {
|
||||||
@@ -181,20 +182,19 @@ void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) {
|
|||||||
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
|
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
|
||||||
DolphinStats stats = dolphin_stats(dolphin);
|
DolphinStats stats = dolphin_stats(dolphin);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
debug_view->view, (DesktopDebugViewModel * model) {
|
debug_view->view,
|
||||||
|
DesktopDebugViewModel * model,
|
||||||
|
{
|
||||||
model->icounter = stats.icounter;
|
model->icounter = stats.icounter;
|
||||||
model->butthurt = stats.butthurt;
|
model->butthurt = stats.butthurt;
|
||||||
model->timestamp = stats.timestamp;
|
model->timestamp = stats.timestamp;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
furi_record_close(RECORD_DOLPHIN);
|
furi_record_close(RECORD_DOLPHIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view) {
|
void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
debug_view->view, (DesktopDebugViewModel * model) {
|
debug_view->view, DesktopDebugViewModel * model, { model->screen = 0; }, true);
|
||||||
model->screen = 0;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,27 +24,24 @@ void desktop_lock_menu_set_callback(
|
|||||||
|
|
||||||
void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set) {
|
void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
lock_menu->view,
|
||||||
model->pin_is_set = pin_is_set;
|
DesktopLockMenuViewModel * model,
|
||||||
return true;
|
{ model->pin_is_set = pin_is_set; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode) {
|
void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
lock_menu->view,
|
||||||
model->dummy_mode = dummy_mode;
|
DesktopLockMenuViewModel * model,
|
||||||
return true;
|
{ model->dummy_mode = dummy_mode; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) {
|
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) {
|
||||||
furi_assert(idx < DesktopLockMenuIndexTotalCount);
|
furi_assert(idx < DesktopLockMenuIndexTotalCount);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
lock_menu->view, DesktopLockMenuViewModel * model, { model->idx = idx; }, true);
|
||||||
model->idx = idx;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) {
|
void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) {
|
||||||
@@ -95,10 +92,12 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
|
|||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
bool dummy_mode = false;
|
bool dummy_mode = false;
|
||||||
|
bool update = false;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
lock_menu->view,
|
||||||
bool ret = false;
|
DesktopLockMenuViewModel * model,
|
||||||
|
{
|
||||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
if(model->idx == 0) {
|
if(model->idx == 0) {
|
||||||
@@ -106,7 +105,7 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
|
|||||||
} else {
|
} else {
|
||||||
model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0);
|
model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0);
|
||||||
}
|
}
|
||||||
ret = true;
|
update = true;
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->key == InputKeyDown) {
|
} else if(event->key == InputKeyDown) {
|
||||||
if(model->idx == DesktopLockMenuIndexTotalCount - 1) {
|
if(model->idx == DesktopLockMenuIndexTotalCount - 1) {
|
||||||
@@ -114,14 +113,14 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
|
|||||||
} else {
|
} else {
|
||||||
model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0);
|
model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0);
|
||||||
}
|
}
|
||||||
ret = true;
|
update = true;
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx = model->idx;
|
idx = model->idx;
|
||||||
dummy_mode = model->dummy_mode;
|
dummy_mode = model->dummy_mode;
|
||||||
return ret;
|
},
|
||||||
});
|
update);
|
||||||
|
|
||||||
if(event->key == InputKeyOk) {
|
if(event->key == InputKeyOk) {
|
||||||
if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) {
|
if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) {
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) {
|
|||||||
|
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"icounter %d, butthurt %d",
|
"icounter %ld, butthurt %ld",
|
||||||
dolphin_state->data.icounter,
|
dolphin_state->data.icounter,
|
||||||
dolphin_state->data.butthurt);
|
dolphin_state->data.butthurt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
|||||||
"non-complementary input, discarding key: %s type: %s, sequence: %p",
|
"non-complementary input, discarding key: %s type: %s, sequence: %p",
|
||||||
input_get_key_name(input_event->key),
|
input_get_key_name(input_event->key),
|
||||||
input_get_type_name(input_event->type),
|
input_get_type_name(input_event->type),
|
||||||
input_event->sequence);
|
(void*)input_event->sequence);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
|||||||
view_port,
|
view_port,
|
||||||
input_get_key_name(input_event->key),
|
input_get_key_name(input_event->key),
|
||||||
input_get_type_name(input_event->type),
|
input_get_type_name(input_event->type),
|
||||||
input_event->sequence);
|
(void*)input_event->sequence);
|
||||||
view_port_input(gui->ongoing_input_view_port, input_event);
|
view_port_input(gui->ongoing_input_view_port, input_event);
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
@@ -300,7 +300,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
|||||||
view_port,
|
view_port,
|
||||||
input_get_key_name(input_event->key),
|
input_get_key_name(input_event->key),
|
||||||
input_get_type_name(input_event->type),
|
input_get_type_name(input_event->type),
|
||||||
input_event->sequence);
|
(void*)input_event->sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_unlock(gui);
|
gui_unlock(gui);
|
||||||
|
|||||||
@@ -148,28 +148,32 @@ static void button_menu_process_up(ButtonMenu* button_menu) {
|
|||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
if(model->position > 0) {
|
if(model->position > 0) {
|
||||||
model->position--;
|
model->position--;
|
||||||
} else {
|
} else {
|
||||||
model->position = ButtonMenuItemArray_size(model->items) - 1;
|
model->position = ButtonMenuItemArray_size(model->items) - 1;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void button_menu_process_down(ButtonMenu* button_menu) {
|
static void button_menu_process_down(ButtonMenu* button_menu) {
|
||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
if(model->position < (ButtonMenuItemArray_size(model->items) - 1)) {
|
if(model->position < (ButtonMenuItemArray_size(model->items) - 1)) {
|
||||||
model->position++;
|
model->position++;
|
||||||
} else {
|
} else {
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
|
static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
|
||||||
@@ -178,12 +182,14 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
|
|||||||
ButtonMenuItem* item = NULL;
|
ButtonMenuItem* item = NULL;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
if(model->position < (ButtonMenuItemArray_size(model->items))) {
|
if(model->position < (ButtonMenuItemArray_size(model->items))) {
|
||||||
item = ButtonMenuItemArray_get(model->items, model->position);
|
item = ButtonMenuItemArray_get(model->items, model->position);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
if(item) {
|
if(item) {
|
||||||
if(item->type == ButtonMenuItemTypeControl) {
|
if(item->type == ButtonMenuItemTypeControl) {
|
||||||
@@ -248,22 +254,21 @@ void button_menu_reset(ButtonMenu* button_menu) {
|
|||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
ButtonMenuItemArray_reset(model->items);
|
ButtonMenuItemArray_reset(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->header = NULL;
|
model->header = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void button_menu_set_header(ButtonMenu* button_menu, const char* header) {
|
void button_menu_set_header(ButtonMenu* button_menu, const char* header) {
|
||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view, ButtonMenuModel * model, { model->header = header; }, true);
|
||||||
model->header = header;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonMenuItem* button_menu_add_item(
|
ButtonMenuItem* button_menu_add_item(
|
||||||
@@ -278,15 +283,17 @@ ButtonMenuItem* button_menu_add_item(
|
|||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
item = ButtonMenuItemArray_push_new(model->items);
|
item = ButtonMenuItemArray_push_new(model->items);
|
||||||
item->label = label;
|
item->label = label;
|
||||||
item->index = index;
|
item->index = index;
|
||||||
item->type = type;
|
item->type = type;
|
||||||
item->callback = callback;
|
item->callback = callback;
|
||||||
item->callback_context = callback_context;
|
item->callback_context = callback_context;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@@ -301,12 +308,14 @@ ButtonMenu* button_menu_alloc(void) {
|
|||||||
view_set_input_callback(button_menu->view, button_menu_view_input_callback);
|
view_set_input_callback(button_menu->view, button_menu_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
ButtonMenuItemArray_init(model->items);
|
ButtonMenuItemArray_init(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->header = NULL;
|
model->header = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
button_menu->freeze_input = false;
|
button_menu->freeze_input = false;
|
||||||
return button_menu;
|
return button_menu;
|
||||||
@@ -316,10 +325,10 @@ void button_menu_free(ButtonMenu* button_menu) {
|
|||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
ButtonMenuItemArray_clear(model->items);
|
ButtonMenuModel * model,
|
||||||
return true;
|
{ ButtonMenuItemArray_clear(model->items); },
|
||||||
});
|
true);
|
||||||
view_free(button_menu->view);
|
view_free(button_menu->view);
|
||||||
free(button_menu);
|
free(button_menu);
|
||||||
}
|
}
|
||||||
@@ -328,7 +337,9 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) {
|
|||||||
furi_assert(button_menu);
|
furi_assert(button_menu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_menu->view, (ButtonMenuModel * model) {
|
button_menu->view,
|
||||||
|
ButtonMenuModel * model,
|
||||||
|
{
|
||||||
uint8_t item_position = 0;
|
uint8_t item_position = 0;
|
||||||
ButtonMenuItemArray_it_t it;
|
ButtonMenuItemArray_it_t it;
|
||||||
for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it);
|
for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it);
|
||||||
@@ -338,6 +349,6 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,15 +70,17 @@ ButtonPanel* button_panel_alloc() {
|
|||||||
view_set_input_callback(button_panel->view, button_panel_view_input_callback);
|
view_set_input_callback(button_panel->view, button_panel_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
model->reserve_x = 0;
|
model->reserve_x = 0;
|
||||||
model->reserve_y = 0;
|
model->reserve_y = 0;
|
||||||
model->selected_item_x = 0;
|
model->selected_item_x = 0;
|
||||||
model->selected_item_y = 0;
|
model->selected_item_y = 0;
|
||||||
ButtonMatrix_init(model->button_matrix);
|
ButtonMatrix_init(model->button_matrix);
|
||||||
LabelList_init(model->labels);
|
LabelList_init(model->labels);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return button_panel;
|
return button_panel;
|
||||||
}
|
}
|
||||||
@@ -88,7 +90,9 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re
|
|||||||
furi_check(reserve_y > 0);
|
furi_check(reserve_y > 0);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
model->reserve_x = reserve_x;
|
model->reserve_x = reserve_x;
|
||||||
model->reserve_y = reserve_y;
|
model->reserve_y = reserve_y;
|
||||||
ButtonMatrix_reserve(model->button_matrix, model->reserve_y);
|
ButtonMatrix_reserve(model->button_matrix, model->reserve_y);
|
||||||
@@ -99,8 +103,8 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re
|
|||||||
// TODO: do we need to clear allocated memory of ptr-s to ButtonItem ??
|
// TODO: do we need to clear allocated memory of ptr-s to ButtonItem ??
|
||||||
}
|
}
|
||||||
LabelList_init(model->labels);
|
LabelList_init(model->labels);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void button_panel_free(ButtonPanel* button_panel) {
|
void button_panel_free(ButtonPanel* button_panel) {
|
||||||
@@ -109,11 +113,13 @@ void button_panel_free(ButtonPanel* button_panel) {
|
|||||||
button_panel_reset(button_panel);
|
button_panel_reset(button_panel);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
LabelList_clear(model->labels);
|
LabelList_clear(model->labels);
|
||||||
ButtonMatrix_clear(model->button_matrix);
|
ButtonMatrix_clear(model->button_matrix);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
view_free(button_panel->view);
|
view_free(button_panel->view);
|
||||||
free(button_panel);
|
free(button_panel);
|
||||||
@@ -123,7 +129,9 @@ void button_panel_reset(ButtonPanel* button_panel) {
|
|||||||
furi_assert(button_panel);
|
furi_assert(button_panel);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
for(size_t x = 0; x < model->reserve_x; ++x) {
|
for(size_t x = 0; x < model->reserve_x; ++x) {
|
||||||
for(size_t y = 0; y < model->reserve_y; ++y) {
|
for(size_t y = 0; y < model->reserve_y; ++y) {
|
||||||
ButtonItem** button_item = button_panel_get_item(model, x, y);
|
ButtonItem** button_item = button_panel_get_item(model, x, y);
|
||||||
@@ -137,8 +145,8 @@ void button_panel_reset(ButtonPanel* button_panel) {
|
|||||||
model->selected_item_y = 0;
|
model->selected_item_y = 0;
|
||||||
LabelList_reset(model->labels);
|
LabelList_reset(model->labels);
|
||||||
ButtonMatrix_reset(model->button_matrix);
|
ButtonMatrix_reset(model->button_matrix);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ButtonItem** button_panel_get_item(ButtonPanelModel* model, size_t x, size_t y) {
|
static ButtonItem** button_panel_get_item(ButtonPanelModel* model, size_t x, size_t y) {
|
||||||
@@ -165,7 +173,9 @@ void button_panel_add_item(
|
|||||||
furi_assert(button_panel);
|
furi_assert(button_panel);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
ButtonItem** button_item_ptr =
|
ButtonItem** button_item_ptr =
|
||||||
button_panel_get_item(model, matrix_place_x, matrix_place_y);
|
button_panel_get_item(model, matrix_place_x, matrix_place_y);
|
||||||
furi_check(*button_item_ptr == NULL);
|
furi_check(*button_item_ptr == NULL);
|
||||||
@@ -178,8 +188,8 @@ void button_panel_add_item(
|
|||||||
button_item->icon.name = icon_name;
|
button_item->icon.name = icon_name;
|
||||||
button_item->icon.name_selected = icon_name_selected;
|
button_item->icon.name_selected = icon_name_selected;
|
||||||
button_item->index = index;
|
button_item->index = index;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* button_panel_get_view(ButtonPanel* button_panel) {
|
View* button_panel_get_view(ButtonPanel* button_panel) {
|
||||||
@@ -216,114 +226,123 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
static void button_panel_process_down(ButtonPanel* button_panel) {
|
static void button_panel_process_down(ButtonPanel* button_panel) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
uint16_t new_selected_item_x = model->selected_item_x;
|
uint16_t new_selected_item_x = model->selected_item_x;
|
||||||
uint16_t new_selected_item_y = model->selected_item_y;
|
uint16_t new_selected_item_y = model->selected_item_y;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if(new_selected_item_y >= (model->reserve_y - 1)) return false;
|
if(new_selected_item_y < (model->reserve_y - 1)) {
|
||||||
|
++new_selected_item_y;
|
||||||
|
|
||||||
++new_selected_item_y;
|
for(i = 0; i < model->reserve_x; ++i) {
|
||||||
|
new_selected_item_x = (model->selected_item_x + i) % model->reserve_x;
|
||||||
for(i = 0; i < model->reserve_x; ++i) {
|
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
||||||
new_selected_item_x = (model->selected_item_x + i) % model->reserve_x;
|
break;
|
||||||
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
}
|
||||||
break;
|
}
|
||||||
|
if(i != model->reserve_x) {
|
||||||
|
model->selected_item_x = new_selected_item_x;
|
||||||
|
model->selected_item_y = new_selected_item_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == model->reserve_x) return false;
|
},
|
||||||
|
true);
|
||||||
model->selected_item_x = new_selected_item_x;
|
|
||||||
model->selected_item_y = new_selected_item_y;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void button_panel_process_up(ButtonPanel* button_panel) {
|
static void button_panel_process_up(ButtonPanel* button_panel) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
size_t new_selected_item_x = model->selected_item_x;
|
size_t new_selected_item_x = model->selected_item_x;
|
||||||
size_t new_selected_item_y = model->selected_item_y;
|
size_t new_selected_item_y = model->selected_item_y;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if(new_selected_item_y <= 0) return false;
|
if(new_selected_item_y > 0) {
|
||||||
|
--new_selected_item_y;
|
||||||
|
|
||||||
--new_selected_item_y;
|
for(i = 0; i < model->reserve_x; ++i) {
|
||||||
|
new_selected_item_x = (model->selected_item_x + i) % model->reserve_x;
|
||||||
for(i = 0; i < model->reserve_x; ++i) {
|
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
||||||
new_selected_item_x = (model->selected_item_x + i) % model->reserve_x;
|
break;
|
||||||
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
}
|
||||||
break;
|
}
|
||||||
|
if(i != model->reserve_x) {
|
||||||
|
model->selected_item_x = new_selected_item_x;
|
||||||
|
model->selected_item_y = new_selected_item_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == model->reserve_x) return false;
|
},
|
||||||
|
true);
|
||||||
model->selected_item_x = new_selected_item_x;
|
|
||||||
model->selected_item_y = new_selected_item_y;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void button_panel_process_left(ButtonPanel* button_panel) {
|
static void button_panel_process_left(ButtonPanel* button_panel) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
size_t new_selected_item_x = model->selected_item_x;
|
size_t new_selected_item_x = model->selected_item_x;
|
||||||
size_t new_selected_item_y = model->selected_item_y;
|
size_t new_selected_item_y = model->selected_item_y;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if(new_selected_item_x <= 0) return false;
|
if(new_selected_item_x > 0) {
|
||||||
|
--new_selected_item_x;
|
||||||
|
|
||||||
--new_selected_item_x;
|
for(i = 0; i < model->reserve_y; ++i) {
|
||||||
|
new_selected_item_y = (model->selected_item_y + i) % model->reserve_y;
|
||||||
for(i = 0; i < model->reserve_y; ++i) {
|
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
||||||
new_selected_item_y = (model->selected_item_y + i) % model->reserve_y;
|
break;
|
||||||
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
}
|
||||||
break;
|
}
|
||||||
|
if(i != model->reserve_y) {
|
||||||
|
model->selected_item_x = new_selected_item_x;
|
||||||
|
model->selected_item_y = new_selected_item_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == model->reserve_y) return false;
|
},
|
||||||
|
true);
|
||||||
model->selected_item_x = new_selected_item_x;
|
|
||||||
model->selected_item_y = new_selected_item_y;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void button_panel_process_right(ButtonPanel* button_panel) {
|
static void button_panel_process_right(ButtonPanel* button_panel) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
uint16_t new_selected_item_x = model->selected_item_x;
|
uint16_t new_selected_item_x = model->selected_item_x;
|
||||||
uint16_t new_selected_item_y = model->selected_item_y;
|
uint16_t new_selected_item_y = model->selected_item_y;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if(new_selected_item_x >= (model->reserve_x - 1)) return false;
|
if(new_selected_item_x < (model->reserve_x - 1)) {
|
||||||
|
++new_selected_item_x;
|
||||||
|
|
||||||
++new_selected_item_x;
|
for(i = 0; i < model->reserve_y; ++i) {
|
||||||
|
new_selected_item_y = (model->selected_item_y + i) % model->reserve_y;
|
||||||
for(i = 0; i < model->reserve_y; ++i) {
|
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
||||||
new_selected_item_y = (model->selected_item_y + i) % model->reserve_y;
|
break;
|
||||||
if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) {
|
}
|
||||||
break;
|
}
|
||||||
|
if(i != model->reserve_y) {
|
||||||
|
model->selected_item_x = new_selected_item_x;
|
||||||
|
model->selected_item_y = new_selected_item_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == model->reserve_y) return false;
|
},
|
||||||
|
true);
|
||||||
model->selected_item_x = new_selected_item_x;
|
|
||||||
model->selected_item_y = new_selected_item_y;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void button_panel_process_ok(ButtonPanel* button_panel) {
|
void button_panel_process_ok(ButtonPanel* button_panel) {
|
||||||
ButtonItem* button_item = NULL;
|
ButtonItem* button_item = NULL;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
button_item =
|
button_item =
|
||||||
*button_panel_get_item(model, model->selected_item_x, model->selected_item_y);
|
*button_panel_get_item(model, model->selected_item_x, model->selected_item_y);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
if(button_item && button_item->callback) {
|
if(button_item && button_item->callback) {
|
||||||
button_item->callback(button_item->callback_context, button_item->index);
|
button_item->callback(button_item->callback_context, button_item->index);
|
||||||
@@ -374,12 +393,14 @@ void button_panel_add_label(
|
|||||||
furi_assert(button_panel);
|
furi_assert(button_panel);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
button_panel->view, (ButtonPanelModel * model) {
|
button_panel->view,
|
||||||
|
ButtonPanelModel * model,
|
||||||
|
{
|
||||||
LabelElement* label = LabelList_push_raw(model->labels);
|
LabelElement* label = LabelList_push_raw(model->labels);
|
||||||
label->x = x;
|
label->x = x;
|
||||||
label->y = y;
|
label->y = y;
|
||||||
label->font = font;
|
label->font = font;
|
||||||
label->str = label_str;
|
label->str = label_str;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -618,42 +618,30 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) {
|
|||||||
switch(event->key) {
|
switch(event->key) {
|
||||||
case InputKeyLeft:
|
case InputKeyLeft:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view, ByteInputModel * model, { byte_input_handle_left(model); }, true);
|
||||||
byte_input_handle_left(model);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case InputKeyRight:
|
case InputKeyRight:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view,
|
||||||
byte_input_handle_right(model);
|
ByteInputModel * model,
|
||||||
return true;
|
{ byte_input_handle_right(model); },
|
||||||
});
|
true);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case InputKeyUp:
|
case InputKeyUp:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view, ByteInputModel * model, { byte_input_handle_up(model); }, true);
|
||||||
byte_input_handle_up(model);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case InputKeyDown:
|
case InputKeyDown:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view, ByteInputModel * model, { byte_input_handle_down(model); }, true);
|
||||||
byte_input_handle_down(model);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case InputKeyOk:
|
case InputKeyOk:
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view, ByteInputModel * model, { byte_input_handle_ok(model); }, true);
|
||||||
byte_input_handle_ok(model);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -664,10 +652,10 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) {
|
|||||||
if((event->type == InputTypeLong || event->type == InputTypeRepeat) &&
|
if((event->type == InputTypeLong || event->type == InputTypeRepeat) &&
|
||||||
event->key == InputKeyBack) {
|
event->key == InputKeyBack) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view,
|
||||||
byte_input_clear_selected_byte(model);
|
ByteInputModel * model,
|
||||||
return true;
|
{ byte_input_clear_selected_byte(model); },
|
||||||
});
|
true);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,14 +691,16 @@ ByteInput* byte_input_alloc() {
|
|||||||
view_set_input_callback(byte_input->view, byte_input_view_input_callback);
|
view_set_input_callback(byte_input->view, byte_input_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view,
|
||||||
|
ByteInputModel * model,
|
||||||
|
{
|
||||||
model->header = "";
|
model->header = "";
|
||||||
model->input_callback = NULL;
|
model->input_callback = NULL;
|
||||||
model->changed_callback = NULL;
|
model->changed_callback = NULL;
|
||||||
model->callback_context = NULL;
|
model->callback_context = NULL;
|
||||||
byte_input_reset_model_input_data(model);
|
byte_input_reset_model_input_data(model);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return byte_input;
|
return byte_input;
|
||||||
}
|
}
|
||||||
@@ -755,15 +745,17 @@ void byte_input_set_result_callback(
|
|||||||
uint8_t* bytes,
|
uint8_t* bytes,
|
||||||
uint8_t bytes_count) {
|
uint8_t bytes_count) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view,
|
||||||
|
ByteInputModel * model,
|
||||||
|
{
|
||||||
byte_input_reset_model_input_data(model);
|
byte_input_reset_model_input_data(model);
|
||||||
model->input_callback = input_callback;
|
model->input_callback = input_callback;
|
||||||
model->changed_callback = changed_callback;
|
model->changed_callback = changed_callback;
|
||||||
model->callback_context = callback_context;
|
model->callback_context = callback_context;
|
||||||
model->bytes = bytes;
|
model->bytes = bytes;
|
||||||
model->bytes_count = bytes_count;
|
model->bytes_count = bytes_count;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -774,8 +766,5 @@ void byte_input_set_result_callback(
|
|||||||
*/
|
*/
|
||||||
void byte_input_set_header_text(ByteInput* byte_input, const char* text) {
|
void byte_input_set_header_text(ByteInput* byte_input, const char* text) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view, (ByteInputModel * model) {
|
byte_input->view, ByteInputModel * model, { model->header = text; }, true);
|
||||||
model->header = text;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,12 +90,14 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) {
|
|||||||
const char* right_text = NULL;
|
const char* right_text = NULL;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
left_text = model->left_text;
|
left_text = model->left_text;
|
||||||
center_text = model->center_text;
|
center_text = model->center_text;
|
||||||
right_text = model->right_text;
|
right_text = model->right_text;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
if(dialog_ex->callback) {
|
if(dialog_ex->callback) {
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
@@ -149,7 +151,9 @@ DialogEx* dialog_ex_alloc() {
|
|||||||
view_set_draw_callback(dialog_ex->view, dialog_ex_view_draw_callback);
|
view_set_draw_callback(dialog_ex->view, dialog_ex_view_draw_callback);
|
||||||
view_set_input_callback(dialog_ex->view, dialog_ex_view_input_callback);
|
view_set_input_callback(dialog_ex->view, dialog_ex_view_input_callback);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
model->header.text = NULL;
|
model->header.text = NULL;
|
||||||
model->header.x = 0;
|
model->header.x = 0;
|
||||||
model->header.y = 0;
|
model->header.y = 0;
|
||||||
@@ -169,9 +173,8 @@ DialogEx* dialog_ex_alloc() {
|
|||||||
model->left_text = NULL;
|
model->left_text = NULL;
|
||||||
model->center_text = NULL;
|
model->center_text = NULL;
|
||||||
model->right_text = NULL;
|
model->right_text = NULL;
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
dialog_ex->enable_extended_events = false;
|
dialog_ex->enable_extended_events = false;
|
||||||
return dialog_ex;
|
return dialog_ex;
|
||||||
}
|
}
|
||||||
@@ -206,14 +209,16 @@ void dialog_ex_set_header(
|
|||||||
Align vertical) {
|
Align vertical) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
model->header.text = text;
|
model->header.text = text;
|
||||||
model->header.x = x;
|
model->header.x = x;
|
||||||
model->header.y = y;
|
model->header.y = y;
|
||||||
model->header.horizontal = horizontal;
|
model->header.horizontal = horizontal;
|
||||||
model->header.vertical = vertical;
|
model->header.vertical = vertical;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_set_text(
|
void dialog_ex_set_text(
|
||||||
@@ -225,52 +230,47 @@ void dialog_ex_set_text(
|
|||||||
Align vertical) {
|
Align vertical) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
model->text.text = text;
|
model->text.text = text;
|
||||||
model->text.x = x;
|
model->text.x = x;
|
||||||
model->text.y = y;
|
model->text.y = y;
|
||||||
model->text.horizontal = horizontal;
|
model->text.horizontal = horizontal;
|
||||||
model->text.vertical = vertical;
|
model->text.vertical = vertical;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, const Icon* icon) {
|
void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, const Icon* icon) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
model->icon.x = x;
|
model->icon.x = x;
|
||||||
model->icon.y = y;
|
model->icon.y = y;
|
||||||
model->icon.icon = icon;
|
model->icon.icon = icon;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_set_left_button_text(DialogEx* dialog_ex, const char* text) {
|
void dialog_ex_set_left_button_text(DialogEx* dialog_ex, const char* text) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view, DialogExModel * model, { model->left_text = text; }, true);
|
||||||
model->left_text = text;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_set_center_button_text(DialogEx* dialog_ex, const char* text) {
|
void dialog_ex_set_center_button_text(DialogEx* dialog_ex, const char* text) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view, DialogExModel * model, { model->center_text = text; }, true);
|
||||||
model->center_text = text;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) {
|
void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) {
|
||||||
furi_assert(dialog_ex);
|
furi_assert(dialog_ex);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view, DialogExModel * model, { model->right_text = text; }, true);
|
||||||
model->right_text = text;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialog_ex_reset(DialogEx* dialog_ex) {
|
void dialog_ex_reset(DialogEx* dialog_ex) {
|
||||||
@@ -279,15 +279,17 @@ void dialog_ex_reset(DialogEx* dialog_ex) {
|
|||||||
.text = NULL, .x = 0, .y = 0, .horizontal = AlignLeft, .vertical = AlignLeft};
|
.text = NULL, .x = 0, .y = 0, .horizontal = AlignLeft, .vertical = AlignLeft};
|
||||||
IconElement clean_icon_el = {.icon = NULL, .x = 0, .y = 0};
|
IconElement clean_icon_el = {.icon = NULL, .x = 0, .y = 0};
|
||||||
with_view_model(
|
with_view_model(
|
||||||
dialog_ex->view, (DialogExModel * model) {
|
dialog_ex->view,
|
||||||
|
DialogExModel * model,
|
||||||
|
{
|
||||||
model->header = clean_text_el;
|
model->header = clean_text_el;
|
||||||
model->text = clean_text_el;
|
model->text = clean_text_el;
|
||||||
model->icon = clean_icon_el;
|
model->icon = clean_icon_el;
|
||||||
model->left_text = NULL;
|
model->left_text = NULL;
|
||||||
model->center_text = NULL;
|
model->center_text = NULL;
|
||||||
model->right_text = NULL;
|
model->right_text = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
dialog_ex->context = NULL;
|
dialog_ex->context = NULL;
|
||||||
dialog_ex->callback = NULL;
|
dialog_ex->callback = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) {
|
|||||||
furi_string_set(obj->path, src->path);
|
furi_string_set(obj->path, src->path);
|
||||||
furi_string_set(obj->display_name, src->display_name);
|
furi_string_set(obj->display_name, src->display_name);
|
||||||
if(src->custom_icon_data) {
|
if(src->custom_icon_data) {
|
||||||
obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE);
|
|
||||||
memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE);
|
memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE);
|
||||||
} else {
|
} else {
|
||||||
obj->custom_icon_data = NULL;
|
obj->custom_icon_data = NULL;
|
||||||
@@ -140,10 +139,7 @@ FileBrowser* file_browser_alloc(FuriString* result_path) {
|
|||||||
browser->result_path = result_path;
|
browser->result_path = result_path;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { items_array_init(model->items); }, false);
|
||||||
items_array_init(model->items);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
@@ -152,10 +148,7 @@ void file_browser_free(FileBrowser* browser) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { items_array_clear(model->items); }, false);
|
||||||
items_array_clear(model->items);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
view_free(browser->view);
|
view_free(browser->view);
|
||||||
free(browser);
|
free(browser);
|
||||||
@@ -179,11 +172,13 @@ void file_browser_configure(
|
|||||||
browser->hide_ext = hide_ext;
|
browser->hide_ext = hide_ext;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
model->file_icon = file_icon;
|
model->file_icon = file_icon;
|
||||||
model->hide_ext = hide_ext;
|
model->hide_ext = hide_ext;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_browser_start(FileBrowser* browser, FuriString* path) {
|
void file_browser_start(FileBrowser* browser, FuriString* path) {
|
||||||
@@ -200,14 +195,16 @@ void file_browser_stop(FileBrowser* browser) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
file_browser_worker_free(browser->worker);
|
file_browser_worker_free(browser->worker);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
items_array_reset(model->items);
|
items_array_reset(model->items);
|
||||||
model->item_cnt = 0;
|
model->item_cnt = 0;
|
||||||
model->item_idx = 0;
|
model->item_idx = 0;
|
||||||
model->array_offset = 0;
|
model->array_offset = 0;
|
||||||
model->list_offset = 0;
|
model->list_offset = 0;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) {
|
void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) {
|
||||||
@@ -258,7 +255,9 @@ static void browser_update_offset(FileBrowser* browser) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
uint16_t bounds = model->item_cnt > (LIST_ITEMS - 1) ? 2 : model->item_cnt;
|
uint16_t bounds = model->item_cnt > (LIST_ITEMS - 1) ? 2 : model->item_cnt;
|
||||||
|
|
||||||
if((model->item_cnt > (LIST_ITEMS - 1)) &&
|
if((model->item_cnt > (LIST_ITEMS - 1)) &&
|
||||||
@@ -273,9 +272,8 @@ static void browser_update_offset(FileBrowser* browser) {
|
|||||||
model->list_offset =
|
model->list_offset =
|
||||||
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
|
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return false;
|
false);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -286,7 +284,9 @@ static void
|
|||||||
int32_t load_offset = 0;
|
int32_t load_offset = 0;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
items_array_reset(model->items);
|
items_array_reset(model->items);
|
||||||
if(is_root) {
|
if(is_root) {
|
||||||
model->item_cnt = item_cnt;
|
model->item_cnt = item_cnt;
|
||||||
@@ -304,8 +304,8 @@ static void
|
|||||||
model->is_root = is_root;
|
model->is_root = is_root;
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
model->folder_loading = false;
|
model->folder_loading = false;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
browser_update_offset(browser);
|
browser_update_offset(browser);
|
||||||
|
|
||||||
file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
||||||
@@ -320,7 +320,9 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) {
|
|||||||
back_item.type = BrowserItemTypeBack;
|
back_item.type = BrowserItemTypeBack;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
items_array_reset(model->items);
|
items_array_reset(model->items);
|
||||||
model->array_offset = list_load_offset;
|
model->array_offset = list_load_offset;
|
||||||
if(!model->is_root) {
|
if(!model->is_root) {
|
||||||
@@ -330,8 +332,8 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) {
|
|||||||
model->array_offset += 1;
|
model->array_offset += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
BrowserItem_t_clear(&back_item);
|
BrowserItem_t_clear(&back_item);
|
||||||
}
|
}
|
||||||
@@ -372,19 +374,21 @@ static void
|
|||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
items_array_push_back(model->items, item);
|
items_array_push_back(model->items, item);
|
||||||
// TODO: calculate if element is visible
|
// TODO: calculate if element is visible
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
furi_string_free(item.display_name);
|
furi_string_free(item.display_name);
|
||||||
furi_string_free(item.path);
|
furi_string_free(item.path);
|
||||||
|
if(item.custom_icon_data) {
|
||||||
|
free(item.custom_icon_data);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { model->list_loading = false; }, true);
|
||||||
model->list_loading = false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,10 +397,7 @@ static void browser_long_load_cb(void* context) {
|
|||||||
FileBrowser* browser = (FileBrowser*)context;
|
FileBrowser* browser = (FileBrowser*)context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { model->folder_loading = true; }, true);
|
||||||
model->folder_loading = true;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void browser_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
static void browser_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||||
@@ -506,17 +507,16 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
bool is_loading = false;
|
bool is_loading = false;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { is_loading = model->folder_loading; }, false);
|
||||||
is_loading = model->folder_loading;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(is_loading) {
|
if(is_loading) {
|
||||||
return false;
|
return false;
|
||||||
} else if(event->key == InputKeyUp || event->key == InputKeyDown) {
|
} else if(event->key == InputKeyUp || event->key == InputKeyDown) {
|
||||||
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
model->item_idx =
|
model->item_idx =
|
||||||
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
||||||
@@ -541,8 +541,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
browser_update_offset(browser);
|
browser_update_offset(browser);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
@@ -551,7 +551,9 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
BrowserItem_t* selected_item = NULL;
|
BrowserItem_t* selected_item = NULL;
|
||||||
int32_t select_index = 0;
|
int32_t select_index = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{
|
||||||
if(browser_is_item_in_array(model, model->item_idx)) {
|
if(browser_is_item_in_array(model, model->item_idx)) {
|
||||||
selected_item =
|
selected_item =
|
||||||
items_array_get(model->items, model->item_idx - model->array_offset);
|
items_array_get(model->items, model->item_idx - model->array_offset);
|
||||||
@@ -560,8 +562,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
select_index -= 1;
|
select_index -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
|
|
||||||
if(selected_item) {
|
if(selected_item) {
|
||||||
if(selected_item->type == BrowserItemTypeBack) {
|
if(selected_item->type == BrowserItemTypeBack) {
|
||||||
@@ -582,10 +584,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
bool is_root = false;
|
bool is_root = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
browser->view, (FileBrowserModel * model) {
|
browser->view, FileBrowserModel * model, { is_root = model->is_root; }, false);
|
||||||
is_root = model->is_root;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if(!is_root) {
|
if(!is_root) {
|
||||||
file_browser_worker_folder_exit(browser->worker);
|
file_browser_worker_folder_exit(browser->worker);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ static int32_t browser_worker(void* context) {
|
|||||||
browser_folder_init(browser, path, filename, &items_cnt, &file_idx);
|
browser_folder_init(browser, path, filename, &items_cnt, &file_idx);
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"Enter folder: %s items: %u idx: %d",
|
"Enter folder: %s items: %lu idx: %ld",
|
||||||
furi_string_get_cstr(path),
|
furi_string_get_cstr(path),
|
||||||
items_cnt,
|
items_cnt,
|
||||||
file_idx);
|
file_idx);
|
||||||
@@ -313,7 +313,7 @@ static int32_t browser_worker(void* context) {
|
|||||||
}
|
}
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"Exit to: %s items: %u idx: %d",
|
"Exit to: %s items: %lu idx: %ld",
|
||||||
furi_string_get_cstr(path),
|
furi_string_get_cstr(path),
|
||||||
items_cnt,
|
items_cnt,
|
||||||
file_idx);
|
file_idx);
|
||||||
@@ -330,7 +330,7 @@ static int32_t browser_worker(void* context) {
|
|||||||
browser_folder_init(browser, path, filename, &items_cnt, &file_idx);
|
browser_folder_init(browser, path, filename, &items_cnt, &file_idx);
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"Refresh folder: %s items: %u idx: %d",
|
"Refresh folder: %s items: %lu idx: %ld",
|
||||||
furi_string_get_cstr(path),
|
furi_string_get_cstr(path),
|
||||||
items_cnt,
|
items_cnt,
|
||||||
browser->item_sel_idx);
|
browser->item_sel_idx);
|
||||||
@@ -340,7 +340,8 @@ static int32_t browser_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(flags & WorkerEvtLoad) {
|
if(flags & WorkerEvtLoad) {
|
||||||
FURI_LOG_D(TAG, "Load offset: %u cnt: %u", browser->load_offset, browser->load_count);
|
FURI_LOG_D(
|
||||||
|
TAG, "Load offset: %lu cnt: %lu", browser->load_offset, browser->load_count);
|
||||||
browser_folder_load(browser, path, browser->load_offset, browser->load_count);
|
browser_folder_load(browser, path, browser->load_offset, browser->load_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,25 +103,29 @@ static bool menu_input_callback(InputEvent* event, void* context) {
|
|||||||
static void menu_enter(void* context) {
|
static void menu_enter(void* context) {
|
||||||
Menu* menu = context;
|
Menu* menu = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_start(item->icon);
|
icon_animation_start(item->icon);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_exit(void* context) {
|
static void menu_exit(void* context) {
|
||||||
Menu* menu = context;
|
Menu* menu = context;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_stop(item->icon);
|
icon_animation_stop(item->icon);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu* menu_alloc() {
|
Menu* menu_alloc() {
|
||||||
@@ -135,11 +139,13 @@ Menu* menu_alloc() {
|
|||||||
view_set_exit_callback(menu->view, menu_exit);
|
view_set_exit_callback(menu->view, menu_exit);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
MenuItemArray_init(model->items);
|
MenuItemArray_init(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
@@ -168,7 +174,9 @@ void menu_add_item(
|
|||||||
|
|
||||||
MenuItem* item = NULL;
|
MenuItem* item = NULL;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
item = MenuItemArray_push_new(model->items);
|
item = MenuItemArray_push_new(model->items);
|
||||||
item->label = label;
|
item->label = label;
|
||||||
item->icon = icon ? icon_animation_alloc(icon) : icon_animation_alloc(&A_Plugins_14);
|
item->icon = icon ? icon_animation_alloc(icon) : icon_animation_alloc(&A_Plugins_14);
|
||||||
@@ -176,14 +184,16 @@ void menu_add_item(
|
|||||||
item->index = index;
|
item->index = index;
|
||||||
item->callback = callback;
|
item->callback = callback;
|
||||||
item->callback_context = context;
|
item->callback_context = context;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_reset(Menu* menu) {
|
void menu_reset(Menu* menu) {
|
||||||
furi_assert(menu);
|
furi_assert(menu);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
for
|
for
|
||||||
M_EACH(item, model->items, MenuItemArray_t) {
|
M_EACH(item, model->items, MenuItemArray_t) {
|
||||||
icon_animation_stop(item->icon);
|
icon_animation_stop(item->icon);
|
||||||
@@ -192,25 +202,27 @@ void menu_reset(Menu* menu) {
|
|||||||
|
|
||||||
MenuItemArray_reset(model->items);
|
MenuItemArray_reset(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_set_selected_item(Menu* menu, uint32_t index) {
|
void menu_set_selected_item(Menu* menu, uint32_t index) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
if(index >= MenuItemArray_size(model->items)) {
|
MenuModel * model,
|
||||||
return false;
|
{
|
||||||
|
if(index < MenuItemArray_size(model->items)) {
|
||||||
|
model->position = index;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
model->position = index;
|
true);
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_process_up(Menu* menu) {
|
static void menu_process_up(Menu* menu) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_stop(item->icon);
|
icon_animation_stop(item->icon);
|
||||||
@@ -226,13 +238,15 @@ static void menu_process_up(Menu* menu) {
|
|||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_start(item->icon);
|
icon_animation_start(item->icon);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_process_down(Menu* menu) {
|
static void menu_process_down(Menu* menu) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_stop(item->icon);
|
icon_animation_stop(item->icon);
|
||||||
@@ -248,19 +262,21 @@ static void menu_process_down(Menu* menu) {
|
|||||||
if(item && item->icon) {
|
if(item && item->icon) {
|
||||||
icon_animation_start(item->icon);
|
icon_animation_start(item->icon);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_process_ok(Menu* menu) {
|
static void menu_process_ok(Menu* menu) {
|
||||||
MenuItem* item = NULL;
|
MenuItem* item = NULL;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
menu->view, (MenuModel * model) {
|
menu->view,
|
||||||
|
MenuModel * model,
|
||||||
|
{
|
||||||
if(model->position < MenuItemArray_size(model->items)) {
|
if(model->position < MenuItemArray_size(model->items)) {
|
||||||
item = MenuItemArray_get(model->items, model->position);
|
item = MenuItemArray_get(model->items, model->position);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
if(item && item->callback) {
|
if(item && item->callback) {
|
||||||
item->callback(item->callback_context, item->index);
|
item->callback(item->callback_context, item->index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,9 @@ Popup* popup_alloc() {
|
|||||||
view_set_exit_callback(popup->view, popup_stop_timer);
|
view_set_exit_callback(popup->view, popup_stop_timer);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
popup->view, (PopupModel * model) {
|
popup->view,
|
||||||
|
PopupModel * model,
|
||||||
|
{
|
||||||
model->header.text = NULL;
|
model->header.text = NULL;
|
||||||
model->header.x = 0;
|
model->header.x = 0;
|
||||||
model->header.y = 0;
|
model->header.y = 0;
|
||||||
@@ -140,8 +142,8 @@ Popup* popup_alloc() {
|
|||||||
model->icon.x = 0;
|
model->icon.x = 0;
|
||||||
model->icon.y = 0;
|
model->icon.y = 0;
|
||||||
model->icon.icon = NULL;
|
model->icon.icon = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,14 +178,16 @@ void popup_set_header(
|
|||||||
Align vertical) {
|
Align vertical) {
|
||||||
furi_assert(popup);
|
furi_assert(popup);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
popup->view, (PopupModel * model) {
|
popup->view,
|
||||||
|
PopupModel * model,
|
||||||
|
{
|
||||||
model->header.text = text;
|
model->header.text = text;
|
||||||
model->header.x = x;
|
model->header.x = x;
|
||||||
model->header.y = y;
|
model->header.y = y;
|
||||||
model->header.horizontal = horizontal;
|
model->header.horizontal = horizontal;
|
||||||
model->header.vertical = vertical;
|
model->header.vertical = vertical;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void popup_set_text(
|
void popup_set_text(
|
||||||
@@ -195,25 +199,29 @@ void popup_set_text(
|
|||||||
Align vertical) {
|
Align vertical) {
|
||||||
furi_assert(popup);
|
furi_assert(popup);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
popup->view, (PopupModel * model) {
|
popup->view,
|
||||||
|
PopupModel * model,
|
||||||
|
{
|
||||||
model->text.text = text;
|
model->text.text = text;
|
||||||
model->text.x = x;
|
model->text.x = x;
|
||||||
model->text.y = y;
|
model->text.y = y;
|
||||||
model->text.horizontal = horizontal;
|
model->text.horizontal = horizontal;
|
||||||
model->text.vertical = vertical;
|
model->text.vertical = vertical;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, const Icon* icon) {
|
void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, const Icon* icon) {
|
||||||
furi_assert(popup);
|
furi_assert(popup);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
popup->view, (PopupModel * model) {
|
popup->view,
|
||||||
|
PopupModel * model,
|
||||||
|
{
|
||||||
model->icon.x = x;
|
model->icon.x = x;
|
||||||
model->icon.y = y;
|
model->icon.y = y;
|
||||||
model->icon.icon = icon;
|
model->icon.icon = icon;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void popup_set_timeout(Popup* popup, uint32_t timeout_in_ms) {
|
void popup_set_timeout(Popup* popup, uint32_t timeout_in_ms) {
|
||||||
@@ -233,12 +241,14 @@ void popup_reset(Popup* popup) {
|
|||||||
furi_assert(popup);
|
furi_assert(popup);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
popup->view, (PopupModel * model) {
|
popup->view,
|
||||||
|
PopupModel * model,
|
||||||
|
{
|
||||||
memset(&model->header, 0, sizeof(model->header));
|
memset(&model->header, 0, sizeof(model->header));
|
||||||
memset(&model->text, 0, sizeof(model->text));
|
memset(&model->text, 0, sizeof(model->text));
|
||||||
memset(&model->icon, 0, sizeof(model->icon));
|
memset(&model->icon, 0, sizeof(model->icon));
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
popup->callback = NULL;
|
popup->callback = NULL;
|
||||||
popup->context = NULL;
|
popup->context = NULL;
|
||||||
popup->timer_enabled = false;
|
popup->timer_enabled = false;
|
||||||
|
|||||||
@@ -128,13 +128,15 @@ Submenu* submenu_alloc() {
|
|||||||
view_set_input_callback(submenu->view, submenu_view_input_callback);
|
view_set_input_callback(submenu->view, submenu_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
SubmenuItemArray_init(model->items);
|
SubmenuItemArray_init(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
model->header = NULL;
|
model->header = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return submenu;
|
return submenu;
|
||||||
}
|
}
|
||||||
@@ -143,10 +145,7 @@ void submenu_free(Submenu* submenu) {
|
|||||||
furi_assert(submenu);
|
furi_assert(submenu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view, SubmenuModel * model, { SubmenuItemArray_clear(model->items); }, true);
|
||||||
SubmenuItemArray_clear(model->items);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
view_free(submenu->view);
|
view_free(submenu->view);
|
||||||
free(submenu);
|
free(submenu);
|
||||||
}
|
}
|
||||||
@@ -167,32 +166,38 @@ void submenu_add_item(
|
|||||||
furi_assert(submenu);
|
furi_assert(submenu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
item = SubmenuItemArray_push_new(model->items);
|
item = SubmenuItemArray_push_new(model->items);
|
||||||
item->label = label;
|
item->label = label;
|
||||||
item->index = index;
|
item->index = index;
|
||||||
item->callback = callback;
|
item->callback = callback;
|
||||||
item->callback_context = callback_context;
|
item->callback_context = callback_context;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void submenu_reset(Submenu* submenu) {
|
void submenu_reset(Submenu* submenu) {
|
||||||
furi_assert(submenu);
|
furi_assert(submenu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
SubmenuItemArray_reset(model->items);
|
SubmenuItemArray_reset(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
model->header = NULL;
|
model->header = NULL;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
|
void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
uint32_t position = 0;
|
uint32_t position = 0;
|
||||||
SubmenuItemArray_it_t it;
|
SubmenuItemArray_it_t it;
|
||||||
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
|
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
|
||||||
@@ -225,14 +230,15 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
|
|||||||
(SubmenuItemArray_size(model->items) - items_on_screen);
|
(SubmenuItemArray_size(model->items) - items_on_screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void submenu_process_up(Submenu* submenu) {
|
void submenu_process_up(Submenu* submenu) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
uint8_t items_on_screen = model->header ? 3 : 4;
|
uint8_t items_on_screen = model->header ? 3 : 4;
|
||||||
if(model->position > 0) {
|
if(model->position > 0) {
|
||||||
model->position--;
|
model->position--;
|
||||||
@@ -246,13 +252,15 @@ void submenu_process_up(Submenu* submenu) {
|
|||||||
model->window_position = model->position - (items_on_screen - 1);
|
model->window_position = model->position - (items_on_screen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void submenu_process_down(Submenu* submenu) {
|
void submenu_process_down(Submenu* submenu) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
uint8_t items_on_screen = model->header ? 3 : 4;
|
uint8_t items_on_screen = model->header ? 3 : 4;
|
||||||
if(model->position < (SubmenuItemArray_size(model->items) - 1)) {
|
if(model->position < (SubmenuItemArray_size(model->items) - 1)) {
|
||||||
model->position++;
|
model->position++;
|
||||||
@@ -265,20 +273,22 @@ void submenu_process_down(Submenu* submenu) {
|
|||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void submenu_process_ok(Submenu* submenu) {
|
void submenu_process_ok(Submenu* submenu) {
|
||||||
SubmenuItem* item = NULL;
|
SubmenuItem* item = NULL;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
if(model->position < (SubmenuItemArray_size(model->items))) {
|
if(model->position < (SubmenuItemArray_size(model->items))) {
|
||||||
item = SubmenuItemArray_get(model->items, model->position);
|
item = SubmenuItemArray_get(model->items, model->position);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
if(item && item->callback) {
|
if(item && item->callback) {
|
||||||
item->callback(item->callback_context, item->index);
|
item->callback(item->callback_context, item->index);
|
||||||
@@ -289,8 +299,5 @@ void submenu_set_header(Submenu* submenu, const char* header) {
|
|||||||
furi_assert(submenu);
|
furi_assert(submenu);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, (SubmenuModel * model) {
|
submenu->view, SubmenuModel * model, { model->header = header; }, true);
|
||||||
model->header = header;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,20 +21,24 @@ typedef struct {
|
|||||||
|
|
||||||
static void text_box_process_down(TextBox* text_box) {
|
static void text_box_process_down(TextBox* text_box) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view,
|
||||||
|
TextBoxModel * model,
|
||||||
|
{
|
||||||
if(model->scroll_pos < model->scroll_num - 1) {
|
if(model->scroll_pos < model->scroll_num - 1) {
|
||||||
model->scroll_pos++;
|
model->scroll_pos++;
|
||||||
// Search next line start
|
// Search next line start
|
||||||
while(*model->text_pos++ != '\n')
|
while(*model->text_pos++ != '\n')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_box_process_up(TextBox* text_box) {
|
static void text_box_process_up(TextBox* text_box) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view,
|
||||||
|
TextBoxModel * model,
|
||||||
|
{
|
||||||
if(model->scroll_pos > 0) {
|
if(model->scroll_pos > 0) {
|
||||||
model->scroll_pos--;
|
model->scroll_pos--;
|
||||||
// Reach last symbol of previous line
|
// Reach last symbol of previous line
|
||||||
@@ -46,8 +50,8 @@ static void text_box_process_up(TextBox* text_box) {
|
|||||||
model->text_pos++;
|
model->text_pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
|
static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
|
||||||
@@ -137,13 +141,15 @@ TextBox* text_box_alloc() {
|
|||||||
view_set_input_callback(text_box->view, text_box_view_input_callback);
|
view_set_input_callback(text_box->view, text_box_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view,
|
||||||
|
TextBoxModel * model,
|
||||||
|
{
|
||||||
model->text = NULL;
|
model->text = NULL;
|
||||||
model->text_formatted = furi_string_alloc_set("");
|
model->text_formatted = furi_string_alloc_set("");
|
||||||
model->formatted = false;
|
model->formatted = false;
|
||||||
model->font = TextBoxFontText;
|
model->font = TextBoxFontText;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return text_box;
|
return text_box;
|
||||||
}
|
}
|
||||||
@@ -152,10 +158,7 @@ void text_box_free(TextBox* text_box) {
|
|||||||
furi_assert(text_box);
|
furi_assert(text_box);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view, TextBoxModel * model, { furi_string_free(model->text_formatted); }, true);
|
||||||
furi_string_free(model->text_formatted);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
view_free(text_box->view);
|
view_free(text_box->view);
|
||||||
free(text_box);
|
free(text_box);
|
||||||
}
|
}
|
||||||
@@ -169,13 +172,15 @@ void text_box_reset(TextBox* text_box) {
|
|||||||
furi_assert(text_box);
|
furi_assert(text_box);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view,
|
||||||
|
TextBoxModel * model,
|
||||||
|
{
|
||||||
model->text = NULL;
|
model->text = NULL;
|
||||||
furi_string_set(model->text_formatted, "");
|
furi_string_set(model->text_formatted, "");
|
||||||
model->font = TextBoxFontText;
|
model->font = TextBoxFontText;
|
||||||
model->focus = TextBoxFocusStart;
|
model->focus = TextBoxFocusStart;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_box_set_text(TextBox* text_box, const char* text) {
|
void text_box_set_text(TextBox* text_box, const char* text) {
|
||||||
@@ -183,31 +188,27 @@ void text_box_set_text(TextBox* text_box, const char* text) {
|
|||||||
furi_assert(text);
|
furi_assert(text);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view,
|
||||||
|
TextBoxModel * model,
|
||||||
|
{
|
||||||
model->text = text;
|
model->text = text;
|
||||||
furi_string_reset(model->text_formatted);
|
furi_string_reset(model->text_formatted);
|
||||||
furi_string_reserve(model->text_formatted, strlen(text));
|
furi_string_reserve(model->text_formatted, strlen(text));
|
||||||
model->formatted = false;
|
model->formatted = false;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_box_set_font(TextBox* text_box, TextBoxFont font) {
|
void text_box_set_font(TextBox* text_box, TextBoxFont font) {
|
||||||
furi_assert(text_box);
|
furi_assert(text_box);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view, TextBoxModel * model, { model->font = font; }, true);
|
||||||
model->font = font;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_box_set_focus(TextBox* text_box, TextBoxFocus focus) {
|
void text_box_set_focus(TextBox* text_box, TextBoxFocus focus) {
|
||||||
furi_assert(text_box);
|
furi_assert(text_box);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view, (TextBoxModel * model) {
|
text_box->view, TextBoxModel * model, { model->focus = focus; }, true);
|
||||||
model->focus = focus;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,10 +429,10 @@ void text_input_timer_callback(void* context) {
|
|||||||
TextInput* text_input = context;
|
TextInput* text_input = context;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
model->valadator_message_visible = false;
|
TextInputModel * model,
|
||||||
return true;
|
{ model->valadator_message_visible = false; },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextInput* text_input_alloc() {
|
TextInput* text_input_alloc() {
|
||||||
@@ -446,10 +446,10 @@ TextInput* text_input_alloc() {
|
|||||||
text_input->timer = furi_timer_alloc(text_input_timer_callback, FuriTimerTypeOnce, text_input);
|
text_input->timer = furi_timer_alloc(text_input_timer_callback, FuriTimerTypeOnce, text_input);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
model->validator_text = furi_string_alloc();
|
TextInputModel * model,
|
||||||
return false;
|
{ model->validator_text = furi_string_alloc(); },
|
||||||
});
|
false);
|
||||||
|
|
||||||
text_input_reset(text_input);
|
text_input_reset(text_input);
|
||||||
|
|
||||||
@@ -459,10 +459,10 @@ TextInput* text_input_alloc() {
|
|||||||
void text_input_free(TextInput* text_input) {
|
void text_input_free(TextInput* text_input) {
|
||||||
furi_assert(text_input);
|
furi_assert(text_input);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
furi_string_free(model->validator_text);
|
TextInputModel * model,
|
||||||
return false;
|
{ furi_string_free(model->validator_text); },
|
||||||
});
|
false);
|
||||||
|
|
||||||
// Send stop command
|
// Send stop command
|
||||||
furi_timer_stop(text_input->timer);
|
furi_timer_stop(text_input->timer);
|
||||||
@@ -477,7 +477,9 @@ void text_input_free(TextInput* text_input) {
|
|||||||
void text_input_reset(TextInput* text_input) {
|
void text_input_reset(TextInput* text_input) {
|
||||||
furi_assert(text_input);
|
furi_assert(text_input);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
|
TextInputModel * model,
|
||||||
|
{
|
||||||
model->text_buffer_size = 0;
|
model->text_buffer_size = 0;
|
||||||
model->header = "";
|
model->header = "";
|
||||||
model->selected_row = 0;
|
model->selected_row = 0;
|
||||||
@@ -491,8 +493,8 @@ void text_input_reset(TextInput* text_input) {
|
|||||||
model->validator_callback_context = NULL;
|
model->validator_callback_context = NULL;
|
||||||
furi_string_reset(model->validator_text);
|
furi_string_reset(model->validator_text);
|
||||||
model->valadator_message_visible = false;
|
model->valadator_message_visible = false;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* text_input_get_view(TextInput* text_input) {
|
View* text_input_get_view(TextInput* text_input) {
|
||||||
@@ -508,7 +510,9 @@ void text_input_set_result_callback(
|
|||||||
size_t text_buffer_size,
|
size_t text_buffer_size,
|
||||||
bool clear_default_text) {
|
bool clear_default_text) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
|
TextInputModel * model,
|
||||||
|
{
|
||||||
model->callback = callback;
|
model->callback = callback;
|
||||||
model->callback_context = callback_context;
|
model->callback_context = callback_context;
|
||||||
model->text_buffer = text_buffer;
|
model->text_buffer = text_buffer;
|
||||||
@@ -519,8 +523,8 @@ void text_input_set_result_callback(
|
|||||||
model->selected_row = 2;
|
model->selected_row = 2;
|
||||||
model->selected_column = 8;
|
model->selected_column = 8;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_input_set_validator(
|
void text_input_set_validator(
|
||||||
@@ -528,37 +532,36 @@ void text_input_set_validator(
|
|||||||
TextInputValidatorCallback callback,
|
TextInputValidatorCallback callback,
|
||||||
void* callback_context) {
|
void* callback_context) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
|
TextInputModel * model,
|
||||||
|
{
|
||||||
model->validator_callback = callback;
|
model->validator_callback = callback;
|
||||||
model->validator_callback_context = callback_context;
|
model->validator_callback_context = callback_context;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input) {
|
TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input) {
|
||||||
TextInputValidatorCallback validator_callback = NULL;
|
TextInputValidatorCallback validator_callback = NULL;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
validator_callback = model->validator_callback;
|
TextInputModel * model,
|
||||||
return false;
|
{ validator_callback = model->validator_callback; },
|
||||||
});
|
false);
|
||||||
return validator_callback;
|
return validator_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* text_input_get_validator_callback_context(TextInput* text_input) {
|
void* text_input_get_validator_callback_context(TextInput* text_input) {
|
||||||
void* validator_callback_context = NULL;
|
void* validator_callback_context = NULL;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view,
|
||||||
validator_callback_context = model->validator_callback_context;
|
TextInputModel * model,
|
||||||
return false;
|
{ validator_callback_context = model->validator_callback_context; },
|
||||||
});
|
false);
|
||||||
return validator_callback_context;
|
return validator_callback_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_input_set_header_text(TextInput* text_input, const char* text) {
|
void text_input_set_header_text(TextInput* text_input, const char* text) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_input->view, (TextInputModel * model) {
|
text_input->view, TextInputModel * model, { model->header = text; }, true);
|
||||||
model->header = text;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,9 @@ static void variable_item_list_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
void variable_item_list_set_selected_item(VariableItemList* variable_item_list, uint8_t index) {
|
void variable_item_list_set_selected_item(VariableItemList* variable_item_list, uint8_t index) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
uint8_t position = index;
|
uint8_t position = index;
|
||||||
if(position >= VariableItemArray_size(model->items)) {
|
if(position >= VariableItemArray_size(model->items)) {
|
||||||
position = 0;
|
position = 0;
|
||||||
@@ -112,9 +114,8 @@ void variable_item_list_set_selected_item(VariableItemList* variable_item_list,
|
|||||||
model->window_position = (VariableItemArray_size(model->items) - 4);
|
model->window_position = (VariableItemArray_size(model->items) - 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return true;
|
true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t variable_item_list_get_selected_item_index(VariableItemList* variable_item_list) {
|
uint8_t variable_item_list_get_selected_item_index(VariableItemList* variable_item_list) {
|
||||||
@@ -181,7 +182,9 @@ static bool variable_item_list_input_callback(InputEvent* event, void* context)
|
|||||||
|
|
||||||
void variable_item_list_process_up(VariableItemList* variable_item_list) {
|
void variable_item_list_process_up(VariableItemList* variable_item_list) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
uint8_t items_on_screen = 4;
|
uint8_t items_on_screen = 4;
|
||||||
if(model->position > 0) {
|
if(model->position > 0) {
|
||||||
model->position--;
|
model->position--;
|
||||||
@@ -195,13 +198,15 @@ void variable_item_list_process_up(VariableItemList* variable_item_list) {
|
|||||||
model->window_position = model->position - (items_on_screen - 1);
|
model->window_position = model->position - (items_on_screen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void variable_item_list_process_down(VariableItemList* variable_item_list) {
|
void variable_item_list_process_down(VariableItemList* variable_item_list) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
uint8_t items_on_screen = 4;
|
uint8_t items_on_screen = 4;
|
||||||
if(model->position < (VariableItemArray_size(model->items) - 1)) {
|
if(model->position < (VariableItemArray_size(model->items) - 1)) {
|
||||||
model->position++;
|
model->position++;
|
||||||
@@ -214,8 +219,8 @@ void variable_item_list_process_down(VariableItemList* variable_item_list) {
|
|||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableItem* variable_item_list_get_selected_item(VariableItemListModel* model) {
|
VariableItem* variable_item_list_get_selected_item(VariableItemListModel* model) {
|
||||||
@@ -239,7 +244,9 @@ VariableItem* variable_item_list_get_selected_item(VariableItemListModel* model)
|
|||||||
|
|
||||||
void variable_item_list_process_left(VariableItemList* variable_item_list) {
|
void variable_item_list_process_left(VariableItemList* variable_item_list) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
VariableItem* item = variable_item_list_get_selected_item(model);
|
VariableItem* item = variable_item_list_get_selected_item(model);
|
||||||
if(item->current_value_index > 0) {
|
if(item->current_value_index > 0) {
|
||||||
item->current_value_index--;
|
item->current_value_index--;
|
||||||
@@ -247,13 +254,15 @@ void variable_item_list_process_left(VariableItemList* variable_item_list) {
|
|||||||
item->change_callback(item);
|
item->change_callback(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void variable_item_list_process_right(VariableItemList* variable_item_list) {
|
void variable_item_list_process_right(VariableItemList* variable_item_list) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
VariableItem* item = variable_item_list_get_selected_item(model);
|
VariableItem* item = variable_item_list_get_selected_item(model);
|
||||||
if(item->current_value_index < (item->values_count - 1)) {
|
if(item->current_value_index < (item->values_count - 1)) {
|
||||||
item->current_value_index++;
|
item->current_value_index++;
|
||||||
@@ -261,18 +270,20 @@ void variable_item_list_process_right(VariableItemList* variable_item_list) {
|
|||||||
item->change_callback(item);
|
item->change_callback(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void variable_item_list_process_ok(VariableItemList* variable_item_list) {
|
void variable_item_list_process_ok(VariableItemList* variable_item_list) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
if(variable_item_list->callback) {
|
if(variable_item_list->callback) {
|
||||||
variable_item_list->callback(variable_item_list->context, model->position);
|
variable_item_list->callback(variable_item_list->context, model->position);
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableItemList* variable_item_list_alloc() {
|
VariableItemList* variable_item_list_alloc() {
|
||||||
@@ -285,12 +296,14 @@ VariableItemList* variable_item_list_alloc() {
|
|||||||
view_set_input_callback(variable_item_list->view, variable_item_list_input_callback);
|
view_set_input_callback(variable_item_list->view, variable_item_list_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
VariableItemArray_init(model->items);
|
VariableItemArray_init(model->items);
|
||||||
model->position = 0;
|
model->position = 0;
|
||||||
model->window_position = 0;
|
model->window_position = 0;
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return variable_item_list;
|
return variable_item_list;
|
||||||
}
|
}
|
||||||
@@ -299,15 +312,17 @@ void variable_item_list_free(VariableItemList* variable_item_list) {
|
|||||||
furi_assert(variable_item_list);
|
furi_assert(variable_item_list);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
VariableItemArray_it_t it;
|
VariableItemArray_it_t it;
|
||||||
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
|
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
|
||||||
VariableItemArray_next(it)) {
|
VariableItemArray_next(it)) {
|
||||||
furi_string_free(VariableItemArray_ref(it)->current_value_text);
|
furi_string_free(VariableItemArray_ref(it)->current_value_text);
|
||||||
}
|
}
|
||||||
VariableItemArray_clear(model->items);
|
VariableItemArray_clear(model->items);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
view_free(variable_item_list->view);
|
view_free(variable_item_list->view);
|
||||||
free(variable_item_list);
|
free(variable_item_list);
|
||||||
}
|
}
|
||||||
@@ -316,15 +331,17 @@ void variable_item_list_reset(VariableItemList* variable_item_list) {
|
|||||||
furi_assert(variable_item_list);
|
furi_assert(variable_item_list);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
VariableItemArray_it_t it;
|
VariableItemArray_it_t it;
|
||||||
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
|
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
|
||||||
VariableItemArray_next(it)) {
|
VariableItemArray_next(it)) {
|
||||||
furi_string_free(VariableItemArray_ref(it)->current_value_text);
|
furi_string_free(VariableItemArray_ref(it)->current_value_text);
|
||||||
}
|
}
|
||||||
VariableItemArray_reset(model->items);
|
VariableItemArray_reset(model->items);
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* variable_item_list_get_view(VariableItemList* variable_item_list) {
|
View* variable_item_list_get_view(VariableItemList* variable_item_list) {
|
||||||
@@ -343,7 +360,9 @@ VariableItem* variable_item_list_add(
|
|||||||
furi_assert(variable_item_list);
|
furi_assert(variable_item_list);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
item = VariableItemArray_push_new(model->items);
|
item = VariableItemArray_push_new(model->items);
|
||||||
item->label = label;
|
item->label = label;
|
||||||
item->values_count = values_count;
|
item->values_count = values_count;
|
||||||
@@ -351,8 +370,8 @@ VariableItem* variable_item_list_add(
|
|||||||
item->context = context;
|
item->context = context;
|
||||||
item->current_value_index = 0;
|
item->current_value_index = 0;
|
||||||
item->current_value_text = furi_string_alloc();
|
item->current_value_text = furi_string_alloc();
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@@ -363,12 +382,14 @@ void variable_item_list_set_enter_callback(
|
|||||||
void* context) {
|
void* context) {
|
||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
variable_item_list->view, (VariableItemListModel * model) {
|
variable_item_list->view,
|
||||||
|
VariableItemListModel * model,
|
||||||
|
{
|
||||||
UNUSED(model);
|
UNUSED(model);
|
||||||
variable_item_list->callback = callback;
|
variable_item_list->callback = callback;
|
||||||
variable_item_list->context = context;
|
variable_item_list->context = context;
|
||||||
return false;
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void variable_item_set_current_value_index(VariableItem* item, uint8_t current_value_index) {
|
void variable_item_set_current_value_index(VariableItem* item, uint8_t current_value_index) {
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
// Call all Widget Elements input handlers
|
// Call all Widget Elements input handlers
|
||||||
with_view_model(
|
with_view_model(
|
||||||
widget->view, (GuiWidgetModel * model) {
|
widget->view,
|
||||||
|
GuiWidgetModel * model,
|
||||||
|
{
|
||||||
ElementArray_it_t it;
|
ElementArray_it_t it;
|
||||||
ElementArray_it(it, model->element);
|
ElementArray_it(it, model->element);
|
||||||
while(!ElementArray_end_p(it)) {
|
while(!ElementArray_end_p(it)) {
|
||||||
@@ -46,8 +48,8 @@ static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
ElementArray_next(it);
|
ElementArray_next(it);
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
@@ -61,10 +63,7 @@ Widget* widget_alloc() {
|
|||||||
view_set_input_callback(widget->view, gui_widget_view_input_callback);
|
view_set_input_callback(widget->view, gui_widget_view_input_callback);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
widget->view, (GuiWidgetModel * model) {
|
widget->view, GuiWidgetModel * model, { ElementArray_init(model->element); }, true);
|
||||||
ElementArray_init(model->element);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
@@ -73,7 +72,9 @@ void widget_reset(Widget* widget) {
|
|||||||
furi_assert(widget);
|
furi_assert(widget);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
widget->view, (GuiWidgetModel * model) {
|
widget->view,
|
||||||
|
GuiWidgetModel * model,
|
||||||
|
{
|
||||||
ElementArray_it_t it;
|
ElementArray_it_t it;
|
||||||
ElementArray_it(it, model->element);
|
ElementArray_it(it, model->element);
|
||||||
while(!ElementArray_end_p(it)) {
|
while(!ElementArray_end_p(it)) {
|
||||||
@@ -83,8 +84,8 @@ void widget_reset(Widget* widget) {
|
|||||||
ElementArray_next(it);
|
ElementArray_next(it);
|
||||||
}
|
}
|
||||||
ElementArray_reset(model->element);
|
ElementArray_reset(model->element);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void widget_free(Widget* widget) {
|
void widget_free(Widget* widget) {
|
||||||
@@ -93,10 +94,7 @@ void widget_free(Widget* widget) {
|
|||||||
widget_reset(widget);
|
widget_reset(widget);
|
||||||
// Free elements container
|
// Free elements container
|
||||||
with_view_model(
|
with_view_model(
|
||||||
widget->view, (GuiWidgetModel * model) {
|
widget->view, GuiWidgetModel * model, { ElementArray_clear(model->element); }, true);
|
||||||
ElementArray_clear(model->element);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
view_free(widget->view);
|
view_free(widget->view);
|
||||||
free(widget);
|
free(widget);
|
||||||
@@ -112,11 +110,13 @@ static void widget_add_element(Widget* widget, WidgetElement* element) {
|
|||||||
furi_assert(element);
|
furi_assert(element);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
widget->view, (GuiWidgetModel * model) {
|
widget->view,
|
||||||
|
GuiWidgetModel * model,
|
||||||
|
{
|
||||||
element->parent = widget;
|
element->parent = widget;
|
||||||
ElementArray_push_back(model->element, element);
|
ElementArray_push_back(model->element, element);
|
||||||
return true;
|
},
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void widget_add_string_multiline_element(
|
void widget_add_string_multiline_element(
|
||||||
|
|||||||
@@ -211,25 +211,25 @@ void view_commit_model(View* view, bool update);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define with_view_model_cpp(view, type, var, function_body) \
|
#define with_view_model_cpp(view, type, var, code, update) \
|
||||||
{ \
|
{ \
|
||||||
type* p = static_cast<type*>(view_get_model(view)); \
|
type var = static_cast<type>(view_get_model(view)); \
|
||||||
bool update = [&](type * var) function_body(p); \
|
{code}; \
|
||||||
view_commit_model(view, update); \
|
view_commit_model(view, update); \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/** With clause for view model
|
/** With clause for view model
|
||||||
*
|
*
|
||||||
* @param view View instance pointer
|
* @param view View instance pointer
|
||||||
* @param function_body a (){} lambda declaration, executed within you
|
* @param type View model type
|
||||||
* parent function context
|
* @param code Code block that will be executed between model lock and unlock
|
||||||
|
* @param update Bool flag, if true, view will be updated after code block. Can be variable, so code block can decide if update is needed.
|
||||||
*
|
*
|
||||||
* @return true if you want to emit view update, false otherwise
|
|
||||||
*/
|
*/
|
||||||
#define with_view_model(view, function_body) \
|
#define with_view_model(view, type, code, update) \
|
||||||
{ \
|
{ \
|
||||||
void* p = view_get_model(view); \
|
type = view_get_model(view); \
|
||||||
bool update = ({ bool __fn__ function_body __fn__; })(p); \
|
{code}; \
|
||||||
view_commit_model(view, update); \
|
view_commit_model(view, update); \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
|||||||
"non-complementary input, discarding key: %s, type: %s, sequence: %p",
|
"non-complementary input, discarding key: %s, type: %s, sequence: %p",
|
||||||
input_get_key_name(event->key),
|
input_get_key_name(event->key),
|
||||||
input_get_type_name(event->type),
|
input_get_type_name(event->type),
|
||||||
event->sequence);
|
(void*)event->sequence);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
|||||||
view_dispatcher->current_view,
|
view_dispatcher->current_view,
|
||||||
input_get_key_name(event->key),
|
input_get_key_name(event->key),
|
||||||
input_get_type_name(event->type),
|
input_get_type_name(event->type),
|
||||||
event->sequence);
|
(void*)event->sequence);
|
||||||
view_input(view_dispatcher->ongoing_input_view, event);
|
view_input(view_dispatcher->ongoing_input_view, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ static void loader_cli_print_usage() {
|
|||||||
printf("Cmd list:\r\n");
|
printf("Cmd list:\r\n");
|
||||||
printf("\tlist\t - List available applications\r\n");
|
printf("\tlist\t - List available applications\r\n");
|
||||||
printf("\topen <Application Name:string>\t - Open application by name\r\n");
|
printf("\topen <Application Name:string>\t - Open application by name\r\n");
|
||||||
|
printf("\tinfo\t - Show loader state\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static FlipperApplication const* loader_find_application_by_name_in_list(
|
static FlipperApplication const* loader_find_application_by_name_in_list(
|
||||||
@@ -98,10 +99,15 @@ const FlipperApplication* loader_find_application_by_name(const char* name) {
|
|||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loader_cli_open(Cli* cli, FuriString* args, Loader* instance) {
|
static void loader_cli_open(Cli* cli, FuriString* args, Loader* instance) {
|
||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
if(loader_is_locked(instance)) {
|
if(loader_is_locked(instance)) {
|
||||||
printf("Can't start, furi application is running");
|
if(instance->application) {
|
||||||
|
furi_assert(instance->application->name);
|
||||||
|
printf("Can't start, %s application is running", instance->application->name);
|
||||||
|
} else {
|
||||||
|
printf("Can't start, furi application is running");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +143,7 @@ void loader_cli_open(Cli* cli, FuriString* args, Loader* instance) {
|
|||||||
furi_string_free(application_name);
|
furi_string_free(application_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loader_cli_list(Cli* cli, FuriString* args, Loader* instance) {
|
static void loader_cli_list(Cli* cli, FuriString* args, Loader* instance) {
|
||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
UNUSED(args);
|
UNUSED(args);
|
||||||
UNUSED(instance);
|
UNUSED(instance);
|
||||||
@@ -159,6 +165,22 @@ void loader_cli_list(Cli* cli, FuriString* args, Loader* instance) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void loader_cli_info(Cli* cli, FuriString* args, Loader* instance) {
|
||||||
|
UNUSED(cli);
|
||||||
|
UNUSED(args);
|
||||||
|
if(!loader_is_locked(instance)) {
|
||||||
|
printf("No application is running\r\n");
|
||||||
|
} else {
|
||||||
|
printf("Running application: ");
|
||||||
|
if(instance->application) {
|
||||||
|
furi_assert(instance->application->name);
|
||||||
|
printf("%s\r\n", instance->application->name);
|
||||||
|
} else {
|
||||||
|
printf("unknown\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void loader_cli(Cli* cli, FuriString* args, void* _ctx) {
|
static void loader_cli(Cli* cli, FuriString* args, void* _ctx) {
|
||||||
furi_assert(_ctx);
|
furi_assert(_ctx);
|
||||||
Loader* instance = _ctx;
|
Loader* instance = _ctx;
|
||||||
@@ -182,6 +204,11 @@ static void loader_cli(Cli* cli, FuriString* args, void* _ctx) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(furi_string_cmp_str(cmd, "info") == 0) {
|
||||||
|
loader_cli_info(cli, args, instance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
loader_cli_print_usage();
|
loader_cli_print_usage();
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
|
|||||||
@@ -87,19 +87,13 @@ View* power_off_get_view(PowerOff* power_off) {
|
|||||||
void power_off_set_time_left(PowerOff* power_off, uint8_t time_left) {
|
void power_off_set_time_left(PowerOff* power_off, uint8_t time_left) {
|
||||||
furi_assert(power_off);
|
furi_assert(power_off);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
power_off->view, (PowerOffModel * model) {
|
power_off->view, PowerOffModel * model, { model->time_left_sec = time_left; }, true);
|
||||||
model->time_left_sec = time_left;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerOffResponse power_off_get_response(PowerOff* power_off) {
|
PowerOffResponse power_off_get_response(PowerOff* power_off) {
|
||||||
furi_assert(power_off);
|
furi_assert(power_off);
|
||||||
PowerOffResponse response;
|
PowerOffResponse response;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
power_off->view, (PowerOffModel * model) {
|
power_off->view, PowerOffModel * model, { response = model->response; }, false);
|
||||||
response = model->response;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <m-dict.h>
|
#include <m-dict.h>
|
||||||
|
|
||||||
#define TAG "RpcSrv"
|
#define TAG "RpcSrv"
|
||||||
@@ -61,7 +60,7 @@ struct RpcSession {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
RpcHandlerDict_t handlers;
|
RpcHandlerDict_t handlers;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
PB_Main* decoded_message;
|
PB_Main* decoded_message;
|
||||||
bool terminate;
|
bool terminate;
|
||||||
void** system_contexts;
|
void** system_contexts;
|
||||||
@@ -151,7 +150,7 @@ size_t
|
|||||||
furi_assert(encoded_bytes);
|
furi_assert(encoded_bytes);
|
||||||
furi_assert(size > 0);
|
furi_assert(size > 0);
|
||||||
|
|
||||||
size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout);
|
size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout);
|
||||||
|
|
||||||
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
|
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
|
||||||
|
|
||||||
@@ -160,7 +159,7 @@ size_t
|
|||||||
|
|
||||||
size_t rpc_session_get_available_size(RpcSession* session) {
|
size_t rpc_session_get_available_size(RpcSession* session) {
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
return xStreamBufferSpacesAvailable(session->stream);
|
return furi_stream_buffer_spaces_available(session->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||||
@@ -174,9 +173,9 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
|||||||
size_t bytes_received = 0;
|
size_t bytes_received = 0;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
bytes_received +=
|
bytes_received += furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(session->stream, buf + bytes_received, count - bytes_received, 0);
|
session->stream, buf + bytes_received, count - bytes_received, 0);
|
||||||
if(xStreamBufferIsEmpty(session->stream)) {
|
if(furi_stream_buffer_is_empty(session->stream)) {
|
||||||
if(session->buffer_is_empty_callback) {
|
if(session->buffer_is_empty_callback) {
|
||||||
session->buffer_is_empty_callback(session->context);
|
session->buffer_is_empty_callback(session->context);
|
||||||
}
|
}
|
||||||
@@ -190,7 +189,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
|||||||
} else {
|
} else {
|
||||||
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||||
if(flags & RpcEvtDisconnect) {
|
if(flags & RpcEvtDisconnect) {
|
||||||
if(xStreamBufferIsEmpty(session->stream)) {
|
if(furi_stream_buffer_is_empty(session->stream)) {
|
||||||
session->terminate = true;
|
session->terminate = true;
|
||||||
istream->bytes_left = 0;
|
istream->bytes_left = 0;
|
||||||
bytes_received = 0;
|
bytes_received = 0;
|
||||||
@@ -279,7 +278,7 @@ static int32_t rpc_session_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(message_decode_failed) {
|
if(message_decode_failed) {
|
||||||
xStreamBufferReset(session->stream);
|
furi_stream_buffer_reset(session->stream);
|
||||||
if(!session->terminate) {
|
if(!session->terminate) {
|
||||||
/* Protobuf can't determine start and end of message.
|
/* Protobuf can't determine start and end of message.
|
||||||
* Handle this by adding varint at beginning
|
* Handle this by adding varint at beginning
|
||||||
@@ -329,7 +328,7 @@ static void rpc_session_free_callback(FuriThreadState thread_state, void* contex
|
|||||||
free(session->system_contexts);
|
free(session->system_contexts);
|
||||||
free(session->decoded_message);
|
free(session->decoded_message);
|
||||||
RpcHandlerDict_clear(session->handlers);
|
RpcHandlerDict_clear(session->handlers);
|
||||||
vStreamBufferDelete(session->stream);
|
furi_stream_buffer_free(session->stream);
|
||||||
|
|
||||||
furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
|
furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
|
||||||
if(session->terminated_callback) {
|
if(session->terminated_callback) {
|
||||||
@@ -348,7 +347,7 @@ RpcSession* rpc_session_open(Rpc* rpc) {
|
|||||||
|
|
||||||
RpcSession* session = malloc(sizeof(RpcSession));
|
RpcSession* session = malloc(sizeof(RpcSession));
|
||||||
session->callbacks_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
session->callbacks_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
session->stream = xStreamBufferCreate(RPC_BUFFER_SIZE, 1);
|
session->stream = furi_stream_buffer_alloc(RPC_BUFFER_SIZE, 1);
|
||||||
session->rpc = rpc;
|
session->rpc = rpc;
|
||||||
session->terminate = false;
|
session->terminate = false;
|
||||||
session->decode_error = false;
|
session->decode_error = false;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
furi_assert(!rpc_app->last_id);
|
furi_assert(!rpc_app->last_id);
|
||||||
furi_assert(!rpc_app->last_data);
|
furi_assert(!rpc_app->last_data);
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id);
|
FURI_LOG_D(TAG, "StartProcess: id %ld", request->command_id);
|
||||||
|
|
||||||
PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
|
PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
|
|
||||||
furi_record_close(RECORD_LOADER);
|
furi_record_close(RECORD_LOADER);
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result);
|
FURI_LOG_D(TAG, "StartProcess: response id %ld, result %d", request->command_id, result);
|
||||||
rpc_send_and_release_empty(session, request->command_id, result);
|
rpc_send_and_release_empty(session, request->command_id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) {
|
|||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
|
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id);
|
FURI_LOG_D(TAG, "ExitRequest: id %ld", request->command_id);
|
||||||
furi_assert(!rpc_app->last_id);
|
furi_assert(!rpc_app->last_id);
|
||||||
furi_assert(!rpc_app->last_data);
|
furi_assert(!rpc_app->last_data);
|
||||||
rpc_app->last_id = request->command_id;
|
rpc_app->last_id = request->command_id;
|
||||||
@@ -116,7 +116,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) {
|
|||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
TAG, "ExitRequest: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status);
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) {
|
|||||||
|
|
||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id);
|
FURI_LOG_D(TAG, "LoadFile: id %ld", request->command_id);
|
||||||
furi_assert(!rpc_app->last_id);
|
furi_assert(!rpc_app->last_id);
|
||||||
furi_assert(!rpc_app->last_data);
|
furi_assert(!rpc_app->last_data);
|
||||||
rpc_app->last_id = request->command_id;
|
rpc_app->last_id = request->command_id;
|
||||||
@@ -141,7 +141,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) {
|
|||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
TAG, "LoadFile: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status);
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) {
|
|||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
TAG, "ButtonPress: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status);
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context)
|
|||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
TAG, "ButtonRelease: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status);
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool
|
|||||||
free(rpc_app->last_data);
|
free(rpc_app->last_data);
|
||||||
rpc_app->last_data = NULL;
|
rpc_app->last_data = NULL;
|
||||||
}
|
}
|
||||||
FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status);
|
FURI_LOG_D(TAG, "AppConfirm: event %d last_id %ld status %d", event, last_id, status);
|
||||||
rpc_send_and_release_empty(session, last_id, status);
|
rpc_send_and_release_empty(session, last_id, status);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context) {
|
|||||||
Rpc* rpc = context;
|
Rpc* rpc = context;
|
||||||
|
|
||||||
uint32_t mem_before = memmgr_get_free_heap();
|
uint32_t mem_before = memmgr_get_free_heap();
|
||||||
FURI_LOG_D(TAG, "Free memory %d", mem_before);
|
FURI_LOG_D(TAG, "Free memory %ld", mem_before);
|
||||||
|
|
||||||
furi_hal_usb_lock();
|
furi_hal_usb_lock();
|
||||||
RpcSession* rpc_session = rpc_session_open(rpc);
|
RpcSession* rpc_session = rpc_session_open(rpc);
|
||||||
|
|||||||
@@ -158,9 +158,9 @@ void rpc_debug_print_message(const PB_Main* message) {
|
|||||||
case PB_Main_storage_info_response_tag: {
|
case PB_Main_storage_info_response_tag: {
|
||||||
furi_string_cat_printf(str, "\tinfo_response {\r\n");
|
furi_string_cat_printf(str, "\tinfo_response {\r\n");
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
str, "\t\ttotal_space: %lu\r\n", message->content.storage_info_response.total_space);
|
str, "\t\ttotal_space: %llu\r\n", message->content.storage_info_response.total_space);
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
str, "\t\tfree_space: %lu\r\n", message->content.storage_info_response.free_space);
|
str, "\t\tfree_space: %llu\r\n", message->content.storage_info_response.free_space);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PB_Main_storage_stat_request_tag: {
|
case PB_Main_storage_stat_request_tag: {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static void storage_cli_info(Cli* cli, FuriString* path) {
|
|||||||
storage_cli_print_error(error);
|
storage_cli_print_error(error);
|
||||||
} else {
|
} else {
|
||||||
printf(
|
printf(
|
||||||
"Label: %s\r\nType: LittleFS\r\n%luKB total\r\n%luKB free\r\n",
|
"Label: %s\r\nType: LittleFS\r\n%luKiB total\r\n%luKiB free\r\n",
|
||||||
furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown",
|
furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown",
|
||||||
(uint32_t)(total_space / 1024),
|
(uint32_t)(total_space / 1024),
|
||||||
(uint32_t)(free_space / 1024));
|
(uint32_t)(free_space / 1024));
|
||||||
@@ -65,7 +65,7 @@ static void storage_cli_info(Cli* cli, FuriString* path) {
|
|||||||
storage_cli_print_error(error);
|
storage_cli_print_error(error);
|
||||||
} else {
|
} else {
|
||||||
printf(
|
printf(
|
||||||
"Label: %s\r\nType: %s\r\n%luKB total\r\n%luKB free\r\n",
|
"Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n",
|
||||||
sd_info.label,
|
sd_info.label,
|
||||||
sd_api_get_fs_type_text(sd_info.fs_type),
|
sd_api_get_fs_type_text(sd_info.fs_type),
|
||||||
sd_info.kb_total,
|
sd_info.kb_total,
|
||||||
@@ -364,7 +364,7 @@ static void storage_cli_stat(Cli* cli, FuriString* path) {
|
|||||||
storage_cli_print_error(error);
|
storage_cli_print_error(error);
|
||||||
} else {
|
} else {
|
||||||
printf(
|
printf(
|
||||||
"Storage, %luKB total, %luKB free\r\n",
|
"Storage, %luKiB total, %luKiB free\r\n",
|
||||||
(uint32_t)(total_space / 1024),
|
(uint32_t)(total_space / 1024),
|
||||||
(uint32_t)(free_space / 1024));
|
(uint32_t)(free_space / 1024));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,11 @@ bool storage_file_open(
|
|||||||
furi_event_flag_free(event);
|
furi_event_flag_free(event);
|
||||||
|
|
||||||
FURI_LOG_T(
|
FURI_LOG_T(
|
||||||
TAG, "File %p - %p open (%s)", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE, path);
|
TAG,
|
||||||
|
"File %p - %p open (%s)",
|
||||||
|
(void*)((uint32_t)file - SRAM_BASE),
|
||||||
|
(void*)(file->file_id - SRAM_BASE),
|
||||||
|
path);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -132,7 +136,11 @@ bool storage_file_close(File* file) {
|
|||||||
S_API_MESSAGE(StorageCommandFileClose);
|
S_API_MESSAGE(StorageCommandFileClose);
|
||||||
S_API_EPILOGUE;
|
S_API_EPILOGUE;
|
||||||
|
|
||||||
FURI_LOG_T(TAG, "File %p - %p closed", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE);
|
FURI_LOG_T(
|
||||||
|
TAG,
|
||||||
|
"File %p - %p closed",
|
||||||
|
(void*)((uint32_t)file - SRAM_BASE),
|
||||||
|
(void*)(file->file_id - SRAM_BASE));
|
||||||
file->type = FileTypeClosed;
|
file->type = FileTypeClosed;
|
||||||
|
|
||||||
return S_RETURN_BOOL;
|
return S_RETURN_BOOL;
|
||||||
@@ -291,7 +299,11 @@ bool storage_dir_open(File* file, const char* path) {
|
|||||||
furi_event_flag_free(event);
|
furi_event_flag_free(event);
|
||||||
|
|
||||||
FURI_LOG_T(
|
FURI_LOG_T(
|
||||||
TAG, "Dir %p - %p open (%s)", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE, path);
|
TAG,
|
||||||
|
"Dir %p - %p open (%s)",
|
||||||
|
(void*)((uint32_t)file - SRAM_BASE),
|
||||||
|
(void*)(file->file_id - SRAM_BASE),
|
||||||
|
path);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -303,7 +315,11 @@ bool storage_dir_close(File* file) {
|
|||||||
S_API_MESSAGE(StorageCommandDirClose);
|
S_API_MESSAGE(StorageCommandDirClose);
|
||||||
S_API_EPILOGUE;
|
S_API_EPILOGUE;
|
||||||
|
|
||||||
FURI_LOG_T(TAG, "Dir %p - %p closed", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE);
|
FURI_LOG_T(
|
||||||
|
TAG,
|
||||||
|
"Dir %p - %p closed",
|
||||||
|
(void*)((uint32_t)file - SRAM_BASE),
|
||||||
|
(void*)(file->file_id - SRAM_BASE));
|
||||||
|
|
||||||
file->type = FileTypeClosed;
|
file->type = FileTypeClosed;
|
||||||
|
|
||||||
@@ -675,7 +691,7 @@ File* storage_file_alloc(Storage* storage) {
|
|||||||
file->type = FileTypeClosed;
|
file->type = FileTypeClosed;
|
||||||
file->storage = storage;
|
file->storage = storage;
|
||||||
|
|
||||||
FURI_LOG_T(TAG, "File/Dir %p alloc", (uint32_t)file - SRAM_BASE);
|
FURI_LOG_T(TAG, "File/Dir %p alloc", (void*)((uint32_t)file - SRAM_BASE));
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@@ -697,7 +713,7 @@ void storage_file_free(File* file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FURI_LOG_T(TAG, "File/Dir %p free", (uint32_t)file - SRAM_BASE);
|
FURI_LOG_T(TAG, "File/Dir %p free", (void*)((uint32_t)file - SRAM_BASE));
|
||||||
free(file);
|
free(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ static int storage_int_device_read(
|
|||||||
|
|
||||||
FURI_LOG_T(
|
FURI_LOG_T(
|
||||||
TAG,
|
TAG,
|
||||||
"Device read: block %d, off %d, buffer: %p, size %d, translated address: %p",
|
"Device read: block %ld, off %ld, buffer: %p, size %ld, translated address: %p",
|
||||||
block,
|
block,
|
||||||
off,
|
off,
|
||||||
buffer,
|
buffer,
|
||||||
size,
|
size,
|
||||||
address);
|
(void*)address);
|
||||||
|
|
||||||
memcpy(buffer, (void*)address, size);
|
memcpy(buffer, (void*)address, size);
|
||||||
|
|
||||||
@@ -100,12 +100,12 @@ static int storage_int_device_prog(
|
|||||||
|
|
||||||
FURI_LOG_T(
|
FURI_LOG_T(
|
||||||
TAG,
|
TAG,
|
||||||
"Device prog: block %d, off %d, buffer: %p, size %d, translated address: %p",
|
"Device prog: block %ld, off %ld, buffer: %p, size %ld, translated address: %p",
|
||||||
block,
|
block,
|
||||||
off,
|
off,
|
||||||
buffer,
|
buffer,
|
||||||
size,
|
size,
|
||||||
address);
|
(void*)address);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
while(size > 0) {
|
while(size > 0) {
|
||||||
@@ -122,7 +122,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc
|
|||||||
LFSData* lfs_data = c->context;
|
LFSData* lfs_data = c->context;
|
||||||
size_t page = lfs_data->start_page + block;
|
size_t page = lfs_data->start_page + block;
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page);
|
FURI_LOG_D(TAG, "Device erase: page %ld, translated page: %x", block, page);
|
||||||
|
|
||||||
furi_hal_flash_erase(page);
|
furi_hal_flash_erase(page);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -740,8 +740,8 @@ void storage_int_init(StorageData* storage) {
|
|||||||
LFSData* lfs_data = storage_int_lfs_data_alloc();
|
LFSData* lfs_data = storage_int_lfs_data_alloc();
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
"Config: start %p, read %d, write %d, page size: %d, page count: %d, cycles: %d",
|
"Config: start %p, read %ld, write %ld, page size: %ld, page count: %ld, cycles: %ld",
|
||||||
lfs_data->start_address,
|
(void*)lfs_data->start_address,
|
||||||
lfs_data->config.read_size,
|
lfs_data->config.read_size,
|
||||||
lfs_data->config.prog_size,
|
lfs_data->config.prog_size,
|
||||||
lfs_data->config.block_size,
|
lfs_data->config.block_size,
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) {
|
|||||||
furi_assert(battery_info);
|
furi_assert(battery_info);
|
||||||
furi_assert(data);
|
furi_assert(data);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
battery_info->view, (BatteryInfoModel * model) {
|
battery_info->view,
|
||||||
memcpy(model, data, sizeof(BatteryInfoModel));
|
BatteryInfoModel * model,
|
||||||
return true;
|
{ memcpy(model, data, sizeof(BatteryInfoModel)); },
|
||||||
});
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void storage_settings_scene_internal_info_on_enter(void* context) {
|
|||||||
} else {
|
} else {
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
app->text_string,
|
app->text_string,
|
||||||
"Label: %s\nType: LittleFS\n%lu KB total\n%lu KB free",
|
"Label: %s\nType: LittleFS\n%lu KiB total\n%lu KiB free",
|
||||||
furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown",
|
furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown",
|
||||||
(uint32_t)(total_space / 1024),
|
(uint32_t)(total_space / 1024),
|
||||||
(uint32_t)(free_space / 1024));
|
(uint32_t)(free_space / 1024));
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) {
|
|||||||
} else {
|
} else {
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
app->text_string,
|
app->text_string,
|
||||||
"Label: %s\nType: %s\n%lu KB total\n%lu KB free",
|
"Label: %s\nType: %s\n%lu KiB total\n%lu KiB free",
|
||||||
sd_info.label,
|
sd_info.label,
|
||||||
sd_api_get_fs_type_text(sd_info.fs_type),
|
sd_api_get_fs_type_text(sd_info.fs_type),
|
||||||
sd_info.kb_total,
|
sd_info.kb_total,
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) {
|
|||||||
match = false;
|
match = false;
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG,
|
TAG,
|
||||||
"OB MISMATCH: #%d: real %08X != %08X (exp.), full %08X",
|
"OB MISMATCH: #%d: real %08lX != %08lX (exp.), full %08lX",
|
||||||
idx,
|
idx,
|
||||||
device_ob_value_masked,
|
device_ob_value_masked,
|
||||||
ref_value,
|
ref_value,
|
||||||
@@ -289,7 +289,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) {
|
|||||||
(manifest->ob_reference.obs[idx].values.base &
|
(manifest->ob_reference.obs[idx].values.base &
|
||||||
manifest->ob_write_mask.obs[idx].values.base);
|
manifest->ob_write_mask.obs[idx].values.base);
|
||||||
|
|
||||||
FURI_LOG_W(TAG, "Fixing up OB byte #%d to %08X", idx, patched_value);
|
FURI_LOG_W(TAG, "Fixing up OB byte #%d to %08lX", idx, patched_value);
|
||||||
ob_dirty = true;
|
ob_dirty = true;
|
||||||
|
|
||||||
bool is_fixed = furi_hal_flash_ob_set_word(idx, patched_value) &&
|
bool is_fixed = furi_hal_flash_ob_set_word(idx, patched_value) &&
|
||||||
@@ -301,7 +301,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) {
|
|||||||
* reference value */
|
* reference value */
|
||||||
FURI_LOG_W(
|
FURI_LOG_W(
|
||||||
TAG,
|
TAG,
|
||||||
"OB #%d is FUBAR (fixed&masked %08X, not %08X)",
|
"OB #%d is FUBAR (fixed&masked %08lX, not %08lX)",
|
||||||
idx,
|
idx,
|
||||||
patched_value,
|
patched_value,
|
||||||
ref_value);
|
ref_value);
|
||||||
@@ -310,7 +310,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) {
|
|||||||
} else {
|
} else {
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
TAG,
|
TAG,
|
||||||
"OB MATCH: #%d: real %08X == %08X (exp.)",
|
"OB MATCH: #%d: real %08lX == %08lX (exp.)",
|
||||||
idx,
|
idx,
|
||||||
device_ob_value_masked,
|
device_ob_value_masked,
|
||||||
ref_value);
|
ref_value);
|
||||||
|
|||||||
@@ -28,22 +28,25 @@ void updater_main_model_set_state(
|
|||||||
const char* message,
|
const char* message,
|
||||||
uint8_t progress,
|
uint8_t progress,
|
||||||
bool failed) {
|
bool failed) {
|
||||||
|
bool update = false;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
main_view->view, (UpdaterProgressModel * model) {
|
main_view->view,
|
||||||
|
UpdaterProgressModel * model,
|
||||||
|
{
|
||||||
model->failed = failed;
|
model->failed = failed;
|
||||||
model->progress = progress;
|
model->progress = progress;
|
||||||
if(furi_string_cmp_str(model->status, message)) {
|
if(furi_string_cmp_str(model->status, message)) {
|
||||||
furi_string_set(model->status, message);
|
furi_string_set(model->status, message);
|
||||||
model->rendered_progress = progress;
|
model->rendered_progress = progress;
|
||||||
return true;
|
update = true;
|
||||||
}
|
} else if(
|
||||||
if((model->rendered_progress > progress) ||
|
(model->rendered_progress > progress) ||
|
||||||
((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) {
|
((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) {
|
||||||
model->rendered_progress = progress;
|
model->rendered_progress = progress;
|
||||||
return true;
|
update = true;
|
||||||
}
|
}
|
||||||
return false;
|
},
|
||||||
});
|
update);
|
||||||
}
|
}
|
||||||
|
|
||||||
View* updater_main_get_view(UpdaterMainView* main_view) {
|
View* updater_main_get_view(UpdaterMainView* main_view) {
|
||||||
@@ -104,10 +107,10 @@ UpdaterMainView* updater_main_alloc() {
|
|||||||
view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(UpdaterProgressModel));
|
view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(UpdaterProgressModel));
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
main_view->view, (UpdaterProgressModel * model) {
|
main_view->view,
|
||||||
model->status = furi_string_alloc_set("Waiting for SD card");
|
UpdaterProgressModel * model,
|
||||||
return true;
|
{ model->status = furi_string_alloc_set("Waiting for SD card"); },
|
||||||
});
|
true);
|
||||||
|
|
||||||
view_set_context(main_view->view, main_view);
|
view_set_context(main_view->view, main_view);
|
||||||
view_set_input_callback(main_view->view, updater_main_input);
|
view_set_input_callback(main_view->view, updater_main_input);
|
||||||
@@ -119,10 +122,7 @@ UpdaterMainView* updater_main_alloc() {
|
|||||||
void updater_main_free(UpdaterMainView* main_view) {
|
void updater_main_free(UpdaterMainView* main_view) {
|
||||||
furi_assert(main_view);
|
furi_assert(main_view);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
main_view->view, (UpdaterProgressModel * model) {
|
main_view->view, UpdaterProgressModel * model, { furi_string_free(model->status); }, false);
|
||||||
furi_string_free(model->status);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
view_free(main_view->view);
|
view_free(main_view->view);
|
||||||
free(main_view);
|
free(main_view);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/icons/Interface/SmallArrowDown_3x5.png
Normal file
BIN
assets/icons/Interface/SmallArrowDown_3x5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/icons/Interface/SmallArrowUp_3x5.png
Normal file
BIN
assets/icons/Interface/SmallArrowUp_3x5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
@@ -47,7 +47,7 @@ Only 2 parameters are mandatory: ***appid*** and ***apptype***, others are optio
|
|||||||
The following parameters are used only for [FAPs](./AppsOnSDCard.md):
|
The following parameters are used only for [FAPs](./AppsOnSDCard.md):
|
||||||
|
|
||||||
* **sources**: list of strings, file name masks, used for gathering sources within app folder. Default value of `["*.c*"]` includes C and C++ source files. Application cannot use `"lib"` folder for their own source code, as it is reserved for **fap_private_libs**.
|
* **sources**: list of strings, file name masks, used for gathering sources within app folder. Default value of `["*.c*"]` includes C and C++ source files. Application cannot use `"lib"` folder for their own source code, as it is reserved for **fap_private_libs**.
|
||||||
* **fap_version**: tuple, 2 numbers in form of (x,y): application version to be embedded within .fap file. Default value is (0,1), meanig version "0.1".
|
* **fap_version**: tuple, 2 numbers in form of (x,y): application version to be embedded within .fap file. Default value is (0,1), meaning version "0.1".
|
||||||
* **fap_icon**: name of a .png file, 1-bit color depth, 10x10px, to be embedded within .fap file.
|
* **fap_icon**: name of a .png file, 1-bit color depth, 10x10px, to be embedded within .fap file.
|
||||||
* **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption.
|
* **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption.
|
||||||
* **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system.
|
* **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ FAPs are created and developed the same way as internal applications that are pa
|
|||||||
|
|
||||||
To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details.
|
To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details.
|
||||||
|
|
||||||
* To build your application, run `./fbt firmware_{APPID}`, where APPID is your application's ID in its manifest.
|
* To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest.
|
||||||
* To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu).
|
* To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu).
|
||||||
* To build all FAPs, run `./fbt plugin_dist`.
|
* To build all FAPs, run `./fbt plugin_dist`.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,2.0,,
|
Version,+,2.2,,
|
||||||
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,,
|
||||||
@@ -1342,6 +1342,16 @@ Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t"
|
|||||||
Function,+,furi_semaphore_free,void,FuriSemaphore*
|
Function,+,furi_semaphore_free,void,FuriSemaphore*
|
||||||
Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore*
|
Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore*
|
||||||
Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore*
|
Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore*
|
||||||
|
Function,+,furi_stream_buffer_alloc,FuriStreamBuffer*,"size_t, size_t"
|
||||||
|
Function,+,furi_stream_buffer_bytes_available,size_t,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_free,void,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_is_empty,_Bool,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_is_full,_Bool,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_receive,size_t,"FuriStreamBuffer*, void*, size_t, uint32_t"
|
||||||
|
Function,+,furi_stream_buffer_reset,FuriStatus,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_send,size_t,"FuriStreamBuffer*, const void*, size_t, uint32_t"
|
||||||
|
Function,+,furi_stream_buffer_spaces_available,size_t,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_set_trigger_level,_Bool,"FuriStreamBuffer*, size_t"
|
||||||
Function,+,furi_string_alloc,FuriString*,
|
Function,+,furi_string_alloc,FuriString*,
|
||||||
Function,+,furi_string_alloc_move,FuriString*,FuriString*
|
Function,+,furi_string_alloc_move,FuriString*,FuriString*
|
||||||
Function,+,furi_string_alloc_printf,FuriString*,"const char[], ..."
|
Function,+,furi_string_alloc_printf,FuriString*,"const char[], ..."
|
||||||
@@ -2729,7 +2739,9 @@ Variable,+,I_SDQuestion_35x43,const Icon,
|
|||||||
Variable,+,I_SDcardFail_11x8,const Icon,
|
Variable,+,I_SDcardFail_11x8,const Icon,
|
||||||
Variable,+,I_SDcardMounted_11x8,const Icon,
|
Variable,+,I_SDcardMounted_11x8,const Icon,
|
||||||
Variable,+,I_Scanning_123x52,const Icon,
|
Variable,+,I_Scanning_123x52,const Icon,
|
||||||
|
Variable,+,I_SmallArrowDown_3x5,const Icon,
|
||||||
Variable,+,I_SmallArrowDown_4x7,const Icon,
|
Variable,+,I_SmallArrowDown_4x7,const Icon,
|
||||||
|
Variable,+,I_SmallArrowUp_3x5,const Icon,
|
||||||
Variable,+,I_SmallArrowUp_4x7,const Icon,
|
Variable,+,I_SmallArrowUp_4x7,const Icon,
|
||||||
Variable,+,I_Smile_18x18,const Icon,
|
Variable,+,I_Smile_18x18,const Icon,
|
||||||
Variable,+,I_Space_65x18,const Icon,
|
Variable,+,I_Space_65x18,const Icon,
|
||||||
|
|||||||
|
@@ -184,7 +184,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
||||||
FURI_LOG_I(TAG, "Pass key request event. Pin: ******");
|
FURI_LOG_I(TAG, "Pass key request event. Pin: ******");
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_I(TAG, "Pass key request event. Pin: %06d", pin);
|
FURI_LOG_I(TAG, "Pass key request event. Pin: %06ld", pin);
|
||||||
}
|
}
|
||||||
GapEvent event = {.type = GapEventTypePinCodeShow, .data.pin_code = pin};
|
GapEvent event = {.type = GapEventTypePinCodeShow, .data.pin_code = pin};
|
||||||
gap->on_event_cb(event, gap->context);
|
gap->on_event_cb(event, gap->context);
|
||||||
@@ -227,7 +227,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: {
|
case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: {
|
||||||
uint32_t pin =
|
uint32_t pin =
|
||||||
((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value;
|
((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value;
|
||||||
FURI_LOG_I(TAG, "Verify numeric comparison: %06d", pin);
|
FURI_LOG_I(TAG, "Verify numeric comparison: %06ld", pin);
|
||||||
GapEvent event = {.type = GapEventTypePinCodeVerify, .data.pin_code = pin};
|
GapEvent event = {.type = GapEventTypePinCodeVerify, .data.pin_code = pin};
|
||||||
bool result = gap->on_event_cb(event, gap->context);
|
bool result = gap->on_event_cb(event, gap->context);
|
||||||
aci_gap_numeric_comparison_value_confirm_yesno(gap->service.connection_handle, result);
|
aci_gap_numeric_comparison_value_confirm_yesno(gap->service.connection_handle, result);
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
|||||||
.size = attribute_modified->Attr_Data_Length,
|
.size = attribute_modified->Attr_Data_Length,
|
||||||
}};
|
}};
|
||||||
uint32_t buff_free_size = serial_svc->callback(event, serial_svc->context);
|
uint32_t buff_free_size = serial_svc->callback(event, serial_svc->context);
|
||||||
FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size);
|
FURI_LOG_D(TAG, "Available buff size: %ld", buff_free_size);
|
||||||
furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk);
|
furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk);
|
||||||
}
|
}
|
||||||
ret = SVCCTL_EvtAckFlowEnable;
|
ret = SVCCTL_EvtAckFlowEnable;
|
||||||
}
|
}
|
||||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||||
FURI_LOG_T(TAG, "Ack received", blecore_evt->ecode);
|
FURI_LOG_T(TAG, "Ack received");
|
||||||
if(serial_svc->callback) {
|
if(serial_svc->callback) {
|
||||||
SerialServiceEvent event = {
|
SerialServiceEvent event = {
|
||||||
.event = SerialServiceEventTypeDataSent,
|
.event = SerialServiceEventTypeDataSent,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -27,7 +28,7 @@ void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size
|
|||||||
* @param format
|
* @param format
|
||||||
* @param ...
|
* @param ...
|
||||||
*/
|
*/
|
||||||
void furi_hal_console_printf(const char format[], ...);
|
void furi_hal_console_printf(const char format[], ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
|
||||||
|
|
||||||
void furi_hal_console_puts(const char* data);
|
void furi_hal_console_puts(const char* data);
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ void furi_hal_flash_init() {
|
|||||||
// WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
|
// WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
|
||||||
/* Actually, reset all error flags on start */
|
/* Actually, reset all error flags on start */
|
||||||
if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) {
|
if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) {
|
||||||
FURI_LOG_E(TAG, "FLASH->SR 0x%08X", FLASH->SR);
|
FURI_LOG_E(TAG, "FLASH->SR 0x%08lX", FLASH->SR);
|
||||||
WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS);
|
WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,10 +514,10 @@ bool furi_hal_flash_ob_set_word(size_t word_idx, const uint32_t value) {
|
|||||||
|
|
||||||
FURI_LOG_W(
|
FURI_LOG_W(
|
||||||
TAG,
|
TAG,
|
||||||
"Setting OB reg %d for word %d (addr 0x%08X) to 0x%08X",
|
"Setting OB reg %d for word %d (addr 0x%08lX) to 0x%08lX",
|
||||||
reg_def->ob_reg,
|
reg_def->ob_reg,
|
||||||
word_idx,
|
word_idx,
|
||||||
reg_def->ob_register_address,
|
(uint32_t)reg_def->ob_register_address,
|
||||||
value);
|
value);
|
||||||
|
|
||||||
/* 1. Clear OPTLOCK option lock bit with the clearing sequence */
|
/* 1. Clear OPTLOCK option lock bit with the clearing sequence */
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ void furi_hal_memory_init() {
|
|||||||
memory->region[SRAM_B].size = sram2b_unprotected_size;
|
memory->region[SRAM_B].size = sram2b_unprotected_size;
|
||||||
|
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG, "SRAM2A: 0x%p, %d", memory->region[SRAM_A].start, memory->region[SRAM_A].size);
|
TAG, "SRAM2A: 0x%p, %ld", memory->region[SRAM_A].start, memory->region[SRAM_A].size);
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG, "SRAM2B: 0x%p, %d", memory->region[SRAM_B].start, memory->region[SRAM_B].size);
|
TAG, "SRAM2B: 0x%p, %ld", memory->region[SRAM_B].start, memory->region[SRAM_B].size);
|
||||||
|
|
||||||
if((memory->region[SRAM_A].size > 0) || (memory->region[SRAM_B].size > 0)) {
|
if((memory->region[SRAM_A].size > 0) || (memory->region[SRAM_B].size > 0)) {
|
||||||
if((memory->region[SRAM_A].size > 0)) {
|
if((memory->region[SRAM_A].size > 0)) {
|
||||||
|
|||||||
@@ -569,13 +569,13 @@ void furi_hal_power_info_get(FuriHalPowerInfoCallback out, void* context) {
|
|||||||
furi_string_printf(value, "%u", furi_hal_power_get_bat_health_pct());
|
furi_string_printf(value, "%u", furi_hal_power_get_bat_health_pct());
|
||||||
out("battery_health", furi_string_get_cstr(value), false, context);
|
out("battery_health", furi_string_get_cstr(value), false, context);
|
||||||
|
|
||||||
furi_string_printf(value, "%u", furi_hal_power_get_battery_remaining_capacity());
|
furi_string_printf(value, "%lu", furi_hal_power_get_battery_remaining_capacity());
|
||||||
out("capacity_remain", furi_string_get_cstr(value), false, context);
|
out("capacity_remain", furi_string_get_cstr(value), false, context);
|
||||||
|
|
||||||
furi_string_printf(value, "%u", furi_hal_power_get_battery_full_capacity());
|
furi_string_printf(value, "%lu", furi_hal_power_get_battery_full_capacity());
|
||||||
out("capacity_full", furi_string_get_cstr(value), false, context);
|
out("capacity_full", furi_string_get_cstr(value), false, context);
|
||||||
|
|
||||||
furi_string_printf(value, "%u", furi_hal_power_get_battery_design_capacity());
|
furi_string_printf(value, "%lu", furi_hal_power_get_battery_design_capacity());
|
||||||
out("capacity_design", furi_string_get_cstr(value), true, context);
|
out("capacity_design", furi_string_get_cstr(value), true, context);
|
||||||
|
|
||||||
furi_string_free(value);
|
furi_string_free(value);
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) {
|
|||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
for(uint8_t y = i; y < i + 10; y++) {
|
for(uint8_t y = i; y < i + 10; y++) {
|
||||||
FURI_LOG_D(TAG, "PA[%lu]: %02X", y, preset_data[y]);
|
FURI_LOG_D(TAG, "PA[%u]: %02X", y, preset_data[y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user