diff --git a/flipper_companion_apps/applications/external/esp32cam_camera/application.fam b/flipper_companion_apps/applications/external/esp32cam_camera/application.fam index 59e8b9c..3e53f25 100644 --- a/flipper_companion_apps/applications/external/esp32cam_camera/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_camera/application.fam @@ -1,15 +1,15 @@ App( appid="mayhem_camera", - name="[MAYHEM] Camera v1.0.0", + name="[MAYHEM] Camera", apptype=FlipperAppType.EXTERNAL, entry_point="camera_app", cdefines=["APP_CAMERA"], requires=["gui"], - stack_size=8*1024, + stack_size=8 * 1024, order=1, - fap_icon="icon.png", - fap_category="GPIO", - fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]", - fap_author="Z4urce", - fap_weburl="https://github.com/Z4urce/flipper-camera" -) \ No newline at end of file + fap_icon="icon.png", + fap_category="GPIO/MAYHEM", + fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]", + fap_author="Z4urce", + fap_weburl="https://github.com/Z4urce/flipper-camera", +) diff --git a/flipper_companion_apps/applications/external/esp32cam_camera/camera.c b/flipper_companion_apps/applications/external/esp32cam_camera/camera.c index 932fee1..58538ee 100644 --- a/flipper_companion_apps/applications/external/esp32cam_camera/camera.c +++ b/flipper_companion_apps/applications/external/esp32cam_camera/camera.c @@ -1,5 +1,6 @@ #include "camera.h" +#include static void camera_view_draw_callback(Canvas* canvas, void* _model) { UartDumpModel* model = _model; @@ -20,16 +21,15 @@ static void camera_view_draw_callback(Canvas* canvas, void* _model) { } } - if (!model->initialized){ - + if(!model->initialized) { /*if(!model->marauderInitialized) { // Init marauder into stream mode uint8_t data[] = "\nstream\n"; - furi_hal_uart_tx(FuriHalUartIdUSART1, data, sizeof(data)); + furi_hal_serial_tx(app->serial_handle, data, sizeof(data)); }*/ - - canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48); + + canvas_draw_icon(canvas, 80, 21, &I_WarningDolphinFlip_45x42); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 8, 12, "Waiting ESP32-CAM..."); canvas_draw_str(canvas, 20, 24, "VCC - 3V3/5V"); @@ -40,11 +40,11 @@ static void camera_view_draw_callback(Canvas* canvas, void* _model) { } void get_timefilename(FuriString* name) { - FuriHalRtcDateTime datetime = {0}; + DateTime datetime = {0}; furi_hal_rtc_get_datetime(&datetime); furi_string_printf( name, - EXT_PATH("DCIM/%.4d%.2d%.2d-%.2d%.2d%.2d.bmp"), + APP_DATA_PATH("%.4d%.2d%.2d-%.2d%.2d%.2d.bmp"), datetime.year, datetime.month, datetime.day, @@ -74,22 +74,26 @@ static void save_image(void* context) { get_timefilename(file_name); // this functions open a file, using write access and creates new file if not exist. - bool result = storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS); + bool result = + storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS); //bool result = storage_file_open(file, EXT_PATH("DCIM/test.bmp"), FSAM_WRITE, FSOM_OPEN_ALWAYS); furi_string_free(file_name); - if (result){ + if(result) { storage_file_write(file, bitmap_header, BITMAP_HEADER_LENGTH); - with_view_model(app->view, UartDumpModel * model, { - int8_t row_buffer[ROW_BUFFER_LENGTH]; - for (size_t i = 64; i > 0; --i) { - for (size_t j = 0; j < ROW_BUFFER_LENGTH; ++j){ - row_buffer[j] = model->pixels[((i-1)*ROW_BUFFER_LENGTH) + j]; + with_view_model( + app->view, + UartDumpModel * model, + { + int8_t row_buffer[ROW_BUFFER_LENGTH]; + for(size_t i = 64; i > 0; --i) { + for(size_t j = 0; j < ROW_BUFFER_LENGTH; ++j) { + row_buffer[j] = model->pixels[((i - 1) * ROW_BUFFER_LENGTH) + j]; + } + storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH); } - storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH); - } - - }, false); + }, + false); } // Closing the "file descriptor" @@ -102,26 +106,23 @@ static void save_image(void* context) { } static bool camera_view_input_callback(InputEvent* event, void* context) { - if (event->type == InputTypePress){ + if(event->type == InputTypePress) { uint8_t data[1]; - if (event->key == InputKeyUp){ + if(event->key == InputKeyUp) { data[0] = 'C'; - } - else if (event->key == InputKeyDown){ + } else if(event->key == InputKeyDown) { data[0] = 'c'; - } - else if (event->key == InputKeyRight){ + } else if(event->key == InputKeyRight) { data[0] = '>'; - } - else if (event->key == InputKeyLeft){ + } else if(event->key == InputKeyLeft) { data[0] = '<'; - } - else if (event->key == InputKeyOk){ + } else if(event->key == InputKeyOk) { save_image(context); } - furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); + UartEchoApp* app = context; + furi_hal_serial_tx(app->serial_handle, data, 1); } - + return false; } @@ -130,47 +131,52 @@ static uint32_t camera_exit(void* context) { return VIEW_NONE; } -static void camera_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +static void + camera_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { furi_assert(context); UartEchoApp* app = context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(app->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); } } static void process_ringbuffer(UartDumpModel* model, uint8_t byte) { - //// 1. Phase: filling the ringbuffer - if (model->ringbuffer_index == 0 && byte != 'Y'){ // First char has to be 'Y' in the buffer. + if(model->ringbuffer_index == 0 && byte != 'Y') { // First char has to be 'Y' in the buffer. return; } - - if (model->ringbuffer_index == 1 && byte != ':'){ // Second char has to be ':' in the buffer or reset. + + if(model->ringbuffer_index == 1 && + byte != ':') { // Second char has to be ':' in the buffer or reset. model->ringbuffer_index = 0; process_ringbuffer(model, byte); return; } - model->row_ringbuffer[model->ringbuffer_index] = byte; // Assign current byte to the ringbuffer; + model->row_ringbuffer[model->ringbuffer_index] = + byte; // Assign current byte to the ringbuffer; ++model->ringbuffer_index; // Increment the ringbuffer index - if (model->ringbuffer_index < RING_BUFFER_LENGTH){ // Let's wait 'till the buffer fills. + if(model->ringbuffer_index < RING_BUFFER_LENGTH) { // Let's wait 'till the buffer fills. return; } //// 2. Phase: flushing the ringbuffer to the framebuffer model->ringbuffer_index = 0; // Let's reset the ringbuffer model->initialized = true; // We've successfully established the connection - size_t row_start_index = model->row_ringbuffer[2] * ROW_BUFFER_LENGTH; // Third char will determine the row number + size_t row_start_index = + model->row_ringbuffer[2] * ROW_BUFFER_LENGTH; // Third char will determine the row number - if (row_start_index > LAST_ROW_INDEX){ // Failsafe + if(row_start_index > LAST_ROW_INDEX) { // Failsafe row_start_index = 0; } - for (size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) { - model->pixels[row_start_index + i] = model->row_ringbuffer[i+3]; // Writing the remaining 16 bytes into the frame buffer + for(size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) { + model->pixels[row_start_index + i] = + model->row_ringbuffer[i + 3]; // Writing the remaining 16 bytes into the frame buffer } } @@ -192,10 +198,11 @@ static int32_t camera_worker(void* context) { length = furi_stream_buffer_receive(app->rx_stream, data, intended_data_size, 0); if(length > 0) { - //furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); + //furi_hal_serial_tx(app->serial_handle, data, length); with_view_model( app->view, - UartDumpModel * model, { + UartDumpModel * model, + { for(size_t i = 0; i < length; i++) { process_ringbuffer(model, data[i]); } @@ -205,7 +212,8 @@ static int32_t camera_worker(void* context) { } while(length > 0); notification_message(app->notification, &sequence_notification); - with_view_model(app->view, UartDumpModel * model, { UNUSED(model); }, true); + with_view_model( + app->view, UartDumpModel * model, { UNUSED(model); }, true); } } @@ -251,19 +259,19 @@ static UartEchoApp* camera_app_alloc() { furi_thread_start(app->worker_thread); // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, camera_on_irq_cb, app); + app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart); + furi_check(app->serial_handle); + furi_hal_serial_init(app->serial_handle, 230400); + furi_hal_serial_async_rx_start(app->serial_handle, camera_on_irq_cb, app, false); furi_hal_power_disable_external_3_3v(); furi_hal_power_disable_otg(); furi_delay_ms(200); furi_hal_power_enable_external_3_3v(); furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'c'}, 1); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'c'}, 1); } furi_delay_ms(1); return app; @@ -272,7 +280,9 @@ static UartEchoApp* camera_app_alloc() { static void camera_app_free(UartEchoApp* app) { furi_assert(app); - furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced + furi_hal_serial_async_rx_stop(app->serial_handle); + furi_hal_serial_deinit(app->serial_handle); + furi_hal_serial_control_release(app->serial_handle); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); @@ -298,11 +308,19 @@ static void camera_app_free(UartEchoApp* app) { int32_t camera_app(void* p) { UNUSED(p); + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + UartEchoApp* app = camera_app_alloc(); view_dispatcher_run(app->view_dispatcher); camera_app_free(app); - + furi_hal_power_disable_otg(); + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_camera/camera.h b/flipper_companion_apps/applications/external/esp32cam_camera/camera.h index f4fef23..17247a6 100644 --- a/flipper_companion_apps/applications/external/esp32cam_camera/camera.h +++ b/flipper_companion_apps/applications/external/esp32cam_camera/camera.h @@ -14,19 +14,22 @@ #include #include #include -#include -#include +#include +#include #include #include #include #include +#include + #define THREAD_ALLOC 2048 #define FRAME_WIDTH 128 #define FRAME_HEIGTH 64 #define FRAME_BIT_DEPTH 1 -#define FRAME_BUFFER_LENGTH (FRAME_WIDTH * FRAME_HEIGTH * FRAME_BIT_DEPTH / 8) // 128*64*1 / 8 = 1024 +#define FRAME_BUFFER_LENGTH \ + (FRAME_WIDTH * FRAME_HEIGTH * FRAME_BIT_DEPTH / 8) // 128*64*1 / 8 = 1024 #define ROW_BUFFER_LENGTH (FRAME_WIDTH / 8) // 128/8 = 16 #define LAST_ROW_INDEX (FRAME_BUFFER_LENGTH - ROW_BUFFER_LENGTH) // 1024 - 16 = 1008 #define RING_BUFFER_LENGTH (ROW_BUFFER_LENGTH + 3) // ROW_BUFFER_LENGTH + Header => 16 + 3 = 19 @@ -34,17 +37,10 @@ #define IMAGE_FILE_DIRECTORY_PATH EXT_PATH("DCIM") static const unsigned char bitmap_header[BITMAP_HEADER_LENGTH] = { - 0x42, 0x4D, 0x3E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0x00 -}; - -const uint8_t _I_DolphinCommon_56x48_0[] = {0x01,0x00,0xdf,0x00,0x00,0x1f,0xfe,0x0e,0x05,0x3f,0x04,0x06,0x78,0x06,0x30,0x20,0xf8,0x00,0xc6,0x12,0x1c,0x04,0x0c,0x0a,0x38,0x08,0x08,0x0c,0x60,0xc0,0x21,0xe0,0x04,0x0a,0x18,0x02,0x1b,0x00,0x18,0xa3,0x00,0x21,0x90,0x01,0x8a,0x20,0x02,0x19,0x80,0x18,0x80,0x64,0x09,0x20,0x89,0x81,0x8c,0x3e,0x41,0xe2,0x80,0x50,0x00,0x43,0x08,0x01,0x0c,0xfc,0x68,0x40,0x61,0xc0,0x50,0x30,0x00,0x63,0xa0,0x7f,0x80,0xc4,0x41,0x19,0x07,0xff,0x02,0x06,0x18,0x24,0x03,0x41,0xf3,0x2b,0x10,0x19,0x38,0x10,0x30,0x31,0x7f,0xe0,0x34,0x08,0x30,0x19,0x60,0x80,0x65,0x86,0x0a,0x4c,0x0c,0x30,0x81,0xb9,0x41,0xa0,0x54,0x08,0xc7,0xe2,0x06,0x8a,0x18,0x25,0x02,0x21,0x0f,0x19,0x88,0xd8,0x6e,0x1b,0x01,0xd1,0x1b,0x86,0x39,0x66,0x3a,0xa4,0x1a,0x50,0x06,0x48,0x18,0x18,0xd0,0x03,0x01,0x41,0x98,0xcc,0x60,0x39,0x01,0x49,0x2d,0x06,0x03,0x50,0xf8,0x40,0x3e,0x02,0xc1,0x82,0x86,0xc7,0xfe,0x0f,0x28,0x2c,0x91,0xd2,0x90,0x9a,0x18,0x19,0x3e,0x6d,0x73,0x12,0x16,0x00,0x32,0x49,0x72,0xc0,0x7e,0x5d,0x44,0xba,0x2c,0x08,0xa4,0xc8,0x82,0x06,0x17,0xe0,0x81,0x90,0x2a,0x40,0x61,0xe1,0xa2,0x44,0x0c,0x76,0x2b,0xe8,0x89,0x26,0x43,0x83,0x31,0x8c,0x78,0x0c,0xb0,0x48,0x10,0x1a,0xe0,0x00,0x63,}; -const uint8_t* const _I_DolphinCommon_56x48[] = {_I_DolphinCommon_56x48_0}; -const Icon I_DolphinCommon_56x48 = {.width=56,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinCommon_56x48}; + 0x42, 0x4D, 0x3E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00}; typedef struct UartDumpModel UartDumpModel; @@ -55,6 +51,7 @@ typedef struct { View* view; FuriThread* worker_thread; FuriStreamBuffer* rx_stream; + FuriHalSerialHandle* serial_handle; } UartEchoApp; struct UartDumpModel { diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/application.fam b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/application.fam index 0355d84..e741a58 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/application.fam @@ -1,14 +1,14 @@ App( appid="mayhem_marauder", - name="[MAYHEM] Marauder v0.6.6", - fap_version=(6,6), + name="[MAYHEM] Marauder", + fap_version=(6, 6), apptype=FlipperAppType.EXTERNAL, entry_point="wifi_marauder_app", requires=["gui"], stack_size=4 * 1024, order=2, fap_icon="wifi_10px.png", - fap_category="GPIO", + fap_category="GPIO/MAYHEM", fap_icon_assets="assets", fap_description="ESP32-CAM version of Marauder. Includes all functionality from the original plus some options to trigger the camera and flashlight. [Unplug the USB cable to test with Mayhem]", ) diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_console_output.c index d67c681..eb4a55b 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -122,15 +122,11 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { app->log_file_path, sequential_file_resolve_path( app->storage, MARAUDER_APP_FOLDER_LOGS, prefix, "log")); - if(app->log_file_path != NULL) { - if(storage_file_open( - app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - app->is_writing_log = true; - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); - } + if(storage_file_open( + app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + app->is_writing_log = true; } else { - dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path"); + dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); } } @@ -157,11 +153,11 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { // Send command with newline '\n' if(app->selected_tx_string) { wifi_marauder_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); + app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); + wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1); if(send_html && the_html) { - wifi_marauder_uart_tx(the_html, html_size); - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); + wifi_marauder_uart_tx(app->uart, the_html, html_size); + wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1); free(the_html); send_html = false; } @@ -169,7 +165,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { // Run the script if the file with the script has been opened if(app->script != NULL) { - app->script_worker = wifi_marauder_script_worker_alloc(); + app->script_worker = wifi_marauder_script_worker_alloc(app->uart); wifi_marauder_script_worker_start(app->script_worker, app->script); } } @@ -195,7 +191,7 @@ void wifi_marauder_scene_console_output_on_exit(void* context) { // Automatically stop the scan when exiting view if(app->is_command) { - wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n")); + wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n")); furi_delay_ms(50); } diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c index 1ac78ef..ecfef15 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c @@ -63,8 +63,8 @@ bool wifi_marauder_scene_script_confirm_delete_on_event(void* context, SceneMana app->script = NULL; DialogMessage* message = dialog_message_alloc(); - dialog_message_set_text(message, "Deleted!", 88, 32, AlignCenter, AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); + dialog_message_set_text(message, "Deleted!", 83, 19, AlignLeft, AlignBottom); + dialog_message_set_icon(message, &I_DolphinMafia_119x62, 0, 2); dialog_message_set_buttons(message, NULL, "Ok", NULL); dialog_message_show(app->dialogs, message); dialog_message_free(message); diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_options.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_options.c index 896f6bf..e62f967 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_options.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_script_options.c @@ -19,8 +19,8 @@ void wifi_marauder_scene_script_options_save_script(WifiMarauderApp* app) { wifi_marauder_script_save_json(app->storage, script_path, app->script); DialogMessage* message = dialog_message_alloc(); - dialog_message_set_text(message, "Saved!", 88, 32, AlignCenter, AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); + dialog_message_set_text(message, "Saved!", 5, 7, AlignLeft, AlignTop); + dialog_message_set_icon(message, &I_DolphinDone_80x58, 36, 5); dialog_message_set_buttons(message, NULL, "Ok", NULL); dialog_message_show(app->dialogs, message); dialog_message_free(message); diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_text_input.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_text_input.c index e6091a4..b721e86 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_text_input.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_text_input.c @@ -44,24 +44,24 @@ void wifi_marauder_scene_text_input_on_enter(void* context) { } // Setup view - WIFI_TextInput* text_input = app->text_input; + TextInput* text_input = app->text_input; // Add help message to header if(app->special_case_input_step == 1) { - wifi_text_input_set_header_text(text_input, "Enter source MAC"); + text_input_set_header_text(text_input, "Enter source MAC"); } else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { - wifi_text_input_set_header_text(text_input, "Enter # SSIDs to generate"); + text_input_set_header_text(text_input, "Enter # SSIDs to generate"); } else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) { - wifi_text_input_set_header_text(text_input, "Enter SSID name to add"); + text_input_set_header_text(text_input, "Enter SSID name to add"); } else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) { - wifi_text_input_set_header_text(text_input, "Remove target from SSID list"); + text_input_set_header_text(text_input, "Remove target from SSID list"); } else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) { - wifi_text_input_set_header_text(text_input, "Add target from AP list"); + text_input_set_header_text(text_input, "Add target from AP list"); } else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) { - wifi_text_input_set_header_text(text_input, "Add target from SSID list"); + text_input_set_header_text(text_input, "Add target from SSID list"); } else { - wifi_text_input_set_header_text(text_input, "Add command arguments"); + text_input_set_header_text(text_input, "Add command arguments"); } - wifi_text_input_set_result_callback( + text_input_set_result_callback( text_input, wifi_marauder_scene_text_input_callback, app, @@ -84,7 +84,7 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev consumed = true; } else if(event.event == WifiMarauderEventSaveSourceMac) { if(12 != strlen(app->text_input_store)) { - wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); } else { snprintf( app->special_case_input_src_addr, @@ -106,12 +106,12 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev // Advance scene to input destination MAC, clear text input app->special_case_input_step = 2; bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); - wifi_text_input_set_header_text(app->text_input, "Enter destination MAC"); + text_input_set_header_text(app->text_input, "Enter destination MAC"); } consumed = true; } else if(event.event == WifiMarauderEventSaveDestinationMac) { if(12 != strlen(app->text_input_store)) { - wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); } else { snprintf( app->special_case_input_dst_addr, @@ -150,5 +150,5 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev void wifi_marauder_scene_text_input_on_exit(void* context) { WifiMarauderApp* app = context; - wifi_text_input_reset(app->text_input); + text_input_reset(app->text_input); } diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_user_input.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_user_input.c index 8edd020..856ebeb 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_user_input.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/scenes/wifi_marauder_scene_user_input.c @@ -100,19 +100,20 @@ void wifi_marauder_scene_user_input_on_enter(void* context) { switch(app->user_input_type) { // Loads the string value of the reference case WifiMarauderUserInputTypeString: - wifi_text_input_set_header_text(app->text_input, "Enter value:"); - wifi_text_input_set_validator(app->text_input, NULL, app); + text_input_set_header_text(app->text_input, "Enter value:"); + text_input_set_validator(app->text_input, NULL, app); if(app->user_input_string_reference != NULL) { strncpy( app->text_input_store, *app->user_input_string_reference, strlen(*app->user_input_string_reference) + 1); } + text_input_add_illegal_symbols(app->text_input); break; // Loads the numerical value of the reference case WifiMarauderUserInputTypeNumber: - wifi_text_input_set_header_text(app->text_input, "Enter a valid number:"); - wifi_text_input_set_validator( + text_input_set_header_text(app->text_input, "Enter a valid number:"); + text_input_set_validator( app->text_input, wifi_marauder_scene_user_input_validator_number_callback, app); if(app->user_input_number_reference != NULL) { char number_str[32]; @@ -122,8 +123,8 @@ void wifi_marauder_scene_user_input_on_enter(void* context) { break; // File name case WifiMarauderUserInputTypeFileName: - wifi_text_input_set_header_text(app->text_input, "Enter file name:"); - wifi_text_input_set_validator( + text_input_set_header_text(app->text_input, "Enter file name:"); + text_input_set_validator( app->text_input, wifi_marauder_scene_user_input_validator_file_callback, app); break; default: @@ -131,7 +132,7 @@ void wifi_marauder_scene_user_input_on_enter(void* context) { return; } - wifi_text_input_set_result_callback( + text_input_set_result_callback( app->text_input, wifi_marauder_scene_user_input_ok_callback, app, @@ -155,11 +156,10 @@ bool wifi_marauder_scene_user_input_on_event(void* context, SceneManagerEvent ev } return consumed; - } void wifi_marauder_scene_user_input_on_exit(void* context) { WifiMarauderApp* app = context; memset(app->text_input_store, 0, sizeof(app->text_input_store)); - wifi_text_input_reset(app->text_input); + text_input_reset(app->text_input); } diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_executor.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_executor.c index 41f6285..5037580 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_executor.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_executor.c @@ -5,20 +5,20 @@ void _wifi_marauder_script_delay(WifiMarauderScriptWorker* worker, uint32_t dela for(uint32_t i = 0; i < delay_secs && worker->is_running; i++) furi_delay_ms(1000); } -void _send_stop() { +void _send_stop(WifiMarauderScriptWorker* worker) { const char stop_command[] = "stopscan\n"; - wifi_marauder_uart_tx((uint8_t*)(stop_command), strlen(stop_command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(stop_command), strlen(stop_command)); } -void _send_line_break() { - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); +void _send_line_break(WifiMarauderScriptWorker* worker) { + wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); } -void _send_channel_select(int channel) { +void _send_channel_select(WifiMarauderScriptWorker* worker, int channel) { char command[30]; - _send_line_break(); + _send_line_break(worker); snprintf(command, sizeof(command), "channel -s %d\n", channel); - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); } void _wifi_marauder_script_execute_scan( @@ -27,7 +27,7 @@ void _wifi_marauder_script_execute_scan( char command[15]; // Set channel if(stage->channel > 0) { - _send_channel_select(stage->channel); + _send_channel_select(worker, stage->channel); } // Start scan if(stage->type == WifiMarauderScriptScanTypeAp) { @@ -35,12 +35,14 @@ void _wifi_marauder_script_execute_scan( } else { snprintf(command, sizeof(command), "scansta\n"); } - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } -void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage) { +void _wifi_marauder_script_execute_select( + WifiMarauderScriptStageSelect* stage, + WifiMarauderScriptWorker* worker) { const char* select_type = NULL; switch(stage->type) { case WifiMarauderScriptSelectTypeAp: @@ -79,61 +81,61 @@ void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage) command, sizeof(command), "select %s -f \"%s\"\n", select_type, stage->filter); } - wifi_marauder_uart_tx((uint8_t*)command, command_length); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, command_length); } void _wifi_marauder_script_execute_deauth( WifiMarauderScriptStageDeauth* stage, WifiMarauderScriptWorker* worker) { const char attack_command[] = "attack -t deauth\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_probe( WifiMarauderScriptStageProbe* stage, WifiMarauderScriptWorker* worker) { const char attack_command[] = "attack -t probe\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_sniff_raw( WifiMarauderScriptStageSniffRaw* stage, WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffraw\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); + const char sniff_command[] = "sniffraw -serial\n"; + wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_sniff_beacon( WifiMarauderScriptStageSniffBeacon* stage, WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffbeacon\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); + const char sniff_command[] = "sniffbeacon -serial\n"; + wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_sniff_deauth( WifiMarauderScriptStageSniffDeauth* stage, WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffdeauth\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); + const char sniff_command[] = "sniffdeauth -serial\n"; + wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_sniff_esp( WifiMarauderScriptStageSniffEsp* stage, WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffesp\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); + const char sniff_command[] = "sniffesp -serial\n"; + wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_sniff_pmkid( @@ -150,10 +152,10 @@ void _wifi_marauder_script_execute_sniff_pmkid( len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d"); } - len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n"); - wifi_marauder_uart_tx((uint8_t*)attack_command, len); + len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n"); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } } else { char attack_command[50] = "sniffpmkid"; @@ -167,27 +169,27 @@ void _wifi_marauder_script_execute_sniff_pmkid( if(stage->force_deauth) { len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d"); } - len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n"); - wifi_marauder_uart_tx((uint8_t*)attack_command, len); + len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n"); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } } void _wifi_marauder_script_execute_sniff_pwn( WifiMarauderScriptStageSniffPwn* stage, WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffpwn\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); + const char sniff_command[] = "sniffpwn -serial\n"; + wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_beacon_list( WifiMarauderScriptStageBeaconList* stage, WifiMarauderScriptWorker* worker) { const char clearlist_command[] = "clearlist -s\n"; - wifi_marauder_uart_tx((uint8_t*)(clearlist_command), strlen(clearlist_command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(clearlist_command), strlen(clearlist_command)); char command[100]; char* ssid; @@ -195,8 +197,8 @@ void _wifi_marauder_script_execute_beacon_list( for(int i = 0; i < stage->ssid_count; i++) { ssid = stage->ssids[i]; snprintf(command, sizeof(command), "ssid -a -n \"%s\"", ssid); - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); - _send_line_break(); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); + _send_line_break(worker); } if(stage->random_ssids > 0) { char add_random_command[50]; @@ -205,27 +207,30 @@ void _wifi_marauder_script_execute_beacon_list( sizeof(add_random_command), "ssid -a -r -g %d\n", stage->random_ssids); - wifi_marauder_uart_tx((uint8_t*)add_random_command, strlen(add_random_command)); + wifi_marauder_uart_tx( + worker->uart, (uint8_t*)add_random_command, strlen(add_random_command)); } const char attack_command[] = "attack -t beacon -l\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } void _wifi_marauder_script_execute_beacon_ap( WifiMarauderScriptStageBeaconAp* stage, WifiMarauderScriptWorker* worker) { const char command[] = "attack -t beacon -a\n"; - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); + _send_stop(worker); } -void _wifi_marauder_script_execute_exec(WifiMarauderScriptStageExec* stage) { +void _wifi_marauder_script_execute_exec( + WifiMarauderScriptStageExec* stage, + WifiMarauderScriptWorker* worker) { if(stage->command != NULL) { - wifi_marauder_uart_tx((uint8_t*)stage->command, strlen(stage->command)); - _send_line_break(); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)stage->command, strlen(stage->command)); + _send_line_break(worker); } } @@ -248,8 +253,8 @@ void wifi_marauder_script_execute_start(void* context) { sizeof(command), "settings -s EnableLED %s", script->enable_led ? "enable" : "disable"); - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); - _send_line_break(); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); + _send_line_break(worker); } // Enables or disables PCAP saving according to script settings @@ -259,8 +264,8 @@ void wifi_marauder_script_execute_start(void* context) { sizeof(command), "settings -s SavePCAP %s", script->save_pcap ? "enable" : "disable"); - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); - _send_line_break(); + wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); + _send_line_break(worker); } } @@ -274,7 +279,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co _wifi_marauder_script_execute_scan((WifiMarauderScriptStageScan*)stage_data, worker); break; case WifiMarauderScriptStageTypeSelect: - _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data); + _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data, worker); break; case WifiMarauderScriptStageTypeDeauth: _wifi_marauder_script_execute_deauth((WifiMarauderScriptStageDeauth*)stage_data, worker); @@ -315,7 +320,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co (WifiMarauderScriptStageBeaconAp*)stage_data, worker); break; case WifiMarauderScriptStageTypeExec: - _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data); + _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data, worker); break; case WifiMarauderScriptStageTypeDelay: _wifi_marauder_script_execute_delay((WifiMarauderScriptStageDelay*)stage_data, worker); diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.c index 2e11b0e..5fbcad6 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.c @@ -1,7 +1,7 @@ #include "../wifi_marauder_app_i.h" #include "wifi_marauder_script_worker.h" -WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() { +WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(WifiMarauderUart* uart) { WifiMarauderScriptWorker* worker = malloc(sizeof(WifiMarauderScriptWorker)); if(worker == NULL) { return NULL; @@ -9,6 +9,7 @@ WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() { worker->callback_start = NULL; worker->callback_stage = NULL; worker->worker_thread = NULL; + worker->uart = uart; worker->is_running = false; return worker; } diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.h b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.h index 0fe91e1..4f7555e 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.h +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/script/wifi_marauder_script_worker.h @@ -11,6 +11,7 @@ typedef enum { typedef struct WifiMarauderScriptWorker { WifiMarauderScript* script; FuriThread* worker_thread; + WifiMarauderUart* uart; void (*callback_start)(void*); void (*callback_stage)(WifiMarauderScriptStage*, void*); void* context; diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app.c index c72b9ca..a8eada2 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app.c @@ -2,6 +2,7 @@ #include #include +#include static bool wifi_marauder_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -64,11 +65,9 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->text_box_store = furi_string_alloc(); furi_string_reserve(app->text_box_store, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE); - app->text_input = wifi_text_input_alloc(); + app->text_input = text_input_alloc(); view_dispatcher_add_view( - app->view_dispatcher, - WifiMarauderAppViewTextInput, - wifi_text_input_get_view(app->text_input)); + app->view_dispatcher, WifiMarauderAppViewTextInput, text_input_get_view(app->text_input)); app->widget = widget_alloc(); view_dispatcher_add_view( @@ -148,7 +147,7 @@ void wifi_marauder_app_free(WifiMarauderApp* app) { widget_free(app->widget); text_box_free(app->text_box); furi_string_free(app->text_box_store); - wifi_text_input_free(app->text_input); + text_input_free(app->text_input); submenu_free(app->submenu); variable_item_list_free(app->var_item_list); storage_file_free(app->capture_file); @@ -173,17 +172,17 @@ void wifi_marauder_app_free(WifiMarauderApp* app) { int32_t wifi_marauder_app(void* p) { UNUSED(p); - furi_hal_power_disable_external_3_3v(); - furi_hal_power_disable_otg(); - furi_delay_ms(200); - furi_hal_power_enable_external_3_3v(); - furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'w'}, 1); + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + + uint8_t attempts = 0; + while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + furi_hal_power_enable_otg(); + furi_delay_ms(10); } - furi_delay_ms(1); + furi_delay_ms(200); WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc(); @@ -192,6 +191,11 @@ int32_t wifi_marauder_app(void* p) { wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app); wifi_marauder_app->lp_uart = wifi_marauder_lp_uart_init(wifi_marauder_app); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + wifi_marauder_uart_tx(wifi_marauder_app->uart, (uint8_t[1]){'w'}, 1); + } + furi_delay_ms(1); view_dispatcher_run(wifi_marauder_app->view_dispatcher); @@ -201,5 +205,9 @@ int32_t wifi_marauder_app(void* p) { furi_hal_power_disable_otg(); } + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app_i.h b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app_i.h index 63ec3bd..80edf21 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app_i.h +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_app_i.h @@ -20,13 +20,15 @@ #include #include #include -#include "wifi_marauder_text_input.h" +#include #include #include #include #include +#include + #define NUM_MENU_ITEMS (22) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) @@ -59,7 +61,7 @@ struct WifiMarauderApp { FuriString* text_box_store; size_t text_box_store_strlen; TextBox* text_box; - WIFI_TextInput* text_input; + TextInput* text_input; Storage* storage; File* capture_file; File* log_file; diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.c deleted file mode 100644 index 4c1e1aa..0000000 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.c +++ /dev/null @@ -1,749 +0,0 @@ -#include "wifi_marauder_text_input.h" -#include -#include "wifi_marauder_app_i.h" -#include - -struct WIFI_TextInput { - View* view; - FuriTimer* timer; -}; - -typedef struct { - const char text; - const uint8_t x; - const uint8_t y; -} WIFI_TextInputKey; - -typedef struct { - const WIFI_TextInputKey* rows[3]; - const uint8_t keyboard_index; -} Keyboard; - -typedef struct { - const char* header; - char* text_buffer; - size_t text_buffer_size; - size_t minimum_length; - bool clear_default_text; - - bool cursor_select; - size_t cursor_pos; - - WIFI_TextInputCallback callback; - void* callback_context; - - uint8_t selected_row; - uint8_t selected_column; - uint8_t selected_keyboard; - - WIFI_TextInputValidatorCallback validator_callback; - void* validator_callback_context; - FuriString* validator_text; - bool validator_message_visible; -} WIFI_TextInputModel; - -static const uint8_t keyboard_origin_x = 1; -static const uint8_t keyboard_origin_y = 29; -static const uint8_t keyboard_row_count = 3; -static const uint8_t keyboard_count = 2; - -#define ENTER_KEY '\r' -#define BACKSPACE_KEY '\b' -#define SWITCH_KEYBOARD_KEY 0xfe - -static const WIFI_TextInputKey keyboard_keys_row_1[] = { - {'q', 1, 8}, - {'w', 10, 8}, - {'e', 19, 8}, - {'r', 28, 8}, - {'t', 37, 8}, - {'y', 46, 8}, - {'u', 55, 8}, - {'i', 64, 8}, - {'o', 73, 8}, - {'p', 82, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const WIFI_TextInputKey keyboard_keys_row_2[] = { - {'a', 1, 20}, - {'s', 10, 20}, - {'d', 19, 20}, - {'f', 28, 20}, - {'g', 37, 20}, - {'h', 46, 20}, - {'j', 55, 20}, - {'k', 64, 20}, - {'l', 73, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const WIFI_TextInputKey keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'z', 13, 32}, - {'x', 21, 32}, - {'c', 28, 32}, - {'v', 36, 32}, - {'b', 44, 32}, - {'n', 52, 32}, - {'m', 59, 32}, - {'_', 67, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_1[] = { - {'!', 2, 8}, - {'@', 12, 8}, - {'#', 22, 8}, - {'$', 32, 8}, - {'%', 42, 8}, - {'^', 52, 8}, - {'&', 62, 8}, - {'(', 71, 8}, - {')', 81, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_2[] = { - {'~', 2, 20}, - {'+', 12, 20}, - {'-', 22, 20}, - {'=', 32, 20}, - {'[', 42, 20}, - {']', 52, 20}, - {'{', 62, 20}, - {'}', 72, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'.', 15, 32}, - {',', 29, 32}, - {';', 41, 32}, - {'`', 53, 32}, - {'\'', 65, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const Keyboard keyboard = { - .rows = - { - keyboard_keys_row_1, - keyboard_keys_row_2, - keyboard_keys_row_3, - }, - .keyboard_index = 0, -}; - -static const Keyboard symbol_keyboard = { - .rows = - { - symbol_keyboard_keys_row_1, - symbol_keyboard_keys_row_2, - symbol_keyboard_keys_row_3, - }, - .keyboard_index = 1, -}; - -static const Keyboard* keyboards[] = { - &keyboard, - &symbol_keyboard, -}; - -static void switch_keyboard(WIFI_TextInputModel* model) { - model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count; -} - -static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { - uint8_t row_size = 0; - if(keyboard == &symbol_keyboard) { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(symbol_keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(symbol_keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(symbol_keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } else { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } - - return row_size; -} - -static const WIFI_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) { - const WIFI_TextInputKey* row = NULL; - if(row_index < 3) { - row = keyboard->rows[row_index]; - } else { - furi_crash(NULL); - } - - return row; -} - -static char get_selected_char(WIFI_TextInputModel* model) { - return get_row( - keyboards[model->selected_keyboard], model->selected_row)[model->selected_column] - .text; -} - -static bool char_is_lowercase(char letter) { - return (letter >= 0x61 && letter <= 0x7A); -} - -static char char_to_uppercase(const char letter) { - if(letter == '_') { - return 0x20; - } else if(char_is_lowercase(letter)) { - return (letter - 0x20); - } else { - return letter; - } -} - -static void wifi_text_input_backspace_cb(WIFI_TextInputModel* model) { - if(model->clear_default_text) { - model->text_buffer[0] = 0; - model->cursor_pos = 0; - } else if(model->cursor_pos > 0) { - char* move = model->text_buffer + model->cursor_pos; - memmove(move - 1, move, strlen(move) + 1); - model->cursor_pos--; - } -} - -static void wifi_text_input_view_draw_callback(Canvas* canvas, void* _model) { - WIFI_TextInputModel* model = _model; - uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; - uint8_t needed_string_width = canvas_width(canvas) - 8; - uint8_t start_pos = 4; - - model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos; - size_t cursor_pos = model->cursor_pos; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_str(canvas, 2, 8, model->header); - elements_slightly_rounded_frame(canvas, 1, 12, 126, 15); - - char buf[model->text_buffer_size + 1]; - if(model->text_buffer) { - strlcpy(buf, model->text_buffer, sizeof(buf)); - } - char* str = buf; - - if(model->clear_default_text) { - elements_slightly_rounded_box( - canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10); - canvas_set_color(canvas, ColorWhite); - } else { - char* move = str + cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - str[cursor_pos] = '|'; - } - - if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) { - canvas_draw_str(canvas, start_pos, 22, "..."); - start_pos += 6; - needed_string_width -= 8; - for(uint32_t off = 0; - strlen(str) && canvas_string_width(canvas, str) > needed_string_width && - off < cursor_pos; - off++) { - str++; - } - } - - if(canvas_string_width(canvas, str) > needed_string_width) { - needed_string_width -= 4; - size_t len = strlen(str); - while(len && canvas_string_width(canvas, str) > needed_string_width) { - str[len--] = '\0'; - } - //strcat(str, "..."); // TODO - find replacement - } - - canvas_draw_str(canvas, start_pos, 22, str); - - canvas_set_font(canvas, FontKeyboard); - - for(uint8_t row = 0; row < keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row); - const WIFI_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row); - - for(size_t column = 0; column < column_count; column++) { - bool selected = !model->cursor_select && model->selected_row == row && - model->selected_column == column; - const Icon* icon = NULL; - if(keys[column].text == ENTER_KEY) { - icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11; - } else if(keys[column].text == SWITCH_KEYBOARD_KEY) { - icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11; - } else if(keys[column].text == BACKSPACE_KEY) { - icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9; - } - canvas_set_color(canvas, ColorBlack); - if(icon != NULL) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - icon); - } else { - if(selected) { - canvas_draw_box( - canvas, - keyboard_origin_x + keys[column].x - 1, - keyboard_origin_y + keys[column].y - 8, - 7, - 10); - canvas_set_color(canvas, ColorWhite); - } - - if(model->clear_default_text || text_length == 0) { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - char_to_uppercase(keys[column].text)); - } else { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - keys[column].text); - } - } - } - } - if(model->validator_message_visible) { - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 8, 10, 110, 48); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); - canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); - canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); - canvas_set_font(canvas, FontKeyboard); - } -} - -static void - wifi_text_input_handle_up(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->selected_row > 0) { - model->selected_row--; - if(model->selected_row == 0 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) { - model->selected_column = model->selected_column + 1; - } - if(model->selected_row == 1 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 5) - model->selected_column += 2; - else if(model->selected_column > 1) - model->selected_column += 1; - } - } else { - model->cursor_select = true; - model->clear_default_text = false; - } -} - -static void - wifi_text_input_handle_down(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - model->cursor_select = false; - } else if(model->selected_row < keyboard_row_count - 1) { - model->selected_row++; - if(model->selected_row == 1 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) { - model->selected_column = model->selected_column - 1; - } - if(model->selected_row == 2 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 7) - model->selected_column -= 2; - else if(model->selected_column > 1) - model->selected_column -= 1; - } - } -} - -static void - wifi_text_input_handle_left(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - if(model->cursor_pos > 0) { - model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u); - } - } else if(model->selected_column > 0) { - model->selected_column--; - } else { - model->selected_column = - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1; - } -} - -static void - wifi_text_input_handle_right(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u); - } else if( - model->selected_column < - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) { - model->selected_column++; - } else { - model->selected_column = 0; - } -} - -static void wifi_text_input_handle_ok( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputModel* model, - InputType type) { - if(model->cursor_select) return; - bool shift = type == InputTypeLong; - bool repeat = type == InputTypeRepeat; - char selected = get_selected_char(model); - size_t text_length = strlen(model->text_buffer); - - if(selected == ENTER_KEY) { - if(model->validator_callback && - (!model->validator_callback( - model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->validator_message_visible = true; - furi_timer_start(wifi_text_input->timer, furi_kernel_get_tick_frequency() * 4); - } else if(model->callback != 0 && text_length >= model->minimum_length) { - model->callback(model->callback_context); - } - } else if(selected == SWITCH_KEYBOARD_KEY) { - switch_keyboard(model); - } else { - if(selected == BACKSPACE_KEY) { - wifi_text_input_backspace_cb(model); - } else if(!repeat) { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - if(shift != (text_length == 0)) { - selected = char_to_uppercase(selected); - } - if(model->clear_default_text) { - model->text_buffer[0] = selected; - model->text_buffer[1] = '\0'; - model->cursor_pos = 1; - } else { - char* move = model->text_buffer + model->cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - model->text_buffer[model->cursor_pos] = selected; - model->cursor_pos++; - } - } - } - model->clear_default_text = false; - } -} - -static bool wifi_text_input_view_input_callback(InputEvent* event, void* context) { - WIFI_TextInput* wifi_text_input = context; - furi_assert(wifi_text_input); - - bool consumed = false; - - // Acquire model - WIFI_TextInputModel* model = view_get_model(wifi_text_input->view); - - if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->validator_message_visible) { - model->validator_message_visible = false; - consumed = true; - } else if(event->type == InputTypeShort) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeLong) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - case InputKeyBack: - wifi_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeRepeat) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - case InputKeyBack: - wifi_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } - - // Commit model - view_commit_model(wifi_text_input->view, consumed); - - return consumed; -} - -void wifi_text_input_timer_callback(void* context) { - furi_assert(context); - WIFI_TextInput* wifi_text_input = context; - - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { model->validator_message_visible = false; }, - true); -} - -WIFI_TextInput* wifi_text_input_alloc() { - WIFI_TextInput* wifi_text_input = malloc(sizeof(WIFI_TextInput)); - wifi_text_input->view = view_alloc(); - view_set_context(wifi_text_input->view, wifi_text_input); - view_allocate_model(wifi_text_input->view, ViewModelTypeLocking, sizeof(WIFI_TextInputModel)); - view_set_draw_callback(wifi_text_input->view, wifi_text_input_view_draw_callback); - view_set_input_callback(wifi_text_input->view, wifi_text_input_view_input_callback); - - wifi_text_input->timer = - furi_timer_alloc(wifi_text_input_timer_callback, FuriTimerTypeOnce, wifi_text_input); - - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->validator_text = furi_string_alloc(); - model->minimum_length = 1; - model->cursor_pos = 0; - model->cursor_select = false; - }, - false); - - wifi_text_input_reset(wifi_text_input); - - return wifi_text_input; -} - -void wifi_text_input_free(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { furi_string_free(model->validator_text); }, - false); - - // Send stop command - furi_timer_stop(wifi_text_input->timer); - // Release allocated memory - furi_timer_free(wifi_text_input->timer); - - view_free(wifi_text_input->view); - - free(wifi_text_input); -} - -void wifi_text_input_reset(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->header = ""; - model->selected_row = 0; - model->selected_column = 0; - model->selected_keyboard = 0; - model->minimum_length = 1; - model->clear_default_text = false; - model->cursor_pos = 0; - model->cursor_select = false; - model->text_buffer = NULL; - model->text_buffer_size = 0; - model->callback = NULL; - model->callback_context = NULL; - model->validator_callback = NULL; - model->validator_callback_context = NULL; - furi_string_reset(model->validator_text); - model->validator_message_visible = false; - }, - true); -} - -View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - return wifi_text_input->view; -} - -void wifi_text_input_set_result_callback( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->callback = callback; - model->callback_context = callback_context; - model->text_buffer = text_buffer; - model->text_buffer_size = text_buffer_size; - model->clear_default_text = clear_default_text; - model->cursor_select = false; - if(text_buffer && text_buffer[0] != '\0') { - model->cursor_pos = strlen(text_buffer); - // Set focus on Save - model->selected_row = 2; - model->selected_column = 9; - model->selected_keyboard = 0; - } else { - model->cursor_pos = 0; - } - }, - true); -} - -void wifi_text_input_set_minimum_length(WIFI_TextInput* wifi_text_input, size_t minimum_length) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { model->minimum_length = minimum_length; }, - true); -} - -void wifi_text_input_set_validator( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputValidatorCallback callback, - void* callback_context) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->validator_callback = callback; - model->validator_callback_context = callback_context; - }, - true); -} - -WIFI_TextInputValidatorCallback - wifi_text_input_get_validator_callback(WIFI_TextInput* wifi_text_input) { - WIFI_TextInputValidatorCallback validator_callback = NULL; - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { validator_callback = model->validator_callback; }, - false); - return validator_callback; -} - -void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* wifi_text_input) { - void* validator_callback_context = NULL; - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { validator_callback_context = model->validator_callback_context; }, - false); - return validator_callback_context; -} - -void wifi_text_input_set_header_text(WIFI_TextInput* wifi_text_input, const char* text) { - with_view_model( - wifi_text_input->view, WIFI_TextInputModel * model, { model->header = text; }, true); -} diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.h b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.h deleted file mode 100644 index 5682106..0000000 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_text_input.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include -#include "wifi_marauder_validators.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Text input anonymous structure */ -typedef struct WIFI_TextInput WIFI_TextInput; -typedef void (*WIFI_TextInputCallback)(void* context); -typedef bool (*WIFI_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); - -/** Allocate and initialize text input - * - * This text input is used to enter string - * - * @return WIFI_TextInput instance - */ -WIFI_TextInput* wifi_text_input_alloc(); - -/** Deinitialize and free text input - * - * @param text_input WIFI_TextInput instance - */ -void wifi_text_input_free(WIFI_TextInput* text_input); - -/** Clean text input view Note: this function does not free memory - * - * @param text_input Text input instance - */ -void wifi_text_input_reset(WIFI_TextInput* text_input); - -/** Get text input view - * - * @param text_input WIFI_TextInput instance - * - * @return View instance that can be used for embedding - */ -View* wifi_text_input_get_view(WIFI_TextInput* text_input); - -/** Set text input result callback - * - * @param text_input WIFI_TextInput instance - * @param callback callback fn - * @param callback_context callback context - * @param text_buffer pointer to YOUR text buffer, that we going - * to modify - * @param text_buffer_size YOUR text buffer size in bytes. Max string - * length will be text_buffer_size-1. - * @param clear_default_text clear text from text_buffer on first OK - * event - */ -void wifi_text_input_set_result_callback( - WIFI_TextInput* text_input, - WIFI_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text); - -void wifi_text_input_set_validator( - WIFI_TextInput* text_input, - WIFI_TextInputValidatorCallback callback, - void* callback_context); - -void wifi_text_input_set_minimum_length(WIFI_TextInput* text_input, size_t minimum_length); - -WIFI_TextInputValidatorCallback wifi_text_input_get_validator_callback(WIFI_TextInput* text_input); - -void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* text_input); - -/** Set text input header text - * - * @param text_input WIFI_TextInput instance - * @param text text to be shown - */ -void wifi_text_input_set_header_text(WIFI_TextInput* text_input, const char* text); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.c b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.c index 77ad239..aded560 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.c +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.c @@ -1,15 +1,15 @@ #include "wifi_marauder_app_i.h" #include "wifi_marauder_uart.h" -#define UART_CH (FuriHalUartIdUSART1) -#define LP_UART_CH (FuriHalUartIdLPUART1) +#define UART_CH (FuriHalSerialIdUsart) +#define LP_UART_CH (FuriHalSerialIdLpuart) #define BAUDRATE (230400) struct WifiMarauderUart { WifiMarauderApp* app; - FuriHalUartId channel; FuriThread* rx_thread; FuriStreamBuffer* rx_stream; + FuriHalSerialHandle* serial_handle; uint8_t rx_buf[RX_BUF_SIZE + 1]; void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); }; @@ -28,15 +28,26 @@ void wifi_marauder_uart_set_handle_rx_data_cb( #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) -void wifi_marauder_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +void wifi_marauder_uart_on_irq_cb( + FuriHalSerialHandle* handle, + FuriHalSerialRxEvent event, + void* context) { WifiMarauderUart* uart = (WifiMarauderUart*)context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); } } +void workaround_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { + // For some reason furi_hal_serial enforces different callbacks for usart/lpuart + // The callbacks receive context and handle pointers, user callbacks can handle it + // API really should not be doing this, if it gets fixed then revert this commit + wifi_marauder_uart_on_irq_cb(handle, event, context); +} + static int32_t uart_worker(void* context) { WifiMarauderUart* uart = (void*)context; @@ -58,20 +69,17 @@ static int32_t uart_worker(void* context) { return 0; } -void wifi_marauder_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(UART_CH, data, len); -} - -void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(LP_UART_CH, data, len); +void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len) { + furi_hal_serial_tx(uart->serial_handle, data, len); } -WifiMarauderUart* - wifi_marauder_uart_init(WifiMarauderApp* app, FuriHalUartId channel, const char* thread_name) { +WifiMarauderUart* wifi_marauder_uart_init( + WifiMarauderApp* app, + FuriHalSerialId channel, + const char* thread_name) { WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart)); uart->app = app; - uart->channel = channel; uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); uart->rx_thread = furi_thread_alloc(); furi_thread_set_name(uart->rx_thread, thread_name); @@ -79,13 +87,17 @@ WifiMarauderUart* furi_thread_set_context(uart->rx_thread, uart); furi_thread_set_callback(uart->rx_thread, uart_worker); furi_thread_start(uart->rx_thread); - if(channel == FuriHalUartIdUSART1) { - furi_hal_console_disable(); - } else if(channel == FuriHalUartIdLPUART1) { - furi_hal_uart_init(channel, BAUDRATE); + uart->serial_handle = furi_hal_serial_control_acquire(channel); + if(!uart->serial_handle) { + furi_delay_ms(5000); } - furi_hal_uart_set_br(channel, BAUDRATE); - furi_hal_uart_set_irq_cb(channel, wifi_marauder_uart_on_irq_cb, uart); + furi_check(uart->serial_handle); + furi_hal_serial_init(uart->serial_handle, BAUDRATE); + furi_hal_serial_async_rx_start( + uart->serial_handle, + channel == FuriHalSerialIdUsart ? workaround_on_irq_cb : wifi_marauder_uart_on_irq_cb, + uart, + false); return uart; } @@ -101,15 +113,13 @@ WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app) { void wifi_marauder_uart_free(WifiMarauderUart* uart) { furi_assert(uart); + furi_hal_serial_async_rx_stop(uart->serial_handle); + furi_hal_serial_deinit(uart->serial_handle); + furi_hal_serial_control_release(uart->serial_handle); + furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); furi_thread_join(uart->rx_thread); furi_thread_free(uart->rx_thread); - furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL); - if(uart->channel == FuriHalUartIdLPUART1) { - furi_hal_uart_deinit(uart->channel); - } - furi_hal_console_enable(); - free(uart); } \ No newline at end of file diff --git a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.h b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.h index e352cfe..abb0134 100644 --- a/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.h +++ b/flipper_companion_apps/applications/external/esp32cam_marauder_companion/wifi_marauder_uart.h @@ -9,8 +9,7 @@ typedef struct WifiMarauderUart WifiMarauderUart; void wifi_marauder_uart_set_handle_rx_data_cb( WifiMarauderUart* uart, void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); -void wifi_marauder_uart_tx(uint8_t* data, size_t len); -void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len); +void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len); WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app); WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app); void wifi_marauder_uart_free(WifiMarauderUart* uart); diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/application.fam b/flipper_companion_apps/applications/external/esp32cam_morseflasher/application.fam index e8de408..7adbef3 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/application.fam @@ -1,6 +1,6 @@ App( appid="mayhem_morseflash", - name="[MAYHEM] Morse Flasher v0.1", + name="[MAYHEM] Morse Flash", apptype=FlipperAppType.EXTERNAL, entry_point="uart_terminal_app", cdefines=["APP_UART_TERMINAL"], @@ -9,6 +9,6 @@ App( order=90, fap_icon_assets="assets", fap_icon="icon.png", - fap_category="GPIO", + fap_category="GPIO/MAYHEM", fap_description="ESP32-CAM app to stream a message in morse using the powerful flashlight. [Unplug the USB cable to test with Mayhem]", ) diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_config.h b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_config.h index febdce1..5131080 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_config.h +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_config.h @@ -1,3 +1,3 @@ ADD_SCENE(uart_terminal, start, Start) ADD_SCENE(uart_terminal, console_output, ConsoleOutput) -ADD_SCENE(uart_terminal, text_input, UART_TextInput) +ADD_SCENE(uart_terminal, text_input, TextInput) diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_console_output.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_console_output.c index df3d202..d53c99b 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_console_output.c +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_console_output.c @@ -35,8 +35,9 @@ void uart_terminal_scene_console_output_on_enter(void* context) { furi_string_reset(app->text_box_store); app->text_box_store_strlen = 0; - // app->show_stopscan_tip in the if is just a hack to get the help displayed since there is no commands in this app - if(app->show_stopscan_tip || 0 == strncmp("help", app->selected_tx_string, strlen("help"))) { + // app->show_stopscan_tip in the if is just a hack to get the help displayed since there is no commands in this app + if(app->show_stopscan_tip || + 0 == strncmp("help", app->selected_tx_string, strlen("help"))) { const char* help_msg = "Morse Flasher for\nMayhem Fin\n\nBased on UART terminal by\ncool4uma, which is a\nmodified WiFi Marauder\ncompanion by 0xchocolate\n\n"; furi_string_cat_str(app->text_box_store, help_msg); @@ -63,8 +64,8 @@ void uart_terminal_scene_console_output_on_enter(void* context) { // Send command with newline '\n' /*if(!app->is_command && app->selected_tx_string)*/ { uart_terminal_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\n"), 1); + app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); + uart_terminal_uart_tx(app->uart, (uint8_t*)("\n"), 1); } } @@ -91,6 +92,6 @@ void uart_terminal_scene_console_output_on_exit(void* context) { // Automatically logut when exiting view //if(app->is_command) { - // uart_terminal_uart_tx((uint8_t*)("exit\n"), strlen("exit\n")); + // uart_terminal_uart_tx(app->uart,(uint8_t*)("exit\n"), strlen("exit\n")); //} } diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_start.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_start.c index 8d63828..a815b97 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_start.c +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_start.c @@ -27,7 +27,14 @@ const UART_TerminalItem items[NUM_MENU_ITEMS] = { {"Quick message", {"SOS", "CQD", "VVV", "Eureka", "E.T ph...", "what h...", "Mayhem", "Flipper"}, 8, - {"sos", "cqd", "vvv", "eureka", "e.t. phone home", "what hath god wrought!", "let the mayhem begin", "flipper zero in da housa"}, + {"sos", + "cqd", + "vvv", + "eureka", + "e.t. phone home", + "what hath god wrought!", + "let the mayhem begin", + "flipper zero in da housa"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_text_input.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_text_input.c index b3b4690..fd33aee 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_text_input.c +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/scenes/uart_terminal_scene_text_input.c @@ -23,10 +23,10 @@ void uart_terminal_scene_text_input_on_enter(void* context) { } // Setup view - UART_TextInput* text_input = app->text_input; + TextInput* text_input = app->text_input; // Add help message to header - uart_text_input_set_header_text(text_input, "Send new morse message"); - uart_text_input_set_result_callback( + text_input_set_header_text(text_input, "Send new morse message"); + text_input_set_result_callback( text_input, uart_terminal_scene_text_input_callback, app, @@ -34,6 +34,8 @@ void uart_terminal_scene_text_input_on_enter(void* context) { UART_TERMINAL_TEXT_INPUT_STORE_SIZE, false); + text_input_add_illegal_symbols(text_input); + view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewTextInput); } @@ -56,5 +58,5 @@ bool uart_terminal_scene_text_input_on_event(void* context, SceneManagerEvent ev void uart_terminal_scene_text_input_on_exit(void* context) { UART_TerminalApp* app = context; - uart_text_input_reset(app->text_input); + text_input_reset(app->text_input); } diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app.c index f339902..79fb0fd 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app.c +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app.c @@ -2,6 +2,7 @@ #include #include +#include static bool uart_terminal_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -56,9 +57,9 @@ UART_TerminalApp* uart_terminal_app_alloc() { app->text_box_store = furi_string_alloc(); furi_string_reserve(app->text_box_store, UART_TERMINAL_TEXT_BOX_STORE_SIZE); - app->text_input = uart_text_input_alloc(); + app->text_input = text_input_alloc(); view_dispatcher_add_view( - app->view_dispatcher, UART_TerminalAppViewTextInput, uart_text_input_get_view(app->text_input)); + app->view_dispatcher, UART_TerminalAppViewTextInput, text_input_get_view(app->text_input)); scene_manager_next_scene(app->scene_manager, UART_TerminalSceneStart); @@ -74,7 +75,7 @@ void uart_terminal_app_free(UART_TerminalApp* app) { view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewTextInput); text_box_free(app->text_box); furi_string_free(app->text_box_store); - uart_text_input_free(app->text_input); + text_input_free(app->text_input); // View dispatcher view_dispatcher_free(app->view_dispatcher); @@ -90,32 +91,35 @@ void uart_terminal_app_free(UART_TerminalApp* app) { int32_t uart_terminal_app(void* p) { UNUSED(p); - - // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(UART_CH, BAUDRATE); // TODO: Clean this - //furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); - + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + furi_hal_power_disable_external_3_3v(); furi_hal_power_disable_otg(); furi_delay_ms(200); furi_hal_power_enable_external_3_3v(); furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(UART_CH, (uint8_t[1]){'.'}, 1); - } - furi_delay_ms(1); UART_TerminalApp* uart_terminal_app = uart_terminal_app_alloc(); uart_terminal_app->uart = uart_terminal_uart_init(uart_terminal_app); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + uart_terminal_uart_tx(uart_terminal_app->uart, (uint8_t[1]){'.'}, 1); + } + furi_delay_ms(1); + view_dispatcher_run(uart_terminal_app->view_dispatcher); uart_terminal_app_free(uart_terminal_app); furi_hal_power_disable_otg(); - + + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app_i.h b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app_i.h index 88dce09..7f4978c 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app_i.h +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_app_i.h @@ -9,14 +9,14 @@ #include #include #include -#include "uart_text_input.h" +#include #include #define NUM_MENU_ITEMS (3) #define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096) #define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512) -#define UART_CH (FuriHalUartIdUSART1) +#define UART_CH (FuriHalSerialIdUsart) #define BAUDRATE (230400) struct UART_TerminalApp { @@ -28,7 +28,7 @@ struct UART_TerminalApp { FuriString* text_box_store; size_t text_box_store_strlen; TextBox* text_box; - UART_TextInput* text_input; + TextInput* text_input; VariableItemList* var_item_list; diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.c index 45bfe99..b4ce274 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.c +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.c @@ -7,6 +7,7 @@ struct UART_TerminalUart { FuriStreamBuffer* rx_stream; uint8_t rx_buf[RX_BUF_SIZE + 1]; void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); + FuriHalSerialHandle* serial_handle; }; typedef enum { @@ -23,10 +24,14 @@ void uart_terminal_uart_set_handle_rx_data_cb( #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) -void uart_terminal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +void uart_terminal_uart_on_irq_cb( + FuriHalSerialHandle* handle, + FuriHalSerialRxEvent event, + void* context) { UART_TerminalUart* uart = (UART_TerminalUart*)context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); } @@ -53,22 +58,15 @@ static int32_t uart_worker(void* context) { return 0; } -void uart_terminal_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(UART_CH, data, len); +void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len) { + furi_hal_serial_tx(uart->serial_handle, data, len); } UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) { UART_TerminalUart* uart = malloc(sizeof(UART_TerminalUart)); - - /*furi_hal_console_disable(); - if(app->BAUDRATE == 0) { - app->BAUDRATE = 230400; - } - furi_hal_uart_set_br(UART_CH, app->BAUDRATE); - furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart);*/ uart->app = app; - uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); + uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); uart->rx_thread = furi_thread_alloc(); furi_thread_set_name(uart->rx_thread, "UART_TerminalUartRxThread"); furi_thread_set_stack_size(uart->rx_thread, 1024); @@ -77,9 +75,10 @@ UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) { furi_thread_start(uart->rx_thread); - furi_hal_console_disable(); - furi_hal_uart_set_br(UART_CH, BAUDRATE); - furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart); + uart->serial_handle = furi_hal_serial_control_acquire(UART_CH); + furi_check(uart->serial_handle); + furi_hal_serial_init(uart->serial_handle, BAUDRATE); + furi_hal_serial_async_rx_start(uart->serial_handle, uart_terminal_uart_on_irq_cb, uart, false); return uart; } @@ -87,12 +86,13 @@ UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) { void uart_terminal_uart_free(UART_TerminalUart* uart) { furi_assert(uart); + furi_hal_serial_async_rx_stop(uart->serial_handle); + furi_hal_serial_deinit(uart->serial_handle); + furi_hal_serial_control_release(uart->serial_handle); + furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); furi_thread_join(uart->rx_thread); furi_thread_free(uart->rx_thread); - furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL); - furi_hal_console_enable(); - free(uart); } \ No newline at end of file diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.h b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.h index ca95c92..1d2ee11 100644 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.h +++ b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_terminal_uart.h @@ -9,6 +9,6 @@ typedef struct UART_TerminalUart UART_TerminalUart; void uart_terminal_uart_set_handle_rx_data_cb( UART_TerminalUart* uart, void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); -void uart_terminal_uart_tx(uint8_t* data, size_t len); +void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len); UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app); void uart_terminal_uart_free(UART_TerminalUart* uart); diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.c b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.c deleted file mode 100644 index a52e1aa..0000000 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.c +++ /dev/null @@ -1,637 +0,0 @@ -#include "uart_text_input.h" -#include -#include "mayhem_morseflash_icons.h" -#include - -struct UART_TextInput { - View* view; - FuriTimer* timer; -}; - -typedef struct { - const char text; - const uint8_t x; - const uint8_t y; -} UART_TextInputKey; - -typedef struct { - const char* header; - char* text_buffer; - size_t text_buffer_size; - bool clear_default_text; - - UART_TextInputCallback callback; - void* callback_context; - - uint8_t selected_row; - uint8_t selected_column; - - UART_TextInputValidatorCallback validator_callback; - void* validator_callback_context; - FuriString* validator_text; - bool valadator_message_visible; -} UART_TextInputModel; - -static const uint8_t keyboard_origin_x = 1; -static const uint8_t keyboard_origin_y = 29; -static const uint8_t keyboard_row_count = 4; - -#define ENTER_KEY '\r' -#define BACKSPACE_KEY '\b' - -static const UART_TextInputKey keyboard_keys_row_1[] = { - {'{', 1, 0}, - {'(', 9, 0}, - {'[', 17, 0}, - {'|', 25, 0}, - {'@', 33, 0}, - {'&', 41, 0}, - {'#', 49, 0}, - {';', 57, 0}, - {'^', 65, 0}, - {'*', 73, 0}, - {'`', 81, 0}, - {'"', 89, 0}, - {'~', 97, 0}, - {'\'', 105, 0}, - {'.', 113, 0}, - {'/', 120, 0}, -}; - -static const UART_TextInputKey keyboard_keys_row_2[] = { - {'q', 1, 10}, - {'w', 9, 10}, - {'e', 17, 10}, - {'r', 25, 10}, - {'t', 33, 10}, - {'y', 41, 10}, - {'u', 49, 10}, - {'i', 57, 10}, - {'o', 65, 10}, - {'p', 73, 10}, - {'0', 81, 10}, - {'1', 89, 10}, - {'2', 97, 10}, - {'3', 105, 10}, - {'=', 113, 10}, - {'-', 120, 10}, -}; - -static const UART_TextInputKey keyboard_keys_row_3[] = { - {'a', 1, 21}, - {'s', 9, 21}, - {'d', 18, 21}, - {'f', 25, 21}, - {'g', 33, 21}, - {'h', 41, 21}, - {'j', 49, 21}, - {'k', 57, 21}, - {'l', 65, 21}, - {BACKSPACE_KEY, 72, 13}, - {'4', 89, 21}, - {'5', 97, 21}, - {'6', 105, 21}, - {'$', 113, 21}, - {'%', 120, 21}, - -}; - -static const UART_TextInputKey keyboard_keys_row_4[] = { - {'z', 1, 33}, - {'x', 9, 33}, - {'c', 18, 33}, - {'v', 25, 33}, - {'b', 33, 33}, - {'n', 41, 33}, - {'m', 49, 33}, - {'_', 57, 33}, - {ENTER_KEY, 64, 24}, - {'7', 89, 33}, - {'8', 97, 33}, - {'9', 105, 33}, - {'!', 113, 33}, - {'+', 120, 33}, -}; - -static uint8_t get_row_size(uint8_t row_index) { - uint8_t row_size = 0; - - switch(row_index + 1) { - case 1: - row_size = sizeof(keyboard_keys_row_1) / sizeof(UART_TextInputKey); - break; - case 2: - row_size = sizeof(keyboard_keys_row_2) / sizeof(UART_TextInputKey); - break; - case 3: - row_size = sizeof(keyboard_keys_row_3) / sizeof(UART_TextInputKey); - break; - case 4: - row_size = sizeof(keyboard_keys_row_4) / sizeof(UART_TextInputKey); - break; - } - - return row_size; -} - -static const UART_TextInputKey* get_row(uint8_t row_index) { - const UART_TextInputKey* row = NULL; - - switch(row_index + 1) { - case 1: - row = keyboard_keys_row_1; - break; - case 2: - row = keyboard_keys_row_2; - break; - case 3: - row = keyboard_keys_row_3; - break; - case 4: - row = keyboard_keys_row_4; - break; - } - - return row; -} - -static char get_selected_char(UART_TextInputModel* model) { - return get_row(model->selected_row)[model->selected_column].text; -} - -static bool char_is_lowercase(char letter) { - return (letter >= 0x61 && letter <= 0x7A); -} - -static char char_to_uppercase(const char letter) { - switch(letter) { - case '_': - return 0x20; - break; - case '(': - return 0x29; - break; - case '{': - return 0x7d; - break; - case '[': - return 0x5d; - break; - case '/': - return 0x5c; - break; - case ';': - return 0x3a; - break; - case '.': - return 0x2c; - break; - case '!': - return 0x3f; - break; - case '<': - return 0x3e; - break; - } - if(isalpha(letter)) { - return (letter - 0x20); - } else { - return letter; - } -} - -static void uart_text_input_backspace_cb(UART_TextInputModel* model) { - uint8_t text_length = model->clear_default_text ? 1 : strlen(model->text_buffer); - if(text_length > 0) { - model->text_buffer[text_length - 1] = 0; - } -} - -static void uart_text_input_view_draw_callback(Canvas* canvas, void* _model) { - UART_TextInputModel* model = _model; - uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; - uint8_t needed_string_width = canvas_width(canvas) - 8; - uint8_t start_pos = 4; - - const char* text = model->text_buffer; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_str(canvas, 2, 7, model->header); - elements_slightly_rounded_frame(canvas, 1, 8, 126, 12); - - if(canvas_string_width(canvas, text) > needed_string_width) { - canvas_draw_str(canvas, start_pos, 17, "..."); - start_pos += 6; - needed_string_width -= 8; - } - - while(text != 0 && canvas_string_width(canvas, text) > needed_string_width) { - text++; - } - - if(model->clear_default_text) { - elements_slightly_rounded_box( - canvas, start_pos - 1, 14, canvas_string_width(canvas, text) + 2, 10); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 18, "|"); - canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 18, "|"); - } - canvas_draw_str(canvas, start_pos, 17, text); - - canvas_set_font(canvas, FontKeyboard); - - for(uint8_t row = 0; row <= keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(row); - const UART_TextInputKey* keys = get_row(row); - - for(size_t column = 0; column < column_count; column++) { - if(keys[column].text == ENTER_KEY) { - canvas_set_color(canvas, ColorBlack); - if(model->selected_row == row && model->selected_column == column) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeySaveSelected_24x11); - } else { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeySave_24x11); - } - } else if(keys[column].text == BACKSPACE_KEY) { - canvas_set_color(canvas, ColorBlack); - if(model->selected_row == row && model->selected_column == column) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeyBackspaceSelected_16x9); - } else { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeyBackspace_16x9); - } - } else { - if(model->selected_row == row && model->selected_column == column) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box( - canvas, - keyboard_origin_x + keys[column].x - 1, - keyboard_origin_y + keys[column].y - 8, - 7, - 10); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - - if(model->clear_default_text || - (text_length == 0 && char_is_lowercase(keys[column].text))) { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - //char_to_uppercase(keys[column].text)); - keys[column].text); - } else { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - keys[column].text); - } - } - } - } - if(model->valadator_message_visible) { - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 8, 10, 110, 48); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); - canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); - canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); - canvas_set_font(canvas, FontKeyboard); - } -} - -static void - uart_text_input_handle_up(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_row > 0) { - model->selected_row--; - if(model->selected_column > get_row_size(model->selected_row) - 6) { - model->selected_column = model->selected_column + 1; - } - } -} - -static void - uart_text_input_handle_down(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_row < keyboard_row_count - 1) { - model->selected_row++; - if(model->selected_column > get_row_size(model->selected_row) - 4) { - model->selected_column = model->selected_column - 1; - } - } -} - -static void - uart_text_input_handle_left(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_column > 0) { - model->selected_column--; - } else { - model->selected_column = get_row_size(model->selected_row) - 1; - } -} - -static void - uart_text_input_handle_right(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_column < get_row_size(model->selected_row) - 1) { - model->selected_column++; - } else { - model->selected_column = 0; - } -} - -static void uart_text_input_handle_ok( - UART_TextInput* uart_text_input, - UART_TextInputModel* model, - bool shift) { - char selected = get_selected_char(model); - uint8_t text_length = strlen(model->text_buffer); - - if(shift) { - selected = char_to_uppercase(selected); - } - - if(selected == ENTER_KEY) { - if(model->validator_callback && - (!model->validator_callback( - model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->valadator_message_visible = true; - furi_timer_start(uart_text_input->timer, furi_kernel_get_tick_frequency() * 4); - } else if(model->callback != 0 && text_length > 0) { - model->callback(model->callback_context); - } - } else if(selected == BACKSPACE_KEY) { - uart_text_input_backspace_cb(model); - } else { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - if(text_length == 0 && char_is_lowercase(selected)) { - //selected = char_to_uppercase(selected); - } - model->text_buffer[text_length] = selected; - model->text_buffer[text_length + 1] = 0; - } - } - model->clear_default_text = false; -} - -static bool uart_text_input_view_input_callback(InputEvent* event, void* context) { - UART_TextInput* uart_text_input = context; - furi_assert(uart_text_input); - - bool consumed = false; - - // Acquire model - UART_TextInputModel* model = view_get_model(uart_text_input->view); - - if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->valadator_message_visible) { - model->valadator_message_visible = false; - consumed = true; - } else if(event->type == InputTypeShort) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyOk: - uart_text_input_handle_ok(uart_text_input, model, false); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeLong) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyOk: - uart_text_input_handle_ok(uart_text_input, model, true); - break; - case InputKeyBack: - uart_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeRepeat) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyBack: - uart_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } - - // Commit model - view_commit_model(uart_text_input->view, consumed); - - return consumed; -} - -void uart_text_input_timer_callback(void* context) { - furi_assert(context); - UART_TextInput* uart_text_input = context; - - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { model->valadator_message_visible = false; }, - true); -} - -UART_TextInput* uart_text_input_alloc() { - UART_TextInput* uart_text_input = malloc(sizeof(UART_TextInput)); - uart_text_input->view = view_alloc(); - view_set_context(uart_text_input->view, uart_text_input); - view_allocate_model(uart_text_input->view, ViewModelTypeLocking, sizeof(UART_TextInputModel)); - view_set_draw_callback(uart_text_input->view, uart_text_input_view_draw_callback); - view_set_input_callback(uart_text_input->view, uart_text_input_view_input_callback); - - uart_text_input->timer = - furi_timer_alloc(uart_text_input_timer_callback, FuriTimerTypeOnce, uart_text_input); - - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { model->validator_text = furi_string_alloc(); }, - false); - - uart_text_input_reset(uart_text_input); - - return uart_text_input; -} - -void uart_text_input_free(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { furi_string_free(model->validator_text); }, - false); - - // Send stop command - furi_timer_stop(uart_text_input->timer); - // Release allocated memory - furi_timer_free(uart_text_input->timer); - - view_free(uart_text_input->view); - - free(uart_text_input); -} - -void uart_text_input_reset(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->text_buffer_size = 0; - model->header = ""; - model->selected_row = 0; - model->selected_column = 0; - model->clear_default_text = false; - model->text_buffer = NULL; - model->text_buffer_size = 0; - model->callback = NULL; - model->callback_context = NULL; - model->validator_callback = NULL; - model->validator_callback_context = NULL; - furi_string_reset(model->validator_text); - model->valadator_message_visible = false; - }, - true); -} - -View* uart_text_input_get_view(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - return uart_text_input->view; -} - -void uart_text_input_set_result_callback( - UART_TextInput* uart_text_input, - UART_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text) { - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->callback = callback; - model->callback_context = callback_context; - model->text_buffer = text_buffer; - model->text_buffer_size = text_buffer_size; - model->clear_default_text = clear_default_text; - if(text_buffer && text_buffer[0] != '\0') { - // Set focus on Save - model->selected_row = 2; - model->selected_column = 8; - } - }, - true); -} - -void uart_text_input_set_validator( - UART_TextInput* uart_text_input, - UART_TextInputValidatorCallback callback, - void* callback_context) { - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->validator_callback = callback; - model->validator_callback_context = callback_context; - }, - true); -} - -UART_TextInputValidatorCallback - uart_text_input_get_validator_callback(UART_TextInput* uart_text_input) { - UART_TextInputValidatorCallback validator_callback = NULL; - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { validator_callback = model->validator_callback; }, - false); - return validator_callback; -} - -void* uart_text_input_get_validator_callback_context(UART_TextInput* uart_text_input) { - void* validator_callback_context = NULL; - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { validator_callback_context = model->validator_callback_context; }, - false); - return validator_callback_context; -} - -void uart_text_input_set_header_text(UART_TextInput* uart_text_input, const char* text) { - with_view_model( - uart_text_input->view, UART_TextInputModel * model, { model->header = text; }, true); -} diff --git a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.h b/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.h deleted file mode 100644 index 5e4e36d..0000000 --- a/flipper_companion_apps/applications/external/esp32cam_morseflasher/uart_text_input.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include "uart_validators.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Text input anonymous structure */ -typedef struct UART_TextInput UART_TextInput; -typedef void (*UART_TextInputCallback)(void* context); -typedef bool (*UART_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); - -/** Allocate and initialize text input - * - * This text input is used to enter string - * - * @return UART_TextInput instance - */ -UART_TextInput* uart_text_input_alloc(); - -/** Deinitialize and free text input - * - * @param uart_text_input UART_TextInput instance - */ -void uart_text_input_free(UART_TextInput* uart_text_input); - -/** Clean text input view Note: this function does not free memory - * - * @param uart_text_input Text input instance - */ -void uart_text_input_reset(UART_TextInput* uart_text_input); - -/** Get text input view - * - * @param uart_text_input UART_TextInput instance - * - * @return View instance that can be used for embedding - */ -View* uart_text_input_get_view(UART_TextInput* uart_text_input); - -/** Set text input result callback - * - * @param uart_text_input UART_TextInput instance - * @param callback callback fn - * @param callback_context callback context - * @param text_buffer pointer to YOUR text buffer, that we going - * to modify - * @param text_buffer_size YOUR text buffer size in bytes. Max string - * length will be text_buffer_size-1. - * @param clear_default_text clear text from text_buffer on first OK - * event - */ -void uart_text_input_set_result_callback( - UART_TextInput* uart_text_input, - UART_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text); - -void uart_text_input_set_validator( - UART_TextInput* uart_text_input, - UART_TextInputValidatorCallback callback, - void* callback_context); - -UART_TextInputValidatorCallback - uart_text_input_get_validator_callback(UART_TextInput* uart_text_input); - -void* uart_text_input_get_validator_callback_context(UART_TextInput* uart_text_input); - -/** Set text input header text - * - * @param uart_text_input UART_TextInput instance - * @param text text to be shown - */ -void uart_text_input_set_header_text(UART_TextInput* uart_text_input, const char* text); - -#ifdef __cplusplus -} -#endif diff --git a/flipper_companion_apps/applications/external/esp32cam_motion_detection/application.fam b/flipper_companion_apps/applications/external/esp32cam_motion_detection/application.fam index b7273f6..840ee8f 100644 --- a/flipper_companion_apps/applications/external/esp32cam_motion_detection/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_motion_detection/application.fam @@ -1,15 +1,15 @@ App( appid="mayhem_motion", - name="[MAYHEM] Motion detection v0.1", + name="[MAYHEM] Motion detection", apptype=FlipperAppType.EXTERNAL, entry_point="uart_echo_app", cdefines=["APP_QRCODE"], requires=["gui"], - stack_size=8*1024, + stack_size=8 * 1024, order=1, - fap_icon="icon.png", - fap_category="GPIO", - fap_description="ESP32-CAM Motion detection. It generates a beep when motion is detected. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", - fap_author="eried", - fap_weburl="https://flipper.ried.cl" -) \ No newline at end of file + fap_icon="icon.png", + fap_category="GPIO/MAYHEM", + fap_description="ESP32-CAM Motion detection. It generates a beep when motion is detected. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", + fap_author="eried", + fap_weburl="https://flipper.ried.cl", +) diff --git a/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.c b/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.c index e1b5bcb..a8c6a8d 100644 --- a/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.c +++ b/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.c @@ -1,5 +1,7 @@ #include "uart_echo.h" +#include + static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { UartDumpModel* model = _model; @@ -40,11 +42,13 @@ static uint32_t uart_echo_exit(void* context) { return VIEW_NONE; } -static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +static void + uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { furi_assert(context); UartEchoApp* app = context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(app->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); } @@ -52,7 +56,7 @@ static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { static void uart_echo_push_to_list(UartDumpModel* model, void* context, const char data) { // Alarm sound - if(data == '!'){ + if(data == '!') { UartEchoApp* app = context; notification_message(app->notification, &sequence_alarm); } @@ -114,7 +118,7 @@ static int32_t uart_echo_worker(void* context) { uint8_t data[64]; length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0); if(length > 0 && app->initialized) { - furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); + furi_hal_serial_tx(app->serial_handle, data, length); with_view_model( app->view, UartDumpModel * model, @@ -176,19 +180,19 @@ static UartEchoApp* uart_echo_app_alloc() { furi_thread_start(app->worker_thread); // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); + app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart); + furi_check(app->serial_handle); + furi_hal_serial_init(app->serial_handle, 230400); + furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false); furi_hal_power_disable_external_3_3v(); furi_hal_power_disable_otg(); furi_delay_ms(200); furi_hal_power_enable_external_3_3v(); furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'m'}, 1); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'m'}, 1); } furi_delay_ms(1); app->initialized = true; @@ -198,7 +202,9 @@ static UartEchoApp* uart_echo_app_alloc() { static void uart_echo_app_free(UartEchoApp* app) { furi_assert(app); - furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced + furi_hal_serial_async_rx_stop(app->serial_handle); + furi_hal_serial_deinit(app->serial_handle); + furi_hal_serial_control_release(app->serial_handle); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); @@ -233,9 +239,19 @@ static void uart_echo_app_free(UartEchoApp* app) { int32_t uart_echo_app(void* p) { UNUSED(p); + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + UartEchoApp* app = uart_echo_app_alloc(); view_dispatcher_run(app->view_dispatcher); uart_echo_app_free(app); furi_hal_power_disable_otg(); + + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.h b/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.h index 70ed18a..30e6547 100644 --- a/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.h +++ b/flipper_companion_apps/applications/external/esp32cam_motion_detection/uart_echo.h @@ -4,8 +4,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -38,6 +38,7 @@ typedef struct { View* view; FuriThread* worker_thread; FuriStreamBuffer* rx_stream; + FuriHalSerialHandle* serial_handle; bool initialized; } UartEchoApp; diff --git a/flipper_companion_apps/applications/external/esp32cam_nannycam/application.fam b/flipper_companion_apps/applications/external/esp32cam_nannycam/application.fam index 1282b6a..177e4f0 100644 --- a/flipper_companion_apps/applications/external/esp32cam_nannycam/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_nannycam/application.fam @@ -1,15 +1,15 @@ App( appid="mayhem_nannycam", - name="[MAYHEM] Nanny Cam v0.1", + name="[MAYHEM] Nanny Cam", apptype=FlipperAppType.EXTERNAL, entry_point="uart_echo_app", cdefines=["APP_QRCODE"], requires=["gui"], - stack_size=8*1024, + stack_size=8 * 1024, order=1, - fap_icon="icon.png", - fap_category="GPIO", - fap_description="ESP32-CAM simple app to start a remote camera. [Unplug the USB cable to test with Mayhem]", - fap_author="eried", - fap_weburl="https://flipper.ried.cl" -) \ No newline at end of file + fap_icon="icon.png", + fap_category="GPIO/MAYHEM", + fap_description="ESP32-CAM simple app to start a remote camera. [Unplug the USB cable to test with Mayhem]", + fap_author="eried", + fap_weburl="https://flipper.ried.cl", +) diff --git a/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.c b/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.c index 8a59d38..777153a 100644 --- a/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.c +++ b/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.c @@ -1,5 +1,7 @@ #include "uart_echo.h" +#include + static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { UartDumpModel* model = _model; @@ -40,11 +42,13 @@ static uint32_t uart_echo_exit(void* context) { return VIEW_NONE; } -static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +static void + uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { furi_assert(context); UartEchoApp* app = context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(app->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); } @@ -108,7 +112,7 @@ static int32_t uart_echo_worker(void* context) { uint8_t data[64]; length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0); if(length > 0 && app->initialized) { - furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); + furi_hal_serial_tx(app->serial_handle, data, length); with_view_model( app->view, UartDumpModel * model, @@ -170,19 +174,19 @@ static UartEchoApp* uart_echo_app_alloc() { furi_thread_start(app->worker_thread); // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); + app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart); + furi_check(app->serial_handle); + furi_hal_serial_init(app->serial_handle, 230400); + furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false); furi_hal_power_disable_external_3_3v(); furi_hal_power_disable_otg(); furi_delay_ms(200); furi_hal_power_enable_external_3_3v(); furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'n'}, 1); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'n'}, 1); } furi_delay_ms(1); app->initialized = true; @@ -192,7 +196,9 @@ static UartEchoApp* uart_echo_app_alloc() { static void uart_echo_app_free(UartEchoApp* app) { furi_assert(app); - furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced + furi_hal_serial_async_rx_stop(app->serial_handle); + furi_hal_serial_deinit(app->serial_handle); + furi_hal_serial_control_release(app->serial_handle); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); @@ -227,9 +233,19 @@ static void uart_echo_app_free(UartEchoApp* app) { int32_t uart_echo_app(void* p) { UNUSED(p); + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + UartEchoApp* app = uart_echo_app_alloc(); view_dispatcher_run(app->view_dispatcher); uart_echo_app_free(app); furi_hal_power_disable_otg(); + + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.h b/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.h index 98eefd0..d78be86 100644 --- a/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.h +++ b/flipper_companion_apps/applications/external/esp32cam_nannycam/uart_echo.h @@ -4,8 +4,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -21,6 +21,7 @@ typedef struct { View* view; FuriThread* worker_thread; FuriStreamBuffer* rx_stream; + FuriHalSerialHandle* serial_handle; bool initialized; } UartEchoApp; diff --git a/flipper_companion_apps/applications/external/esp32cam_qrcode/application.fam b/flipper_companion_apps/applications/external/esp32cam_qrcode/application.fam index 473b363..e2faf73 100644 --- a/flipper_companion_apps/applications/external/esp32cam_qrcode/application.fam +++ b/flipper_companion_apps/applications/external/esp32cam_qrcode/application.fam @@ -1,15 +1,15 @@ App( appid="mayhem_qrcode", - name="[MAYHEM] QR Code v0.1", + name="[MAYHEM] QR Code", apptype=FlipperAppType.EXTERNAL, entry_point="uart_echo_app", cdefines=["APP_QRCODE"], requires=["gui"], - stack_size=8*1024, + stack_size=8 * 1024, order=1, - fap_icon="icon.png", - fap_category="GPIO", - fap_description="ESP32-CAM simple app to show a payload from QR codes. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", - fap_author="eried", - fap_weburl="https://flipper.ried.cl" -) \ No newline at end of file + fap_icon="icon.png", + fap_category="GPIO/MAYHEM", + fap_description="ESP32-CAM simple app to show a payload from QR codes. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", + fap_author="eried", + fap_weburl="https://flipper.ried.cl", +) diff --git a/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.c b/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.c index 3514a4d..19f2f5c 100644 --- a/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.c +++ b/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.c @@ -1,5 +1,7 @@ #include "uart_echo.h" +#include + static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { UartDumpModel* model = _model; @@ -40,11 +42,13 @@ static uint32_t uart_echo_exit(void* context) { return VIEW_NONE; } -static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +static void + uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { furi_assert(context); UartEchoApp* app = context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(app->rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); } @@ -108,7 +112,7 @@ static int32_t uart_echo_worker(void* context) { uint8_t data[64]; length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0); if(length > 0 && app->initialized) { - furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); + furi_hal_serial_tx(app->serial_handle, data, length); with_view_model( app->view, UartDumpModel * model, @@ -170,19 +174,19 @@ static UartEchoApp* uart_echo_app_alloc() { furi_thread_start(app->worker_thread); // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); + app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart); + furi_check(app->serial_handle); + furi_hal_serial_init(app->serial_handle, 230400); + furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false); furi_hal_power_disable_external_3_3v(); furi_hal_power_disable_otg(); furi_delay_ms(200); furi_hal_power_enable_external_3_3v(); furi_hal_power_enable_otg(); - for(int i=0;i<2;i++) - { - furi_delay_ms(500); - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'q'}, 1); + for(int i = 0; i < 2; i++) { + furi_delay_ms(500); + furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'q'}, 1); } furi_delay_ms(1); app->initialized = true; @@ -192,7 +196,9 @@ static UartEchoApp* uart_echo_app_alloc() { static void uart_echo_app_free(UartEchoApp* app) { furi_assert(app); - furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced + furi_hal_serial_async_rx_stop(app->serial_handle); + furi_hal_serial_deinit(app->serial_handle); + furi_hal_serial_control_release(app->serial_handle); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); @@ -227,9 +233,19 @@ static void uart_echo_app_free(UartEchoApp* app) { int32_t uart_echo_app(void* p) { UNUSED(p); + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + UartEchoApp* app = uart_echo_app_alloc(); view_dispatcher_run(app->view_dispatcher); uart_echo_app_free(app); furi_hal_power_disable_otg(); + + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.h b/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.h index e68ba32..d52c284 100644 --- a/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.h +++ b/flipper_companion_apps/applications/external/esp32cam_qrcode/uart_echo.h @@ -4,8 +4,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -21,6 +21,7 @@ typedef struct { View* view; FuriThread* worker_thread; FuriStreamBuffer* rx_stream; + FuriHalSerialHandle* serial_handle; bool initialized; } UartEchoApp;