aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-05-29 15:07:30 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-05-29 15:07:30 +0200
commit439859f1133fb88e64df31acaa1b2845e36ba348 (patch)
tree5b969df2140de21bfce64bc63e403e3e3429386b
parent81cbd31a1a6a0e521ab262492245ec109c25ec8b (diff)
add documentation + string escape
-rw-r--r--client/cmd.cpp18
-rw-r--r--client/cmd.h18
-rw-r--r--client/parse.cpp17
-rw-r--r--client/pbc.194
4 files changed, 123 insertions, 24 deletions
diff --git a/client/cmd.cpp b/client/cmd.cpp
index 2871daf..a6242af 100644
--- a/client/cmd.cpp
+++ b/client/cmd.cpp
@@ -67,15 +67,15 @@ void cmd_send(char* addr_str) {
free(data);
}
-void cmd_status(char*) {
- const char msg[] = {
- PB_CMD_READ,
- 0x00, // addr 0 = global state
- };
- i2c_send(BUSADDR_MAIN, msg, sizeof(msg));
- // NOTE: the reply handler will automatically print the state once it's
- // received
-}
+// void cmd_status(char*) {
+// const char msg[] = {
+// PB_CMD_READ,
+// 0x00, // addr 0 = global state
+// };
+// i2c_send(BUSADDR_MAIN, msg, sizeof(msg));
+// // NOTE: the reply handler will automatically print the state once it's
+// // received
+// }
void cmd_reset(char*) {
const char msg[] = {
diff --git a/client/cmd.h b/client/cmd.h
index 9c58fb6..7fefe98 100644
--- a/client/cmd.h
+++ b/client/cmd.h
@@ -17,7 +17,6 @@ cmd_handle_t cmd_exit;
cmd_handle_t cmd_test;
cmd_handle_t cmd_help;
cmd_complete_t cmd_help_complete;
-cmd_handle_t cmd_status;
cmd_handle_t cmd_reset;
cmd_handle_t cmd_ls;
cmd_handle_t cmd_send;
@@ -30,21 +29,11 @@ static const cmd_t cmds[] = {
.info = "exit pbc",
},
{
- .handle = cmd_test,
- .name = "test",
- .info = "send a test puzbus message",
- },
- {
.handle = cmd_help,
.name = "help",
.info = "show this help",
},
{
- .handle = cmd_status,
- .name = "status",
- .info = "show global puzzle box state (main controller state)",
- },
- {
.handle = cmd_reset,
.name = "reset",
.info = "set game state to 'idle' for one or more puzzle modules",
@@ -57,7 +46,7 @@ static const cmd_t cmds[] = {
{
.handle = cmd_ls,
.name = "ls",
- .info = "list connected puzzle modules",
+ .info = "list connected puzzle modules and their state",
},
#ifdef DEBUG
{
@@ -65,6 +54,11 @@ static const cmd_t cmds[] = {
.name = "send",
.info = "[debug] send raw message",
},
+ {
+ .handle = cmd_test,
+ .name = "test",
+ .info = "[debug] send a test puzbus message",
+ },
#endif
};
static const size_t cmds_length = sizeof(cmds) / sizeof(cmds[0]);
diff --git a/client/parse.cpp b/client/parse.cpp
index 56d1137..16f0781 100644
--- a/client/parse.cpp
+++ b/client/parse.cpp
@@ -6,7 +6,6 @@
#include "parse.h"
static int parse_string(const char * str, char * data, size_t * offset) {
- char closing = str[0];
char escape = false;
int i = 0;
size_t len = strlen(str);
@@ -21,15 +20,27 @@ static int parse_string(const char * str, char * data, size_t * offset) {
default:
return -i;
}
+ char closing = str[i];
for (i = 1; i < len && str[i] != '\0'; i++, *offset += 1) {
char c = str[i];
- // TODO: handle escaped characters
-
if (c == closing)
return i + 1; // +1 for closing quote
+ if (escape && c == '\\') {
+ char x = str[i + 1];
+ if (x == '0') c = '\0';
+ else if (x == 't') c = '\t';
+ else if (x == 'n') c = '\n';
+ else if (x == 'r') c = '\r';
+ else if (x == '\\') c = '\\';
+ else if (x == '\"') c = '\"';
+ else if (x == '\'') c = '\'';
+ else break;
+ i++;
+ }
+
if (data != NULL)
data[*offset] = c;
}
diff --git a/client/pbc.1 b/client/pbc.1
index e69de29..f5a2198 100644
--- a/client/pbc.1
+++ b/client/pbc.1
@@ -0,0 +1,94 @@
+\# vim: ft=groff
+.de I2C
+I\*{2\*}C
+..
+.TH pbc 1
+.SH NAME
+pbc \- puzzle box client
+.SH SYNPOSIS
+pbc <addr> [port]
+.SH DESCRIPTION
+Connect to a puzzle box at the IPv4 address specified by \fIaddr\fP and
+optionally port specified by \fIport\fP. The default port is 9191. Once
+connected, a
+.MR readline 3 -based
+CLI is started, and commands can be sent.
+.SH COMMANDS
+.TP
+exit
+Disconnect from the puzzle box and exit pbc. This command takes no arguments.
+.TP
+help
+Print a list of available commands with descriptions. This command takes no
+arguments.
+.TP
+ls
+List all puzzle modules, their state, and the combined state of all puzzle
+modules (global state of the main controller).
+.TP
+reset [mod ...]
+Set the main controller or specific puzzle module's global state to \fIidle\fP.
+If no modules are specified, the main controller's state is updated. One or
+more modules can be specified to update them at once.
+.TP
+skip [mod ...]
+Set the main controller or specific puzzle module's global state to
+\fIsolved\fP. If no modules are specified, the main controller's state is
+updated. One or more modules can be specified to update them at once.
+.SH DEBUG COMMANDS
+The commands detailed under this section are only available in version of pbc
+compiled with debug support.
+.TP
+send <addr> <data>
+Send arbitrary data specified by \fIdata\fP to the
+.I2C
+address specified by \fIaddr\fP. \fIdata\fP may consist of multiple arguments
+separated by IFS, in which case the arguments are concatenated.
+.TP
+test
+Send a test command containing the ASCII string "Hello world!" to
+.I2C
+address 0x39. This command takes no arguments.
+.SH DATA FORMATS
+.TP
+number
+Numbers can be specified as decimal or hexadecimal using a "0x" prefix. All
+numbers are unsigned. Decimal literals are always cast to 8-bit integers, while
+hexadecimal literals are cast to the smallest type that will fit the specified
+number. Numbers are always sent as little endian.
+
+Examples: 0 123 255 0x10 0x1245 0xdeadBEEF
+.TP
+hexstr
+Hexadecimal string literals are specified by hexadecimal bytes separated by
+colons. Each byte must be exactly 2 hexadecimal characters long and followed by
+a colon (except for the last byte). The minimum length of a hexstr is 2 bytes,
+as it must include at least a single colon.
+
+Examples: de:ad:be:ef 00:00
+.TP
+string
+A string literal starts and ends with a single quote. All characters within
+this literal are sent as-is, and no escaping is possible.
+
+Examples: 'Hello world!' 'string' ' hello '
+
+When double quotes are used instead of single quotes, the following escape
+sequences are recognised and replaced with special characters:
+
+\\0 -> 0x00 (null)
+.br
+\\t -> 0x09 (tab)
+.br
+\\n -> 0x0a (newline)
+.br
+\\r -> 0x0d (carriage return)
+.br
+\\\\ -> 0x5c (backslash)
+.br
+\\" -> 0x22 (double quote)
+.br
+\\' -> 0x27 (single quote)
+
+Examples: "Hello world!\\0" "foo\\nbar"
+