mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-18 16:53:45 +00:00
b2a12d091a
* Menu app. Lib: add mlib submodule. * Menu: new startup lib dependency definition * Menu: hierarchy in menu. Cube: fix heap1/4 inconsistency, stack protection. * GUI: rendering pipeline initial version. * GUI: layered widget composing, FURI record. Menu: FURI record, api. * GUI: input dispatching. Menu: switch to input from GUI. * GUI, MENU: code style cleanup, fix type conversion warnings. * GUI, Menu: syntax check. * Makefile: check and reinit submodules, format. * Menu: lock on event processing. Makefile: proper submodule initialization. * Menu: fix stack corruption by queue. * GUI: refactor. * Makefile: format rule fix, st-util pid. * GUI, Menu, FURI: format with clang-format. * GUI, MENU: locks in critical sections, fix stack corruption, ready signaling. * Makefile: clang format rule cleanup. * GUI,MENU: migrate to new API. * Applications: PRODUCTION_HW variable, skip drivers build on local target. * refactor production build * add git to dockerfile * GUI: uncomment lock block Co-authored-by: Aleksandr Kutuzov <aku@plooks.com>
201 lines
5.2 KiB
C
201 lines
5.2 KiB
C
#pragma once
|
|
|
|
#include "cmsis_os.h"
|
|
|
|
#ifdef HAVE_FREERTOS
|
|
#include <semphr.h>
|
|
#endif
|
|
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#define MAX_TASK_RECORDS 8
|
|
#define MAX_RECORD_SUBSCRIBERS 8
|
|
|
|
inline static void* furi_alloc(size_t size) {
|
|
void* p = malloc(size);
|
|
assert(p);
|
|
return memset(p, 0, size);
|
|
}
|
|
|
|
/// application is just a function
|
|
typedef void (*FlipperApplication)(void*);
|
|
|
|
/// pointer to value callback function
|
|
typedef void (*FlipperRecordCallback)(const void*, size_t, void*);
|
|
|
|
typedef enum {
|
|
FlipperRecordStateMute, ///< record open and mute this handler
|
|
FlipperRecordStateUnmute, ///< record unmuted
|
|
FlipperRecordStateDeleted ///< record owner halt
|
|
} FlipperRecordState;
|
|
|
|
/// pointer to state callback function
|
|
typedef void (*FlipperRecordStateCallback)(FlipperRecordState, void*);
|
|
|
|
struct _FuriRecord;
|
|
|
|
typedef struct {
|
|
bool allocated;
|
|
FlipperRecordCallback cb; ///< value cb
|
|
FlipperRecordStateCallback state_cb; ///< state cb
|
|
uint8_t mute_counter; ///< see "wiki/FURI#mute-algorithm"
|
|
bool no_mute;
|
|
struct _FuriRecord* record; ///< parent record
|
|
void* ctx;
|
|
} FuriRecordSubscriber;
|
|
|
|
/// FURI record handler
|
|
struct _FuriRecord {
|
|
const char* name;
|
|
void* value;
|
|
size_t size;
|
|
StaticSemaphore_t mutex_buffer;
|
|
SemaphoreHandle_t mutex;
|
|
uint8_t mute_counter;
|
|
FuriRecordSubscriber subscribers[MAX_RECORD_SUBSCRIBERS];
|
|
};
|
|
|
|
typedef struct _FuriRecord FuriRecord;
|
|
|
|
/// store info about active task
|
|
typedef struct {
|
|
const char* name;
|
|
FlipperApplication application;
|
|
const char* prev_name;
|
|
FlipperApplication prev;
|
|
TaskHandle_t handler;
|
|
uint8_t records_count; ///< count of records which task open
|
|
FuriRecord* records[MAX_TASK_RECORDS]; ///< list of records which task open
|
|
|
|
bool ready;
|
|
} FuriApp;
|
|
|
|
// application dependency info
|
|
typedef struct {
|
|
uint8_t count;
|
|
const char** name;
|
|
} FlipperAppLibrary;
|
|
|
|
// application startup info
|
|
typedef struct {
|
|
FlipperApplication app;
|
|
const char* name;
|
|
FlipperAppLibrary libs;
|
|
} FlipperStartupApp;
|
|
|
|
/*!
|
|
Simply starts application.
|
|
It call app entrypoint with param passed as argument.
|
|
Useful for daemon applications and pop-up.
|
|
*/
|
|
FuriApp* furiac_start(FlipperApplication app, const char* name, void* param);
|
|
|
|
/*!
|
|
Swtich to other application.
|
|
FURI stop current app, call app entrypoint with param passed as
|
|
argument and save current application entrypoint to prev field
|
|
in current application registry.
|
|
Useful for UI or "active" application.
|
|
*/
|
|
void furiac_switch(FlipperApplication app, char* name, void* param);
|
|
|
|
/*!
|
|
Stop current application
|
|
(stop thread and clear application's stack), start application
|
|
from prev entry in current application registry, cleanup current
|
|
application registry.
|
|
*/
|
|
void furiac_exit(void* param);
|
|
|
|
/*!
|
|
Mark application as prepared and ready to perform actions
|
|
*/
|
|
void furiac_ready();
|
|
|
|
/*
|
|
Wait for the libraries we depend on
|
|
*/
|
|
void furiac_wait_libs(const FlipperAppLibrary* libs);
|
|
|
|
/*!
|
|
Stop specified app without returning to prev application.
|
|
*/
|
|
bool furiac_kill(FuriApp* app);
|
|
|
|
// find task pointer by handle
|
|
FuriApp* find_task(TaskHandle_t handler);
|
|
|
|
/*!
|
|
Creates named FURI record.
|
|
\param[in] name you can open this record anywhere
|
|
\param[in] value pointer to data.
|
|
\param[in] size size of data.
|
|
If NULL, create FURI Pipe (only callbacks management, no data/mutex)
|
|
|
|
Returns false if registry have not enough memory for creating.
|
|
*/
|
|
bool furi_create_deprecated(const char* name, void* value, size_t size);
|
|
|
|
/*!
|
|
Opens existing FURI record by name.
|
|
Returns NULL if record does not exist.
|
|
\param[in] solo if true another applications handlers set into "muted" state.
|
|
When appication has exited or record has closed, all handlers is unmuted.
|
|
It may be useful for concurrently acces to resources like framebuffer or beeper.
|
|
\param[in] no_mute if true, another applications cannot mute this handler.
|
|
*/
|
|
FuriRecordSubscriber* furi_open_deprecated(
|
|
const char* name,
|
|
bool solo,
|
|
bool no_mute,
|
|
FlipperRecordCallback value_callback,
|
|
FlipperRecordStateCallback state_callback,
|
|
void* ctx);
|
|
|
|
/*!
|
|
|
|
*/
|
|
void furi_close(FuriRecordSubscriber* handler);
|
|
|
|
/*!
|
|
read message from record.
|
|
Returns true if success, false otherwise (closed/non-existent record)
|
|
Also return false if you try to read from FURI pipe
|
|
|
|
TODO: enum return value with execution status
|
|
*/
|
|
bool furi_read(FuriRecordSubscriber* record, void* data, size_t size);
|
|
|
|
/*!
|
|
write message to record.
|
|
Returns true if success, false otherwise (closed/non-existent record or muted).
|
|
|
|
TODO: enum return value with execution status
|
|
*/
|
|
bool furi_write(FuriRecordSubscriber* record, const void* data, size_t size);
|
|
|
|
/*!
|
|
lock value mutex.
|
|
It can be useful if records contain pointer to buffer which you want to change.
|
|
You must call furi_give after operation on data and
|
|
you shouldn't block executing between take and give calls
|
|
|
|
Returns pointer to data, NULL if closed/non-existent record or muted
|
|
|
|
TODO: enum return value with execution status
|
|
*/
|
|
void* furi_take(FuriRecordSubscriber* record);
|
|
|
|
/*!
|
|
unlock value mutex.
|
|
*/
|
|
void furi_give(FuriRecordSubscriber* record);
|
|
|
|
/*!
|
|
unlock value mutex and notify subscribers that data is chaned.
|
|
*/
|
|
void furi_commit(FuriRecordSubscriber* handler);
|