/** * FlipperDroid — application state */ #pragma once #include #include #include #include #include #include #include #include "fd_protocol.h" /* USB CDC channel — channel 0 is Flipper CLI, we use channel 1 */ #define FD_CDC_CHANNEL 0 /* App views */ typedef enum { FdViewStatus, FdViewGpio, FdViewSubghz, FdViewLog, } FdView; /* GPIO pin entry */ typedef struct { uint8_t id; const GpioPin* pin; const char* name; bool initialized; bool output; bool value; } FdGpioEntry; /* Ring buffer for log messages */ #define FD_LOG_LINES 8 #define FD_LOG_COLS 30 typedef struct { char lines[FD_LOG_LINES][FD_LOG_COLS + 1]; uint8_t head; uint8_t count; } FdLogBuffer; /* Main application state */ typedef struct { /* Furi */ Gui* gui; ViewPort* view_port; FuriMessageQueue* input_queue; NotificationApp* notifications; FuriMutex* mutex; /* Threads */ FuriThread* rx_thread; FuriThread* event_thread; bool running; /* Connection */ bool connected; uint32_t rx_count; uint32_t tx_count; uint32_t err_count; uint32_t connect_tick; /* View */ FdView current_view; uint8_t selected_gpio; /* SubGHz */ bool subghz_rx_active; uint32_t subghz_freq; float subghz_last_rssi; /* IR */ bool ir_rx_active; /* GPIO */ FdGpioEntry gpio[12]; uint8_t gpio_count; /* Log */ FdLogBuffer log; } FdApp; /* Lifecycle */ FdApp* fd_app_alloc(void); void fd_app_free(FdApp* app); int32_t fd_app_run(FdApp* app); /* GUI callbacks */ void fd_draw_callback(Canvas* canvas, void* ctx); void fd_input_callback(InputEvent* event, void* ctx); /* Log */ void fd_log(FdApp* app, const char* fmt, ...); /* USB I/O */ void fd_usb_tx(const uint8_t* data, uint16_t len); uint16_t fd_usb_rx(uint8_t* buf, uint16_t max_len, uint32_t timeout_ms); /* Frame TX helpers */ void fd_send_ok(FdApp* app, const uint8_t* data, uint16_t len); void fd_send_err(FdApp* app, FdError err, const char* msg); void fd_send_event(FdApp* app, FdEvent ev, const uint8_t* data, uint16_t len); /* Command dispatch */ void fd_handle_cmd(FdApp* app, uint8_t cmd, const uint8_t* payload, uint16_t len); /* Workers */ int32_t fd_rx_worker(void* ctx); int32_t fd_event_worker(void* ctx);