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, +};