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 <dmitry.baryshkov@linaro.org>
This commit is contained in:
Dmitry Baryshkov
2023-10-02 17:33:03 +03:00
parent fb23cabbc4
commit 3b089f313e
9 changed files with 171 additions and 78 deletions

View File

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

View File

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

View File

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

View File

@@ -32,11 +32,17 @@
#include <sys/stat.h>
#include <err.h>
#include <stdlib.h>
#include <unistd.h>
#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,
};

View File

@@ -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);
}

View File

@@ -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

View File

@@ -33,13 +33,6 @@
#include <yaml.h>
#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);
}

View File

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

View File

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