diff --git a/cdba-power.c b/cdba-power.c index 8d3f786..d8902d2 100644 --- a/cdba-power.c +++ b/cdba-power.c @@ -23,6 +23,7 @@ void cdba_send_buf(int type, size_t len, const void *buf) static void usage(const char *name) { fprintf(stderr, "Usage: %s on|off\n", name); + fprintf(stderr, "Usage: %s all-off\n", name); exit(EXIT_FAILURE); } @@ -33,22 +34,47 @@ bool ready(void) return device_is_running(selected_device); } +static int all_off(void) +{ + struct device *next = NULL, *dev; + int ret = 0; + + while ((next = device_next(next))) { + dev = device_open_power_only(next->board, "nobody"); + if (!dev) { + fprintf(stderr, "failed to open %s\n", next->board); + ret = EXIT_FAILURE; + continue; + } + + device_usb(dev, false); + device_power_off(dev); + device_close(dev); + } + + return ret; +} + int main(int argc, char **argv) { const char *home; const char *name; + bool all = false; 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 + if (argc == 2 && !strcmp(argv[1], "all-off")) { + all = true; + } else if (argc == 3) { + if (!strcmp(argv[2], "on")) + on = true; + else if (!strcmp(argv[2], "off")) + on = false; + else + usage(argv[0]); + } else { usage(argv[0]); + } home = getenv("HOME"); if (home) @@ -63,6 +89,9 @@ int main(int argc, char **argv) } } + if (all) + return all_off(); + name = argv[1]; selected_device = device_open(name, "nobody"); if (!selected_device) { diff --git a/device.c b/device.c index 8b76524..3380507 100644 --- a/device.c +++ b/device.c @@ -49,6 +49,17 @@ void device_add(struct device *device) list_append(&devices, &device->node); } +struct device *device_next(struct device *device) +{ + struct list_head *item; + + item = device ? device->node.next : devices.next; + if (item == &devices) + return NULL; + + return list_entry(item, struct device, node); +} + static void device_lock(struct device *device) { char lock[PATH_MAX]; @@ -103,8 +114,8 @@ static bool device_check_access(struct device *device, return false; } -struct device *device_open(const char *board, - const char *username) +static struct device *__device_open(const char *board, const char *username, + bool power_only) { struct device *device; @@ -133,10 +144,20 @@ struct device *device_open(const char *board, if (device_has_control(device, open)) { device->cdb = device_control(device, open); - if (!device->cdb) + if (!device->cdb) { + if (power_only) { + warnx("failed to open device controller for %s", + board); + return NULL; + } errx(1, "failed to open device controller"); + } } + /* Switching power and USB off needs neither console nor fastboot. */ + if (power_only) + return device; + device->console = device_console(device, open); if (!device->console) errx(1, "failed to open device console"); @@ -159,6 +180,20 @@ struct device *device_open(const char *board, return device; } +struct device *device_open(const char *board, const char *username) +{ + return __device_open(board, username, false); +} + +/* + * Open only the board's controller (no console), enough to switch power and + * USB off. Unlike device_open() this doesn't exit if the console is missing. + */ +struct device *device_open_power_only(const char *board, const char *username) +{ + return __device_open(board, username, true); +} + static void device_impl_power(struct device *device, bool on) { device_control(device, power, on); diff --git a/device.h b/device.h index 664f942..54a6aaa 100644 --- a/device.h +++ b/device.h @@ -94,9 +94,12 @@ struct device_qdl_user { }; void device_add(struct device *device); +struct device *device_next(struct device *device); struct device *device_open(const char *board, const char *username); +struct device *device_open_power_only(const char *board, + const char *username); void device_close(struct device *dev); int device_power_on(struct device *device, enum power_on_mode mode); int device_power_off(struct device *device); diff --git a/drivers/alpaca.c b/drivers/alpaca.c index f720670..37628fb 100644 --- a/drivers/alpaca.c +++ b/drivers/alpaca.c @@ -38,8 +38,10 @@ static void *alpaca_open(struct device *dev) alpaca = calloc(1, sizeof(*alpaca)); alpaca->alpaca_fd = tty_open(dev->control_dev, &alpaca->alpaca_tios); - if (alpaca->alpaca_fd < 0) - err(1, "failed to open %s", dev->control_dev); + if (alpaca->alpaca_fd < 0) { + free(alpaca); + return NULL; + } alpaca_device_power(alpaca, 0); diff --git a/drivers/ftdi-gpio.c b/drivers/ftdi-gpio.c index 070b3d3..52c7442 100644 --- a/drivers/ftdi-gpio.c +++ b/drivers/ftdi-gpio.c @@ -308,9 +308,18 @@ static void *ftdi_gpio_open(struct device *dev) ret = ftdi_usb_open_string(ftdi_gpio->interface[ftdi_interface], ftdi_gpio->options->ftdi.description); - if (ret < 0) - errx(1, "failed to open ftdi gpio device '%s' (%d)", - ftdi_gpio->options->ftdi.description, ret); + if (ret < 0) { + warnx("failed to open ftdi gpio device '%s' (%d)", + ftdi_gpio->options->ftdi.description, ret); + for (i = 0; i < FTDI_INTERFACE_COUNT; ++i) { + if (!ftdi_gpio->interface[i]) + continue; + ftdi_usb_close(ftdi_gpio->interface[i]); + ftdi_free(ftdi_gpio->interface[i]); + } + free(ftdi_gpio); + return NULL; + } ftdi_set_bitmode(ftdi_gpio->interface[ftdi_interface], 0xFF, BITMODE_BITBANG); diff --git a/drivers/pic32cx.c b/drivers/pic32cx.c index 0049fe1..ea032b4 100644 --- a/drivers/pic32cx.c +++ b/drivers/pic32cx.c @@ -49,8 +49,10 @@ static void *pic32cx_open(struct device *dev) pic32cx = calloc(1, sizeof(*pic32cx)); pic32cx->fd = tty_open(dev->control_dev, &pic32cx->tios); - if (pic32cx->fd < 0) - err(1, "failed to open %s", dev->control_dev); + if (pic32cx->fd < 0) { + free(pic32cx); + return NULL; + } pic32cx_device_power(pic32cx, 1); diff --git a/drivers/qcomlt_dbg.c b/drivers/qcomlt_dbg.c index fe55cf4..d058955 100644 --- a/drivers/qcomlt_dbg.c +++ b/drivers/qcomlt_dbg.c @@ -52,8 +52,10 @@ static void *qcomlt_dbg_open(struct device *dev) dbg = calloc(1, sizeof(*dbg)); dbg->fd = tty_open(dev->control_dev, &dbg->orig_tios); - if (dbg->fd < 0) - err(1, "failed to open %s", dev->control_dev); + if (dbg->fd < 0) { + free(dbg); + return NULL; + } // fprintf(stderr, "qcomlt_dbg_open()\n"); write(dbg->fd, "brpu", 4); diff --git a/tty.c b/tty.c index 4c75cfe..e4f49a1 100644 --- a/tty.c +++ b/tty.c @@ -20,8 +20,10 @@ int tty_open(const char *tty, struct termios *old) int fd; fd = open(tty, O_RDWR | O_NOCTTY | O_EXCL); - if (fd < 0) - err(1, "unable to open \"%s\"", tty); + if (fd < 0) { + warn("unable to open \"%s\"", tty); + return -1; + } ret = tcgetattr(fd, old); if (ret < 0)