mirror of
https://github.com/linux-msm/cdba.git
synced 2026-02-25 13:11:56 -08:00
Compare commits
35 Commits
topic/prot
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6c766db1f | ||
|
|
031948ff19 | ||
|
|
30c30ce84c | ||
|
|
95a40706be | ||
|
|
4320c482d3 | ||
|
|
cdee00d9a4 | ||
|
|
5bade34946 | ||
|
|
3c1e7cc886 | ||
|
|
bad935cbf2 | ||
|
|
9335390898 | ||
|
|
b6d70e8b0c | ||
|
|
06531f3db1 | ||
|
|
828d76df63 | ||
|
|
e799564f44 | ||
|
|
720922913c | ||
|
|
8bd8eeda33 | ||
|
|
f801448422 | ||
|
|
3922dc793a | ||
|
|
61babbf9ac | ||
|
|
358fea7207 | ||
|
|
b0df12edc0 | ||
|
|
59db2941f5 | ||
|
|
8715e3b74d | ||
|
|
aa0e50bb1d | ||
|
|
0852da5424 | ||
|
|
2f3e661f4d | ||
|
|
2899fbcbb1 | ||
|
|
61139604fb | ||
|
|
cbad92a838 | ||
|
|
95ff3049f8 | ||
|
|
5db3df360a | ||
|
|
02210fe6e2 | ||
|
|
b3b50a7441 | ||
|
|
c86932d361 | ||
|
|
d77816052d |
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -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: |
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/yaml.yml
vendored
2
.github/workflows/yaml.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Git checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install additional packages
|
||||
run: |
|
||||
|
||||
8
README
8
README
@@ -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.
|
||||
|
||||
@@ -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
73
cdba.c
@@ -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
18
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
|
||||
|
||||
@@ -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
|
||||
|
||||
24
device.c
24
device.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
7
device.h
7
device.h
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
15
schema.yaml
15
schema.yaml
@@ -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
|
||||
|
||||
3
status.c
3
status.c
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user