From fb23cabbc4dc0dfbefc42bc2a18e84219d21e3b4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 2 Oct 2023 17:32:13 +0300 Subject: [PATCH 1/6] device: change device_usb logic Allow PPPS function even if there is no device->usb callback. PPPS is useable even with no control interface. Signed-off-by: Dmitry Baryshkov --- device.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/device.c b/device.c index 826b038..a39d173 100644 --- a/device.c +++ b/device.c @@ -254,12 +254,10 @@ void device_print_status(struct device *device) void device_usb(struct device *device, bool on) { - if (device->usb) { - if (device->ppps_path) - ppps_power(device, on); - else - device->usb(device, on); - } + if (device->ppps_path) + ppps_power(device, on); + else if (device->usb) + device->usb(device, on); } int device_write(struct device *device, const void *buf, size_t len) From 3b089f313edbf08fac56186fab9307407bbc7673 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 2 Oct 2023 17:33:03 +0300 Subject: [PATCH 2/6] device: separate backend operations Separate backend operations into control and console operations. Main idea is that each device has single set of console ops (conmux or console) and at most one way to control it. Each backend driver exports a structure with the set of callbacks. Signed-off-by: Dmitry Baryshkov --- alpaca.c | 8 ++++++ cdb_assist.c | 10 ++++++++ conmux.c | 16 ++++++++++++ console.c | 33 ++++++++++++++++++++----- device.c | 60 ++++++++++++++++++++++++++------------------ device.h | 41 +++++++++++++++++++++--------- device_parser.c | 66 ++++++++++++++++++++++--------------------------- ftdi-gpio.c | 7 ++++++ qcomlt_dbg.c | 8 ++++++ 9 files changed, 171 insertions(+), 78 deletions(-) diff --git a/alpaca.c b/alpaca.c index fd7e996..f9994ad 100644 --- a/alpaca.c +++ b/alpaca.c @@ -43,6 +43,7 @@ #include "cdba-server.h" #include "alpaca.h" +#include "device.h" struct alpaca { int alpaca_fd; @@ -147,3 +148,10 @@ void alpaca_key(struct device *dev, int key, bool asserted) break; } } + +const struct control_ops alpaca_ops = { + .open = alpaca_open, + .power = alpaca_power, + .usb = alpaca_usb, + .key = alpaca_key, +}; diff --git a/cdb_assist.c b/cdb_assist.c index 549afbd..aab4b0a 100644 --- a/cdb_assist.c +++ b/cdb_assist.c @@ -43,6 +43,7 @@ #include "cdba-server.h" #include "cdb_assist.h" +#include "device.h" struct cdb_assist { char serial[9]; @@ -382,3 +383,12 @@ void cdb_assist_key(struct device *dev, int key, bool asserted) break; } } + +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, + .usb = cdb_assist_usb, + .key = cdb_assist_key, +}; diff --git a/conmux.c b/conmux.c index ef0e914..da7073a 100644 --- a/conmux.c +++ b/conmux.c @@ -42,6 +42,7 @@ #include "cdba-server.h" #include "conmux.h" +#include "device.h" extern int h_errno; @@ -331,3 +332,18 @@ int conmux_write(struct device *dev, const void *buf, size_t len) return write(conmux->fd, buf, len); } + +void *conmux_console_open(struct device *dev) +{ + return dev->cdb; +} + +const struct control_ops conmux_ops = { + .open = conmux_open, + .power = conmux_power, +}; + +const struct console_ops conmux_console_ops = { + .open = conmux_console_open, + .write = conmux_write, +}; diff --git a/console.c b/console.c index 0a21523..bdb6488 100644 --- a/console.c +++ b/console.c @@ -32,11 +32,17 @@ #include #include +#include #include #include "cdba-server.h" #include "device.h" +struct console { + int console_fd; + struct termios console_tios; +}; + static int console_data(int fd, void *data) { char buf[128]; @@ -51,21 +57,36 @@ static int console_data(int fd, void *data) return 0; } -void console_open(struct device *device) +void *console_open(struct device *device) { - device->console_fd = tty_open(device->console_dev, &device->console_tios); - if (device->console_fd < 0) + struct console *console; + + console = calloc(1, sizeof(*console)); + console->console_fd = tty_open(device->console_dev, &console->console_tios); + if (console->console_fd < 0) err(1, "failed to open %s", device->console_dev); - watch_add_readfd(device->console_fd, console_data, device); + watch_add_readfd(console->console_fd, console_data, device); + + return console; } int console_write(struct device *device, const void *buf, size_t len) { - return write(device->console_fd, buf, len);; + struct console *console = device->console; + + return write(console->console_fd, buf, len);; } void console_send_break(struct device *device) { - tcsendbreak(device->console_fd, 0); + struct console *console = device->console; + + tcsendbreak(console->console_fd, 0); } + +const struct console_ops console_ops = { + .open = console_open, + .write = console_write, + .send_break = console_send_break, +}; diff --git a/device.c b/device.c index a39d173..01f369c 100644 --- a/device.c +++ b/device.c @@ -43,12 +43,23 @@ #include "cdba-server.h" #include "device.h" #include "fastboot.h" -#include "console.h" #include "list.h" #include "ppps.h" #define ARRAY_SIZE(x) ((sizeof(x)/sizeof((x)[0]))) +#define device_has_control(_dev, _op) \ + ((_dev)->control_ops && (_dev)->control_ops->_op) + +#define device_control(_dev, _op, ...) \ + (_dev)->control_ops->_op((_dev) , ## __VA_ARGS__) + +#define device_has_console(_dev, _op) \ + ((_dev)->console_ops && (_dev)->console_ops->_op) + +#define device_console(_dev, _op, ...) \ + (_dev)->console_ops->_op((_dev) , ## __VA_ARGS__) + static struct list_head devices = LIST_INIT(devices); void device_add(struct device *device) @@ -118,21 +129,24 @@ struct device *device_open(const char *board, return NULL; found: - assert(device->open || device->console_dev); - if (!device_check_access(device, username)) return NULL; + assert(device->console_ops); + assert(device->console_ops->open); + assert(device->console_ops->write); + device_lock(device); - if (device->open) { - device->cdb = device->open(device); + if (device_has_control(device, open)) { + device->cdb = device_control(device, open); if (!device->cdb) errx(1, "failed to open device controller"); } - if (device->console_dev) - console_open(device); + device->console = device_console(device, open); + if (!device->console) + errx(1, "failed to open device console"); if (device->usb_always_on) device_usb(device, true); @@ -144,13 +158,13 @@ found: static void device_impl_power(struct device *device, bool on) { - device->power(device, on); + device_control(device, power, on); } static void device_key(struct device *device, int key, bool asserted) { - if (device->key) - device->key(device, key, asserted); + if (device_has_control(device, key)) + device_control(device, key, key, asserted); } enum { @@ -219,7 +233,7 @@ static void device_tick(void *data) static int device_power_on(struct device *device) { - if (!device || !device->power) + if (!device || !device_has_control(device, power)) return 0; device->state = DEVICE_STATE_START; @@ -230,10 +244,10 @@ static int device_power_on(struct device *device) static int device_power_off(struct device *device) { - if (!device || !device->power) + if (!device || !device_has_control(device, power)) return 0; - device->power(device, false); + device_control(device, power, false); return 0; } @@ -248,16 +262,16 @@ int device_power(struct device *device, bool on) void device_print_status(struct device *device) { - if (device->print_status) - device->print_status(device); + if (device_has_control(device, print_status)) + device_control(device, print_status); } void device_usb(struct device *device, bool on) { if (device->ppps_path) ppps_power(device, on); - else if (device->usb) - device->usb(device, on); + else if (device_has_control(device, usb)) + device_control(device, usb, on); } int device_write(struct device *device, const void *buf, size_t len) @@ -265,9 +279,7 @@ int device_write(struct device *device, const void *buf, size_t len) if (!device) return 0; - assert(device->write); - - return device->write(device, buf, len); + return device_console(device, write, buf, len); } void device_fastboot_boot(struct device *device) @@ -292,8 +304,8 @@ void device_boot(struct device *device, const void *data, size_t len) void device_send_break(struct device *device) { - if (device->send_break) - device->send_break(device); + if (device_has_console(device, send_break)) + device_console(device, send_break); } void device_list_devices(const char *username) @@ -346,6 +358,6 @@ void device_close(struct device *dev) device_usb(dev, false); device_power(dev, false); - if (dev->close) - dev->close(dev); + if (device_has_control(dev, close)) + device_control(dev, close); } diff --git a/device.h b/device.h index 0ee659b..2dba972 100644 --- a/device.h +++ b/device.h @@ -7,6 +7,23 @@ struct cdb_assist; struct fastboot; struct fastboot_ops; +struct device; + +struct control_ops { + void *(*open)(struct device *dev); + void (*close)(struct device *dev); + 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); +}; + +struct console_ops { + void *(*open)(struct device *dev); + int (*write)(struct device *dev, const void *buf, size_t len); + + void (*send_break)(struct device *dev); +}; struct device { char *board; @@ -27,22 +44,13 @@ struct device { void (*boot)(struct device *); - void *(*open)(struct device *dev); - void (*close)(struct device *dev); - int (*power)(struct device *dev, bool on); - void (*usb)(struct device *dev, bool on); - void (*print_status)(struct device *dev); - int (*write)(struct device *dev, const void *buf, size_t len); - void (*fastboot_key)(struct device *dev, bool on); - void (*key)(struct device *device, int key, bool asserted); + const struct control_ops *control_ops; + const struct console_ops *console_ops; - void (*send_break)(struct device *dev); const char *set_active; void *cdb; - - int console_fd; - struct termios console_tios; + void *console; struct list_head node; }; @@ -78,4 +86,13 @@ enum { DEVICE_KEY_POWER, }; +extern const struct control_ops alpaca_ops; +extern const struct control_ops cdb_assist_ops; +extern const struct control_ops conmux_ops; +extern const struct control_ops ftdi_gpio_ops; +extern const struct control_ops qcomlt_dbg_ops; + +extern const struct console_ops conmux_console_ops; +extern const struct console_ops console_ops; + #endif diff --git a/device_parser.c b/device_parser.c index bab9a1b..e4a386f 100644 --- a/device_parser.c +++ b/device_parser.c @@ -33,13 +33,6 @@ #include #include "device.h" -#include "alpaca.h" -#include "ftdi-gpio.h" -#include "cdb_assist.h" -#include "conmux.h" -#include "console.h" -#include "qcomlt_dbg.h" -#include "ppps.h" #define TOKEN_LENGTH 16384 @@ -82,6 +75,26 @@ static bool expect(struct device_parser *dp, int type, char *scalar) exit(1); } +static void set_control_ops(struct device *dev, const struct control_ops *ops) +{ + if (dev->control_ops) { + fprintf(stderr, "device parser: control operations are already selected for %s\n", dev->name); + exit(1); + } + + dev->control_ops = ops; +} + +static void set_console_ops(struct device *dev, const struct console_ops *ops) +{ + if (dev->console_ops) { + fprintf(stderr, "device parser: console operations are already selected for %s\n", dev->name); + exit(1); + } + + dev->console_ops = ops; +} + static void parse_board(struct device_parser *dp) { struct device *dev; @@ -121,44 +134,25 @@ static void parse_board(struct device_parser *dp) dev->name = strdup(value); } else if (!strcmp(key, "cdba")) { dev->control_dev = strdup(value); - - dev->open = cdb_assist_open; - dev->close = cdb_assist_close; - dev->power = cdb_assist_power; - dev->print_status = cdb_assist_print_status; - dev->usb = cdb_assist_usb; - dev->key = cdb_assist_key; + set_control_ops(dev, &cdb_assist_ops); } else if (!strcmp(key, "conmux")) { + /* conmux handles both control and console */ dev->control_dev = strdup(value); - - dev->open = conmux_open; - dev->power = conmux_power; - dev->write = conmux_write; + dev->console_dev = strdup(value); + set_control_ops(dev, &conmux_ops); + set_console_ops(dev, &conmux_console_ops); } else if (!strcmp(key, "alpaca")) { dev->control_dev = strdup(value); - - dev->open = alpaca_open; - dev->power = alpaca_power; - dev->usb = alpaca_usb; - dev->key = alpaca_key; + set_control_ops(dev, &alpaca_ops); } else if (!strcmp(key, "ftdi_gpio")) { dev->control_dev = strdup(value); - - dev->open = ftdi_gpio_open; - dev->power = ftdi_gpio_power; - dev->usb = ftdi_gpio_usb; - dev->key = ftdi_gpio_key; + set_control_ops(dev, &ftdi_gpio_ops); } else if (!strcmp(key, "qcomlt_debug_board")) { dev->control_dev = strdup(value); - - dev->open = qcomlt_dbg_open; - dev->power = qcomlt_dbg_power; - dev->usb = qcomlt_dbg_usb; - dev->key = qcomlt_dbg_key; + set_control_ops(dev, &qcomlt_dbg_ops); } else if (!strcmp(key, "console")) { dev->console_dev = strdup(value); - dev->write = console_write; - dev->send_break = console_send_break; + set_console_ops(dev, &console_ops); } else if (!strcmp(key, "voltage")) { dev->voltage = strtoul(value, NULL, 10); } else if (!strcmp(key, "fastboot")) { @@ -188,7 +182,7 @@ static void parse_board(struct device_parser *dp) } } - if (!dev->board || !dev->serial || !(dev->open || dev->console_dev)) { + if (!dev->board || !dev->serial || !dev->console_dev) { fprintf(stderr, "device parser: insufficiently defined device\n"); exit(1); } diff --git a/ftdi-gpio.c b/ftdi-gpio.c index 3f37856..24b9be5 100644 --- a/ftdi-gpio.c +++ b/ftdi-gpio.c @@ -251,3 +251,10 @@ void ftdi_gpio_key(struct device *dev, int key, bool asserted) break; } } + +const struct control_ops ftdi_gpio_ops = { + .open = ftdi_gpio_open, + .power = ftdi_gpio_power, + .usb = ftdi_gpio_usb, + .key = ftdi_gpio_key, +}; diff --git a/qcomlt_dbg.c b/qcomlt_dbg.c index 92d04a8..6095f5c 100644 --- a/qcomlt_dbg.c +++ b/qcomlt_dbg.c @@ -44,6 +44,7 @@ #include "cdba-server.h" #include "qcomlt_dbg.h" +#include "device.h" struct qcomlt_dbg { int fd; @@ -99,3 +100,10 @@ void qcomlt_dbg_key(struct device *dev, int key, bool asserted) break; } } + +const struct control_ops qcomlt_dbg_ops = { + .open = qcomlt_dbg_open, + .power = qcomlt_dbg_power, + .usb = qcomlt_dbg_usb, + .key = qcomlt_dbg_key, +}; From 2014d2c0d85a148536165f7db236b706688dbeb1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 17 Dec 2021 06:21:04 +0300 Subject: [PATCH 3/6] backends: remove unused headers Remove headers declaring internal backends API. Signed-off-by: Dmitry Baryshkov --- alpaca.c | 1 - alpaca.h | 13 ------------- cdb_assist.c | 5 +++-- cdb_assist.h | 23 ----------------------- conmux.c | 1 - conmux.h | 12 ------------ console.h | 10 ---------- ftdi-gpio.c | 2 +- ftdi-gpio.h | 13 ------------- qcomlt_dbg.c | 1 - qcomlt_dbg.h | 11 ----------- 11 files changed, 4 insertions(+), 88 deletions(-) delete mode 100644 alpaca.h delete mode 100644 cdb_assist.h delete mode 100644 conmux.h delete mode 100644 console.h delete mode 100644 ftdi-gpio.h delete mode 100644 qcomlt_dbg.h diff --git a/alpaca.c b/alpaca.c index f9994ad..93551ba 100644 --- a/alpaca.c +++ b/alpaca.c @@ -42,7 +42,6 @@ #include #include "cdba-server.h" -#include "alpaca.h" #include "device.h" struct alpaca { diff --git a/alpaca.h b/alpaca.h deleted file mode 100644 index 930d35c..0000000 --- a/alpaca.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __ALPACA_H__ -#define __ALPACA_H__ - -#include "device.h" - -struct alpaca; - -void *alpaca_open(struct device *dev); -int alpaca_power(struct device *dev, bool on); -void alpaca_usb(struct device *dev, bool on); -void alpaca_key(struct device *dev, int key, bool on); - -#endif diff --git a/cdb_assist.c b/cdb_assist.c index aab4b0a..6b508b7 100644 --- a/cdb_assist.c +++ b/cdb_assist.c @@ -42,7 +42,6 @@ #include #include "cdba-server.h" -#include "cdb_assist.h" #include "device.h" struct cdb_assist { @@ -90,6 +89,8 @@ enum { STATE_num_num_m, }; +static void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV); + static void cdb_parser_bool(struct cdb_assist *cdb, const char *key, bool set) { static const char *sz_keys[] = { "vbat", "btn1", "btn2", "btn3", "vbus" }; @@ -361,7 +362,7 @@ void cdb_assist_print_status(struct device *dev) cdba_send_buf(MSG_STATUS_UPDATE, n, buf); } -void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV) +static void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV) { char buf[20]; int n; diff --git a/cdb_assist.h b/cdb_assist.h deleted file mode 100644 index babcd65..0000000 --- a/cdb_assist.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __CDB_ASSIST_H__ -#define __CDB_ASSIST_H__ - -#include - -#include "device.h" - -struct cdb_assist; - -void *cdb_assist_open(struct device *dev); -void cdb_assist_close(struct device *dev); - -int cdb_assist_power(struct device *dev, bool on); -void cdb_assist_usb(struct device *dev, bool on); -void cdb_assist_key(struct device *dev, int key, bool asserted); -void cdb_gpio(struct cdb_assist *cdb, int gpio, bool on); -int cdb_target_write(struct device *dev, const void *buf, size_t len); -void cdb_send_break(struct device *dev); -unsigned int cdb_vref(struct cdb_assist *cdb); -void cdb_assist_print_status(struct device *dev); -void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV); - -#endif diff --git a/conmux.c b/conmux.c index da7073a..66a1463 100644 --- a/conmux.c +++ b/conmux.c @@ -41,7 +41,6 @@ #include #include "cdba-server.h" -#include "conmux.h" #include "device.h" extern int h_errno; diff --git a/conmux.h b/conmux.h deleted file mode 100644 index b23fa13..0000000 --- a/conmux.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __CONMUX_H__ -#define __CONMUX_H__ - -#include "device.h" - -struct conmux; - -void *conmux_open(struct device *dev); -int conmux_power(struct device *dev, bool on); -int conmux_write(struct device *dev, const void *buf, size_t len); - -#endif diff --git a/console.h b/console.h deleted file mode 100644 index 62258a2..0000000 --- a/console.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __CONSOLE_H__ -#define __CONSOLE_H__ - -#include "device.h" - -void console_open(struct device *device); -int console_write(struct device *device, const void *buf, size_t len); -void console_send_break(struct device *device); - -#endif diff --git a/ftdi-gpio.c b/ftdi-gpio.c index 24b9be5..3195a57 100644 --- a/ftdi-gpio.c +++ b/ftdi-gpio.c @@ -41,7 +41,7 @@ #include #include "cdba-server.h" -#include "ftdi-gpio.h" +#include "device.h" #include diff --git a/ftdi-gpio.h b/ftdi-gpio.h deleted file mode 100644 index a705d28..0000000 --- a/ftdi-gpio.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __FTDI_GPIO_H__ -#define __FTDI_GPIO_H__ - -#include "device.h" - -struct ftdi_gpio; - -void *ftdi_gpio_open(struct device *dev); -int ftdi_gpio_power(struct device *dev, bool on); -void ftdi_gpio_usb(struct device *dev, bool on); -void ftdi_gpio_key(struct device *dev, int key, bool on); - -#endif diff --git a/qcomlt_dbg.c b/qcomlt_dbg.c index 6095f5c..2b1ad82 100644 --- a/qcomlt_dbg.c +++ b/qcomlt_dbg.c @@ -43,7 +43,6 @@ #include #include "cdba-server.h" -#include "qcomlt_dbg.h" #include "device.h" struct qcomlt_dbg { diff --git a/qcomlt_dbg.h b/qcomlt_dbg.h deleted file mode 100644 index 1fc976e..0000000 --- a/qcomlt_dbg.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __QCOMLT_DBG_H__ -#define __QCOMLT_DBG_H__ - -#include "device.h" - -void *qcomlt_dbg_open(struct device *dev); -int qcomlt_dbg_power(struct device *dev, bool on); -void qcomlt_dbg_usb(struct device *dev, bool on); -void qcomlt_dbg_key(struct device *dev, int key, bool asserted); - -#endif From 8663f5c7b47481a3ae3947f8229b9c497614ae1a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 17 Dec 2021 06:29:35 +0300 Subject: [PATCH 4/6] backends: mark all functions as static Now as each backend exports data structure, mark all functions as static. Signed-off-by: Dmitry Baryshkov --- alpaca.c | 8 ++++---- cdb_assist.c | 21 ++++++++------------- conmux.c | 10 +++++----- console.c | 6 +++--- ftdi-gpio.c | 8 ++++---- qcomlt_dbg.c | 8 ++++---- 6 files changed, 28 insertions(+), 33 deletions(-) diff --git a/alpaca.c b/alpaca.c index 93551ba..12f4c99 100644 --- a/alpaca.c +++ b/alpaca.c @@ -53,7 +53,7 @@ struct alpaca { static int alpaca_device_power(struct alpaca *alpaca, int on); static int alpaca_usb_device_power(struct alpaca *alpaca, int on); -void *alpaca_open(struct device *dev) +static void *alpaca_open(struct device *dev) { struct alpaca *alpaca; @@ -121,7 +121,7 @@ static int alpaca_power_off(struct device *dev) return 0; } -int alpaca_power(struct device *dev, bool on) +static int alpaca_power(struct device *dev, bool on) { if (on) return alpaca_power_on(dev); @@ -129,14 +129,14 @@ int alpaca_power(struct device *dev, bool on) return alpaca_power_off(dev); } -void alpaca_usb(struct device *dev, bool on) +static void alpaca_usb(struct device *dev, bool on) { struct alpaca *alpaca = dev->cdb; alpaca_usb_device_power(alpaca, on); } -void alpaca_key(struct device *dev, int key, bool asserted) +static void alpaca_key(struct device *dev, int key, bool asserted) { switch (key) { case DEVICE_KEY_FASTBOOT: diff --git a/cdb_assist.c b/cdb_assist.c index 6b508b7..d62ef22 100644 --- a/cdb_assist.c +++ b/cdb_assist.c @@ -273,7 +273,7 @@ static int cdb_ctrl_write(struct cdb_assist *cdb, const char *buf, size_t len) return write(cdb->control_tty, buf, len); } -void *cdb_assist_open(struct device *dev) +static void *cdb_assist_open(struct device *dev) { struct cdb_assist *cdb; int ret; @@ -295,7 +295,7 @@ void *cdb_assist_open(struct device *dev) return cdb; } -void cdb_assist_close(struct device *dev) +static void cdb_assist_close(struct device *dev) { struct cdb_assist *cdb = dev->cdb; @@ -311,14 +311,14 @@ static void cdb_power(struct cdb_assist *cdb, bool on) cdb_ctrl_write(cdb, &cmd[on], 1); } -void cdb_vbus(struct cdb_assist *cdb, bool on) +static void cdb_vbus(struct cdb_assist *cdb, bool on) { const char cmd[] = "vV"; cdb_ctrl_write(cdb, &cmd[on], 1); } -int cdb_assist_power(struct device *dev, bool on) +static int cdb_assist_power(struct device *dev, bool on) { struct cdb_assist *cdb = dev->cdb; @@ -327,23 +327,18 @@ int cdb_assist_power(struct device *dev, bool on) return 0; } -void cdb_assist_usb(struct device *dev, bool on) +static void cdb_assist_usb(struct device *dev, bool on) { cdb_vbus(dev->cdb, on); } -void cdb_gpio(struct cdb_assist *cdb, int gpio, bool on) +static void cdb_gpio(struct cdb_assist *cdb, int gpio, bool on) { const char *cmd[] = { "aA", "bB", "cC" }; cdb_ctrl_write(cdb, &cmd[gpio][on], 1); } -unsigned int cdb_vref(struct cdb_assist *cdb) -{ - return cdb->vref; -} - -void cdb_assist_print_status(struct device *dev) +static void cdb_assist_print_status(struct device *dev) { struct cdb_assist *cdb = dev->cdb; char buf[128]; @@ -371,7 +366,7 @@ static void cdb_set_voltage(struct cdb_assist *cdb, unsigned mV) cdb_ctrl_write(cdb, buf, n); } -void cdb_assist_key(struct device *dev, int key, bool asserted) +static void cdb_assist_key(struct device *dev, int key, bool asserted) { struct cdb_assist *cdb = dev->cdb; diff --git a/conmux.c b/conmux.c index 66a1463..1cd8504 100644 --- a/conmux.c +++ b/conmux.c @@ -224,7 +224,7 @@ static int conmux_data(int fd, void *data) return 0; } -void *conmux_open(struct device *dev) +static void *conmux_open(struct device *dev) { struct addrinfo hints = {0}, *addrs, *addr; struct conmux_response resp = {}; @@ -297,7 +297,7 @@ void *conmux_open(struct device *dev) return conmux; } -int conmux_power_on(struct device *dev) +static int conmux_power_on(struct device *dev) { struct conmux *conmux = dev->cdb; char sz[] = "~$hardreset\n"; @@ -317,7 +317,7 @@ static int conmux_power_off(struct device *dev) return write(conmux->fd, sz, sizeof(sz)); } -int conmux_power(struct device *dev, bool on) +static int conmux_power(struct device *dev, bool on) { if (on) return conmux_power_on(dev); @@ -325,14 +325,14 @@ int conmux_power(struct device *dev, bool on) return conmux_power_off(dev); } -int conmux_write(struct device *dev, const void *buf, size_t len) +static int conmux_write(struct device *dev, const void *buf, size_t len) { struct conmux *conmux = dev->cdb; return write(conmux->fd, buf, len); } -void *conmux_console_open(struct device *dev) +static void *conmux_console_open(struct device *dev) { return dev->cdb; } diff --git a/console.c b/console.c index bdb6488..d758c8b 100644 --- a/console.c +++ b/console.c @@ -57,7 +57,7 @@ static int console_data(int fd, void *data) return 0; } -void *console_open(struct device *device) +static void *console_open(struct device *device) { struct console *console; @@ -71,14 +71,14 @@ void *console_open(struct device *device) return console; } -int console_write(struct device *device, const void *buf, size_t len) +static int console_write(struct device *device, const void *buf, size_t len) { struct console *console = device->console; return write(console->console_fd, buf, len);; } -void console_send_break(struct device *device) +static void console_send_break(struct device *device) { struct console *console = device->console; diff --git a/ftdi-gpio.c b/ftdi-gpio.c index 3195a57..dcac871 100644 --- a/ftdi-gpio.c +++ b/ftdi-gpio.c @@ -159,7 +159,7 @@ static void ftdi_gpio_parse_config(struct ftdi_gpio *ftdi_gpio, char *control_de } } -void *ftdi_gpio_open(struct device *dev) +static void *ftdi_gpio_open(struct device *dev) { struct ftdi_gpio *ftdi_gpio; int ret; @@ -224,21 +224,21 @@ static void ftdi_gpio_device_usb(struct ftdi_gpio *ftdi_gpio, bool on) ftdi_gpio_toggle_io(ftdi_gpio, GPIO_USB_DISCONNECT, on); } -int ftdi_gpio_power(struct device *dev, bool on) +static int ftdi_gpio_power(struct device *dev, bool on) { struct ftdi_gpio *ftdi_gpio = dev->cdb; return ftdi_gpio_device_power(ftdi_gpio, on); } -void ftdi_gpio_usb(struct device *dev, bool on) +static void ftdi_gpio_usb(struct device *dev, bool on) { struct ftdi_gpio *ftdi_gpio = dev->cdb; ftdi_gpio_device_usb(ftdi_gpio, on); } -void ftdi_gpio_key(struct device *dev, int key, bool asserted) +static void ftdi_gpio_key(struct device *dev, int key, bool asserted) { struct ftdi_gpio *ftdi_gpio = dev->cdb; diff --git a/qcomlt_dbg.c b/qcomlt_dbg.c index 2b1ad82..bda7e61 100644 --- a/qcomlt_dbg.c +++ b/qcomlt_dbg.c @@ -50,7 +50,7 @@ struct qcomlt_dbg { struct termios orig_tios; }; -void *qcomlt_dbg_open(struct device *dev) +static void *qcomlt_dbg_open(struct device *dev) { struct qcomlt_dbg *dbg; @@ -68,7 +68,7 @@ void *qcomlt_dbg_open(struct device *dev) return dbg; } -int qcomlt_dbg_power(struct device *dev, bool on) +static int qcomlt_dbg_power(struct device *dev, bool on) { struct qcomlt_dbg *dbg = dev->cdb; @@ -76,7 +76,7 @@ int qcomlt_dbg_power(struct device *dev, bool on) return write(dbg->fd, &("pP"[on]), 1); } -void qcomlt_dbg_usb(struct device *dev, bool on) +static void qcomlt_dbg_usb(struct device *dev, bool on) { struct qcomlt_dbg *dbg = dev->cdb; @@ -84,7 +84,7 @@ void qcomlt_dbg_usb(struct device *dev, bool on) write(dbg->fd, &("uU"[on]), 1); } -void qcomlt_dbg_key(struct device *dev, int key, bool asserted) +static void qcomlt_dbg_key(struct device *dev, int key, bool asserted) { struct qcomlt_dbg *dbg = dev->cdb; From 310004badb0db64c29ebdd1b5cf89489f10da743 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 21 Dec 2021 02:18:55 +0300 Subject: [PATCH 5/6] external: control the board using external program Control the board using external program. It will be called with 3 arguments: , where command is one of "power", "usb", "key-fastboot", "key-power". Signed-off-by: Dmitry Baryshkov --- device.h | 1 + device_parser.c | 3 ++ external.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 1 + 4 files changed, 130 insertions(+) create mode 100644 external.c diff --git a/device.h b/device.h index 2dba972..b41e66a 100644 --- a/device.h +++ b/device.h @@ -90,6 +90,7 @@ extern const struct control_ops alpaca_ops; extern const struct control_ops cdb_assist_ops; extern const struct control_ops conmux_ops; extern const struct control_ops ftdi_gpio_ops; +extern const struct control_ops external_ops; extern const struct control_ops qcomlt_dbg_ops; extern const struct console_ops conmux_console_ops; diff --git a/device_parser.c b/device_parser.c index e4a386f..d9f2800 100644 --- a/device_parser.c +++ b/device_parser.c @@ -147,6 +147,9 @@ static void parse_board(struct device_parser *dp) } else if (!strcmp(key, "ftdi_gpio")) { dev->control_dev = strdup(value); set_control_ops(dev, &ftdi_gpio_ops); + } else if (!strcmp(key, "external")) { + dev->control_dev = strdup(value); + set_control_ops(dev, &external_ops); } else if (!strcmp(key, "qcomlt_debug_board")) { dev->control_dev = strdup(value); set_control_ops(dev, &qcomlt_dbg_ops); diff --git a/external.c b/external.c new file mode 100644 index 0000000..0fb82e1 --- /dev/null +++ b/external.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021-2023, Linaro Ltd. + * 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 "cdba-server.h" +#include "device.h" + +struct external { + const char *path; + const char *board; +}; + +static int external_helper(struct external *ext, const char *command, bool on) +{ + pid_t pid, pid_ret; + int status; + + pid = fork(); + switch (pid) { + case 0: + /* Do not clobber stdout with program messages or cdba will become confused */ + dup2(2, 1); + return execlp(ext->path, ext->path, ext->board, command, on ? "on": "off", NULL); + case -1: + return -1; + default: + break; + } + + pid_ret = waitpid(pid, &status, 0); + if (pid_ret < 0) + return pid_ret; + + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + errno = -EINTR; + else + errno = -EIO; + + return -1; +} + +static void *external_open(struct device *dev) +{ + struct external *ext; + + dev->has_power_key = true; + + ext = calloc(1, sizeof(*ext)); + + ext->path = dev->control_dev; + ext->board = dev->board; + + return ext; +} + +static int external_power(struct device *dev, bool on) +{ + struct external *ext = dev->cdb; + + return external_helper(ext, "power", on); +} + +static void external_usb(struct device *dev, bool on) +{ + struct external *ext = dev->cdb; + + external_helper(ext, "usb", on); +} + +static void external_key(struct device *dev, int key, bool asserted) +{ + struct external *ext = dev->cdb; + + switch (key) { + case DEVICE_KEY_FASTBOOT: + external_helper(ext, "key-fastboot", asserted); + break; + case DEVICE_KEY_POWER: + external_helper(ext, "key-power", asserted); + break; + } +} + +const struct control_ops external_ops = { + .open = external_open, + .power = external_power, + .usb = external_usb, + .key = external_key, +}; diff --git a/meson.build b/meson.build index 0392b0e..15254b6 100644 --- a/meson.build +++ b/meson.build @@ -61,6 +61,7 @@ server_srcs = ['cdba-server.c', 'conmux.c', 'device.c', 'device_parser.c', + 'external.c', 'fastboot.c', 'alpaca.c', 'ftdi-gpio.c', From a0de781e1bd3c2fb39e42e1bc05a5059723ca03c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 23 Sep 2023 18:28:16 +0300 Subject: [PATCH 6/6] cdba-server: sanitise file descriptors before device_close() If we got to device_close(), the parent SSH might have been exited, making standard file descriptors unusable. Rebind them to /dev/null, so that any output during device_close (both from the cdba server and the helpers) doesn't cause SIGPIPE. Signed-off-by: Dmitry Baryshkov --- cdba-server.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cdba-server.c b/cdba-server.c index 5bd7a25..df6db01 100644 --- a/cdba-server.c +++ b/cdba-server.c @@ -406,6 +406,17 @@ int main(int argc, char **argv) done: + /* if we got here, stdin/out/err might be not accessible anymore */ + ret = open("/dev/null", O_RDWR); + if (ret >= 0) { + close(STDIN_FILENO); + dup2(ret, STDIN_FILENO); + close(STDOUT_FILENO); + dup2(ret, STDOUT_FILENO); + close(STDERR_FILENO); + dup2(ret, STDERR_FILENO); + } + if (selected_device) device_close(selected_device);