From 3922dc793ab5ebcd7dad8cc791de831cd6af4ffd Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 11 Feb 2025 18:25:27 +0100 Subject: [PATCH] cdba: Add keys to remotely press power or fastboot key Add special keys to allow triggering power and fastboot key presses from the cdba client. There is an option to send a short key "pulse" (press followed by release after 100ms) or to press/release keys separately: - ctrl+a -> o: Send power key pulse - ctrl+a -> O: Toggle power key (first use: press, next use: release) - ctrl+a -> f: Send fastboot key pulse - ctrl+a -> F: Toggle fastboot key (first use: press, next use: release) In most cases you want to send the "pulse" (short key press), so it's helpful to have this mapped to a single key. This avoids forgetting to release the key again after pressing it. The protocol between CDBA client and server is: (MSG_KEY_PRESS ) where key is either DEVICE_KEY_FASTBOOT (0) or DEVICE_KEY_POWER (1) and state is either KEY_PRESS_RELEASE (0), KEY_PRESS_PRESS (1) or KEY_PRESS_PULSE (2). The reason for implementing the "pulse" on the server side is that it's hard to guarantee the timing on the client side. We don't know exactly when the packets will arrive on the server. Also, "state" is a full byte anyway, so might as well use some of the extra bits. :-) --- cdba-server.c | 25 +++++++++++++++++++++++++ cdba.c | 29 +++++++++++++++++++++++++++++ cdba.h | 18 ++++++++++++++++++ device.c | 2 +- device.h | 7 ++----- 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/cdba-server.c b/cdba-server.c index c463f19..72b00eb 100644 --- a/cdba-server.c +++ b/cdba-server.c @@ -99,6 +99,28 @@ static void msg_fastboot_continue(void) cdba_send(MSG_FASTBOOT_CONTINUE); } +static void msg_key_release(void *data) +{ + int key = (int)(uintptr_t)data; + + device_key(selected_device, key, false); +} + +static void msg_key_press(const void *data, size_t len) +{ + const struct key_press *press = data; + + if (len != sizeof(*press)) + return; + + if (press->state == KEY_PRESS_PULSE) { + device_key(selected_device, press->key, true); + watch_timer_add(100, msg_key_release, (void*)(uintptr_t)press->key); + } else { + device_key(selected_device, press->key, !!press->state); + } +} + void cdba_send_buf(int type, size_t len, const void *buf) { struct msg msg = { @@ -185,6 +207,9 @@ static int handle_stdin(int fd, void *buf) case MSG_FASTBOOT_CONTINUE: msg_fastboot_continue(); break; + case MSG_KEY_PRESS: + msg_key_press(msg->data, msg->len); + break; default: fprintf(stderr, "unk %d len %d\n", msg->type, msg->len); exit(1); diff --git a/cdba.c b/cdba.c index ee3809f..d1589cd 100644 --- a/cdba.c +++ b/cdba.c @@ -143,8 +143,25 @@ static int cdba_send_buf(int fd, int type, size_t len, const void *buf) return ret < 0 ? ret : 0; } +static int cdba_send_key(int fd, int key, uint8_t state) +{ + struct key_press press = { + .key = key, + .state = state, + }; + + return cdba_send_buf(fd, MSG_KEY_PRESS, sizeof(press), &press); +} + +static int cdba_toggle_key(int fd, int key, bool key_state[DEVICE_KEY_COUNT]) +{ + key_state[key] = !key_state[key]; + return cdba_send_key(fd, key, key_state[key]); +} + static int tty_callback(int *ssh_fds) { + static bool key_state[DEVICE_KEY_COUNT]; static const char ctrl_a = 0x1; static bool special; char buf[32]; @@ -184,6 +201,18 @@ static int tty_callback(int *ssh_fds) case 'B': cdba_send(ssh_fds[0], MSG_SEND_BREAK); break; + case 'o': + cdba_send_key(ssh_fds[0], DEVICE_KEY_POWER, KEY_PRESS_PULSE); + break; + case 'O': + cdba_toggle_key(ssh_fds[0], DEVICE_KEY_POWER, key_state); + break; + case 'f': + cdba_send_key(ssh_fds[0], DEVICE_KEY_FASTBOOT, KEY_PRESS_PULSE); + break; + case 'F': + cdba_toggle_key(ssh_fds[0], DEVICE_KEY_FASTBOOT, key_state); + break; } special = false; diff --git a/cdba.h b/cdba.h index 0264c40..e70c998 100644 --- a/cdba.h +++ b/cdba.h @@ -31,6 +31,24 @@ enum { MSG_LIST_DEVICES, MSG_BOARD_INFO, MSG_FASTBOOT_CONTINUE, + MSG_KEY_PRESS, +}; + +struct key_press { + uint8_t key; + uint8_t state; +} __packed; + +enum { + DEVICE_KEY_FASTBOOT, + DEVICE_KEY_POWER, + DEVICE_KEY_COUNT +}; + +enum { + KEY_PRESS_RELEASE, + KEY_PRESS_PRESS, + KEY_PRESS_PULSE, }; #endif diff --git a/device.c b/device.c index 79856bb..fa81940 100644 --- a/device.c +++ b/device.c @@ -163,7 +163,7 @@ static void device_impl_power(struct device *device, bool on) device_control(device, power, on); } -static void device_key(struct device *device, int key, bool asserted) +void device_key(struct device *device, int key, bool asserted) { if (device_has_control(device, key)) device_control(device, key, key, asserted); diff --git a/device.h b/device.h index 75a780a..e465ea5 100644 --- a/device.h +++ b/device.h @@ -2,6 +2,7 @@ #define __DEVICE_H__ #include +#include "cdba.h" #include "list.h" struct cdb_assist; @@ -76,6 +77,7 @@ struct device *device_open(const char *board, const char *username); void device_close(struct device *dev); int device_power(struct device *device, bool on); +void device_key(struct device *device, int key, bool asserted); void device_status_enable(struct device *device); void device_usb(struct device *device, bool on); @@ -93,11 +95,6 @@ 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, - 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;