/** * @file rpc_app.h * @brief Application RPC subsystem interface. * * The application RPC subsystem provides facilities for interacting with applications, * such as starting/stopping, passing parameters, sending commands and exchanging arbitrary data. * * All commands are handled asynchronously via a user-settable callback. * * For a complete description of message types handled in this subsystem, * see https://github.com/flipperdevices/flipperzero-protobuf/blob/dev/application.proto */ #pragma once #include "rpc.h" #include "rpc_app_error_codes.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Enumeration of possible event data types. */ typedef enum { RpcAppSystemEventDataTypeNone, /**< No data is provided by the event. */ RpcAppSystemEventDataTypeString, /**< Event data contains a zero-terminated string. */ RpcAppSystemEventDataTypeInt32, /**< Event data contains a signed 32-bit integer. */ RpcAppSystemEventDataTypeBytes, /**< Event data contains zero or more bytes. */ } RpcAppSystemEventDataType; /** * @brief Event data structure, containing the type and associated data. * * All below fields except for type are valid only if the respective type is set. */ typedef struct { RpcAppSystemEventDataType type; /**< Type of the data. The meaning of other fields depends on this one. */ union { const char* string; /**< Pointer to a zero-terminated character string. */ int32_t i32; /**< Signed 32-bit integer value. */ struct { const uint8_t* ptr; /**< Pointer to the byte array data. */ size_t size; /**< Size of the byte array, in bytes. */ } bytes; /**< Byte array of arbitrary length. */ }; } RpcAppSystemEventData; /** * @brief Enumeration of possible event types. */ typedef enum { /** * @brief Denotes an invalid state. * * An event of this type shall never be passed into the callback. */ RpcAppEventTypeInvalid, /** * @brief The client side has closed the session. * * After receiving this event, the RPC context is no more valid. */ RpcAppEventTypeSessionClose, /** * @brief The client has requested the application to exit. * * The application must exit after receiving this command. */ RpcAppEventTypeAppExit, /** * @brief The client has requested the application to load a file. * * This command's meaning is application-specific, i.e. the application might or * might not require additional commands after loading a file to do anything useful. */ RpcAppEventTypeLoadFile, /** * @brief The client has informed the application that a button has been pressed. * * This command's meaning is application-specific, e.g. to select a part of the * previously loaded file or to invoke a particular function within the application. */ RpcAppEventTypeButtonPress, /** * @brief The client has informed the application that a button has been released. * * This command's meaning is application-specific, e.g. to cease * all activities to be conducted while a button is being pressed. */ RpcAppEventTypeButtonRelease, /** * @brief The client has sent a byte array of arbitrary size. * * This command's purpose is bi-directional exchange of arbitrary raw data. * Useful for implementing higher-level protocols while using the RPC as a transport layer. */ RpcAppEventTypeDataExchange, } RpcAppSystemEventType; /** * @brief RPC application subsystem event structure. */ typedef struct { RpcAppSystemEventType type; /**< Type of the event. */ RpcAppSystemEventData data; /**< Data associated with the event. */ } RpcAppSystemEvent; /** * @brief Callback function type. * * A function of this type must be passed to rpc_system_app_set_callback() by the user code. * * @warning The event pointer is valid ONLY inside the callback function. * * @param[in] event pointer to the event object. Valid only inside the callback function. * @param[in,out] context pointer to the user-defined context object. */ typedef void (*RpcAppSystemCallback)(const RpcAppSystemEvent* event, void* context); /** * @brief RPC application subsystem opaque type declaration. */ typedef struct RpcAppSystem RpcAppSystem; /** * @brief Set the callback function for use by an RpcAppSystem instance. * * @param[in,out] rpc_app pointer to the instance to be configured. * @param[in] callback pointer to the function to be called upon message reception. * @param[in,out] context pointer to the user-defined context object. Will be passed to the callback. */ void rpc_system_app_set_callback( RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* context); /** * @brief Send a notification that an RpcAppSystem instance has been started and is ready. * * Call this function once right after acquiring an RPC context and setting the callback. * * @param[in,out] rpc_app pointer to the instance to be used. */ void rpc_system_app_send_started(RpcAppSystem* rpc_app); /** * @brief Send a notification that the application using an RpcAppSystem instance is about to exit. * * Call this function when the application is about to exit (usually in the *_free() function). * * @param[in,out] rpc_app pointer to the instance to be used. */ void rpc_system_app_send_exited(RpcAppSystem* rpc_app); /** * @brief Send a confirmation that the application using an RpcAppSystem instance has handled the event. * * An explicit confirmation is required for the following event types: * - RpcAppEventTypeAppExit * - RpcAppEventTypeLoadFile * - RpcAppEventTypeButtonPress * - RpcAppEventTypeButtonRelease * - RpcAppEventTypeDataExchange * * Not confirming these events will result in a client-side timeout. * * @param[in,out] rpc_app pointer to the instance to be used. * @param[in] result whether the command was successfully handled or not (true for success). */ void rpc_system_app_confirm(RpcAppSystem* rpc_app, bool result); /** * @brief Set the error code stored in an RpcAppSystem instance. * * The error code can be retrieved by the client at any time by using the GetError request. * The error code value has no meaning within the subsystem, i.e. it is only passed through to the client. * * @param[in,out] rpc_app pointer to the instance to be modified. * @param[in] error_code arbitrary error code to be set. */ void rpc_system_app_set_error_code(RpcAppSystem* rpc_app, uint32_t error_code); /** * @brief Set the error text stored in an RpcAppSystem instance. * * The error text can be retrieved by the client at any time by using the GetError request. * The text has no meaning within the subsystem, i.e. it is only passed through to the client. * * @param[in,out] rpc_app pointer to the instance to be modified. * @param[in] error_text Pointer to a zero-terminated string containing the error text. */ void rpc_system_app_set_error_text(RpcAppSystem* rpc_app, const char* error_text); /** * @brief Reset the error code and text stored in an RpcAppSystem instance. * * Resets the error code to 0 and error text to "" (empty string). * * @param[in,out] rpc_app pointer to the instance to be reset. */ void rpc_system_app_error_reset(RpcAppSystem* rpc_app); /** * @brief Send a byte array of arbitrary data to the client using an RpcAppSystem instance. * * @param[in,out] rpc_app pointer to the instance to be used. * @param[in] data pointer to the data buffer to be sent. * @param[in] data_size size of the data buffer, in bytes. */ void rpc_system_app_exchange_data(RpcAppSystem* rpc_app, const uint8_t* data, size_t data_size); #ifdef __cplusplus } #endif