diff --git a/.gitignore b/.gitignore index 1ef09442..ee1870f2 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ test-device test-*.log ratbag-command hidpp10-dump-page +hidpp20-dump-page diff --git a/src/Makefile.am b/src/Makefile.am index a2ed81c6..a9ff574d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,7 @@ lib_LTLIBRARIES = libratbag.la -noinst_LTLIBRARIES = libhidpp10.la +noinst_LTLIBRARIES = \ + libhidpp10.la \ + libhidpp20.la include_HEADERS = \ libratbag.h @@ -52,3 +54,9 @@ libhidpp10_la_SOURCES = \ hidpp-generic.c \ hidpp10.h \ hidpp10.c + +libhidpp20_la_SOURCES = \ + hidpp-generic.h \ + hidpp-generic.c \ + hidpp20.h \ + hidpp20.c diff --git a/tools/Makefile.am b/tools/Makefile.am index cfd901db..7c6f5fdf 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = hidpp10-dump-page +noinst_PROGRAMS = hidpp10-dump-page hidpp20-dump-page bin_PROGRAMS = ratbag-command noinst_LTLIBRARIES = libshared.la @@ -21,3 +21,8 @@ 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 + +hidpp20_dump_page_SOURCES = hidpp20-dump-page.c +hidpp20_dump_page_LDADD = ../src/libhidpp20.la +hidpp20_dump_page_LDFLAGS = -no-install +hidpp20_dump_page_CFLAGS = -I$(top_srcdir)/src diff --git a/tools/hidpp20-dump-page.c b/tools/hidpp20-dump-page.c new file mode 100644 index 00000000..f22778e9 --- /dev/null +++ b/tools/hidpp20-dump-page.c @@ -0,0 +1,128 @@ +/* + * 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 hidpp20_device *dev, uint8_t rom, size_t page, size_t offset) +{ + int rc = 0; + uint8_t bytes[16]; + + while (offset < 256) { + hidpp_log_info(&dev->base, "%s: page 0x%02zx off 0x%02zx: ", rom ? "ROM " : "FLASH", page, offset); + rc = hidpp20_onboard_profiles_read_memory(dev, rom, 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 hidpp20_device *dev, uint8_t rom) +{ + uint8_t page; + int rc = 0; + + for (page = 0; page < 31; page++) { + rc = dump_page(dev, rom, 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 == ENOENT) { + hidpp_log_info(&dev->base, "\r \n"); + rc = 0; + } + + return rc; +} + +static inline int +dump_everything(struct hidpp20_device *dev) +{ + int rc; + + rc = dump_all_pages(dev, 0); + if (rc) + return rc; + rc = dump_all_pages(dev, 1); + if (rc) + 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 hidpp20_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 = hidpp20_device_new(&base, 0xff); + + if (argc == 2) + rc = dump_everything(dev); + else { + page = atoi(argv[1]); + if (argc > 3) + offset = atoi(argv[2]); + rc = dump_page(dev, 0, page, offset); + } + + hidpp20_device_destroy(dev); + + return rc; +}