From 0cb1fe44addbcc3e2f0c1231d14402b3472fe9c1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Oct 2015 11:41:04 +1000 Subject: [PATCH] tools: ad a hidpp10-dump-page tool to dump a HID++1.0 device's memory For protocol debugging, it's a lot easier to go have a simple helper than having to go through the whole of libratbag. And remove the page-dump helper from the main code. Note that this tool needs a /dev/hidraw device directly, not an event node. It is a debugging tool after all. Signed-off-by: Peter Hutterer --- .gitignore | 1 + src/Makefile.am | 9 +++ src/hidpp10.c | 27 --------- src/libratbag-util.h | 5 ++ tools/Makefile.am | 7 ++- tools/hidpp10-dump-page.c | 115 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 136 insertions(+), 28 deletions(-) create mode 100644 tools/hidpp10-dump-page.c diff --git a/.gitignore b/.gitignore index 1e4fc308..1ef09442 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ test-context test-device test-*.log ratbag-command +hidpp10-dump-page diff --git a/src/Makefile.am b/src/Makefile.am index 19ae3e61..a2ed81c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,5 @@ lib_LTLIBRARIES = libratbag.la +noinst_LTLIBRARIES = libhidpp10.la include_HEADERS = \ libratbag.h @@ -43,3 +44,11 @@ AM_CFLAGS = $(GCC_CFLAGS) DISTCLEANFILES = libratbag-version.h EXTRA_DIST = libratbag-version.h.in libratbag.sym + +# The hidpp libraries are static libraries only for in-tree tools. No API +# stability is guaranteed here. +libhidpp10_la_SOURCES = \ + hidpp-generic.h \ + hidpp-generic.c \ + hidpp10.h \ + hidpp10.c diff --git a/src/hidpp10.c b/src/hidpp10.c index 574c497f..0b93830e 100644 --- a/src/hidpp10.c +++ b/src/hidpp10.c @@ -193,9 +193,6 @@ out_err: /* HID++ 1.0 commands 10 */ /* -------------------------------------------------------------------------- */ -static inline void -hidpp10_dump_all_pages(struct hidpp10_device *dev); - /* -------------------------------------------------------------------------- */ /* 0x00: Enable HID++ Notifications */ /* -------------------------------------------------------------------------- */ @@ -1035,30 +1032,6 @@ hidpp10_read_memory(struct hidpp10_device *dev, uint8_t page, uint8_t offset, return 0; } -static inline void -hidpp10_dump_all_pages(struct hidpp10_device *dev) -{ - uint16_t page, offset; - uint8_t bytes[16]; - int res; - - hidpp_log_info(&dev->base, "::::::: Dumping memory :::::\n"); - - for (page = 0; page < 512; page++) { - hidpp_log_info(&dev->base, ":: page %d\n", page); - for (offset = 0; offset < 256; offset += 16) { - res = hidpp10_read_memory(dev, page, offset, bytes); - if (res != 0) - goto out; - - hidpp_log_buffer(&dev->base, HIDPP_LOG_PRIORITY_INFO, " ", bytes, ARRAY_LENGTH(bytes)); - } - } - -out: - hidpp_log_info(&dev->base, "::::::: Dumping memory complete :::::\n"); -} - /* -------------------------------------------------------------------------- */ /* 0xB2: Device Connection and Disconnection (Pairing) */ /* -------------------------------------------------------------------------- */ diff --git a/src/libratbag-util.h b/src/libratbag-util.h index 186dcccc..b2cb59bf 100644 --- a/src/libratbag-util.h +++ b/src/libratbag-util.h @@ -85,6 +85,10 @@ cleanup_free(void *p) { free(*(void**)p); } +static inline void +cleanup_close(int *p) { + close(*p); +} static inline void cleanup_udev_unref(struct udev **udev) { if (*udev) @@ -99,6 +103,7 @@ cleanup_udev_device_unref(struct udev_device **udev_device) { #define _cleanup_(x) __attribute__((cleanup(x))) #define _cleanup_free_ _cleanup_(cleanup_free) +#define _cleanup_close_ _cleanup_(cleanup_close) #define _cleanup_udev_unref_ _cleanup_(cleanup_udev_unref) #define _cleanup_udev_device_unref_ _cleanup_(cleanup_udev_device_unref) diff --git a/tools/Makefile.am b/tools/Makefile.am index 3ee4dddd..cfd901db 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = +noinst_PROGRAMS = hidpp10-dump-page bin_PROGRAMS = ratbag-command noinst_LTLIBRARIES = libshared.la @@ -16,3 +16,8 @@ ratbag_command_SOURCES = ratbag-command.c ratbag_command_LDADD = ../src/libratbag.la libshared.la $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) ratbag_command_LDFLAGS = -no-install ratbag_command_CFLAGS = $(LIBUDEV_CFLAGS) $(LIBEVDEV_CFLAGS) + +hidpp10_dump_page_SOURCES = hidpp10-dump-page.c +hidpp10_dump_page_LDADD = ../src/libhidpp10.la +hidpp10_dump_page_LDFLAGS = -no-install +hidpp10_dump_page_CFLAGS = -I$(top_srcdir)/src diff --git a/tools/hidpp10-dump-page.c b/tools/hidpp10-dump-page.c new file mode 100644 index 00000000..9997fad3 --- /dev/null +++ b/tools/hidpp10-dump-page.c @@ -0,0 +1,115 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include + +static inline int +dump_page(struct hidpp10_device *dev, size_t page, size_t offset) +{ + int rc = 0; + uint8_t bytes[16]; + + while (offset < 256) { + hidpp_log_info(&dev->base, "page 0x%02zx off 0x%02zx: ", page, offset); + rc = hidpp10_read_memory(dev, page, offset, bytes); + if (rc != 0) + break; + + hidpp_log_buffer(&dev->base, HIDPP_LOG_PRIORITY_INFO, " ", bytes, ARRAY_LENGTH(bytes)); + offset += 16; + } + + return rc; +} + +static inline int +dump_all_pages(struct hidpp10_device *dev) +{ + uint8_t page; + int rc = 0; + + for (page = 0; page < 31; page++) { + rc = dump_page(dev, page, 0); + if (rc != 0) + break; + } + + /* We dumped at least one page successfully and get EAGAIN, so we're + * on the last page. Overwrite the last line with a blank one so it + * doesn't look like an error */ + if (page > 0 && rc == EAGAIN) { + hidpp_log_info(&dev->base, "\r \n"); + rc = 0; + } + + return rc; +} + +void +usage(void) +{ + printf("Usage: %s [page] [offset] /dev/hidraw0\n", program_invocation_short_name); +} + +int +main(int argc, char **argv) +{ + _cleanup_close_ int fd; + const char *path; + size_t page = 0, offset = 0; + struct hidpp10_device *dev = NULL; + struct hidpp_device base; + int rc; + + if (argc < 2 || argc > 4) { + usage(); + return 1; + } + + path = argv[argc - 1]; + fd = open(path, O_RDWR); + if (fd < 0) + error(1, errno, "Failed to open path %s", path); + + hidpp_device_init(&base, fd); + dev = hidpp10_device_new_from_idx(&base, WIRED_DEVICE_IDX); + + if (argc == 2) + rc = dump_all_pages(dev); + else { + page = atoi(argv[1]); + if (argc > 3) + offset = atoi(argv[2]); + rc = dump_page(dev, page, offset); + } + + hidpp10_device_destroy(dev); + + return rc; +}