[FL-2612, FL-2618, FL-2619, FL-2622] CLI, threads, notifications, archive fixes (#1354)

* CLI, notifications, archive fixes
* Led blink fix
* Fix thread flags notification index
* Archive: fix infinite tab switch on empty SD card

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Nikolay Minaylov 2022-07-06 16:54:08 +03:00 committed by GitHub
parent ece142a667
commit e17dae2d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 28 deletions

View File

@ -15,8 +15,9 @@ static void
int32_t load_offset = 0; int32_t load_offset = 0;
browser->is_root = is_root; browser->is_root = is_root;
ArchiveTabEnum tab = archive_get_tab(browser);
if((item_cnt == 0) && (archive_is_home(browser))) { if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) {
archive_switch_tab(browser, browser->last_tab_switch_dir); archive_switch_tab(browser, browser->last_tab_switch_dir);
} else if(!string_start_with_str_p(browser->path, "/app:")) { } else if(!string_start_with_str_p(browser->path, "/app:")) {
with_view_model( with_view_model(
@ -389,6 +390,22 @@ void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
}); });
} }
static bool archive_is_dir_exists(string_t path) {
if(string_equal_str_p(path, "/any")) {
return true;
}
bool state = false;
FileInfo file_info;
Storage* storage = furi_record_open("storage");
if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) {
if(file_info.flags & FSF_DIRECTORY) {
state = true;
}
}
furi_record_close("storage");
return state;
}
void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
furi_assert(browser); furi_assert(browser);
ArchiveTabEnum tab = archive_get_tab(browser); ArchiveTabEnum tab = archive_get_tab(browser);
@ -418,11 +435,15 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
} }
} }
} else { } else {
ArchiveTabEnum tab = archive_get_tab(browser); tab = archive_get_tab(browser);
bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true; if(archive_is_dir_exists(browser->path)) {
file_browser_worker_set_config( bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true;
browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets); file_browser_worker_set_config(
tab_empty = false; // Empty check will be performed later browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets);
tab_empty = false; // Empty check will be performed later
} else {
tab_empty = true;
}
} }
if((tab_empty) && (tab != ArchiveTabBrowser)) { if((tab_empty) && (tab != ArchiveTabBrowser)) {

View File

@ -229,18 +229,22 @@ static void cli_handle_enter(Cli* cli) {
// Search for command // Search for command
furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK);
CliCommand* cli_command = CliCommandTree_get(cli->commands, command); CliCommand* cli_command_ptr = CliCommandTree_get(cli->commands, command);
if(cli_command) {
if(cli_command_ptr) {
CliCommand cli_command;
memcpy(&cli_command, cli_command_ptr, sizeof(CliCommand));
furi_check(osMutexRelease(cli->mutex) == osOK);
cli_nl(cli); cli_nl(cli);
cli_execute_command(cli, cli_command, args); cli_execute_command(cli, &cli_command, args);
} else { } else {
furi_check(osMutexRelease(cli->mutex) == osOK);
cli_nl(cli); cli_nl(cli);
printf( printf(
"`%s` command not found, use `help` or `?` to list all available commands", "`%s` command not found, use `help` or `?` to list all available commands",
string_get_cstr(command)); string_get_cstr(command));
cli_putc(cli, CliSymbolAsciiBell); cli_putc(cli, CliSymbolAsciiBell);
} }
furi_check(osMutexRelease(cli->mutex) == osOK);
cli_reset(cli); cli_reset(cli);
cli_prompt(cli); cli_prompt(cli);

View File

@ -199,6 +199,7 @@ static int32_t vcp_worker(void* context) {
furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL, NULL); furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL, NULL);
// Restore previous USB mode (if it was set during init) // Restore previous USB mode (if it was set during init)
if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) { if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) {
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); xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);

View File

@ -158,7 +158,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
const bool pin_locked = model->pin_locked; const bool pin_locked = model->pin_locked;
view_commit_model(locked_view->view, is_changed); view_commit_model(locked_view->view, is_changed);
if(view_state == DesktopViewLockedStateUnlocked || event->type != InputTypeShort) { if(view_state == DesktopViewLockedStateUnlocked) {
return view_state != DesktopViewLockedStateUnlocked; return view_state != DesktopViewLockedStateUnlocked;
} else if(view_state == DesktopViewLockedStateLocked && pin_locked) { } else if(view_state == DesktopViewLockedStateLocked && pin_locked) {
locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context); locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
@ -173,10 +173,12 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
desktop_view_locked_update_hint_icon_timeout(locked_view); desktop_view_locked_update_hint_icon_timeout(locked_view);
if(event->key == InputKeyBack) { if(event->key == InputKeyBack) {
locked_view->lock_lastpress = press_time; if(event->type == InputTypeShort) {
locked_view->lock_count++; locked_view->lock_lastpress = press_time;
if(locked_view->lock_count == UNLOCK_CNT) { locked_view->lock_count++;
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context); if(locked_view->lock_count == UNLOCK_CNT) {
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
}
} }
} else { } else {
locked_view->lock_count = 0; locked_view->lock_count = 0;

View File

@ -3,6 +3,8 @@
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include <toolbox/path.h> #include <toolbox/path.h>
#define EMULATE_TIMEOUT_TICKS 10
static void ibutton_scene_emulate_callback(void* context, bool emulated) { static void ibutton_scene_emulate_callback(void* context, bool emulated) {
iButton* ibutton = context; iButton* ibutton = context;
if(emulated) { if(emulated) {
@ -95,11 +97,23 @@ bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) {
bool consumed = false; bool consumed = false;
if(event.type == SceneManagerEventTypeTick) { if(event.type == SceneManagerEventTypeTick) {
uint32_t cnt = scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate);
if(cnt > 0) {
cnt--;
if(cnt == 0) {
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink);
}
scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneEmulate, cnt);
}
consumed = true; consumed = true;
} else if(event.type == SceneManagerEventTypeCustom) { } else if(event.type == SceneManagerEventTypeCustom) {
consumed = true; consumed = true;
if(event.event == iButtonCustomEventWorkerEmulated) { if(event.event == iButtonCustomEventWorkerEmulated) {
ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); if(scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate) == 0) {
ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink);
}
scene_manager_set_scene_state(
ibutton->scene_manager, iButtonSceneEmulate, EMULATE_TIMEOUT_TICKS);
} }
} }

View File

@ -93,6 +93,9 @@ void notification_reset_notification_led_layer(NotificationLedLayer* layer) {
} }
void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) { void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) {
if(reset_mask & reset_blink_mask) {
furi_hal_light_blink_stop();
}
if(reset_mask & reset_red_mask) { if(reset_mask & reset_red_mask) {
notification_reset_notification_led_layer(&app->led[0]); notification_reset_notification_led_layer(&app->led[0]);
} }
@ -102,9 +105,6 @@ void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_m
if(reset_mask & reset_blue_mask) { if(reset_mask & reset_blue_mask) {
notification_reset_notification_led_layer(&app->led[2]); notification_reset_notification_led_layer(&app->led[2]);
} }
if(reset_mask & reset_blink_mask) {
furi_hal_light_blink_stop();
}
if(reset_mask & reset_vibro_mask) { if(reset_mask & reset_vibro_mask) {
notification_vibro_off(); notification_vibro_off();
} }
@ -243,6 +243,9 @@ void notification_process_notification_message(
notification_message->data.led_blink.on_time, notification_message->data.led_blink.on_time,
notification_message->data.led_blink.period); notification_message->data.led_blink.period);
reset_mask |= reset_blink_mask; reset_mask |= reset_blink_mask;
reset_mask |= reset_red_mask;
reset_mask |= reset_green_mask;
reset_mask |= reset_blue_mask;
break; break;
case NotificationMessageTypeLedBlinkColor: case NotificationMessageTypeLedBlinkColor:
led_active = true; led_active = true;
@ -251,6 +254,9 @@ void notification_process_notification_message(
case NotificationMessageTypeLedBlinkStop: case NotificationMessageTypeLedBlinkStop:
furi_hal_light_blink_stop(); furi_hal_light_blink_stop();
reset_mask &= ~reset_blink_mask; reset_mask &= ~reset_blink_mask;
reset_mask |= reset_red_mask;
reset_mask |= reset_green_mask;
reset_mask |= reset_blue_mask;
break; break;
case NotificationMessageTypeVibro: case NotificationMessageTypeVibro:
if(notification_message->data.vibro.on) { if(notification_message->data.vibro.on) {
@ -326,7 +332,7 @@ void notification_process_notification_message(
reset_mask |= reset_green_mask; reset_mask |= reset_green_mask;
reset_mask |= reset_blue_mask; reset_mask |= reset_blue_mask;
if(need_minimal_delay) { if((need_minimal_delay) && (reset_notifications)) {
notification_apply_notification_leds(app, led_off_values); notification_apply_notification_leds(app, led_off_values);
furi_hal_delay_ms(minimal_delay); furi_hal_delay_ms(minimal_delay);
} }

View File

@ -7,6 +7,8 @@
#include <task.h> #include <task.h>
#include <m-string.h> #include <m-string.h>
#define THREAD_NOTIFY_INDEX 1 // Index 0 is used for stream buffers
struct FuriThread { struct FuriThread {
FuriThreadState state; FuriThreadState state;
int32_t ret; int32_t ret;
@ -221,13 +223,14 @@ uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags) {
if(FURI_IS_IRQ_MODE()) { if(FURI_IS_IRQ_MODE()) {
yield = pdFALSE; yield = pdFALSE;
(void)xTaskNotifyFromISR(hTask, flags, eSetBits, &yield); (void)xTaskNotifyIndexedFromISR(hTask, THREAD_NOTIFY_INDEX, flags, eSetBits, &yield);
(void)xTaskNotifyAndQueryFromISR(hTask, 0, eNoAction, &rflags, NULL); (void)xTaskNotifyAndQueryIndexedFromISR(
hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags, NULL);
portYIELD_FROM_ISR(yield); portYIELD_FROM_ISR(yield);
} else { } else {
(void)xTaskNotify(hTask, flags, eSetBits); (void)xTaskNotifyIndexed(hTask, THREAD_NOTIFY_INDEX, flags, eSetBits);
(void)xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags); (void)xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags);
} }
} }
/* Return flags after setting */ /* Return flags after setting */
@ -245,11 +248,13 @@ uint32_t furi_thread_flags_clear(uint32_t flags) {
} else { } else {
hTask = xTaskGetCurrentTaskHandle(); hTask = xTaskGetCurrentTaskHandle();
if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &cflags) == pdPASS) { if(xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &cflags) ==
pdPASS) {
rflags = cflags; rflags = cflags;
cflags &= ~flags; cflags &= ~flags;
if(xTaskNotify(hTask, cflags, eSetValueWithOverwrite) != pdPASS) { if(xTaskNotifyIndexed(hTask, THREAD_NOTIFY_INDEX, cflags, eSetValueWithOverwrite) !=
pdPASS) {
rflags = (uint32_t)osError; rflags = (uint32_t)osError;
} }
} else { } else {
@ -270,7 +275,8 @@ uint32_t furi_thread_flags_get(void) {
} else { } else {
hTask = xTaskGetCurrentTaskHandle(); hTask = xTaskGetCurrentTaskHandle();
if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags) != pdPASS) { if(xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags) !=
pdPASS) {
rflags = (uint32_t)osError; rflags = (uint32_t)osError;
} }
} }
@ -300,7 +306,7 @@ uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeo
t0 = xTaskGetTickCount(); t0 = xTaskGetTickCount();
do { do {
rval = xTaskNotifyWait(0, clear, &nval, tout); rval = xTaskNotifyWaitIndexed(THREAD_NOTIFY_INDEX, 0, clear, &nval, tout);
if(rval == pdPASS) { if(rval == pdPASS) {
rflags &= flags; rflags &= flags;