Interim. The Makefile needs to be tuned so we can include to correct files. Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> --- tools/usb/Build | 1 + tools/usb/Makefile | 8 ++- tools/usb/pd-test.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 tools/usb/pd-test.c diff --git a/tools/usb/Build b/tools/usb/Build index 2ad6f97458168..7116198533a75 100644 --- a/tools/usb/Build +++ b/tools/usb/Build @@ -1,2 +1,3 @@ testusb-y += testusb.o ffs-test-y += ffs-test.o +pd-test-y += pd-test.o diff --git a/tools/usb/Makefile b/tools/usb/Makefile index 1b128e551b2e4..e3e41a3397f23 100644 --- a/tools/usb/Makefile +++ b/tools/usb/Makefile @@ -16,7 +16,7 @@ MAKEFLAGS += -r override CFLAGS += -O2 -Wall -Wextra -g -D_GNU_SOURCE -I$(OUTPUT)include -I$(srctree)/tools/include override LDFLAGS += -lpthread -ALL_TARGETS := testusb ffs-test +ALL_TARGETS := testusb ffs-test pd-test ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) all: $(ALL_PROGRAMS) @@ -36,6 +36,12 @@ $(FFS_TEST_IN): FORCE $(OUTPUT)ffs-test: $(FFS_TEST_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +PD_TEST_IN := $(OUTPUT)pd-test-in.o +$(PD_TEST_IN): FORCE + $(Q)$(MAKE) $(build)=pd-test +$(OUTPUT)pd-test: $(PD_TEST_IN) + $(QUIET_LINK)$(CC) $(CFLAGS) $< -o $@ + clean: rm -f $(ALL_PROGRAMS) find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete -o -name '\.*.o.cmd' -delete diff --git a/tools/usb/pd-test.c b/tools/usb/pd-test.c new file mode 100644 index 0000000000000..bb38dd4134581 --- /dev/null +++ b/tools/usb/pd-test.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * USB Power Delivery device tester. + * + * Copyright (C) 2021 Intel Corporation + * Author: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> + */ + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <linux/types.h> + +struct pd_message { + __le16 header; + __le32 payload[7]; +} __attribute__((packed)); + +struct pd_info { + __u8 specification_revision; + __u32 ctrl_msgs_supported; + __u32 data_msgs_supported; + __u32 ext_msgs_supported; +} __attribute__((packed)); + +#define USBPDDEV_INFO _IOR('P', 0x70, struct pd_info) +#define USBPDDEV_CONFIGURE _IOW('P', 0x71, __u32) +#define USBPDDEV_PWR_ROLE _IOR('P', 0x72, int) +#define USBPDDEV_GET_MESSAGE _IOWR('P', 0x73, struct pd_message) +#define USBPDDEV_SET_MESSAGE _IOW('P', 0x74, struct pd_message) +#define USBPDDEV_SUBMIT_MESSAGE _IOWR('P', 0x75, struct pd_message) + +enum pd_data_msg_type { + /* 0 Reserved */ + PD_DATA_SOURCE_CAP = 1, + PD_DATA_REQUEST = 2, + PD_DATA_BIST = 3, + PD_DATA_SINK_CAP = 4, + PD_DATA_BATT_STATUS = 5, + PD_DATA_ALERT = 6, + PD_DATA_GET_COUNTRY_INFO = 7, + PD_DATA_ENTER_USB = 8, + /* 9-14 Reserved */ + PD_DATA_VENDOR_DEF = 15, + /* 16-31 Reserved */ +}; + +int dump_source_pdos(int fd) +{ + struct pd_message msg = {}; + int ret; + int i; + + msg.header = PD_DATA_SOURCE_CAP; + ret = ioctl(fd, USBPDDEV_GET_MESSAGE, &msg); + if (ret < 0) { + printf("No cached Source Capabilities %d\n", ret); + return ret; + } + + printf("Source Capabilities:\n"); + + for (i = 0; i < (msg.header >> 12 & 7); i++) + printf(" PDO%d: 0x%08x\n", i + 1, msg.payload[i]); + + return 0; +} + +int dump_sink_pdos(int fd) +{ + struct pd_message msg = {}; + int ret; + int i; + + msg.header = PD_DATA_SINK_CAP; + ret = ioctl(fd, USBPDDEV_GET_MESSAGE, &msg); + if (ret < 0) { + printf("No cached Sink Capabilities %d\n", ret); + return ret; + } + + printf("Sink Capabilities:\n"); + + for (i = 0; i < (msg.header >> 12 & 7); i++) + printf(" PDO%d: 0x%08x\n", i + 1, msg.payload[i]); + + return 0; +} + +int main(int argc, char **argv) +{ + unsigned int role; + int ret; + int fd; + + if (argc != 2) { + fprintf(stderr, "Usage: %s [DEV]\n" + " %% %s /dev/pd0/port\n\n", + argv[0], argv[0]); + return -1; + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) + return fd; + + ret = ioctl(fd, USBPDDEV_PWR_ROLE, &role); + if (ret < 0) { + printf("USBPDDEV_PWR_ROLE failed %d\n", ret); + goto err; + } + + if (role) + ret = dump_source_pdos(fd); + else + ret = dump_sink_pdos(fd); +err: + close(fd); + + return ret; +} -- 2.33.0