From 5a86b97c2cd884dc5214fda720bb35f1aba387ec Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 12 Mar 2024 21:08:19 +0200 Subject: [PATCH] cdba-power: add power-on/-off tool Add simple tool reusing CDBA code to power boards on and off. Signed-off-by: Dmitry Baryshkov --- cdba-power.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ device.c | 5 +++ device.h | 1 + meson.build | 24 ++++++++++----- watch.c | 28 +++++++++++++---- watch.h | 1 + 6 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 cdba-power.c diff --git a/cdba-power.c b/cdba-power.c new file mode 100644 index 0000000..cd907bf --- /dev/null +++ b/cdba-power.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024, Linaro Ltd. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "cdba-server.h" +#include "device.h" +#include "device_parser.h" +#include "watch.h" + +void cdba_send_buf(int type, size_t len, const void *buf) +{ + /* ignore console messages */ +} + +static void usage(const char *name) +{ + fprintf(stderr, "Usage: %s on|off\n", name); + exit(EXIT_FAILURE); +} + +static struct device *selected_device; + +bool ready(void) +{ + return device_is_running(selected_device); +} + +int main(int argc, char **argv) +{ + const char *home; + const char *name; + bool on; + int ret; + + if (argc != 3) + usage(argv[0]); + + if (!strcmp(argv[2], "on")) + on = true; + else if (!strcmp(argv[2], "off")) + on = false; + else + usage(argv[0]); + + home = getenv("HOME"); + if (home) + chdir(home); + + ret = device_parser(".cdba"); + if (ret) { + ret = device_parser("/etc/cdba"); + if (ret) { + fprintf(stderr, "device parser: unable to open config file\n"); + exit(1); + } + } + + name = argv[1]; + selected_device = device_open(name, "nobody"); + if (!selected_device) { + fprintf(stderr, "failed to open %s\n", name); + exit(EXIT_FAILURE); + } + + if (on) { + device_power(selected_device, true); + watch_main_loop(ready); + + selected_device->usb_always_on = true; + selected_device->power_always_on = true; + } else { + device_usb(selected_device, false); + device_power(selected_device, false); + } + + device_close(selected_device); + + return 0; +} diff --git a/device.c b/device.c index 9922130..848f552 100644 --- a/device.c +++ b/device.c @@ -227,6 +227,11 @@ static void device_tick(void *data) } } +bool device_is_running(struct device *device) +{ + return device->state == DEVICE_STATE_RUNNING; +} + static int device_power_on(struct device *device) { if (!device || !device_has_control(device, power)) diff --git a/device.h b/device.h index 0b8d0e9..0edb048 100644 --- a/device.h +++ b/device.h @@ -91,6 +91,7 @@ void device_send_break(struct device *device); void device_list_devices(const char *username); void device_info(const char *username, const void *data, size_t dlen); void device_fastboot_continue(struct device *device); +bool device_is_running(struct device *device); enum { DEVICE_KEY_FASTBOOT, diff --git a/meson.build b/meson.build index 763c32d..fe03e81 100644 --- a/meson.build +++ b/meson.build @@ -54,7 +54,7 @@ if not ftdi_dep.found() endif gpiod_dep = dependency('libgpiod', required: server_opt) -server_deps = [dependency('libudev', required: server_opt), +cdbalib_deps = [dependency('libudev', required: server_opt), dependency('yaml-0.1', required: server_opt), gpiod_dep, ftdi_dep] @@ -62,7 +62,7 @@ server_deps = [dependency('libudev', required: server_opt), # E.g. Debian reuires -lutil for forkpty if not compiler.has_function('forkpty') util_dep = compiler.find_library('util') - server_deps += util_dep + cdbalib_deps += util_dep endif drivers_srcs = ['drivers/alpaca.c', @@ -80,8 +80,7 @@ else drivers_srcs += ['drivers/local-gpio-v1.c'] endif -server_srcs = ['cdba-server.c', - 'circ_buf.c', +cdbalib_srcs = ['circ_buf.c', 'device.c', 'device_parser.c', 'fastboot.c', @@ -92,17 +91,28 @@ server_srcs = ['cdba-server.c', 'watch.c', 'tty.c'] +server_srcs = ['cdba-server.c'] + build_server = true -foreach d: server_deps +foreach d: cdbalib_deps if not d.found() build_server = false endif endforeach if build_server + libcdba = static_library('cdba', + cdbalib_srcs + drivers_srcs, + dependencies : cdbalib_deps, + ) + executable('cdba-server', - server_srcs + drivers_srcs, - dependencies : server_deps, + server_srcs, + link_with : libcdba, + install : true) + executable('cdba-power', + ['cdba-power.c'], + link_with : libcdba, install : true) elif not server_opt.disabled() message('Skipping CDBA server build') diff --git a/watch.c b/watch.c index 236911b..65755f4 100644 --- a/watch.c +++ b/watch.c @@ -124,7 +124,7 @@ void watch_quit(void) quit_invoked = true; } -int watch_run(void) +int watch_main_loop(bool (*quit_cb)(void)) { struct timeval *timeoutp; struct watch *w; @@ -133,6 +133,9 @@ int watch_run(void) int ret; while (!quit_invoked) { + if (quit_cb && quit_cb()) + break; + nfds = 0; list_for_each_entry(w, &read_watches, node) { @@ -140,11 +143,6 @@ int watch_run(void) FD_SET(w->fd, &rfds); } - if (!FD_ISSET(STDIN_FILENO, &rfds)) { - fprintf(stderr, "rfds is trash!\n"); - return -EINVAL; - } - timeoutp = watch_timer_next(); ret = select(nfds + 1, &rfds, NULL, NULL, timeoutp); if (ret < 0 && errno == EINTR) @@ -170,3 +168,21 @@ int watch_run(void) return 0; } + +int watch_run(void) +{ + struct watch *w; + bool found = false; + + list_for_each_entry(w, &read_watches, node) { + if (w->fd == STDIN_FILENO) + found = true; + } + + if (!found) { + fprintf(stderr, "rfds is trash!\n"); + return -EINVAL; + } + + return watch_main_loop(NULL); +} diff --git a/watch.h b/watch.h index 22ae2bf..dde554b 100644 --- a/watch.h +++ b/watch.h @@ -5,6 +5,7 @@ void watch_add_readfd(int fd, int (*cb)(int, void*), void *data); int watch_add_quit(int (*cb)(int, void*), void *data); void watch_timer_add(int timeout_ms, void (*cb)(void *), void *data); void watch_quit(void); +int watch_main_loop(bool (*quit_cb)(void)); int watch_run(void); #endif