diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-05-29 15:07:30 +0200 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-05-29 15:07:30 +0200 |
commit | 439859f1133fb88e64df31acaa1b2845e36ba348 (patch) | |
tree | 5b969df2140de21bfce64bc63e403e3e3429386b /client | |
parent | 81cbd31a1a6a0e521ab262492245ec109c25ec8b (diff) |
add documentation + string escape
Diffstat (limited to 'client')
-rw-r--r-- | client/cmd.cpp | 18 | ||||
-rw-r--r-- | client/cmd.h | 18 | ||||
-rw-r--r-- | client/parse.cpp | 17 | ||||
-rw-r--r-- | client/pbc.1 | 94 |
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" + |