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 <key:u8, state:u8>)

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. :-)
This commit is contained in:
Stephan Gerhold
2025-02-11 18:25:27 +01:00
parent 61babbf9ac
commit 3922dc793a
5 changed files with 75 additions and 6 deletions

View File

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

29
cdba.c
View File

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

18
cdba.h
View File

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

View File

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

View File

@@ -2,6 +2,7 @@
#define __DEVICE_H__
#include <termios.h>
#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;