diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-06-22 10:39:01 +0200 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-06-22 10:39:01 +0200 |
commit | 2187c3d6196f2a25bc0b74365358c9874dde3a46 (patch) | |
tree | 8b7d91024b77eb8aa1115103b17b2a4d7ef3d402 | |
parent | 8a80226e9dce394573e95d68fc9fe04592ad5907 (diff) |
more code documentation
-rw-r--r-- | Doxyfile | 2 | ||||
-rw-r--r-- | lib/pbdrv/index.dox | 29 | ||||
-rw-r--r-- | lib/pbdrv/pb-buf.h | 2 | ||||
-rw-r--r-- | lib/pbdrv/pb-mod.h | 11 | ||||
-rw-r--r-- | lib/pbdrv/pb-route.c | 8 | ||||
-rw-r--r-- | lib/pbdrv/pb-route.h | 161 | ||||
-rw-r--r-- | lib/pbdrv/pb-types.h | 58 |
7 files changed, 228 insertions, 43 deletions
@@ -25,3 +25,5 @@ INPUT_FILTER = "sed -e 's/\<I2C\>\|\<I<sup>2<\/sup>C\>/\\I2C/g'" USE_MDFILE_AS_MAINPAGE = readme.md +INTERNAL_DOCS = YES + diff --git a/lib/pbdrv/index.dox b/lib/pbdrv/index.dox index ad05078..e4a6c5f 100644 --- a/lib/pbdrv/index.dox +++ b/lib/pbdrv/index.dox @@ -7,15 +7,6 @@ pbdrv is a standalone portable static library for handling (i.e. (de)serialization) of puzzle bus messages. -\defgroup pbdrv-mod pbdrv-mod -\brief Puzzle module driver (superset of \ref pbdrv) - -pbdrv-mod is a superset of pbdrv, and includes functions specific to puzzle bus -modules. pbdrv-mod compiles to an object file instead of a static library -because it may depend on functions that rely on external libraries. pbdrv-mod -is still considered standalone, but requires either using an existing driver, -or (partially) implementing the driver functions. - \note Most \c pb_* functions have a weak implementation, which may be overwritten by a custom implementation. This allows you to use the default implementation where possible, and only implement extensions required for your @@ -25,14 +16,26 @@ TODO: where to find drivers TODO: what are extensions TODO: what to do if there is no driver / extension +\defgroup pbdrv-mod pbdrv-mod +\brief Puzzle module driver (superset of \ref pbdrv) + +pbdrv-mod is a superset of \ref pbdrv, and includes functions specific to +puzzle bus modules. pbdrv-mod compiles to an object file instead of a static +library because it may depend on functions that rely on external libraries. +pbdrv-mod is still considered standalone, but requires either using an existing +driver, or (partially) implementing the driver functions. + +\copydetails pbdrv + \{ -\defgroup hook +\defgroup pb_hook Hook \brief Functions for (partially) overriding default behavior -Hooks are functions with a default (weak) implementation in pbdrv. These -functions can be overwritten by the user to implement custom behavior, without -needing to understand the internals of pbdrv. +Hooks are functions that allow the user to implement custom behavior (i.e. +extend or conditionally replace the default handlers), without needing to +completely overwrite the built-in handlers or understand the internals of \ref +pbdrv. \} diff --git a/lib/pbdrv/pb-buf.h b/lib/pbdrv/pb-buf.h index 049f516..9ff53fe 100644 --- a/lib/pbdrv/pb-buf.h +++ b/lib/pbdrv/pb-buf.h @@ -10,7 +10,7 @@ extern "C" { * \ingroup pbdrv * \ingroup pbdrv-mod * \defgroup pb_buf Buffer - * \brief Binary data buffer type used in pbdrv + * \brief Binary data buffer type used in \ref pbdrv * \{ */ diff --git a/lib/pbdrv/pb-mod.h b/lib/pbdrv/pb-mod.h index 2ff1908..ef2cd77 100644 --- a/lib/pbdrv/pb-mod.h +++ b/lib/pbdrv/pb-mod.h @@ -80,7 +80,7 @@ void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz); /// \} -/// \ingroup hook +/// \ingroup pb_hook /// \{ /** @@ -89,8 +89,7 @@ void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz); * * If your puzzle module defines its own global \c pb_global_state_t, you can * tell the driver to use it by implementing these functions. These functions - * are also used internally by the driver when creating \c STATE \c REQ and \c - * STATE \c RES commands. + * are also used internally by the driver. * * \{ */ @@ -98,11 +97,17 @@ void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz); /** * \brief global state read hook * \return current value of global state enum + * + * The default implementation of this function uses an internal global state + * variable in \ref pbdrv. */ pb_global_state_t pb_hook_mod_state_read(); /** * \brief global state write hook * \param state new value of global state enum + * + * The default implementation of this function uses an internal global state + * variable in \ref pbdrv. */ void pb_hook_mod_state_write(pb_global_state_t state); diff --git a/lib/pbdrv/pb-route.c b/lib/pbdrv/pb-route.c index 709fb7f..f5c32d6 100644 --- a/lib/pbdrv/pb-route.c +++ b/lib/pbdrv/pb-route.c @@ -58,8 +58,8 @@ __weak void pb_route_cmd_prop_set(pb_msg_t * msg) {} //! last known global state of last STATE REQ sender (i.e. main controller) static pb_global_state_t _main_state = PB_GS_NOINIT; -__weak void pb_hook_main_state_update(pb_global_state_t state) {} -__weak void pb_hook_module_init() { +__weak void pb_hook_ev_main_state_update(pb_global_state_t state) {} +__weak void pb_hook_ev_module_init() { pb_hook_mod_state_write(PB_GS_IDLE); } __weak void pb_route_cmd_state_req(pb_msg_t * msg) { @@ -69,8 +69,8 @@ __weak void pb_route_cmd_state_req(pb_msg_t * msg) { pb_cmd_state_t * cmd = msg->cmd; if (cmd->state != _main_state) { // first STATE REQ = module init OK - if (_main_state == PB_GS_NOINIT) pb_hook_module_init(); - pb_hook_main_state_update(cmd->state); + if (_main_state == PB_GS_NOINIT) pb_hook_ev_module_init(); + pb_hook_ev_main_state_update(cmd->state); } _main_state = cmd->state; diff --git a/lib/pbdrv/pb-route.h b/lib/pbdrv/pb-route.h index 233a087..b80e4ec 100644 --- a/lib/pbdrv/pb-route.h +++ b/lib/pbdrv/pb-route.h @@ -6,40 +6,185 @@ extern "C" { #endif +/** + * \ingroup pbdrv-mod + * \defgroup pb_route Routing + * \internal + * \brief Parsed message handler routing + * + * These functions form a tree-shaped call graph, and are used to handle + * specific commands received from \c pb_i2c_recv(). + * + * \{ + */ + +/** + * \brief Handle a message with type {\ref PB_CMD_PROP "PROP", \ref + * PB_CMD_STATE "STATE", \ref PB_CMD_MAGIC "MAGIC"} + * + * Calls the next handler depending on \c msg->type. + */ void pb_route_msg(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_PROP "PROP" message with action {\ref + * pb_route_cmd_prop_req "REQ", \ref pb_route_cmd_prop_res "RES", \ref + * pb_route_cmd_prop_set "SET"} + * + * Calls the next handler depending on \c msg->action. + */ void pb_route_cmd_prop(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_STATE "STATE" message with action {\ref + * pb_route_cmd_state_req "REQ", \ref pb_route_cmd_state_res "RES", \ref + * pb_route_cmd_state_set "SET"} + * + * Calls the next handler depending on \c msg->action. + */ void pb_route_cmd_state(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action {\ref + * pb_route_cmd_magic_req "REQ", \ref pb_route_cmd_magic_res "RES"} + * + * Calls the next handler depending on \c msg->action. + * + * \note Messages with type \c MAGIC and action \c SET will be silently + * ignored, as there is no such command. + */ void pb_route_cmd_magic(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref + * PB_ACTION_REQ "REQ" + * + * The default implementation of this function is empty, as puzzle module + * properties are user-defined. + */ void pb_route_cmd_prop_req(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref + * PB_ACTION_RES "RES" + * + * The default implementation of this function is empty, as puzzle module + * properties are user-defined. + */ void pb_route_cmd_prop_res(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref + * PB_ACTION_SET "SET" + * + * The default implementation of this function is empty, as puzzle module + * properties are user-defined. + */ void pb_route_cmd_prop_set(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref + * PB_ACTION_REQ "REQ" + * + * The default implementation of this function does the following: + * - Call \c pb_hook_ev_module_init() if this is the first received \c STATE \c + * REQ command. + * - Call \c pb_hook_ev_main_state_update() if the main controller state has + * changed. + * - Reply with a \c STATE \c RES message. + */ void pb_route_cmd_state_req(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref + * PB_ACTION_RES "RES" + * + * The default implementation of this function is empty, as only the main + * controller handles this type of command. + */ void pb_route_cmd_state_res(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref + * PB_ACTION_SET "SET" + * + * The default implementation of this function does the following: + * - Write the global state variable using \c pb_hook_mod_state_write(). + */ void pb_route_cmd_state_set(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action \ref + * PB_ACTION_REQ "REQ" + * + * The default implementation of this function does the following: + * - Verify the size of the magic string + * - Verify the content of the magic string + * - Reply with a \c MAGIC \c RES message. + */ void pb_route_cmd_magic_req(pb_msg_t * msg); +/** + * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action \ref + * PB_ACTION_RES "RES" + * + * The default implementation of this function is empty, as only the main + * controller handles this type of command. + */ void pb_route_cmd_magic_res(pb_msg_t * msg); -/// \ingroup hook -/// \{ - -/// \defgroup hook_route Routing -/// \brief Use a custom message handler -/// \{ +/// \} +/** + * \ingroup pb_hook + * \defgroup pb_hook_route Routing + * \brief Conditionally use substitute or extend the built-in message handlers + * \{ + */ + +/** + * \brief \c pb_route_msg() hook + * + * The default implementation of this function immediately returns false. + * + * \return \c true if execution should continue to the default handler, or \c + * false if it should stop (i.e. the message was handled). + */ bool pb_hook_route_msg(pb_msg_t * msg); +//! \c pb_route_cmd_prop() hook \copydetails pb_hook_route_msg bool pb_hook_route_cmd_prop(pb_msg_t * msg); +//! \c pb_route_cmd_state() hook \copydetails pb_hook_route_msg bool pb_hook_route_cmd_state(pb_msg_t * msg); +//! \c pb_route_cmd_magic() hook \copydetails pb_hook_route_msg bool pb_hook_route_cmd_magic(pb_msg_t * msg); /// \} -void pb_hook_main_state_update(pb_global_state_t state); -void pb_hook_module_init(); +/** + * \ingroup pb_hook + * \defgroup pb_hook_ev Events + * \brief Functions called on puzzle bus-related events + * \{ + */ + +/** + * \brief Main controller state update hook + * + * The default implementation of this function is empty. + * + * \param state New state of main controller + * + * \note This function is also called when the first \c STATE \c REQ command is + * received, as the main controller state variable used to check if the state + * actually changed is initialized to \ref PB_GS_NOINIT. In this case, this + * function is called *after* \c pb_hook_ev_module_init(). + */ +void pb_hook_ev_main_state_update(pb_global_state_t state); +/** + * \brief Module initialized hook + * + * The default implementation of this function calls \c + * pb_hook_mod_state_write() with \ref PB_GS_IDLE. + * + * This function is called when the first \c STATE \c REQ command is received, + * indicating this puzzle module has been registered successfully by the main + * controller, and is now part of an active play session. + */ +void pb_hook_ev_module_init(); /// \} diff --git a/lib/pbdrv/pb-types.h b/lib/pbdrv/pb-types.h index f5fbb74..dfd5da9 100644 --- a/lib/pbdrv/pb-types.h +++ b/lib/pbdrv/pb-types.h @@ -8,7 +8,17 @@ extern "C" { #endif +/** + * \ingroup pbdrv + * \ingroup pbdrv-mod + * \defgroup pb_types Types + * \brief Datatypes used within \ref pbdrv + * + * \{ + */ + #ifdef __GNUC__ +//! Mark function as weak (allow user to override implementation) #define __weak __attribute__((weak)) #endif #ifndef __weak @@ -21,15 +31,33 @@ typedef uint16_t i2c_addr_t; //! puzzle bus command types enum pb_cmd_id { - /** \brief puzzle module property (REQ, RES, SET) */ + /** + * \brief puzzle module property (\ref pb_route_cmd_prop_req "REQ", \ref + * pb_route_cmd_prop_res "RES", \ref pb_route_cmd_prop_set "SET") + * + * The \c PROP command type is used for exchanging arbitrary data between + * puzzle modules and/or the puzzle box client (pbc) over the TCP bridge. + * These properties are not used by the puzzle framework. + */ PB_CMD_PROP, - /** \brief puzzle module global state variable (REQ, RES, SET) */ + /** + * \brief puzzle module global state variable (\ref pb_route_cmd_state_req + * "REQ", \ref pb_route_cmd_state_res "RES", \ref pb_route_cmd_state_set + * "SET") + * + * The \c STATE command is used by puzzle modules to inform the main + * controller about their global state. The main controller aggregates the + * states of all connected puzzle modules and exchanges this aggregated state + * with the puzzle modules to indicate when the entire puzzle box is solved. + */ PB_CMD_STATE, /** - * \brief magic (handshake) (REQ, RES) + * \brief magic (handshake) (\ref pb_route_cmd_magic_req "REQ", \ref + * pb_route_cmd_magic_res "RES") * - * This message is used to distinguish between puzzle modules and regular I2C - * slaves on the puzzle bus. + * The \c MAGIC command effectively serves as a 'secret handshake' (using a + * _magic_ value) which is used to distinguish between puzzle modules and + * unrelated I2C devices. */ PB_CMD_MAGIC, }; @@ -57,16 +85,16 @@ static const char pb_cmd_magic_req[] = { 0x70, 0x75, 0x7a, 0x62, 0x75, 0x73 }; //! magic reply from puzzle module back to main controller static const char pb_cmd_magic_res[] = { 0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67 }; -//! puzzle bus message header (shared by all commands) +//! puzzle bus message header / container (shared by all commands) typedef struct { /** - * \brief command type + * \brief Command type (see \ref pb_cmd_id_t) * * This is used to identify what the message is about. */ pb_cmd_id_t type; /** - * \brief command action + * \brief Command action (see \ref pb_action_t) * * This is used to specify what should happen as a result of this message. */ @@ -79,31 +107,33 @@ typedef struct { */ i2c_addr_t sender; /** - * \brief command data (type dependent) + * \brief Command data (dependent on \p type) * * Struct containing command type-specific data. */ void * cmd; } pb_msg_t; -//! PB_CMD_PROP data +//! \ref PB_CMD_PROP data typedef struct { uint8_t propid; //!< id of state property uint8_t * value; //!< new or current value - size_t _value_size; //!< [META] size of \p value + size_t _value_size; //!< size of \p value } pb_cmd_prop_t; -//! PB_CMD_STATE data +//! \ref PB_CMD_STATE data typedef struct { pb_global_state_t state; //!< global state } pb_cmd_state_t; -//! PB_CMD_MAGIC data +//! \ref PB_CMD_MAGIC data typedef struct { char * magic; //!< magic value - size_t _magic_size; //!< [META] size of \p magic + size_t _magic_size; //!< size of \p magic } pb_cmd_magic_t; +/// \} + #ifdef __cplusplus } #endif |