Update from apps repo

This commit is contained in:
Willy-JL
2023-11-20 00:15:14 +00:00
parent 91368a4538
commit e22fa80abe
22 changed files with 224 additions and 133 deletions

View File

@@ -7,7 +7,7 @@ App(
fap_category="GPIO", fap_category="GPIO",
fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.", fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.",
fap_icon="icons/camera_suite.png", fap_icon="icons/camera_suite.png",
fap_version="1.3", fap_version="1.4",
fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam", fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam",
name="[ESP32] Camera Suite", name="[ESP32] Camera Suite",
order=1, order=1,

View File

@@ -1,10 +1,5 @@
#pragma once #pragma once
#include "helpers/camera_suite_storage.h"
#include "scenes/camera_suite_scene.h"
#include "views/camera_suite_view_guide.h"
#include "views/camera_suite_view_start.h"
#include "views/camera_suite_view_camera.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <gui/gui.h> #include <gui/gui.h>
@@ -17,6 +12,12 @@
#include <notification/notification_messages.h> #include <notification/notification_messages.h>
#include <stdlib.h> #include <stdlib.h>
#include "scenes/camera_suite_scene.h"
#include "views/camera_suite_view_guide.h"
#include "views/camera_suite_view_start.h"
#include "views/camera_suite_view_camera.h"
#include "helpers/camera_suite_storage.h"
#define TAG "Camera Suite" #define TAG "Camera Suite"
typedef struct { typedef struct {

View File

@@ -60,7 +60,7 @@ static void camera_suite_view_camera_draw(Canvas* canvas, void* model) {
} }
// Draw the guide if the camera is not initialized. // Draw the guide if the camera is not initialized.
if(!uartDumpModel->initialized) { if(!uartDumpModel->is_initialized) {
canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48); canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 8, 12, "Connect the ESP32-CAM"); canvas_draw_str(canvas, 8, 12, "Connect the ESP32-CAM");
@@ -71,7 +71,7 @@ static void camera_suite_view_camera_draw(Canvas* canvas, void* model) {
} }
} }
static void save_image(void* model) { static void save_image_to_flipper_sd_card(void* model) {
furi_assert(model); furi_assert(model);
UartDumpModel* uartDumpModel = model; UartDumpModel* uartDumpModel = model;
@@ -116,7 +116,7 @@ static void save_image(void* model) {
// Free the file name after use. // Free the file name after use.
furi_string_free(file_name); furi_string_free(file_name);
if(!uartDumpModel->inverted) { if(!uartDumpModel->is_inverted) {
for(size_t i = 0; i < FRAME_BUFFER_LENGTH; ++i) { for(size_t i = 0; i < FRAME_BUFFER_LENGTH; ++i) {
uartDumpModel->pixels[i] = ~uartDumpModel->pixels[i]; uartDumpModel->pixels[i] = ~uartDumpModel->pixels[i];
} }
@@ -155,14 +155,14 @@ static void
furi_assert(model); furi_assert(model);
furi_assert(instance_context); furi_assert(instance_context);
model->is_dithering_enabled = true;
model->is_inverted = false;
uint32_t orientation = instance_context->orientation;
model->orientation = orientation;
for(size_t i = 0; i < FRAME_BUFFER_LENGTH; i++) { for(size_t i = 0; i < FRAME_BUFFER_LENGTH; i++) {
model->pixels[i] = 0; model->pixels[i] = 0;
} }
uint32_t orientation = instance_context->orientation;
model->flash = instance_context->flash;
model->inverted = false;
model->orientation = orientation;
} }
static bool camera_suite_view_camera_input(InputEvent* event, void* context) { static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
@@ -187,157 +187,156 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
break; break;
} }
} else if(event->type == InputTypePress) { } else if(event->type == InputTypePress) {
uint8_t data[1] = {'X'};
switch(event->key) { switch(event->key) {
// Camera: Stop stream.
case InputKeyBack: { case InputKeyBack: {
// Set the camera flash to off.
uint8_t flash_off = 'f';
furi_hal_uart_tx(UART_CH, &flash_off, 1);
furi_delay_ms(50);
// Stop camera stream.
uint8_t stop_camera = 's';
furi_hal_uart_tx(UART_CH, &stop_camera, 1);
// Go back to the main menu.
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
UNUSED(model); UNUSED(model);
// Stop camera stream.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'s'}, 1);
furi_delay_ms(50);
// Go back to the main menu.
instance->callback(CameraSuiteCustomEventSceneCameraBack, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraBack, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Toggle invert on the ESP32-CAM.
case InputKeyLeft: { case InputKeyLeft: {
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
UNUSED(model); // Play sound.
camera_suite_play_happy_bump(instance->context); camera_suite_play_happy_bump(instance->context);
camera_suite_play_input_sound(instance->context); camera_suite_play_input_sound(instance->context);
camera_suite_led_set_rgb(instance->context, 0, 0, 255); camera_suite_led_set_rgb(instance->context, 0, 0, 255);
if(model->inverted) {
data[0] = 'i'; if(model->is_inverted) {
model->inverted = false; // Camera: Set invert to false on the ESP32-CAM.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'i'}, 1);
furi_delay_ms(50);
model->is_inverted = false;
} else { } else {
data[0] = 'I'; // Camera: Set invert to true on the ESP32-CAM.
model->inverted = true; furi_hal_uart_tx(UART_CH, (uint8_t[]){'I'}, 1);
furi_delay_ms(50);
model->is_inverted = true;
} }
instance->callback(CameraSuiteCustomEventSceneCameraLeft, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraLeft, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Enable/disable dithering.
case InputKeyRight: { case InputKeyRight: {
data[0] = '>';
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
UNUSED(model); // Play sound.
camera_suite_play_happy_bump(instance->context); camera_suite_play_happy_bump(instance->context);
camera_suite_play_input_sound(instance->context); camera_suite_play_input_sound(instance->context);
camera_suite_led_set_rgb(instance->context, 0, 0, 255); camera_suite_led_set_rgb(instance->context, 0, 0, 255);
if(model->is_dithering_enabled) {
// Camera: Disable dithering.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'d'}, 1);
furi_delay_ms(50);
model->is_dithering_enabled = false;
} else {
// Camera: Enable dithering.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'D'}, 1);
furi_delay_ms(50);
model->is_dithering_enabled = true;
}
instance->callback(CameraSuiteCustomEventSceneCameraRight, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraRight, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Increase contrast.
case InputKeyUp: { case InputKeyUp: {
data[0] = 'C';
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
UNUSED(model); UNUSED(model);
// Play sound.
camera_suite_play_happy_bump(instance->context); camera_suite_play_happy_bump(instance->context);
camera_suite_play_input_sound(instance->context); camera_suite_play_input_sound(instance->context);
camera_suite_led_set_rgb(instance->context, 0, 0, 255); camera_suite_led_set_rgb(instance->context, 0, 0, 255);
// Camera: Increase contrast.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'C'}, 1);
furi_delay_ms(50);
instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Reduce contrast.
case InputKeyDown: { case InputKeyDown: {
data[0] = 'c';
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
UNUSED(model); UNUSED(model);
// Play sound.
camera_suite_play_happy_bump(instance->context); camera_suite_play_happy_bump(instance->context);
camera_suite_play_input_sound(instance->context); camera_suite_play_input_sound(instance->context);
camera_suite_led_set_rgb(instance->context, 0, 0, 255); camera_suite_led_set_rgb(instance->context, 0, 0, 255);
// Camera: Reduce contrast.
furi_hal_uart_tx(UART_CH, (uint8_t[]){'c'}, 1);
furi_delay_ms(50);
instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Take picture.
case InputKeyOk: { case InputKeyOk: {
with_view_model( with_view_model(
instance->view, instance->view,
UartDumpModel * model, UartDumpModel * model,
{ {
// Play sound.
camera_suite_play_long_bump(instance->context); camera_suite_play_long_bump(instance->context);
camera_suite_play_input_sound(instance->context); camera_suite_play_input_sound(instance->context);
camera_suite_led_set_rgb(instance->context, 0, 0, 255); camera_suite_led_set_rgb(instance->context, 0, 0, 255);
// Save picture directly to ESP32-CAM. // @todo - Save picture directly to ESP32-CAM.
// @todo - Add this functionality. // furi_hal_uart_tx(UART_CH, (uint8_t[]){'P'}, 1);
// data[0] = 'P';
// furi_hal_uart_tx(UART_CH, data, 1);
// if(model->flash) { // Save currently displayed image to the Flipper Zero SD card.
// data[0] = 'F'; save_image_to_flipper_sd_card(model);
// furi_hal_uart_tx(UART_CH, data, 1);
// furi_delay_ms(50);
// }
// Take a picture.
save_image(model);
// if(model->flash) {
// data[0] = 'f';
// }
instance->callback(CameraSuiteCustomEventSceneCameraOk, instance->context); instance->callback(CameraSuiteCustomEventSceneCameraOk, instance->context);
}, },
true); true);
break; break;
} }
// Camera: Do nothing.
case InputKeyMAX: case InputKeyMAX:
default: { default: {
break; break;
} }
} }
if(data[0] != 'X') {
// Send `data` to the ESP32-CAM.
furi_hal_uart_tx(UART_CH, data, 1);
}
} }
return true; return false;
} }
static void camera_suite_view_camera_exit(void* context) { static void camera_suite_view_camera_exit(void* context) {
UNUSED(context); furi_assert(context);
// Set the camera flash to off.
uint8_t flash_off = 'f';
furi_hal_uart_tx(UART_CH, &flash_off, 1);
furi_delay_ms(50);
// Stop camera stream.
uint8_t stop_camera = 's';
furi_hal_uart_tx(UART_CH, &stop_camera, 1);
furi_delay_ms(50);
} }
static void camera_suite_view_camera_enter(void* context) { static void camera_suite_view_camera_enter(void* context) {
@@ -350,30 +349,23 @@ static void camera_suite_view_camera_enter(void* context) {
CameraSuite* instance_context = instance->context; CameraSuite* instance_context = instance->context;
// Start camera stream. // Start camera stream.
uint8_t start_camera = 'S'; furi_hal_uart_tx(UART_CH, (uint8_t[]){'S'}, 1);
furi_hal_uart_tx(UART_CH, &start_camera, 1); furi_delay_ms(50);
furi_delay_ms(75);
// Get/set dither type. // Get/set dither type.
uint8_t dither_type = instance_context->dither; uint8_t dither_type = instance_context->dither;
furi_hal_uart_tx(UART_CH, &dither_type, 1); furi_hal_uart_tx(UART_CH, &dither_type, 1);
furi_delay_ms(75); furi_delay_ms(50);
// Make sure the camera is not inverted. // Make sure the camera is not inverted.
uint8_t invert_camera = 'i'; furi_hal_uart_tx(UART_CH, (uint8_t[]){'i'}, 1);
furi_hal_uart_tx(UART_CH, &invert_camera, 1); furi_delay_ms(50);
furi_delay_ms(75);
// Toggle flash on or off based on the current state. This will keep the // Toggle flash on or off based on the current state. If the user has this
// flash on initially. However we're toggling it for now on input. // on the flash will stay on the entire time the user is in the camera view.
uint8_t flash_state = instance_context->flash ? 'F' : 'f'; uint8_t flash_state = instance_context->flash ? 'F' : 'f';
furi_hal_uart_tx(UART_CH, &flash_state, 1); furi_hal_uart_tx(UART_CH, &flash_state, 1);
furi_delay_ms(75); furi_delay_ms(50);
// Make sure we start with the flash off.
// uint8_t flash_state = 'f';
// furi_hal_uart_tx(UART_CH, &flash_state, 1);
// furi_delay_ms(75);
with_view_model( with_view_model(
instance->view, instance->view,
@@ -429,7 +421,7 @@ static void process_ringbuffer(UartDumpModel* model, uint8_t const byte) {
// Check whether the ring buffer is filled. // Check whether the ring buffer is filled.
if(model->ringbuffer_index >= RING_BUFFER_LENGTH) { if(model->ringbuffer_index >= RING_BUFFER_LENGTH) {
model->ringbuffer_index = 0; // Reset the ring buffer index. model->ringbuffer_index = 0; // Reset the ring buffer index.
model->initialized = true; // Set the connection as successfully established. model->is_initialized = true; // Set the connection as successfully established.
// Compute the starting index for the row in the pixel buffer. // Compute the starting index for the row in the pixel buffer.
size_t row_start_index = model->row_identifier * ROW_BUFFER_LENGTH; size_t row_start_index = model->row_identifier * ROW_BUFFER_LENGTH;

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include "../helpers/camera_suite_custom_event.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <furi_hal_console.h> #include <furi_hal_console.h>
@@ -16,6 +15,8 @@
#include <storage/filesystem_api_defines.h> #include <storage/filesystem_api_defines.h>
#include <storage/storage.h> #include <storage/storage.h>
#include "../helpers/camera_suite_custom_event.h"
#include <xtreme.h> #include <xtreme.h>
#define UART_CH \ #define UART_CH \
@@ -59,9 +60,9 @@ typedef struct CameraSuiteViewCamera {
} CameraSuiteViewCamera; } CameraSuiteViewCamera;
typedef struct UartDumpModel { typedef struct UartDumpModel {
bool flash; bool is_dithering_enabled;
bool initialized; bool is_initialized;
bool inverted; bool is_inverted;
int rotation_angle; int rotation_angle;
uint32_t orientation; uint32_t orientation;
uint8_t pixels[FRAME_BUFFER_LENGTH]; uint8_t pixels[FRAME_BUFFER_LENGTH];

View File

@@ -1,7 +1,7 @@
App( App(
appid="esp_flasher", appid="esp_flasher",
name="[ESP] ESP Flasher", name="[ESP] ESP Flasher",
fap_version=(1, 2), fap_version=(1, 3),
apptype=FlipperAppType.EXTERNAL, apptype=FlipperAppType.EXTERNAL,
entry_point="esp_flasher_app", entry_point="esp_flasher_app",
requires=["gui"], requires=["gui"],

View File

@@ -4,7 +4,7 @@
extern "C" { extern "C" {
#endif #endif
#define ESP_FLASHER_APP_VERSION "v1.2" #define ESP_FLASHER_APP_VERSION "v1.3"
typedef struct EspFlasherApp EspFlasherApp; typedef struct EspFlasherApp EspFlasherApp;

View File

@@ -22,15 +22,16 @@
#include <unistd.h> #include <unistd.h>
#ifdef SERIAL_FLASHER_DEBUG_TRACE #ifdef SERIAL_FLASHER_DEBUG_TRACE
static void transfer_debug_print(const uint8_t* data, uint16_t size, bool write) { static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
{
static bool write_prev = false; static bool write_prev = false;
if(write_prev != write) { if (write_prev != write) {
write_prev = write; write_prev = write;
printf("\n--- %s ---\n", write ? "WRITE" : "READ"); printf("\n--- %s ---\n", write ? "WRITE" : "READ");
} }
for(uint32_t i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
printf("%02x ", data[i]); printf("%02x ", data[i]);
} }
} }
@@ -41,7 +42,8 @@ static int32_t s_uart_port;
static int32_t s_reset_trigger_pin; static int32_t s_reset_trigger_pin;
static int32_t s_gpio0_trigger_pin; static int32_t s_gpio0_trigger_pin;
esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t* config) { esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t *config)
{
s_uart_port = config->uart_port; s_uart_port = config->uart_port;
s_reset_trigger_pin = config->reset_trigger_pin; s_reset_trigger_pin = config->reset_trigger_pin;
s_gpio0_trigger_pin = config->gpio0_trigger_pin; s_gpio0_trigger_pin = config->gpio0_trigger_pin;
@@ -50,7 +52,7 @@ esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t* config) {
uart_config_t uart_config = { uart_config_t uart_config = {
.baud_rate = config->baud_rate, .baud_rate = config->baud_rate,
.data_bits = UART_DATA_8_BITS, .data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE, .parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1, .stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
@@ -60,22 +62,16 @@ esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t* config) {
int rx_buffer_size = config->rx_buffer_size ? config->rx_buffer_size : 400; int rx_buffer_size = config->rx_buffer_size ? config->rx_buffer_size : 400;
int tx_buffer_size = config->tx_buffer_size ? config->tx_buffer_size : 400; int tx_buffer_size = config->tx_buffer_size ? config->tx_buffer_size : 400;
QueueHandle_t* uart_queue = config->uart_queue ? config->uart_queue : NULL; QueueHandle_t *uart_queue = config->uart_queue ? config->uart_queue : NULL;
int queue_size = config->queue_size ? config->queue_size : 0; int queue_size = config->queue_size ? config->queue_size : 0;
if(uart_param_config(s_uart_port, &uart_config) != ESP_OK) { if ( uart_param_config(s_uart_port, &uart_config) != ESP_OK ) {
return ESP_LOADER_ERROR_FAIL; return ESP_LOADER_ERROR_FAIL;
} }
if(uart_set_pin( if ( uart_set_pin(s_uart_port, config->uart_tx_pin, config->uart_rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE) != ESP_OK ) {
s_uart_port,
config->uart_tx_pin,
config->uart_rx_pin,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE) != ESP_OK) {
return ESP_LOADER_ERROR_FAIL; return ESP_LOADER_ERROR_FAIL;
} }
if(uart_driver_install( if ( uart_driver_install(s_uart_port, rx_buffer_size, tx_buffer_size, queue_size, uart_queue, 0) != ESP_OK ) {
s_uart_port, rx_buffer_size, tx_buffer_size, queue_size, uart_queue, 0) != ESP_OK) {
return ESP_LOADER_ERROR_FAIL; return ESP_LOADER_ERROR_FAIL;
} }
@@ -91,32 +87,37 @@ esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t* config) {
return ESP_LOADER_SUCCESS; return ESP_LOADER_SUCCESS;
} }
void loader_port_esp32_deinit(void) { void loader_port_esp32_deinit(void)
{
uart_driver_delete(s_uart_port); uart_driver_delete(s_uart_port);
} }
esp_loader_error_t loader_port_write(const uint8_t* data, uint16_t size, uint32_t timeout) {
uart_write_bytes(s_uart_port, (const char*)data, size); esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
{
uart_write_bytes(s_uart_port, (const char *)data, size);
esp_err_t err = uart_wait_tx_done(s_uart_port, timeout); esp_err_t err = uart_wait_tx_done(s_uart_port, timeout);
if(err == ESP_OK) { if (err == ESP_OK) {
#ifdef SERIAL_FLASHER_DEBUG_TRACE #ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, size, true); transfer_debug_print(data, size, true);
#endif #endif
return ESP_LOADER_SUCCESS; return ESP_LOADER_SUCCESS;
} else if(err == ESP_ERR_TIMEOUT) { } else if (err == ESP_ERR_TIMEOUT) {
return ESP_LOADER_ERROR_TIMEOUT; return ESP_LOADER_ERROR_TIMEOUT;
} else { } else {
return ESP_LOADER_ERROR_FAIL; return ESP_LOADER_ERROR_FAIL;
} }
} }
esp_loader_error_t loader_port_read(uint8_t* data, uint16_t size, uint32_t timeout) {
esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
{
int read = uart_read_bytes(s_uart_port, data, size, timeout); int read = uart_read_bytes(s_uart_port, data, size, timeout);
if(read < 0) { if (read < 0) {
return ESP_LOADER_ERROR_FAIL; return ESP_LOADER_ERROR_FAIL;
} else if(read < size) { } else if (read < size) {
#ifdef SERIAL_FLASHER_DEBUG_TRACE #ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, read, false); transfer_debug_print(data, read, false);
#endif #endif
@@ -129,39 +130,52 @@ esp_loader_error_t loader_port_read(uint8_t* data, uint16_t size, uint32_t timeo
} }
} }
// Set GPIO0 LOW, then // Set GPIO0 LOW, then
// assert reset pin for 50 milliseconds. // assert reset pin for 50 milliseconds.
void loader_port_enter_bootloader(void) { void loader_port_enter_bootloader(void)
{
gpio_set_level(s_gpio0_trigger_pin, 0); gpio_set_level(s_gpio0_trigger_pin, 0);
loader_port_reset_target(); loader_port_reset_target();
loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS); loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
gpio_set_level(s_gpio0_trigger_pin, 1); gpio_set_level(s_gpio0_trigger_pin, 1);
} }
void loader_port_reset_target(void) {
void loader_port_reset_target(void)
{
gpio_set_level(s_reset_trigger_pin, 0); gpio_set_level(s_reset_trigger_pin, 0);
loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS); loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
gpio_set_level(s_reset_trigger_pin, 1); gpio_set_level(s_reset_trigger_pin, 1);
} }
void loader_port_delay_ms(uint32_t ms) {
void loader_port_delay_ms(uint32_t ms)
{
usleep(ms * 1000); usleep(ms * 1000);
} }
void loader_port_start_timer(uint32_t ms) {
void loader_port_start_timer(uint32_t ms)
{
s_time_end = esp_timer_get_time() + ms * 1000; s_time_end = esp_timer_get_time() + ms * 1000;
} }
uint32_t loader_port_remaining_time(void) {
uint32_t loader_port_remaining_time(void)
{
int64_t remaining = (s_time_end - esp_timer_get_time()) / 1000; int64_t remaining = (s_time_end - esp_timer_get_time()) / 1000;
return (remaining > 0) ? (uint32_t)remaining : 0; return (remaining > 0) ? (uint32_t)remaining : 0;
} }
void loader_port_debug_print(const char* str) {
void loader_port_debug_print(const char *str)
{
printf("DEBUG: %s\n", str); printf("DEBUG: %s\n", str);
} }
esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate) { esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
{
esp_err_t err = uart_set_baudrate(s_uart_port, baudrate); esp_err_t err = uart_set_baudrate(s_uart_port, baudrate);
return (err == ESP_OK) ? ESP_LOADER_SUCCESS : ESP_LOADER_ERROR_FAIL; return (err == ESP_OK) ? ESP_LOADER_SUCCESS : ESP_LOADER_ERROR_FAIL;
} }

View File

@@ -6,7 +6,7 @@ App(
cdefines=["APP_FLIZZER_TRACKER"], cdefines=["APP_FLIZZER_TRACKER"],
stack_size=2 * 1024, stack_size=2 * 1024,
order=90, order=90,
fap_version=(0, 3), fap_version=(0, 4),
fap_description="An advanced Flipper Zero chiptune tracker with 4 channels", fap_description="An advanced Flipper Zero chiptune tracker with 4 channels",
fap_author="LTVA", fap_author="LTVA",
fap_weburl="https://github.com/LTVA1/flizzer_tracker", fap_weburl="https://github.com/LTVA1/flizzer_tracker",

View File

@@ -3,6 +3,9 @@
#include "flizzer_tracker.h" #include "flizzer_tracker.h"
#include "flizzer_tracker_hal.h" #include "flizzer_tracker_hal.h"
extern bool audio_modes_values[];
extern char* audio_modes_text[];
FlizzerTrackerApp* init_tracker( FlizzerTrackerApp* init_tracker(
uint32_t sample_rate, uint32_t sample_rate,
uint8_t rate, uint8_t rate,

View File

@@ -1,6 +1,8 @@
#include "instrument.h" #include "instrument.h"
#include "songinfo.h" #include "songinfo.h"
extern void return_from_keyboard_callback(void* ctx);
void edit_instrument_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta) { void edit_instrument_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta) {
if(!(tracker->current_digit)) { if(!(tracker->current_digit)) {
delta *= 16; delta *= 16;

View File

@@ -2,6 +2,8 @@
#include "../diskop.h" #include "../diskop.h"
extern void return_from_keyboard_callback(void* ctx);
void edit_songinfo_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta) { void edit_songinfo_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta) {
if(!(tracker->current_digit)) { if(!(tracker->current_digit)) {
delta *= 16; delta *= 16;

View File

@@ -11,4 +11,3 @@
#include "../util.h" #include "../util.h"
void songinfo_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event); void songinfo_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event);
void return_from_keyboard_callback(void* ctx);

View File

@@ -4,6 +4,9 @@
#define AUDIO_MODES_COUNT 2 #define AUDIO_MODES_COUNT 2
extern bool audio_modes_values[];
extern char* audio_modes_text[];
void return_from_keyboard_callback(void* ctx) { void return_from_keyboard_callback(void* ctx) {
FlizzerTrackerApp* tracker = (FlizzerTrackerApp*)ctx; FlizzerTrackerApp* tracker = (FlizzerTrackerApp*)ctx;

View File

@@ -15,8 +15,7 @@
#include "input/sequence.h" #include "input/sequence.h"
#include "input/songinfo.h" #include "input/songinfo.h"
extern bool audio_modes_values[]; void return_from_keyboard_callback(void* ctx);
extern char* audio_modes_text[];
void overwrite_file_widget_yes_input_callback(GuiButtonType result, InputType type, void* ctx); void overwrite_file_widget_yes_input_callback(GuiButtonType result, InputType type, void* ctx);
void overwrite_file_widget_no_input_callback(GuiButtonType result, InputType type, void* ctx); void overwrite_file_widget_no_input_callback(GuiButtonType result, InputType type, void* ctx);

View File

@@ -1,7 +1,7 @@
App( App(
appid="esp32_wifi_marauder", appid="esp32_wifi_marauder",
name="[ESP32] WiFi Marauder", name="[ESP32] WiFi Marauder",
fap_version=(6, 4), fap_version=(6, 5),
apptype=FlipperAppType.EXTERNAL, apptype=FlipperAppType.EXTERNAL,
entry_point="wifi_marauder_app", entry_point="wifi_marauder_app",
requires=["gui"], requires=["gui"],

View File

@@ -146,11 +146,27 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
} }
} }
bool send_html = false;
uint8_t* the_html = NULL;
size_t html_size = 0;
if(app->selected_tx_string && strncmp(
"evilportal -c sethtmlstr",
app->selected_tx_string,
strlen("evilportal -c sethtmlstr")) == 0) {
send_html = wifi_marauder_ep_read_html_file(app, &the_html, &html_size);
}
// Send command with newline '\n' // Send command with newline '\n'
if(app->selected_tx_string) { if(app->selected_tx_string) {
wifi_marauder_uart_tx( wifi_marauder_uart_tx(
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
wifi_marauder_uart_tx((uint8_t*)("\n"), 1); wifi_marauder_uart_tx((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);
free(the_html);
send_html = false;
}
} }
// Run the script if the file with the script has been opened // Run the script if the file with the script has been opened

View File

@@ -82,6 +82,13 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = {
TOGGLE_ARGS, TOGGLE_ARGS,
FOCUS_CONSOLE_END, FOCUS_CONSOLE_END,
SHOW_STOPSCAN_TIP}, SHOW_STOPSCAN_TIP},
{"Load Evil Portal HTML file",
{""},
1,
{"evilportal -c sethtmlstr"},
NO_ARGS,
FOCUS_CONSOLE_END,
NO_TIP},
{"Targeted Deauth", {"Targeted Deauth",
{"station", "manual"}, {"station", "manual"},
2, 2,

View File

@@ -4,7 +4,7 @@
extern "C" { extern "C" {
#endif #endif
#define WIFI_MARAUDER_APP_VERSION "v0.6.4" #define WIFI_MARAUDER_APP_VERSION "v0.6.5"
typedef struct WifiMarauderApp WifiMarauderApp; typedef struct WifiMarauderApp WifiMarauderApp;

View File

@@ -6,6 +6,7 @@
#include "scenes/wifi_marauder_scene.h" #include "scenes/wifi_marauder_scene.h"
#include "wifi_marauder_custom_event.h" #include "wifi_marauder_custom_event.h"
#include "wifi_marauder_uart.h" #include "wifi_marauder_uart.h"
#include "wifi_marauder_ep.h"
#include "file/sequential_file.h" #include "file/sequential_file.h"
#include "script/wifi_marauder_script.h" #include "script/wifi_marauder_script.h"
#include "script/wifi_marauder_script_worker.h" #include "script/wifi_marauder_script_worker.h"
@@ -28,13 +29,14 @@
#include <assets_icons.h> #include <assets_icons.h>
#define NUM_MENU_ITEMS (23) #define NUM_MENU_ITEMS (24)
#define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096)
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
#define MARAUDER_APP_FOLDER_USER "apps_data/marauder" #define MARAUDER_APP_FOLDER_USER "apps_data/marauder"
#define MARAUDER_APP_FOLDER EXT_PATH(MARAUDER_APP_FOLDER_USER) #define MARAUDER_APP_FOLDER EXT_PATH(MARAUDER_APP_FOLDER_USER)
#define MARAUDER_APP_FOLDER_HTML MARAUDER_APP_FOLDER "/html"
#define MARAUDER_APP_FOLDER_PCAPS MARAUDER_APP_FOLDER "/pcaps" #define MARAUDER_APP_FOLDER_PCAPS MARAUDER_APP_FOLDER "/pcaps"
#define MARAUDER_APP_FOLDER_LOGS MARAUDER_APP_FOLDER "/logs" #define MARAUDER_APP_FOLDER_LOGS MARAUDER_APP_FOLDER "/logs"
#define MARAUDER_APP_FOLDER_USER_PCAPS MARAUDER_APP_FOLDER_USER "/pcaps" #define MARAUDER_APP_FOLDER_USER_PCAPS MARAUDER_APP_FOLDER_USER "/pcaps"

View File

@@ -0,0 +1,44 @@
#include "wifi_marauder_ep.h"
// returns success (if true, then caller needs to free(the_html))
bool wifi_marauder_ep_read_html_file(WifiMarauderApp* app, uint8_t** the_html, size_t* html_size) {
// browse for files
FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_HTML);
FuriString* selected_filepath = furi_string_alloc();
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(&browser_options, ".html", &I_Text_10x10);
if(!dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
return false;
}
File* index_html = storage_file_alloc(app->storage);
if(!storage_file_open(
index_html, furi_string_get_cstr(selected_filepath), FSAM_READ, FSOM_OPEN_EXISTING)) {
dialog_message_show_storage_error(app->dialogs, "Cannot open file");
return false;
}
uint64_t size = storage_file_size(index_html);
*the_html = malloc(size); // to be freed by caller
uint8_t* buf_ptr = *the_html;
size_t read = 0;
while(read < size) {
size_t to_read = size - read;
if(to_read > UINT16_MAX) to_read = UINT16_MAX;
uint16_t now_read = storage_file_read(index_html, buf_ptr, (uint16_t)to_read);
read += now_read;
buf_ptr += now_read;
}
*html_size = read;
storage_file_close(index_html);
storage_file_free(index_html);
furi_string_free(selected_filepath);
furi_string_free(predefined_filepath);
return true;
}

View File

@@ -0,0 +1,6 @@
// evil portal helper
#pragma once
#include "wifi_marauder_app_i.h"
bool wifi_marauder_ep_read_html_file(WifiMarauderApp* app, uint8_t** the_html, size_t* html_size);