aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/cmd.h50
-rw-r--r--client/i2c.cpp4
-rw-r--r--client/i2c.h29
-rw-r--r--client/parse.h14
-rw-r--r--client/rl.cpp15
-rw-r--r--client/rl.h43
-rw-r--r--client/sock.h43
-rw-r--r--client/xxd.h9
8 files changed, 187 insertions, 20 deletions
diff --git a/client/cmd.h b/client/cmd.h
index 961ef89..a3cc44a 100644
--- a/client/cmd.h
+++ b/client/cmd.h
@@ -1,17 +1,44 @@
#pragma once
+/**
+ * \ingroup pbc
+ * \defgroup pbc_cmd cmd
+ * \brief Commands within \ref pbc
+ * \{
+ */
+
#include <stddef.h>
-typedef void cmd_handle_t(char *);
-typedef char** cmd_complete_t(const char*, int, int);
+/**
+ * \internal
+ * \brief Command handler function
+ *
+ * \param line Remaining text after command name on command line
+ */
+typedef void cmd_handle_t(char * line);
+/**
+ * \internal
+ * \brief Command completion function
+ *
+ * \param text Current word to complete
+ * \param start Index in \c rl_line_buffer of cursor position
+ * \param end End index of \p text in \c rl_line_buffer
+ *
+ * \return Array of \c char* with suggestions. The array is terminated by a
+ * NULL pointer.
+ */
+typedef char** cmd_complete_t(const char* text, int start, int end);
-struct cmd {
- cmd_handle_t * handle;
- const char* name;
- const char* info;
- cmd_complete_t * complete;
-};
-typedef struct cmd cmd_t;
+/**
+ * \internal
+ * \brief Command definition struct
+ */
+typedef struct {
+ cmd_handle_t * handle; //!< Handler function (required)
+ const char* name; //!< Command name (required)
+ const char* info; //!< Command info (shown in help command) (optional = NULL)
+ cmd_complete_t * complete; //!< Completion function (optional = NULL)
+} cmd_t;
cmd_handle_t cmd_exit;
cmd_handle_t cmd_test;
@@ -23,6 +50,7 @@ cmd_handle_t cmd_skip;
cmd_handle_t cmd_dump;
cmd_complete_t cmd_dump_complete;
+//! Commands
static const cmd_t cmds[] = {
{
.handle = cmd_exit,
@@ -68,5 +96,9 @@ static const cmd_t cmds[] = {
},
#endif
};
+
+//! Number of commands defined in \c cmds
static const size_t cmds_length = sizeof(cmds) / sizeof(cmds[0]);
+/// \}
+
diff --git a/client/i2c.cpp b/client/i2c.cpp
index 78e5585..3655191 100644
--- a/client/i2c.cpp
+++ b/client/i2c.cpp
@@ -35,9 +35,9 @@ void i2c_send(uint16_t addr, const char * data, size_t data_size) {
static void i2c_handle_cmd_read(uint16_t, const char *, size_t);
-void i2c_recv(uint16_t addr, const char * data, size_t data_size) {
+void i2c_recv(const char * data, size_t data_size) {
if (i2c_dump_recv) {
- printf("[%s] addr(0x%02x) data(0x%02lx):\n", __FUNCTION__, addr, data_size);
+ printf("[%s] data(0x%02lx):\n", __FUNCTION__, data_size);
xxd(data, data_size);
}
}
diff --git a/client/i2c.h b/client/i2c.h
index f9f58f9..87f33c9 100644
--- a/client/i2c.h
+++ b/client/i2c.h
@@ -3,6 +3,33 @@
#include <stdint.h>
#include <stddef.h>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_i2c i2c
+ * \brief I2C abstraction functions
+ * \{
+ */
+
+/**
+ * \brief Fake I2C send function
+ *
+ * This function sends an I2C message to the main controller over TCP using
+ * \ref i2ctcp.
+ *
+ * \param addr I2C address
+ * \param data Data to send
+ * \param data_size size of \p data
+ */
void i2c_send(uint16_t addr, const char * data, size_t data_size);
-void i2c_recv(uint16_t addr, const char * data, size_t data_size);
+/**
+ * \brief Fake I2C receive handler
+ *
+ * This function is called for I2C messages received by the main controller and
+ * forwarded to \ref pbc.
+ *
+ * \param data Received data
+ * \param data_size size of \p data
+ */
+void i2c_recv(const char * data, size_t data_size);
+/// \}
diff --git a/client/parse.h b/client/parse.h
index 94afe70..8b7d235 100644
--- a/client/parse.h
+++ b/client/parse.h
@@ -2,11 +2,23 @@
#include <stddef.h>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_parse parse
+ * \brief Debug send command parser utilities
+ * \{
+ */
+
+//! Internal field separator (i.e. whitespace delimiter)
#define IFS " \t\n"
+//! Octal digit character set
#define SET_OCT "01234567"
+//! Decimal digit character set
#define SET_DEC "0123456789"
+//! Hexadecimal digit character set
#define SET_HEX SET_DEC"abcdefABCDEF"
+//! (Hexadecimal) byte string character set
#define SET_HEX_STR SET_HEX":"
/**
@@ -40,3 +52,5 @@ char* consume_token(char * token, const char * ifs);
*/
int strtodata(const char * str, char ** data, size_t * size);
+/// \}
+
diff --git a/client/rl.cpp b/client/rl.cpp
index fa44bf4..f839d96 100644
--- a/client/rl.cpp
+++ b/client/rl.cpp
@@ -119,24 +119,25 @@ int rl_word(const char * line, int cursor) {
return word;
}
+/// \internal
typedef struct {
const char * word;
- const char ** suggestions;
+ const char ** options;
} __rl_complete_list_data_t;
-char** rl_complete_list(const char * word, const char ** suggestions) {
+char** rl_complete_list(const char * word, const char ** options) {
__rl_complete_list_data_t data = {
.word = word,
- .suggestions = suggestions,
+ .options = options,
};
return rl_completion_matches((char *) &data, [](const char * text, int state) -> char * {
__rl_complete_list_data_t data = *(__rl_complete_list_data_t *) text;
static size_t i = 0;
if (state == 0) i = 0;
- while (data.suggestions[i] != NULL) {
- const char * suggestion = data.suggestions[i++];
- if (strncmp(data.word, suggestion, strlen(data.word)) == 0)
- return strdup(suggestion);
+ while (data.options[i] != NULL) {
+ const char * option = data.options[i++];
+ if (strncmp(data.word, option, strlen(data.word)) == 0)
+ return strdup(option);
}
return NULL;
});
diff --git a/client/rl.h b/client/rl.h
index ab31ddb..d2f8612 100644
--- a/client/rl.h
+++ b/client/rl.h
@@ -1,12 +1,53 @@
#pragma once
+/**
+ * \ingroup pbc
+ * \defgroup pbc_rl rl
+ * \brief GNU Readline related functions
+ * \{
+ */
+
+//! Reset color (ANSI sequence)
#define COLOR_OFF "\x1b[0m"
+//! Set font to bold (ANSI sequence)
#define COLOR_BOLD "\x1b[1m"
+//! Prompt text
#define CLI_PROMPT "(" COLOR_BOLD "pbc" COLOR_OFF ") "
+//! CLI entrypoint
int cli_main();
+
+/**
+ * \brief Print format string to stdout without disturbing the readline prompt
+ *
+ * This function saves and restores the current readline prompt before/after
+ * calling printf. This function is not required for commands that print output
+ * synchronously, as the prompt is only shown after a command handler
+ * completes.
+ */
void rl_printf(const char * fmt, ...);
+/**
+ * \brief Get the index of the word currently under the cursor
+ *
+ * \param line Command line contents
+ * \param cursor Index of cursor position
+ *
+ * This function returns the index of the word from an array made by splitting
+ * \p line on consecutive occurrences of \c IFS.
+ *
+ * \return Index of word
+ */
int rl_word(const char * line, int cursor);
-char ** rl_complete_list(const char * word, const char * suggestions[]);
+/**
+ * \brief Create a completion suggestion string array for readline
+ *
+ * \param word Word to complete
+ * \param options List of possible choices (NULL terminated array of strings)
+ *
+ * \return Suggestions matching \p word
+ */
+char ** rl_complete_list(const char * word, const char * options[]);
+
+/// \}
diff --git a/client/sock.h b/client/sock.h
index 0dee09e..c124e45 100644
--- a/client/sock.h
+++ b/client/sock.h
@@ -3,29 +3,72 @@
#include <cstdint>
#include <thread>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_sock sock
+ * \brief TCP socket handling
+ * \{
+ */
+
+/**
+ * \brief Asynchronous puzzle box socket connection
+ * \note Once connected, this class will call \c i2c_recv() when a complete I2C
+ * message has been received
+ */
class PBSocket {
public:
PBSocket();
PBSocket(const char * addr, uint16_t port);
virtual ~PBSocket();
+ //! Configure target server
void set_server(const char * addr, uint16_t port);
+ //! Attempt to connect to server and start \c sock_task() in a thread
void sock_connect();
+ /**
+ * \brief Send data over the TCP connection
+ *
+ * \param buf Data to send
+ * \param buf_sz Size of \p buf in bytes
+ */
void send(const char * buf, size_t buf_sz);
private:
+ /**
+ * \brief Continously read from the TCP socket and read \ref i2ctcp messages
+ * using \c i2ctcp_read().
+ *
+ * Once a complete message has been parsed, \c i2c_recv() is called with the
+ * complete message. This message is automatically free'd after \c i2c_recv()
+ * returns.
+ *
+ * \note This function is run in a separate thread
+ */
void sock_task();
+ //! Close the socket
void sock_close();
+ //! Pointer to thread running \c sock_task()
std::thread* _thread = nullptr;
+ /**
+ * \brief IP address of server to connect to
+ *
+ * \note This member must contain an IP address, as no hostname resolution is
+ * done in pbc.
+ */
const char * _addr = NULL;
+ //! Port number of server to connect to
uint16_t _port = 0;
+ //! Unix file descriptor of opened socket
int _fd = -1;
};
+//! Singleton \c PBSocket instance
extern PBSocket* sock;
+/// \}
+
diff --git a/client/xxd.h b/client/xxd.h
index fb28bb1..ede9fff 100644
--- a/client/xxd.h
+++ b/client/xxd.h
@@ -7,10 +7,19 @@ extern "C" {
#endif
/**
+ * \ingroup pbc
+ * \defgroup pbc_xxd xxd
+ * \brief Utility hexdump
+ * \{
+ */
+
+/**
* \brief utility function that prints hexdump of data
*/
void xxd(const char * data, size_t size);
+/// \}
+
#ifdef __cplusplus
}
#endif