From 5cef794f6c2d00457bdde2ed72085a7f43d5abba 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 | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ device.c | 5 +++ device.h | 1 + meson.build | 17 ++++++-- watch.c | 28 ++++++++++--- watch.h | 1 + 6 files changed, 153 insertions(+), 10 deletions(-) create mode 100644 cdba-power.c diff --git a/cdba-power.c b/cdba-power.c new file mode 100644 index 0000000..eae7521 --- /dev/null +++ b/cdba-power.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, 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 "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 a791e73..14aa8ed 100644 --- a/device.c +++ b/device.c @@ -245,6 +245,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 78b98a8..d1a212b 100644 --- a/meson.build +++ b/meson.build @@ -65,8 +65,7 @@ if not compiler.has_function('forkpty') server_deps += util_dep endif -server_srcs = ['cdba-server.c', - 'cdb_assist.c', +cdbalib_srcs = ['cdb_assist.c', 'circ_buf.c', 'conmux.c', 'device.c', @@ -85,11 +84,15 @@ server_srcs = ['cdba-server.c', 'tty.c'] if gpiod_dep.version().version_compare('>=2.0') - server_srcs += ['local-gpio-v2.c'] + cdbalib_srcs += ['local-gpio-v2.c'] else - server_srcs += ['local-gpio-v1.c'] + cdbalib_srcs += ['local-gpio-v1.c'] endif +libcdba = static_library('cdba', cdbalib_srcs) + +server_srcs = ['cdba-server.c'] + build_server = true foreach d: server_deps if not d.found() @@ -101,6 +104,12 @@ if build_server executable('cdba-server', server_srcs, dependencies : server_deps, + link_with : libcdba, + install : true) + executable('cdba-power', + ['cdba-power.c'], + dependencies : server_deps, + link_with : libcdba, install : true) elif not server_opt.disabled() message('Skipping CDBA server build') diff --git a/watch.c b/watch.c index 348f257..6dca35e 100644 --- a/watch.c +++ b/watch.c @@ -148,7 +148,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; @@ -157,6 +157,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) { @@ -164,11 +167,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) @@ -194,3 +192,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 b8af2cd..9df68e1 100644 --- a/watch.h +++ b/watch.h @@ -36,6 +36,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