[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:
		
							parent
							
								
									ece142a667
								
							
						
					
					
						commit
						e17dae2d00
					
				| @ -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); | ||||||
|  |         if(archive_is_dir_exists(browser->path)) { | ||||||
|             bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true; |             bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true; | ||||||
|             file_browser_worker_set_config( |             file_browser_worker_set_config( | ||||||
|                 browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets); |                 browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets); | ||||||
|             tab_empty = false; // Empty check will be performed later
 |             tab_empty = false; // Empty check will be performed later
 | ||||||
|  |         } else { | ||||||
|  |             tab_empty = true; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if((tab_empty) && (tab != ArchiveTabBrowser)) { |     if((tab_empty) && (tab != ArchiveTabBrowser)) { | ||||||
|  | |||||||
| @ -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); | ||||||
|  | |||||||
| @ -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); | ||||||
|  | |||||||
| @ -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,11 +173,13 @@ 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) { | ||||||
|  |             if(event->type == InputTypeShort) { | ||||||
|                 locked_view->lock_lastpress = press_time; |                 locked_view->lock_lastpress = press_time; | ||||||
|                 locked_view->lock_count++; |                 locked_view->lock_count++; | ||||||
|                 if(locked_view->lock_count == UNLOCK_CNT) { |                 if(locked_view->lock_count == UNLOCK_CNT) { | ||||||
|                     locked_view->callback(DesktopLockedEventUnlocked, locked_view->context); |                     locked_view->callback(DesktopLockedEventUnlocked, locked_view->context); | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             locked_view->lock_count = 0; |             locked_view->lock_count = 0; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -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,12 +97,24 @@ 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) { | ||||||
|  |             if(scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate) == 0) { | ||||||
|                 ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); |                 ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); | ||||||
|             } |             } | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 ibutton->scene_manager, iButtonSceneEmulate, EMULATE_TIMEOUT_TICKS); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return consumed; |     return consumed; | ||||||
|  | |||||||
| @ -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); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -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; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikolay Minaylov
						Nikolay Minaylov