35 Commits

Author SHA1 Message Date
Dmitry Baryshkov
b6c766db1f Merge pull request #88 from krzk/dupa
schema: Allow Fastboot serial numbers up to 16 characters
2025-07-05 16:31:36 +03:00
Krzysztof Kozlowski
031948ff19 schema: Allow Fastboot serial numbers up to 16 characters
WinLink e850 board reports Fastboot ID/serial of "00000b66ce9c23e0" and
fastboot sources [1] allow up to 256 bytes, so grow the pattern to at least
16 characters:

[1] https://android.googlesource.com/platform/system/core/+/refs/heads/android16-release/fastboot/usb.h#54

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2025-07-05 15:00:58 +02:00
Neil Armstrong
30c30ce84c Merge pull request #86 from lumag/laurent-usb
laurent: add support for controlling USB power
2025-03-18 09:32:35 +01:00
Neil Armstrong
95a40706be Merge pull request #84 from stephan-gh/ftdi-usb1
drivers: ftdi-gpio: Add second USB disconnect GPIO & schema.yaml fixes
2025-03-18 09:28:37 +01:00
Dmitry Baryshkov
4320c482d3 Merge pull request #81 from mwasilew/boot_mode
device_parser: improve error reporting
2025-02-21 19:25:36 +02:00
Dmitry Baryshkov
cdee00d9a4 Merge pull request #83 from stephan-gh/keys
cdba: Add keys to remotely press power or fastboot key
2025-02-21 19:24:42 +02:00
Dmitry Baryshkov
5bade34946 Merge pull request #85 from stephan-gh/local
cdba: Add option to run cdba-server locally without ssh and without timeout
2025-02-21 19:22:50 +02:00
Dmitry Baryshkov
3c1e7cc886 laurent: add separate USB relays support
Extend laurent driver, allowing using a relay to control USB circuits.
For example, the relay might be connected to the DIP switch on RB1 / RB2
boards.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-21 19:19:45 +02:00
Dmitry Baryshkov
bad935cbf2 device: support PPPS in parallel with the driver's USB control
Don't make PPPS path exclusive to the driver USB control. Allow both to
be used at the same time in case the setup uses both PPPS-hubs and
driver-specific control.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-21 19:17:01 +02:00
Dmitry Baryshkov
9335390898 cdba-server: don't try opening the board if there is none
If the cdba failed to find the board, don't call device_fastboot_open().

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-21 19:14:49 +02:00
Stephan Gerhold
b6d70e8b0c cdba: Add option to disable timeout_total when set to 0
If cdba is run with "-t 0", then disable the timeout completely and keep
running until manually interrupted. This is useful for non-shared boards,
e.g. when cdba is just used to power up the board remotely and you then SSH
into a standard Linux distro installed on the board.
2025-02-14 13:58:26 +01:00
Stephan Gerhold
06531f3db1 cdba: Add option to run cdba-server locally without ssh
cdba is mainly intended for remote usage, but it also works well for
controlling devices that you just need occasionally and then directly
connect to your local laptop instead of a remote server.

Another use case is if you just use cdba to power up a standard distro on a
remote board and then SSH into it remotely. To avoid interruptions, it's
better to start cdba locally on the server in a tmux session. That way,
temporary disconnections do not power down the board.

From a protocol perspective, everything is transferred through STDIN and
STDOUT. It makes no difference if we have ssh piping the data to a remote
server, or if the data is directly passed to the cdba-server binary started
locally. The functionality works exactly the same.

Add an option for this in the cdba client. If the -h <host> option is
omitted, cdba-server is started locally.
2025-02-14 13:58:26 +01:00
Stephan Gerhold
828d76df63 cdba: Avoid hardcoding ssh binary path
Use execlp() instead of execl() to search the PATH for the ssh binary. This
avoids problems in case the ssh binary is installed in a different path.
2025-02-14 13:58:26 +01:00
Stephan Gerhold
e799564f44 cdba: Document behavior when omitting <boot.img>
The <boot.img> option is optional in cdba. If omitted, cdba falls back to
falls back to running "fastboot continue" to boot the installed operating
system.
2025-02-14 13:58:21 +01:00
Stephan Gerhold
720922913c drivers: ftdi-gpio: Add second USB disconnect GPIO
Some boards have more than one USB port. In that case, there is a second
GPIO on the debug board to simulate a USB disconnection for those.

Add the option to describe both USB disconnect GPIOs using
"usb0_disconnect" and "usb1_disconnect" and change both of them
when disabling USB power.

In the future it might be useful to control them separately, but for now
this ensures that power to the board is cut properly when the board is
powered off.
2025-02-14 11:42:59 +01:00
Stephan Gerhold
8bd8eeda33 schema.yaml: Fix ftdi_gpio patternProperties
"patternProperties" must be on the same indentation level as "properties",
otherwise it just defines a property called "patternProperties" in
cdba.yaml.

Also add additionalProperties: false, so properties not matching the regex
are actually disallowed and reported.
2025-02-14 11:26:35 +01:00
Stephan Gerhold
f801448422 schema.yaml: Fix unevaluatedItems -> additionalProperties
unevaluatedItems is for array items, we need unevaluatedProperties here.
But actually this can just be additionalProperties.
2025-02-14 11:26:26 +01:00
Stephan Gerhold
3922dc793a 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. :-)
2025-02-14 10:35:27 +01:00
Konrad Dybcio
61babbf9ac Merge pull request #82 from lumag/fix-ci
Fix CI builds
2025-02-12 19:18:42 +01:00
Dmitry Baryshkov
358fea7207 Merge pull request #80 from quic-bjorande/for-linux-msm/dont-detect-fastboot-done-by-usb
cdba: Rely on fastboot completion rather than USB disconnect
2025-02-12 20:17:56 +02:00
Dmitry Baryshkov
b0df12edc0 status: use %lld to print time_t
Some build configurations are switching to 64-bit time_t, breaking
builds on 32-bit architectures. Always use %lld and perform an explicit
conversion to (long long int) in order to make the code compile on all
architectures.

../status.c: In function 'status_send_values':
../status.c:46:53: error: format '%ld' expects argument of type 'long int', but argument 4 has type '__time64_t' {aka 'long long int'} [-Werror=format=]

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-12 12:36:10 +02:00
Dmitry Baryshkov
59db2941f5 CI: add more Fedora releases
Add Fedora 41 and 42 to the list of build configurations.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-12 12:30:33 +02:00
Dmitry Baryshkov
8715e3b74d CI: refresh Ubuntu releases
Ubuntu Mantic has been removed from the mirros, drop it from the CI
workflow. At the same time add new Ubuntu Oracular release.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2025-02-12 12:23:04 +02:00
Milosz Wasilewski
aa0e50bb1d device_parser: improve error reporting
Add more verbose output to config file parsing errors.

Signed-off-by: Milosz Wasilewski <milosz.wasilewski@oss.qualcomm.com>
2025-02-12 10:09:18 +00:00
Bjorn Andersson
0852da5424 cdba: Rely on fastboot completion rather than USB disconnect
The purpose for providing different exit codes (2 vs 110) for timeout
before or after fastboot was to allow tools invoking cdba to detect if
the device arrived at and performed fastboot or not.

In most cases relying on the fastboot (USB) disconnect notification
works fine, but in cases where the provided image fails to decompress
the standard fastboot implementation will OKAY the transfer, fail to
process the image and then return to process further fastboot requests.

This has been observed in cases where the image is too big, or when it
contains a big endian kernel.

Change the logic to rely on the "FASTBOOT_DOWNLOAD" response to
determine that we did reach fastboot and where able to upload the image
and then something happened - i.e. "there's a problem with the image" vs
"there's a setup problem".

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-11-26 09:48:15 -08:00
Konrad Dybcio
2f3e661f4d Merge pull request #77 from eberman-quic/master
ftdi_gpio: Turn on OUTPUT_ENABLE first
2024-06-18 02:47:54 +02:00
Elliot Berman
2899fbcbb1 ftdi_gpio: Turn on OUTPUT_ENABLE first
Observed instability in controlling devices when OUTPUT_ENABLE wasn't
enabled in the first step. I couldn't find any documented reason why
this is, but the documentation does say: "FtdiOutput Pin always kept at
1".

Alpaca always keeps OUTUT_ENABLE as 1, and never turns it off. The
documentation seems to imply it should always be left on. This change
updates the open sequence so that the OUTPUT_ENABLE bit is set first.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
2024-06-05 10:36:23 -07:00
Konrad Dybcio
61139604fb Merge pull request #76 from lumag/lock-who
Fix quitting if the board is locked
2024-05-31 15:57:46 +02:00
Dmitry Baryshkov
cbad92a838 cdba-server: log message on CDBA exit
To identify closing of the session, log the message when CDBA quits.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2024-05-31 16:57:17 +03:00
Dmitry Baryshkov
95ff3049f8 cdba-server: include PID to the syslog message
Include PID into syslog message to simplify identifying the CDBA
sessions.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2024-05-31 16:57:17 +03:00
Dmitry Baryshkov
5db3df360a device: loop around flock/warn
Loop around the flock(), sleeping in the middle. This allows CDBA to
break early if user closes the terminal (by killing SSH or by Ctrl-A-Q
sequence).

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2024-05-31 16:57:14 +03:00
Dmitry Baryshkov
02210fe6e2 Merge pull request #75 from krzk/ci-releases
Refresh CI releases
2024-05-21 10:16:49 +02:00
Krzysztof Kozlowski
b3b50a7441 ci: update checkout to v4 (to fix warning)
Fixes Github deprecation warning:

  Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: actions/checkout@v3

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2024-05-21 09:01:41 +02:00
Krzysztof Kozlowski
c86932d361 ci: add latest Ubuntu release
It is easy to forget to roll to new Ubuntu (or Fedora) release, so
always test on the latest Ubuntu version as well.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2024-05-21 08:47:40 +02:00
Krzysztof Kozlowski
d77816052d ci: add new Fedora and Ubuntu
Refresh the list of distros used for testing: add new Fedora 40 and
Ubuntu 23.10 and 24.04, while dropping unsupported Ubuntu 23.04 (Lunar).

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2024-05-21 08:41:49 +02:00
15 changed files with 251 additions and 60 deletions

View File

@@ -43,10 +43,15 @@ jobs:
# Fails on configure on GCC and clang (process restrictions?)
# - fedora:rawhide
- fedora:latest
- fedora:42
- fedora:41
- fedora:40
- fedora:39
- fedora:38
- fedora:37
- ubuntu:lunar # EOL 01.2024
- ubuntu:latest
- ubuntu:oracular
- ubuntu:noble
- ubuntu:jammy
- ubuntu:focal
# On Ubuntu Bionic the Meson doesn't support feature options
@@ -178,7 +183,7 @@ jobs:
echo "PKG_CONFIG_PATH: $PKG_CONFIG_PATH"
- name: Git checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install additional packages
run: |

View File

@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2

View File

@@ -27,7 +27,7 @@ jobs:
steps:
- name: Git checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install additional packages
run: |

8
README
View File

@@ -19,11 +19,13 @@ from sandbox/cdba/cdba-server. Available devices are read from $HOME/.cdba
= Client side
The client is invoked as:
cdba -b <board> -h <host> [-c <power-cylce-count>] [-s <status-fifo>] boot.img
cdba -b <board> [-h <host>] [-c <power-cylce-count>] [-s <status-fifo>] [boot.img]
<host> will be connected to using ssh and <board> will be selected for
operation. As the board's fastboot interface shows up the given boot.img will
be transfered and booted on the device.
operation. As the board's fastboot interface shows up the given boot.img
will be transfered and booted on the device. If <host> is omitted, the
cdba-server is started locally without using ssh. If [boot.img] is omitted,
"fastboot continue" is run to boot the installed operating system.
The board will execute until the key sequence ^A q is invoked or the board
outputs a sequence of 20 ~ (tilde) chards in a row.

View File

@@ -59,10 +59,10 @@ static void msg_select_board(const void *param)
if (!selected_device) {
fprintf(stderr, "failed to open %s\n", (const char *)param);
watch_quit();
} else {
device_fastboot_open(selected_device, &fastboot_ops);
}
device_fastboot_open(selected_device, &fastboot_ops);
cdba_send(MSG_SELECT_BOARD);
}
@@ -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);
@@ -201,6 +226,11 @@ static void sigpipe_handler(int signo)
watch_quit();
}
static void atexit_handler(void)
{
syslog(LOG_INFO, "exiting");
}
int main(int argc, char **argv)
{
int flags;
@@ -216,7 +246,8 @@ int main(int argc, char **argv)
if (!username)
username = "nobody";
openlog("cdba-server", 0, LOG_DAEMON);
openlog("cdba-server", LOG_PID, LOG_DAEMON);
atexit(atexit_handler);
ret = device_parser(".cdba");
if (ret) {

73
cdba.c
View File

@@ -103,8 +103,13 @@ static int fork_ssh(const char *host, const char *cmd, int *pipes)
close(piped_stderr[0]);
close(piped_stderr[1]);
execl("/usr/bin/ssh", "ssh", host, cmd, NULL);
err(1, "launching ssh failed");
if (host) {
execlp("ssh", "ssh", host, cmd, NULL);
err(1, "launching ssh failed");
} else {
execlp(cmd, cmd, NULL);
err(1, "launching cdba-server failed");
}
default:
close(piped_stdin[0]);
close(piped_stdout[1]);
@@ -143,8 +148,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 +206,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;
@@ -533,13 +567,11 @@ static int handle_message(struct circ_buf *buf)
} else {
quit = true;
}
} else {
fastboot_done = true;
// printf("======================================== MSG_FASTBOOT_PRESENT(off)\n");
}
break;
case MSG_FASTBOOT_DOWNLOAD:
// printf("======================================== MSG_FASTBOOT_DOWNLOAD\n");
fastboot_done = true;
break;
case MSG_FASTBOOT_BOOT:
// printf("======================================== MSG_FASTBOOT_BOOT\n");
@@ -556,6 +588,7 @@ static int handle_message(struct circ_buf *buf)
break;
case MSG_FASTBOOT_CONTINUE:
// printf("======================================== MSG_FASTBOOT_CONTINUE\n");
fastboot_done = true;
break;
default:
fprintf(stderr, "unk %d len %d\n", msg->type, msg->len);
@@ -584,12 +617,12 @@ static void usage(void)
{
extern const char *__progname;
fprintf(stderr, "usage: %s -b <board> -h <host> [-t <timeout>] "
"[-T <inactivity-timeout>] <boot.img>\n",
fprintf(stderr, "usage: %s -b <board> [-h <host>] [-t <timeout>] "
"[-T <inactivity-timeout>] [boot.img]\n",
__progname);
fprintf(stderr, "usage: %s -i -b <board> -h <host>\n",
fprintf(stderr, "usage: %s -i -b <board> [-h <host>]\n",
__progname);
fprintf(stderr, "usage: %s -l -h <host>\n",
fprintf(stderr, "usage: %s -l [-h <host>]\n",
__progname);
exit(1);
}
@@ -605,6 +638,7 @@ int main(int argc, char **argv)
bool power_cycle_on_timeout = true;
struct timeval timeout_inactivity_tv;
struct timeval timeout_total_tv;
struct timeval *timeout = NULL;
struct termios *orig_tios;
const char *server_binary = "cdba-server";
const char *status_pipe = NULL;
@@ -668,9 +702,6 @@ int main(int argc, char **argv)
}
}
if (!host)
usage();
switch (verb) {
case CDBA_BOOT:
if (optind > argc || !board)
@@ -708,6 +739,8 @@ int main(int argc, char **argv)
timeout_total_tv = get_timeout(timeout_total);
timeout_inactivity_tv = get_timeout(timeout_inactivity);
if (timeout_total || timeout_inactivity)
timeout = &tv;
while (!quit) {
if (received_power_off || reached_timeout) {
@@ -745,14 +778,16 @@ int main(int argc, char **argv)
if (!list_empty(&work_items))
FD_SET(ssh_fds[0], &wfds);
gettimeofday(&now, NULL);
if (timeout_inactivity && timercmp(&timeout_inactivity_tv, &timeout_total_tv, <)) {
timersub(&timeout_inactivity_tv, &now, &tv);
} else {
timersub(&timeout_total_tv, &now, &tv);
if (timeout) {
gettimeofday(&now, NULL);
if (timeout_inactivity && (!timeout_total ||
timercmp(&timeout_inactivity_tv, &timeout_total_tv, <))) {
timersub(&timeout_inactivity_tv, &now, timeout);
} else {
timersub(&timeout_total_tv, &now, timeout);
}
}
ret = select(nfds + 1, &rfds, &wfds, NULL, &tv);
ret = select(nfds + 1, &rfds, &wfds, NULL, timeout);
#if 0
printf("select: %d (%c%c%c)\n", ret, FD_ISSET(STDIN_FILENO, &rfds) ? 'X' : '-',
FD_ISSET(ssh_fds[1], &rfds) ? 'X' : '-',

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

@@ -73,3 +73,32 @@ devices:
power:
interface: D
line: 6
- board: myboard-5
name: "My Board 5"
description: |
My super awesome board Number 5
console: /dev/ttyABC1
fastboot: cacafada
ftdi_gpio:
vendor: "0x0403"
product: "0x6011"
index: 0
power:
interface: B
line: 1
active_low: true
fastboot_key:
interface: B
line: 0
active_low: true
power_key:
interface: B
line: 2
usb0_disconnect:
interface: C
line: 7
active_low: true
usb1_disconnect:
interface: A
line: 4
active_low: true

View File

@@ -64,15 +64,21 @@ static void device_lock(struct device *device)
if (fd < 0)
err(1, "failed to open lockfile %s", lock);
n = flock(fd, LOCK_EX | LOCK_NB);
if (!n)
return;
while (1) {
char c;
warnx("board is in use, waiting...");
n = flock(fd, LOCK_EX | LOCK_NB);
if (!n)
return;
n = flock(fd, LOCK_EX);
if (n < 0)
err(1, "failed to lock lockfile %s", lock);
warnx("board is in use, waiting...");
sleep(3);
/* check that connection isn't gone */
if (read(STDIN_FILENO, &c, 1) == 0)
errx(1, "connection is gone");
}
}
static bool device_check_access(struct device *device,
@@ -157,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);
@@ -279,7 +285,7 @@ void device_usb(struct device *device, bool on)
{
if (device->ppps_path)
ppps_power(device, on);
else if (device_has_control(device, usb))
if (device_has_control(device, usb))
device_control(device, usb, on);
}

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;

View File

@@ -22,6 +22,11 @@ static void nextsym(struct device_parser *dp)
{
if (!yaml_parser_parse(&dp->parser, &dp->event)) {
fprintf(stderr, "device parser: error %u\n", dp->parser.error);
fprintf(stderr,
"device parser: index %zu, line %zu, column %zu\n",
dp->parser.context_mark.index,
dp->parser.context_mark.line,
dp->parser.context_mark.column);
exit(1);
}
}
@@ -43,6 +48,33 @@ int device_parser_accept(struct device_parser *dp, int type,
}
}
void decode_yaml_type_error(struct device_parser *dp, int type)
{
char event_type[11][26] = {
"YAML_NO_EVENT",
"YAML_STREAM_START_EVENT",
"YAML_STREAM_END_EVENT",
"YAML_DOCUMENT_START_EVENT",
"YAML_DOCUMENT_END_EVENT",
"YAML_ALIAS_EVENT",
"YAML_SCALAR_EVENT",
"YAML_SEQUENCE_START_EVENT",
"YAML_SEQUENCE_END_EVENT",
"YAML_MAPPING_START_EVENT",
"YAML_MAPPING_END_EVENT"
};
fprintf(stderr,
"device parser: expected %s got %s\n",
event_type[type],
event_type[dp->event.type]);
fprintf(stderr,
"device parser: index %zu, line %zu, column %zu\n",
dp->parser.mark.index,
dp->parser.mark.line,
dp->parser.mark.column);
}
bool device_parser_expect(struct device_parser *dp, int type,
char *scalar, size_t scalar_len)
{
@@ -50,7 +82,7 @@ bool device_parser_expect(struct device_parser *dp, int type,
return true;
}
fprintf(stderr, "device parser: expected %d got %u\n", type, dp->event.type);
decode_yaml_type_error(dp, type);
exit(1);
}

View File

@@ -31,7 +31,8 @@ enum {
GPIO_POWER = 0, // Power input enable
GPIO_FASTBOOT_KEY, // Usually volume key
GPIO_POWER_KEY, // Key to power the device
GPIO_USB_DISCONNECT, // Simulate main USB connection
GPIO_USB0_DISCONNECT, // Simulate main USB connection
GPIO_USB1_DISCONNECT, // Simulate secondary USB connection
GPIO_OUTPUT_ENABLE, // Enable FTDI signals to flow to the board
GPIO_COUNT
};
@@ -131,7 +132,7 @@ static void ftdi_gpio_parse_config(struct ftdi_gpio_options *options, char *valu
else if (strncmp("POWER_KEY", name, off - name - 1) == 0)
gpio_type = GPIO_POWER_KEY;
else if (strncmp("USB_DISCONNECT", name, off - name - 1) == 0)
gpio_type = GPIO_USB_DISCONNECT;
gpio_type = GPIO_USB0_DISCONNECT;
else if (strncmp("OUTPUT_ENABLE", name, off - name - 1) == 0)
gpio_type = GPIO_OUTPUT_ENABLE;
else
@@ -182,7 +183,11 @@ void *ftdi_gpio_parse_options(struct device_parser *dp)
} else if (!strcmp(key, "power_key")) {
gpio_id = GPIO_POWER_KEY;
} else if (!strcmp(key, "usb_disconnect")) {
gpio_id = GPIO_USB_DISCONNECT;
gpio_id = GPIO_USB0_DISCONNECT;
} else if (!strcmp(key, "usb0_disconnect")) {
gpio_id = GPIO_USB0_DISCONNECT;
} else if (!strcmp(key, "usb1_disconnect")) {
gpio_id = GPIO_USB1_DISCONNECT;
} else if (!strcmp(key, "output_enable")) {
gpio_id = GPIO_OUTPUT_ENABLE;
} else {
@@ -311,6 +316,9 @@ static void *ftdi_gpio_open(struct device *dev)
if (ftdi_gpio->options->gpios[GPIO_POWER_KEY].present)
dev->has_power_key = true;
if (ftdi_gpio->options->gpios[GPIO_OUTPUT_ENABLE].present)
ftdi_gpio_toggle_io(ftdi_gpio, GPIO_OUTPUT_ENABLE, 1);
ftdi_gpio_device_power(ftdi_gpio, 0);
if (dev->usb_always_on)
@@ -318,9 +326,6 @@ static void *ftdi_gpio_open(struct device *dev)
else
ftdi_gpio_device_usb(ftdi_gpio, 0);
if (ftdi_gpio->options->gpios[GPIO_OUTPUT_ENABLE].present)
ftdi_gpio_toggle_io(ftdi_gpio, GPIO_OUTPUT_ENABLE, 1);
usleep(500000);
return ftdi_gpio;
@@ -357,7 +362,8 @@ static int ftdi_gpio_device_power(struct ftdi_gpio *ftdi_gpio, bool on)
static void ftdi_gpio_device_usb(struct ftdi_gpio *ftdi_gpio, bool on)
{
ftdi_gpio_toggle_io(ftdi_gpio, GPIO_USB_DISCONNECT, on);
ftdi_gpio_toggle_io(ftdi_gpio, GPIO_USB0_DISCONNECT, on);
ftdi_gpio_toggle_io(ftdi_gpio, GPIO_USB1_DISCONNECT, on);
}
static int ftdi_gpio_power(struct device *dev, bool on)

View File

@@ -23,6 +23,7 @@ struct laurent_options {
const char *server;
const char *password;
unsigned int relay;
int usb_relay;
};
struct laurent {
@@ -42,6 +43,7 @@ void *laurent_parse_options(struct device_parser *dp)
options = calloc(1, sizeof(*options));
options->password = DEFAULT_PASSWORD;
options->usb_relay = -1;
device_parser_accept(dp, YAML_MAPPING_START_EVENT, NULL, 0);
while (device_parser_accept(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
@@ -54,6 +56,8 @@ void *laurent_parse_options(struct device_parser *dp)
options->password = strdup(value);
else if (!strcmp(key, "relay"))
options->relay = strtoul(value, NULL, 0);
else if (!strcmp(key, "usb_relay"))
options->usb_relay = strtoul(value, NULL, 0);
else
errx(1, "%s: unknown option \"%s\"", __func__, key);
}
@@ -124,7 +128,7 @@ static void *laurent_open(struct device *dev)
return laurent;
}
static int laurent_power(struct device *dev, bool on)
static int laurent_control(struct device *dev, unsigned int relay, bool on)
{
struct laurent *laurent = dev->cdb;
char buf[BUFSIZ];
@@ -145,7 +149,7 @@ static int laurent_power(struct device *dev, bool on)
len = snprintf(buf, sizeof(buf), "GET /cmd.cgi?psw=%s&cmd=REL,%u,%d HTTP/1.0\r\n\r\n",
laurent->options->password,
laurent->options->relay,
relay,
on);
if (len < 0) {
warn("asprintf failed\n");
@@ -190,8 +194,30 @@ err:
return -1;
}
static int laurent_power(struct device *dev, bool on)
{
struct laurent *laurent = dev->cdb;
return laurent_control(dev,
laurent->options->relay,
on);
}
static void laurent_usb(struct device *dev, bool on)
{
struct laurent *laurent = dev->cdb;
if (laurent->options->usb_relay < 0)
return;
laurent_control(dev,
laurent->options->usb_relay,
on);
}
const struct control_ops laurent_ops = {
.parse_options = laurent_parse_options,
.open = laurent_open,
.power = laurent_power,
.usb = laurent_usb,
};

View File

@@ -26,7 +26,7 @@ properties:
fastboot:
description: fastboot id
type: string
pattern: "^[0-9a-f]{8}$"
pattern: "^[0-9a-f]{8,16}$"
fastboot_set_active:
description: run fastboot set active before each boot, slot can be selected
@@ -123,9 +123,10 @@ properties:
minimin: 0
devicenode:
$ref: "#/$defs/device_path"
patternProperties:
"^power|fastboot_key|power_key|usb_disconnect|output_enable$":
$ref: "#/$defs/ftdi_gpio"
patternProperties:
"^power|fastboot_key|power_key|usb[01]?_disconnect|output_enable$":
$ref: "#/$defs/ftdi_gpio"
additionalProperties: false
dependentRequired:
index:
@@ -138,7 +139,7 @@ properties:
local_gpio:
description: Local GPIO
type: object
unevaluatedItems: false
additionalProperties: false
patternProperties:
"^power|fastboot_key|power_key|usb_disconnect$":
$ref: "#/$defs/local_gpio"
@@ -146,12 +147,14 @@ properties:
laurent:
description: KernelChip Laurent relays
type: object
unevaluatedItems: false
additionalProperties: false
properties:
server:
type: string
relay:
type: integer
usb_relay:
type: integer
password:
description: password to access the relays, defaults to 'Laurent'
type: string

View File

@@ -43,7 +43,8 @@ void status_send_values(const char *id, struct status_value *values)
status_get_ts(&ts);
len = snprintf(buf, sizeof(buf), "{\"ts\":%ld.%03ld, \"%s\":{ ", ts.tv_sec, ts.tv_nsec / 1000000, id);
len = snprintf(buf, sizeof(buf), "{\"ts\":%lld.%03ld, \"%s\":{ ",
(long long int)ts.tv_sec, ts.tv_nsec / 1000000, id);
for (value = values; value->unit; value++) {
if (value != values) {