From 1cef583b11a13418d00c90273c21aaa6c06326b9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 14:08:01 -0600 Subject: [PATCH 1/8] cdba-server: Introduce helper for sending measurements The current format of the cdb_assist backend status messages was never intended to be parsed by a non-human, and the format doesn't extend well to other backends. Extend the format to be formatted as a json string, with a timestamp, implemented in a separate status module. The button status is skipped from the new status message, as it reflect the output-values as set by cdba itself, rather than any measured state. The timestamp is offset to the first measurement, to avoid disclosing the uptime of the machine cdba-server is running on. Signed-off-by: Bjorn Andersson --- cdb_assist.c | 36 ++++++++++++++---------- meson.build | 3 +- status.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ status.h | 20 +++++++++++++ 4 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 status.c create mode 100644 status.h diff --git a/cdb_assist.c b/cdb_assist.c index d62ef22..555432c 100644 --- a/cdb_assist.c +++ b/cdb_assist.c @@ -43,6 +43,7 @@ #include "cdba-server.h" #include "device.h" +#include "status.h" struct cdb_assist { char serial[9]; @@ -341,20 +342,27 @@ static void cdb_gpio(struct cdb_assist *cdb, int gpio, bool on) static void cdb_assist_print_status(struct device *dev) { struct cdb_assist *cdb = dev->cdb; - char buf[128]; - int n; - - n = sprintf(buf, "%umV %umA%s%s%s%s%s ref: %umV", - cdb->voltage_set, - cdb->current_actual, - cdb->vbat ? " vbat" : "", - cdb->vbus ? " vbus" : "", - cdb->btn[0] ? " btn1" : "", - cdb->btn[1] ? " btn2" : "", - cdb->btn[2] ? " btn3" : "", - cdb->vref); - - cdba_send_buf(MSG_STATUS_UPDATE, n, buf); + struct status_value vbat[] = { + { + .unit = STATUS_MV, + .value = cdb->voltage_set, + }, + { + .unit = STATUS_MA, + .value = cdb->current_actual, + }, + {} + }; + struct status_value vref[] = { + { + .unit = STATUS_MV, + .value = cdb->vref, + }, + {} + }; + + status_send_values("vbat", vbat); + status_send_values("vref", vref); } static void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV) diff --git a/meson.build b/meson.build index 63cb838..317d9d3 100644 --- a/meson.build +++ b/meson.build @@ -71,7 +71,8 @@ server_srcs = ['cdba-server.c', 'local-gpio.c', 'console.c', 'qcomlt_dbg.c', - 'ppps.c'] + 'ppps.c', + 'status.c'] if gpiod_dep.version().version_compare('>=2.0') server_srcs += ['local-gpio-v2.c'] diff --git a/status.c b/status.c new file mode 100644 index 0000000..dfa0357 --- /dev/null +++ b/status.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + +#include "cdba-server.h" +#include "status.h" + +static const char *sz_units[] = { + [STATUS_MV] = "mv", + [STATUS_MA] = "ma", + [STATUS_GPIO] = "gpio", +}; + +static void status_get_ts(struct timespec *ts) +{ + static struct timespec t0; + struct timespec t; + + if (!t0.tv_sec && !t0.tv_nsec) + clock_gettime(CLOCK_MONOTONIC, &t0); + + clock_gettime(CLOCK_MONOTONIC, &t); + + if (t.tv_nsec < t0.tv_nsec) { + ts->tv_sec = t.tv_sec - t0.tv_sec - 1; + ts->tv_nsec = 1000000000 + (t.tv_nsec - t0.tv_nsec); + } else { + ts->tv_sec = t.tv_sec - t0.tv_sec; + ts->tv_nsec = t.tv_nsec - t0.tv_nsec; + } +} + +void status_send_values(const char *id, struct status_value *values) +{ + struct status_value *value; + struct timespec ts; + char chunk[32]; + char buf[256]; + size_t len; + size_t n; + + status_get_ts(&ts); + + len = snprintf(buf, sizeof(buf), "{\"ts\":%ld.%03ld, \"%s\":{ ", ts.tv_sec, ts.tv_nsec / 1000000, id); + + for (value = values; value->unit; value++) { + if (value != values) { + if (len + 3 >= sizeof(buf)) { + warnx("status message overflow"); + return; + } + + strcpy(buf + len, ", "); + len += 2; + } + + n = snprintf(chunk, sizeof(chunk), "\"%s\": %u", sz_units[value->unit], value->value); + + if (len + n + 1>= sizeof(buf)) { + warnx("status message overflow"); + return; + } + + strcpy(buf + len, chunk); + len += n; + } + + if (len + 4 >= sizeof(buf)) { + warnx("status message overflow"); + return; + } + + strcpy(buf + len, "}}\n"); + len += 3; + + cdba_send_buf(MSG_STATUS_UPDATE, len, buf); +} diff --git a/status.h b/status.h new file mode 100644 index 0000000..4a12b1d --- /dev/null +++ b/status.h @@ -0,0 +1,20 @@ +#ifndef __STATUS_H__ +#define __STATUS_H__ + +#include + +enum status_unit { + STATUS_EOF, + STATUS_MV, + STATUS_MA, + STATUS_GPIO, +}; + +struct status_value { + enum status_unit unit; + unsigned int value; +}; + +void status_send_values(const char *id, struct status_value *values); + +#endif From 0a3d51e9c84ce94d1f97a53fc9a5996f18f19b87 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 14:16:43 -0600 Subject: [PATCH 2/8] cdba-server: Repurpose status update request The MSG_STATUS_UPDATE message when sent from the client to the server, has until now indicated a request for a single status update. This was suitable when the update was for human consumption on occasional basis. But with the transition to producing status messages for programatical consumption it makes more sense to just keep the stream on, without the client having to poll the server for updates. This can in particular keep the external "status command" mechanism simpler. Just enabling the stream of status updates would spam the console with status updates for those users that hasn't updated their clients, so the client needs to opt-in to the status stream. Repurpose the status update message (sent from the client) to indicate that the streaming of status updates should be enabled. Signed-off-by: Bjorn Andersson --- cdb_assist.c | 13 ++++++++++--- cdba-server.c | 2 +- device.c | 11 ++++++++--- device.h | 6 ++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/cdb_assist.c b/cdb_assist.c index 555432c..0cc801f 100644 --- a/cdb_assist.c +++ b/cdb_assist.c @@ -339,9 +339,9 @@ static void cdb_gpio(struct cdb_assist *cdb, int gpio, bool on) cdb_ctrl_write(cdb, &cmd[gpio][on], 1); } -static void cdb_assist_print_status(struct device *dev) +static void cdb_assist_print_status(void *data) { - struct cdb_assist *cdb = dev->cdb; + struct cdb_assist *cdb = data; struct status_value vbat[] = { { .unit = STATUS_MV, @@ -365,6 +365,13 @@ static void cdb_assist_print_status(struct device *dev) status_send_values("vref", vref); } +static void cdb_assist_status_enable(struct device *dev) +{ + struct cdb_assist *cdb = dev->cdb; + + watch_timer_add(1000, cdb_assist_print_status, cdb); +} + static void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV) { char buf[20]; @@ -392,7 +399,7 @@ const struct control_ops cdb_assist_ops = { .open = cdb_assist_open, .close = cdb_assist_close, .power = cdb_assist_power, - .print_status = cdb_assist_print_status, + .status_enable = cdb_assist_status_enable, .usb = cdb_assist_usb, .key = cdb_assist_key, }; diff --git a/cdba-server.c b/cdba-server.c index f1a7157..c65f606 100644 --- a/cdba-server.c +++ b/cdba-server.c @@ -210,7 +210,7 @@ static int handle_stdin(int fd, void *buf) // fprintf(stderr, "fastboot boot\n"); break; case MSG_STATUS_UPDATE: - device_print_status(selected_device); + device_status_enable(selected_device); break; case MSG_VBUS_ON: device_usb(selected_device, true); diff --git a/device.c b/device.c index 01f369c..1b1fb8a 100644 --- a/device.c +++ b/device.c @@ -260,10 +260,15 @@ int device_power(struct device *device, bool on) return device_power_off(device); } -void device_print_status(struct device *device) +void device_status_enable(struct device *device) { - if (device_has_control(device, print_status)) - device_control(device, print_status); + if (device->status_enabled) + return; + + if (device_has_control(device, status_enable)) + device_control(device, status_enable); + + device->status_enabled = true; } void device_usb(struct device *device, bool on) diff --git a/device.h b/device.h index 5fdd47b..66e260f 100644 --- a/device.h +++ b/device.h @@ -17,7 +17,7 @@ struct control_ops { int (*power)(struct device *dev, bool on); void (*usb)(struct device *dev, bool on); void (*key)(struct device *device, int key, bool asserted); - void (*print_status)(struct device *dev); + void (*status_enable)(struct device *dev); }; struct console_ops { @@ -46,6 +46,8 @@ struct device { int state; bool has_power_key; + bool status_enabled; + void (*boot)(struct device *); const struct control_ops *control_ops; @@ -73,7 +75,7 @@ struct device *device_open(const char *board, void device_close(struct device *dev); int device_power(struct device *device, bool on); -void device_print_status(struct device *device); +void device_status_enable(struct device *device); void device_usb(struct device *device, bool on); int device_write(struct device *device, const void *buf, size_t len); From 130720a6dfeb75badfb8c3a3c41d8c7c9315a8a9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 14:28:48 -0600 Subject: [PATCH 3/8] cdba: Introduce status pipe The updated format and behavior of the status messages is not useful for human consumption in the console stream, but rather for programatical consumption by 3rd party tools. Switch the status message stream to an optional fifo, which can be consumed separately from the console - by humans or by tools. The fifo is created and opened and status messages requested, if the '-s ' option is specified. Signed-off-by: Bjorn Andersson --- cdba.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/cdba.c b/cdba.c index 00c02b1..a16069a 100644 --- a/cdba.c +++ b/cdba.c @@ -52,6 +52,8 @@ static bool quit; static bool fastboot_repeat; static bool fastboot_done; +static int status_fd = -1; + static const char *fastboot_file; static struct termios *tty_unbuffer(void) @@ -398,12 +400,40 @@ static void request_fastboot_files(void) static void handle_status_update(const void *data, size_t len) { - char *str = alloca(len + 1); + if (status_fd < 0) + return; + + write(status_fd, data, len); +} + +static void status_enable_fn(struct work *work, int ssh_stdin) +{ + cdba_send(ssh_stdin, MSG_STATUS_UPDATE); + + free(work); +} + +static void status_pipe_open(const char *path) +{ + struct work *work; + int ret; + int fd; + + ret = mkfifo(path, 0600); + if (ret < 0 && errno != EEXIST) + err(1, "failed to create fifo %s", path); + + fd = open(path, O_RDWR | O_NONBLOCK); + if (fd < 0) + err(1, "failed to open fifo %s", path); - memcpy(str, data, len); - str[len] = '\n'; + status_fd = fd; - write(STDOUT_FILENO, str, len + 1); + /* Queue a MSG_STATUS_UPDATE request */ + work = malloc(sizeof(*work)); + work->fn = status_enable_fn; + + list_add(&work_items, &work->node); } static void handle_list_devices(const void *data, size_t len) @@ -577,6 +607,7 @@ int main(int argc, char **argv) struct timeval timeout_total_tv; struct termios *orig_tios; const char *server_binary = "cdba-server"; + const char *status_pipe = NULL; int timeout_inactivity = 0; int timeout_total = 600; struct work *next; @@ -597,7 +628,7 @@ int main(int argc, char **argv) int opt; int ret; - while ((opt = getopt(argc, argv, "b:c:C:h:ilRt:S:T:")) != -1) { + while ((opt = getopt(argc, argv, "b:c:C:h:ilRt:S:s:T:")) != -1) { switch (opt) { case 'b': board = optarg; @@ -623,6 +654,9 @@ int main(int argc, char **argv) case 'S': server_binary = optarg; break; + case 's': + status_pipe = optarg; + break; case 't': timeout_total = atoi(optarg); break; @@ -661,6 +695,9 @@ int main(int argc, char **argv) break; } + if (status_pipe) + status_pipe_open(status_pipe); + ret = fork_ssh(host, server_binary, ssh_fds); if (ret) err(1, "failed to connect to \"%s\"", host); From c8e29e34003b39652a0046e30ff15b362133f81f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 14:37:32 -0600 Subject: [PATCH 4/8] qcomlt_dbg: Enable power status reporting The QcomLT DebugBoard has a voltage and current sensor on the 12V DC line, which the firmware will measure upon request. Add a periodic request for this information, parse out the responses and report using the status helper functions. Signed-off-by: Bjorn Andersson --- qcomlt_dbg.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/qcomlt_dbg.c b/qcomlt_dbg.c index bda7e61..64cfc2c 100644 --- a/qcomlt_dbg.c +++ b/qcomlt_dbg.c @@ -44,10 +44,25 @@ #include "cdba-server.h" #include "device.h" +#include "status.h" + +enum qcomlt_parse_state { + STATE_, + STATE_num, + STATE_num_m, + STATE_num_mV, + STATE_num_mV_num, + STATE_num_mV_num_m, + STATE_err, +}; struct qcomlt_dbg { int fd; struct termios orig_tios; + + enum qcomlt_parse_state parse_state; + unsigned long mv; + unsigned long ma; }; static void *qcomlt_dbg_open(struct device *dev) @@ -100,9 +115,124 @@ static void qcomlt_dbg_key(struct device *dev, int key, bool asserted) } } +static int qcomlt_dbg_ctrl_data(int fd, void *data) +{ + struct qcomlt_dbg *dbg = data; + struct status_value dc[] = { + { + .unit = STATUS_MV, + }, + { + .unit = STATUS_MA, + }, + {} + }; + char buf[64]; + ssize_t i; + ssize_t n; + char ch; + + n = read(fd, buf, sizeof(buf)); + if (n < 0) + return n; + + for (i = 0; i < n; i++) { + ch = buf[i]; + + /* + * The control data consists of a stream in the format: + * mV mA + * + * The stream might be split in arbitrary ways across reads, so + * a parser is used instead of sscanf(). + * In the initial state any non-digits are ignored, if a parse + * error occurs thereafter all characters until 'A' are + * dropped, with the result that any unexpected control + * messages are ignored. + */ + switch (dbg->parse_state) { + case STATE_: + if (isdigit(ch)) { + dbg->mv = ch - '0'; + dbg->parse_state = STATE_num; + } + break; + case STATE_num: + if (isdigit(ch)) { + dbg->mv *= 10; + dbg->mv += ch - '0'; + } else if (ch == 'm') { + dbg->parse_state = STATE_num_m; + } else { + dbg->parse_state = STATE_err; + } + break; + case STATE_num_m: + if (ch == 'V') + dbg->parse_state = STATE_num_mV; + else + dbg->parse_state = STATE_err; + break; + case STATE_num_mV: + if (isdigit(ch)) { + dbg->ma = ch - '0'; + dbg->parse_state = STATE_num_mV_num; + } else if (!isspace(ch)) { + dbg->parse_state = STATE_err; + } + break; + case STATE_num_mV_num: + if (isdigit(ch)) { + dbg->ma *= 10; + dbg->ma += ch - '0'; + } else if (ch == 'm') { + dbg->parse_state = STATE_num_mV_num_m; + } else { + dbg->parse_state = STATE_err; + } + break; + case STATE_num_mV_num_m: + if (ch == 'A') { + /* Parser found a match, report it */ + dc[0].value = dbg->mv; + dc[1].value = dbg->ma; + + status_send_values("dc", dc); + } else { + dbg->parse_state = STATE_err; + } + break; + case STATE_err: + if (ch == 'A') + dbg->parse_state = STATE_; + break; + } + } + + return 0; +} + +static void qcomlt_dbg_request_status(void *data) +{ + struct qcomlt_dbg *dbg = data; + + write(dbg->fd, "s", 1); + + watch_timer_add(200, qcomlt_dbg_request_status, dbg); +} + +static void qcomlt_dbg_status_enable(struct device *dev) +{ + struct qcomlt_dbg *dbg = dev->cdb; + + watch_add_readfd(dbg->fd, qcomlt_dbg_ctrl_data, dbg); + watch_timer_add(200, qcomlt_dbg_request_status, dbg); +} + const struct control_ops qcomlt_dbg_ops = { .open = qcomlt_dbg_open, .power = qcomlt_dbg_power, .usb = qcomlt_dbg_usb, .key = qcomlt_dbg_key, + .status_enable = qcomlt_dbg_status_enable, }; From 81e46878eddb2cef5652a724037db410aa7f2567 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 14:47:10 -0600 Subject: [PATCH 5/8] cdba-server: Allow external status command While the CDB Assist and QcomLT Debugboard is measuring voltage and current on the DC jack directly in the backend, other backends and further measurements can be performed using custom tooling. Introduce support for invoking an external "status-cmd" to produce such status updates. The status command should on its stdout produce json-formatted status updates following the same format as the cdba-server: {"ts":%d.%03d, "name": {["mv"|"ma"]: %u}(, "name2": {["mv"|"ma"]: %u})*} with the ts aquired using clock_gettime(CLOCK_MONOTONIC) and provided in seconds and milliseconds since the first measurement. Signed-off-by: Bjorn Andersson --- device.c | 4 +++ device.h | 2 ++ device_parser.c | 2 ++ meson.build | 10 +++++- schema.yaml | 4 +++ status-cmd.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ status-cmd.h | 8 +++++ status.c | 5 +++ status.h | 1 + 9 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 status-cmd.c create mode 100644 status-cmd.h diff --git a/device.c b/device.c index 1b1fb8a..469237e 100644 --- a/device.c +++ b/device.c @@ -45,6 +45,7 @@ #include "fastboot.h" #include "list.h" #include "ppps.h" +#include "status-cmd.h" #define ARRAY_SIZE(x) ((sizeof(x)/sizeof((x)[0]))) @@ -268,6 +269,9 @@ void device_status_enable(struct device *device) if (device_has_control(device, status_enable)) device_control(device, status_enable); + if (device->status_cmd) + status_cmd_open(device); + device->status_enabled = true; } diff --git a/device.h b/device.h index 66e260f..600cbe5 100644 --- a/device.h +++ b/device.h @@ -58,6 +58,8 @@ struct device { void *cdb; void *console; + char *status_cmd; + struct list_head node; }; diff --git a/device_parser.c b/device_parser.c index a137628..fd65816 100644 --- a/device_parser.c +++ b/device_parser.c @@ -193,6 +193,8 @@ static void parse_board(struct device_parser *dp) dev->ppps_path = strdup(value); } else if (!strcmp(key, "ppps3_path")) { dev->ppps3_path = strdup(value); + } else if (!strcmp(key, "status-cmd")) { + dev->status_cmd = strdup(value); } else { fprintf(stderr, "device parser: unknown key \"%s\"\n", key); exit(1); diff --git a/meson.build b/meson.build index 317d9d3..f1d12bd 100644 --- a/meson.build +++ b/meson.build @@ -58,6 +58,13 @@ server_deps = [dependency('libudev', required: server_opt), dependency('yaml-0.1', required: server_opt), gpiod_dep, ftdi_dep] + +# E.g. Debian reuires -lutil for forkpty +if not compiler.has_function('forkpty') + util_dep = compiler.find_library('util') + server_deps += util_dep +endif + server_srcs = ['cdba-server.c', 'cdb_assist.c', 'circ_buf.c', @@ -72,7 +79,8 @@ server_srcs = ['cdba-server.c', 'console.c', 'qcomlt_dbg.c', 'ppps.c', - 'status.c'] + 'status.c', + 'status-cmd.c'] if gpiod_dep.version().version_compare('>=2.0') server_srcs += ['local-gpio-v2.c'] diff --git a/schema.yaml b/schema.yaml index caf0860..d4c0338 100644 --- a/schema.yaml +++ b/schema.yaml @@ -73,6 +73,10 @@ properties: description: USB device name, like 2-2:1.0/2-2-port2 type: string + status-cmd: + description: Command to execute for generating status updates + type: string + qcomlt_debug_board: description: Qlt Debug Board control tty device path $ref: "#/$defs/device_path" diff --git a/status-cmd.c b/status-cmd.c new file mode 100644 index 0000000..3529a63 --- /dev/null +++ b/status-cmd.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023, Qualcomm Innovaction Center, Inc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cdba-server.h" +#include "device.h" +#include "status.h" +#include "status-cmd.h" + +static void launch_status_cmd(struct device *dev) +{ + char *tokens[100]; + char *p; + int t = 0; + + p = strtok(dev->status_cmd, " "); + while (p) { + tokens[t++] = p; + p = strtok(NULL, " "); + if (t == 100) + exit(1); + } + tokens[t] = NULL; + + execvp(tokens[0], tokens); + exit(1); +} + +static int status_data(int fd, void *data) +{ + char buf[128]; + ssize_t n; + + n = read(fd, buf, sizeof(buf)); + if (n <= 0) + return n; + + status_send_raw(buf, n); + return 0; +} + +int status_cmd_open(struct device *dev) +{ + pid_t status_pid; + int fd; + + status_pid = forkpty(&fd, NULL, NULL, NULL); + if (status_pid < 0) + err(1, "failed to fork"); + + if(status_pid == 0) { + launch_status_cmd(dev); + /* Notreached */ + } + + watch_add_readfd(fd, status_data, dev); + + return 0; +} diff --git a/status-cmd.h b/status-cmd.h new file mode 100644 index 0000000..5dc9c24 --- /dev/null +++ b/status-cmd.h @@ -0,0 +1,8 @@ +#ifndef __STATUS_CMD_H__ +#define __STATUS_CMD_H__ + +struct device; + +int status_cmd_open(struct device *dev); + +#endif diff --git a/status.c b/status.c index dfa0357..431c04f 100644 --- a/status.c +++ b/status.c @@ -77,3 +77,8 @@ void status_send_values(const char *id, struct status_value *values) cdba_send_buf(MSG_STATUS_UPDATE, len, buf); } + +void status_send_raw(const char *data, size_t len) +{ + cdba_send_buf(MSG_STATUS_UPDATE, len, data); +} diff --git a/status.h b/status.h index 4a12b1d..4838b51 100644 --- a/status.h +++ b/status.h @@ -16,5 +16,6 @@ struct status_value { }; void status_send_values(const char *id, struct status_value *values); +void status_send_raw(const char *data, size_t len); #endif From cc91b34f3a0c93b353262951b2ed92989aa844d0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 19:52:52 -0600 Subject: [PATCH 6/8] device: Disable USB on boot Leaving USB connected might cause hickups on the USB bus, and causes power measurements to report incorrect data. Turn it off once the image has been downloaded. Signed-off-by: Bjorn Andersson --- device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/device.c b/device.c index 469237e..95cded8 100644 --- a/device.c +++ b/device.c @@ -309,6 +309,11 @@ void device_boot(struct device *device, const void *data, size_t len) fastboot_set_active(device->fastboot, device->set_active); fastboot_download(device->fastboot, data, len); device->boot(device); + + if (device->status_enabled && !device->usb_always_on) { + warnx("disabling USB, use ^A V to enable"); + device_usb(device, false); + } } void device_send_break(struct device *device) From 6d8ff75e310beee4f5ab1fdf43aab85c83b47c9e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 5 Nov 2023 22:00:05 -0600 Subject: [PATCH 7/8] README: Introduce status messages and fifo Introduce description of the status fifo, the status command, and the data format for these in the README. Signed-off-by: Bjorn Andersson --- README | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/README b/README index 8a4d84c..8a1824e 100644 --- a/README +++ b/README @@ -18,7 +18,7 @@ from sandbox/cdba/cdba-server. Available devices are read from $HOME/.cdba = Client side The client is invoked as: - cdba -b -h [-c ] boot.img + cdba -b -h [-c ] [-s ] boot.img will be connected to using ssh and will be selected for operation. As the board's fastboot interface shows up the given boot.img will @@ -31,9 +31,23 @@ If the optional -c is given, the board will upon receiving the tilde sequence restart the board the given number of times. Each time booting the given boot.img. +The optional -s argument can be used to specify that a fifo should be created +and opened. cdba will request the server to start sending status/measurement +updates, which will be written to this fifo. + += Server side + == Device configuration The list of attached devices is read from $HOME/.cdba and is YAML formatted. +== Status command + +The "status-cmd" property for a board specifies a command line that should be +executed to perform measurements and report status updates to the client. The +command is expected to run for the duration of the board session and should +produce a continuous stream of json-formatted lines of status updates according +to the format defined in this document. + === Example devices: - board: db2k @@ -110,3 +124,38 @@ devices: fastboot: cacafada fastboot_set_active: true fastboot_key_timeout: 2 + += Status messages + +The status messages that are used by the client fifo and the server's status +command should be json-formatted, with one status update per line. + +Each message should contain one timestamp member "ts", and one or more +measurement members. Like so: + + {"ts":%d.%03d, "name": {["mv"|"ma"]: %u}(, "name2": {["mv"|"ma"]: %u})*} + +The timestamp member ("ts"), should provide the time since first measurement in +decimal form with millisecond accuracy. + +The key for the measurement members should be an identifier of the measured +resources, and the value should be an object with members for each unit +measured for the given resource and the measured value. + +Valid units to report are "mv", "ma", and "mw". + +Note that the cadence of measurement might differ between different items to be +measured, so not all status messages contains data for all items that can be +measured. + +== Examples + +Single resource "dc" measured at 20.271s, with voltage and current reported: + + {"ts":20.271, "dc":{ "mv": 12165, "ma": 114}} + +Multiple resources measured in a single status message, followed by single +resource measurement, all with voltage and current reported: + + {"ts":38.341, "battery":{"mv":8023, "ma":725}, "vdd_cx":{"mv":750, "ma":466}} + {"ts":44.339, "battery":{"mv":8023, "ma":733}} From 0ad34da4f2d56f51a798d236d61beda3297e5df5 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 6 Nov 2023 09:51:04 -0600 Subject: [PATCH 8/8] samples: Provide sample with status-cmd Provide a sample defining the status-cmd property. Signed-off-by: Bjorn Andersson --- config-samples/sample11.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 config-samples/sample11.yaml diff --git a/config-samples/sample11.yaml b/config-samples/sample11.yaml new file mode 100644 index 0000000..9496b39 --- /dev/null +++ b/config-samples/sample11.yaml @@ -0,0 +1,8 @@ +--- +devices: + - board: myboard + name: "My Board" + alpaca: /dev/ttyACM0 + console: /dev/ttyUSB0 + fastboot: cacafada + status-cmd: /usr/bin/sample-measure-app --sample-rate 100 /dev/measure0