diff --git a/Makefile b/Makefile index 5a6e1ae..ec8d1cb 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ LDFLAGS := $(shell pkg-config --libs yaml-0.1 $(LIBFTDI) libudev) CLIENT_SRCS := cdba.c circ_buf.c CLIENT_OBJS := $(CLIENT_SRCS:.c=.o) -SERVER_SRCS := cdba-server.c cdb_assist.c circ_buf.c conmux.c device.c device_parser.c fastboot.c alpaca.c ftdi-gpio.c console.c qcomlt_dbg.c +SERVER_SRCS := cdba-server.c cdb_assist.c circ_buf.c conmux.c device.c device_parser.c fastboot.c alpaca.c ftdi-gpio.c console.c qcomlt_dbg.c ppps.c SERVER_OBJS := $(SERVER_SRCS:.c=.o) $(CLIENT): $(CLIENT_OBJS) diff --git a/device.c b/device.c index cc14e52..278181c 100644 --- a/device.c +++ b/device.c @@ -44,6 +44,7 @@ #include "fastboot.h" #include "console.h" #include "list.h" +#include "ppps.h" #define ARRAY_SIZE(x) ((sizeof(x)/sizeof((x)[0]))) @@ -252,8 +253,12 @@ void device_print_status(struct device *device) void device_usb(struct device *device, bool on) { - if (device->usb) - device->usb(device, on); + if (device->usb) { + if (device->ppps_path) + ppps_power(device, on); + else + device->usb(device, on); + } } int device_write(struct device *device, const void *buf, size_t len) diff --git a/device.h b/device.h index 5321b70..0ee659b 100644 --- a/device.h +++ b/device.h @@ -15,6 +15,7 @@ struct device { char *name; char *serial; char *description; + char *ppps_path; struct list_head *users; unsigned voltage; bool tickle_mmc; diff --git a/device_parser.c b/device_parser.c index 7956682..bab9a1b 100644 --- a/device_parser.c +++ b/device_parser.c @@ -39,6 +39,7 @@ #include "conmux.h" #include "console.h" #include "qcomlt_dbg.h" +#include "ppps.h" #define TOKEN_LENGTH 16384 @@ -179,6 +180,8 @@ static void parse_board(struct device_parser *dp) dev->fastboot_key_timeout = strtoul(value, NULL, 10); } else if (!strcmp(key, "usb_always_on")) { dev->usb_always_on = !strcmp(value, "true"); + } else if (!strcmp(key, "ppps_path")) { + dev->ppps_path = strdup(value); } else { fprintf(stderr, "device parser: unknown key \"%s\"\n", key); exit(1); diff --git a/ppps.c b/ppps.c new file mode 100644 index 0000000..494a805 --- /dev/null +++ b/ppps.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023, Linaro Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define _GNU_SOURCE /* for asprintf */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device.h" + +#define PPPS_BASE_PATH "/sys/bus/usb/devices" +#define PPPS_BASE_PATH_LEN strlen(PPPS_BASE_PATH) + +void ppps_power(struct device *dev, bool on) +{ + static char *path = NULL; + int rc, fd; + + /* Only need to figure out the whole string once */ + if (!path) { + /* ppps_path should be like "2-2:1.0/2-2-port2" */ + asprintf(&path, "%s/%s/disable", PPPS_BASE_PATH, dev->ppps_path); + } + + // fprintf(stderr, "ppps_power: %-3s %s\n", on ? "on" : "off", path); + + fd = open(path, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); + if (errno != ENOENT) + fprintf(stderr, "Maybe missing permissions (see https://git.io/JIB2Z)\n"); + return; + } + + rc = write(fd, on ? "0" : "1", 1); + if (rc < 0) + fprintf(stderr, "failed to write to %s: %s\n", path, strerror(errno)); + + close(fd); +} diff --git a/ppps.h b/ppps.h new file mode 100644 index 0000000..e6cba63 --- /dev/null +++ b/ppps.h @@ -0,0 +1,6 @@ +#ifndef __PPPS_H__ +#define __PPPS_H__ + +void ppps_power(struct device *dev, bool on); + +#endif