aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile2
-rw-r--r--lib/pbdrv/index.dox29
-rw-r--r--lib/pbdrv/pb-buf.h2
-rw-r--r--lib/pbdrv/pb-mod.h11
-rw-r--r--lib/pbdrv/pb-route.c8
-rw-r--r--lib/pbdrv/pb-route.h161
-rw-r--r--lib/pbdrv/pb-types.h58
7 files changed, 228 insertions, 43 deletions
diff --git a/Doxyfile b/Doxyfile
index 53e75c2..ea9692a 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -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