From 1857378a7605d6a1a4dece68250649e620efe0e4 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 5 Sep 2017 14:06:59 +0200 Subject: [PATCH] hidpp20: new memory model Only reading/writing full sectors are allowed (because we need to set and read the crc anyway). Fixes #122 Signed-off-by: Benjamin Tissoires --- src/hidpp20.c | 353 +++++++++++++++++++------------------- src/hidpp20.h | 18 +- tools/hidpp20-dump-page.c | 33 ++-- 3 files changed, 205 insertions(+), 199 deletions(-) diff --git a/src/hidpp20.c b/src/hidpp20.c index 35e5441b..83b70287 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -1038,8 +1038,7 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, #define CMD_ONBOARD_PROFILES_GET_CURRENT_DPI_INDEX 0xb0 #define CMD_ONBOARD_PROFILES_SET_CURRENT_DPI_INDEX 0xc0 -#define HIDPP20_PAGE_SIZE (16*16) -#define HIDPP20_PROFILE_SIZE HIDPP20_PAGE_SIZE +#define HIDPP20_PROFILE_SIZE 256 #define HIDPP20_BUTTON_HID 0x80 #define HIDPP20_MODE_NO_CHANGE 0x00 @@ -1083,68 +1082,83 @@ hidpp20_onboard_profiles_get_profiles_desc(struct hidpp20_device *device, } int -hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device, - uint8_t read_rom, - uint8_t page, - uint16_t section, - uint8_t result[16]) +hidpp20_onboard_profiles_read_sector(struct hidpp20_device *device, + uint16_t sector, + uint16_t sector_size, + uint8_t *data) { + uint16_t offset; uint8_t feature_index; - int rc; + int rc, count; + union hidpp20_message buf; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = device->index, .msg.address = CMD_ONBOARD_PROFILES_MEMORY_READ, - .msg.parameters[0] = read_rom, - .msg.parameters[1] = page, }; - if (read_rom > 1) - return -EINVAL; - - hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], section); - feature_index = hidpp_root_get_feature_idx(device, HIDPP_PAGE_ONBOARD_PROFILES); if (feature_index == 0) return -ENOTSUP; msg.msg.sub_id = feature_index; + hidpp_set_unaligned_be_u16(&msg.msg.parameters[0], sector); - rc = hidpp20_request_command(device, &msg); - if (rc) - return rc; + count = sector_size; - /* msg.msg.parameters is guaranteed to have a size >= 16 */ - memcpy(result, msg.msg.parameters, 16); + for (offset = 0; offset < sector_size; offset += 16) { + hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], offset); + buf = msg; + rc = hidpp20_request_command(device, &buf); + if (rc) + return rc; + + /* msg.msg.parameters is guaranteed to have a size >= 16 */ + memcpy(data + offset, buf.msg.parameters, min(count, 16)); + + /* + * no need to check for count >= 0: + * if count is negative, then offset will be greater than + * sector_size, thus stopping the loop. + */ + count -= 16; + } return 0; } +static bool +hidpp20_onboard_profiles_is_sector_valid(struct hidpp20_device *device, + uint16_t sector_size, + uint8_t *data) +{ + uint16_t crc, read_crc; + + crc = hidpp_crc_ccitt(data, sector_size - 2); + read_crc = hidpp_get_unaligned_be_u16(&data[sector_size - 2]); + + return crc == read_crc; +} + static int hidpp20_onboard_profiles_write_start(struct hidpp20_device *device, - uint16_t page, - uint16_t section, - uint16_t size) + uint16_t sector, + uint16_t sub_address, + uint16_t count, + uint8_t feature_index) { - uint8_t feature_index; int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = device->index, + .msg.sub_id = feature_index, .msg.address = CMD_ONBOARD_PROFILES_MEMORY_ADDR_WRITE, }; - hidpp_set_unaligned_be_u16(&msg.msg.parameters[0], page); - hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], section); - hidpp_set_unaligned_be_u16(&msg.msg.parameters[4], size); - - feature_index = hidpp_root_get_feature_idx(device, - HIDPP_PAGE_ONBOARD_PROFILES); - if (feature_index == 0) - return -ENOTSUP; - - msg.msg.sub_id = feature_index; + hidpp_set_unaligned_be_u16(&msg.msg.parameters[0], sector); + hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], sub_address); + hidpp_set_unaligned_be_u16(&msg.msg.parameters[4], count); rc = hidpp20_request_command(device, &msg); if (rc) @@ -1154,23 +1168,17 @@ hidpp20_onboard_profiles_write_start(struct hidpp20_device *device, } static int -hidpp20_onboard_profiles_write_end(struct hidpp20_device *device) +hidpp20_onboard_profiles_write_end(struct hidpp20_device *device, + uint8_t feature_index) { - uint8_t feature_index; int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_SHORT, .msg.device_idx = device->index, + .msg.sub_id = feature_index, .msg.address = CMD_ONBOARD_PROFILES_MEMORY_WRITE_END, }; - feature_index = hidpp_root_get_feature_idx(device, - HIDPP_PAGE_ONBOARD_PROFILES); - if (feature_index == 0) - return -ENOTSUP; - - msg.msg.sub_id = feature_index; - rc = hidpp20_request_command(device, &msg); if (rc) return rc; @@ -1180,65 +1188,64 @@ hidpp20_onboard_profiles_write_end(struct hidpp20_device *device) static int hidpp20_onboard_profiles_write_data(struct hidpp20_device *device, - uint16_t page, - uint16_t section, uint8_t *data, - size_t len) + uint8_t feature_index) { - uint8_t feature_index; - int transfered = 0; int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = device->index, + .msg.sub_id = feature_index, .msg.address = CMD_ONBOARD_PROFILES_MEMORY_WRITE, }; + memcpy(msg.msg.parameters, data, 16); + + rc = hidpp20_request_command(device, &msg); + if (rc) + return rc; + + return 0; +} + +static int +hidpp20_onboard_profiles_write_sector(struct hidpp20_device *device, + uint16_t sector, + uint16_t sector_size, + uint8_t *data) +{ + uint8_t feature_index; + uint16_t crc; + int rc, transferred; + feature_index = hidpp_root_get_feature_idx(device, HIDPP_PAGE_ONBOARD_PROFILES); if (feature_index == 0) return -ENOTSUP; - msg.msg.sub_id = feature_index; + crc = hidpp_crc_ccitt(data, sector_size - 2); + hidpp_set_unaligned_be_u16(&data[sector_size - 2], crc); rc = hidpp20_onboard_profiles_write_start(device, - page, - section, - HIDPP20_PAGE_SIZE); + sector, + 0, + sector_size, + feature_index); if (rc) return rc; - while (len >= 16) { - msg.msg.address = CMD_ONBOARD_PROFILES_MEMORY_WRITE; - memcpy(msg.msg.parameters, data, 16); - - rc = hidpp20_request_command(device, &msg); + for (transferred = 0; transferred < sector_size; transferred += 16) { + rc = hidpp20_onboard_profiles_write_data(device, data, feature_index); if (rc) return rc; - - len -= 16; data += 16; - transfered += 16; } - rc = hidpp20_onboard_profiles_write_end(device); + rc = hidpp20_onboard_profiles_write_end(device, feature_index); if (rc) return rc; - return transfered; -} - -static int -hidpp20_onboard_profiles_write_page(struct hidpp20_device *device, - uint16_t page, - uint8_t data[HIDPP20_PAGE_SIZE]) -{ - uint16_t crc; - - crc = hidpp_crc_ccitt(data, HIDPP20_PAGE_SIZE - 2); - hidpp_set_unaligned_be_u16(&data[HIDPP20_PROFILE_SIZE - 2], crc); - - return hidpp20_onboard_profiles_write_data(device, page, 0x00, data, HIDPP20_PAGE_SIZE); + return 0; } static int @@ -1427,13 +1434,6 @@ hidpp20_onboard_profiles_validate(struct hidpp20_device *device, return false; } - if (info->sector_size != HIDPP20_PAGE_SIZE) { - hidpp_log_error(&device->base, - "Unsupported sector size: %d.\n", - info->sector_size); - return false; - } - return true; } @@ -1468,9 +1468,10 @@ hidpp20_onboard_profiles_allocate(struct hidpp20_device *device, return rc; } - profiles = zalloc(sizeof(struct hidpp20_profiles) + - info.profile_count * sizeof(struct hidpp20_profile)); - + profiles = zalloc(sizeof(struct hidpp20_profiles)); + profiles->profiles = zalloc(info.profile_count * sizeof(struct hidpp20_profile)); + profiles->sector_size = info.sector_size; + profiles->sector_count = info.sector_count; profiles->num_profiles = info.profile_count; profiles->num_rom_profiles = info.profile_count_oob; profiles->num_buttons = min(info.button_count, 16); @@ -1545,16 +1546,19 @@ hidpp20_onboard_profiles_macro_next(struct hidpp20_device *device, static int hidpp20_onboard_profiles_read_macro(struct hidpp20_device *device, + struct hidpp20_profiles *profiles, uint8_t page, uint8_t offset, union hidpp20_macro_data **return_macro) { - uint8_t memory[HIDPP20_PAGE_SIZE]; + _cleanup_free_ uint8_t *memory = NULL; union hidpp20_macro_data *macro = NULL; unsigned count = 0; unsigned index = 0; - uint16_t mem_index = 0; + uint16_t mem_index = offset; int rc = -ENOMEM; + memory = hidpp20_onboard_profiles_allocate_sector(profiles); + do { if (count == index) { union hidpp20_macro_data *tmp; @@ -1570,16 +1574,12 @@ hidpp20_onboard_profiles_read_macro(struct hidpp20_device *device, } if (rc == -ENOMEM) { - offset += mem_index; - rc = hidpp20_onboard_profiles_read_memory(device, - 0, + rc = hidpp20_onboard_profiles_read_sector(device, page, - offset, + profiles->sector_size, memory); if (rc) goto out_err; - - mem_index = 0; } rc = hidpp20_onboard_profiles_macro_next(device, @@ -1588,18 +1588,18 @@ hidpp20_onboard_profiles_read_macro(struct hidpp20_device *device, ¯o[index]); if (rc == -EFAULT) goto out_err; - - if (rc != -ENOMEM) { - if (macro[index].any.type == HIDPP20_MACRO_JUMP) { - page = macro[index].jump.page; - offset = macro[index].jump.offset; - mem_index = 0; - /* no need to store the jump in memory */ - index--; - /* force memory fetching */ - rc = -ENOMEM; - } - + if (rc == -ENOMEM) { + mem_index = 0; + page++; + } else if (macro[index].any.type == HIDPP20_MACRO_JUMP) { + page = macro[index].jump.page; + offset = macro[index].jump.offset; + mem_index = offset; + /* no need to store the jump in memory */ + index--; + /* force memory fetching */ + rc = -ENOMEM; + } else { index++; } } while (rc); @@ -1615,6 +1615,7 @@ out_err: static int hidpp20_onboard_profiles_parse_macro(struct hidpp20_device *device, + struct hidpp20_profiles *profiles, uint8_t page, uint8_t offset, union hidpp20_macro_data **return_macro) { @@ -1622,7 +1623,7 @@ hidpp20_onboard_profiles_parse_macro(struct hidpp20_device *device, unsigned i, count = 0; int rc; - rc = hidpp20_onboard_profiles_read_macro(device, page, offset, ¯o); + rc = hidpp20_onboard_profiles_read_macro(device, profiles, page, offset, ¯o); if (rc <= 0) return rc; @@ -1675,26 +1676,17 @@ int hidpp20_onboard_profiles_initialize(struct hidpp20_device *device, struct hidpp20_profiles *profiles) { - unsigned i, offset, num_offset; + unsigned i; int rc; - uint8_t data[HIDPP20_PAGE_SIZE] = {0}; + _cleanup_free_ uint8_t *data = NULL; assert(profiles); - num_offset = hidpp20_onboard_profiles_compute_dict_size(device, - profiles); + data = hidpp20_onboard_profiles_allocate_sector(profiles); - for (offset = 0; offset < num_offset; offset += 16) { - rc = hidpp20_onboard_profiles_read_memory(device, - 0x00, - 0x00, - offset, - data + offset); - if (rc < 0) { - hidpp20_onboard_profiles_destroy(profiles); - return rc; - } - } + rc = hidpp20_onboard_profiles_read_sector(device, 0, profiles->sector_size, data); + if (rc < 0) + return rc; for (i = 0; i < profiles->num_profiles; i++) { uint8_t *d = data + 4 * i; @@ -1703,7 +1695,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device, break; profiles->profiles[i].index = d[1]; - profiles->profiles[i].enabled = d[2]; + profiles->profiles[i].enabled = !!d[2]; } return profiles->num_profiles; @@ -1727,44 +1719,29 @@ hidpp20_onboard_profiles_destroy(struct hidpp20_profiles *profiles_list) } } + free(profiles_list->profiles); free(profiles_list); } static int hidpp20_onboard_profiles_find_and_read_profile(struct hidpp20_device *device, unsigned int index, + uint16_t sector_size, uint8_t *data, unsigned int num_rom_profiles) { + uint16_t sector = index + 1; int rc; - unsigned i; - uint16_t crc, read_crc; - rc = hidpp20_onboard_profiles_read_memory(device, - 0, - index + 1, - 0x00, + rc = hidpp20_onboard_profiles_read_sector(device, + sector, + sector_size, data); if (rc < 0) return rc; - if (data[0] > 0) { - for (i = 1; i < HIDPP20_PROFILE_SIZE / 0x10; i++) { - rc = hidpp20_onboard_profiles_read_memory(device, - 0, - index + 1, - i * 0x10, - data + i * 0x10); - if (rc < 0) - return rc; - } - - crc = hidpp_crc_ccitt(data, HIDPP20_PROFILE_SIZE - 2); - read_crc = hidpp_get_unaligned_be_u16(&data[HIDPP20_PROFILE_SIZE - 2]); - - if (crc == read_crc) - return 0; - } + if (hidpp20_onboard_profiles_is_sector_valid(device, sector_size, data)) + return 0; /* something went wrong, the mouse is using the factory profile in ROM */ if (num_rom_profiles == 0) @@ -1773,15 +1750,14 @@ hidpp20_onboard_profiles_find_and_read_profile(struct hidpp20_device *device, if (index >= num_rom_profiles) index = num_rom_profiles - 1; - for (i = 0; i < HIDPP20_PROFILE_SIZE / 0x10; i++) { - rc = hidpp20_onboard_profiles_read_memory(device, - 1, - index + 1, - i * 0x10, - data + i * 0x10); - if (rc != 0) - return rc; - } + sector = (1 << 8) | (index + 1); + + rc = hidpp20_onboard_profiles_read_sector(device, + sector, + sector_size, + data); + if (rc < 0) + return rc; return 0; } @@ -1792,14 +1768,18 @@ hidpp20_onboard_profiles_set_enable_profile(struct hidpp20_device *device, struct hidpp20_profiles *profiles_list) { unsigned int i, buffer_index = 0; - uint8_t data[HIDPP20_PROFILE_SIZE] = {0}; + uint16_t sector_size = profiles_list->sector_size; + _cleanup_free_ uint8_t *data = NULL; + int rc; + + data = hidpp20_onboard_profiles_allocate_sector(profiles_list); profiles_list->profiles[index].index = index + 1; for (i = 0; i < profiles_list->num_profiles; i++) { data[buffer_index++] = 0x00; data[buffer_index++] = i + 1; - data[buffer_index++] = profiles_list->profiles[i].enabled; + data[buffer_index++] = !!profiles_list->profiles[i].enabled; data[buffer_index++] = 0x00; } @@ -1809,7 +1789,7 @@ hidpp20_onboard_profiles_set_enable_profile(struct hidpp20_device *device, data[buffer_index++] = 0x00; data[buffer_index++] = 0x00; - memset(data + buffer_index, 0xff, sizeof(data) - buffer_index); + memset(data + buffer_index, 0xff, sector_size - buffer_index); hidpp_log_buf_debug(&device->base, "dictionary: ", @@ -1817,7 +1797,11 @@ hidpp20_onboard_profiles_set_enable_profile(struct hidpp20_device *device, hidpp20_onboard_profiles_compute_dict_size(device, profiles_list)); - return hidpp20_onboard_profiles_write_page(device, 0x0000, data); + rc = hidpp20_onboard_profiles_write_sector(device, + 0x0000, + sector_size, + data); + return rc; } union hidpp20_internal_profile { @@ -1846,6 +1830,7 @@ _Static_assert(sizeof(union hidpp20_internal_profile) == HIDPP20_PROFILE_SIZE, " static void hidpp20_buttons_to_cpu(struct hidpp20_device *device, + struct hidpp20_profiles *profiles, struct hidpp20_profile *profile, union hidpp20_button_binding *buttons, unsigned int count) @@ -1884,6 +1869,7 @@ hidpp20_buttons_to_cpu(struct hidpp20_device *device, profile->macros[i] = NULL; } hidpp20_onboard_profiles_parse_macro(device, + profiles, b->macro.page, b->macro.offset, &profile->macros[i]); @@ -1988,8 +1974,8 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, unsigned int index, struct hidpp20_profiles *profiles_list) { - union hidpp20_internal_profile pdata = {0}; - uint8_t *data = pdata.data; + union hidpp20_internal_profile *pdata; + _cleanup_free_ uint8_t *data = NULL; struct hidpp20_profile *profile = &profiles_list->profiles[index]; unsigned i; int rc; @@ -1997,33 +1983,37 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, if (index >= profiles_list->num_profiles) return -EINVAL; + data = hidpp20_onboard_profiles_allocate_sector(profiles_list); + pdata = (union hidpp20_internal_profile *)data; + rc = hidpp20_onboard_profiles_find_and_read_profile(device, index, + profiles_list->sector_size, data, profiles_list->num_rom_profiles); if (rc != 0) return rc; - profile->report_rate = 1000 / max(1, pdata.profile.report_rate); - profile->default_dpi = pdata.profile.default_dpi; - profile->switched_dpi = pdata.profile.switched_dpi; + profile->report_rate = 1000 / max(1, pdata->profile.report_rate); + profile->default_dpi = pdata->profile.default_dpi; + profile->switched_dpi = pdata->profile.switched_dpi; for (i = 0; i < 5; i++) { profile->dpi[i] = hidpp_get_unaligned_le_u16(&data[2 * i + 3]); } for (i = 0; i < profiles_list->num_leds; i++) - hidpp20_onboard_profiles_read_led(&profile->leds[i], pdata.profile.leds[i]); + hidpp20_onboard_profiles_read_led(&profile->leds[i], pdata->profile.leds[i]); - hidpp20_buttons_to_cpu(device, profile, pdata.profile.buttons, profiles_list->num_buttons); + hidpp20_buttons_to_cpu(device, profiles_list, profile, pdata->profile.buttons, profiles_list->num_buttons); - memcpy(profile->name, pdata.profile.name.txt, sizeof(profile->name)); + memcpy(profile->name, pdata->profile.name.txt, sizeof(profile->name)); /* force terminating '\0' */ profile->name[sizeof(profile->name) - 1] = '\0'; /* check if we are using the default name or not */ for (i = 0; i < sizeof(profile->name); i++) { - if (pdata.profile.name.raw[i] != 0xff) + if (pdata->profile.name.raw[i] != 0xff) break; } if (i == sizeof(profile->name)) @@ -2076,8 +2066,10 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device, unsigned int index, struct hidpp20_profiles *profiles_list) { - union hidpp20_internal_profile pdata = {0}; - uint8_t *data = pdata.data; + union hidpp20_internal_profile *pdata; + _cleanup_free_ uint8_t *data = NULL; + uint16_t sector_size = profiles_list->sector_size; + uint16_t sector = index + 1; struct hidpp20_profile *profile = &profiles_list->profiles[index]; unsigned i; int rc; @@ -2085,8 +2077,12 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device, if (index >= profiles_list->num_profiles) return -EINVAL; + data = hidpp20_onboard_profiles_allocate_sector(profiles_list); + pdata = (union hidpp20_internal_profile *)data; + rc = hidpp20_onboard_profiles_find_and_read_profile(device, index, + profiles_list->sector_size, data, profiles_list->num_rom_profiles); if (rc < 0) @@ -2096,28 +2092,25 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device, if (rc < 0) return rc; - pdata.profile.report_rate = 1000 / profile->report_rate; - pdata.profile.default_dpi = profile->default_dpi; - pdata.profile.switched_dpi = profile->switched_dpi; + pdata->profile.report_rate = 1000 / profile->report_rate; + pdata->profile.default_dpi = profile->default_dpi; + pdata->profile.switched_dpi = profile->switched_dpi; for (i = 0; i < 5; i++) { - pdata.profile.dpi[i] = hidpp_cpu_to_le_u16(profile->dpi[i]); + pdata->profile.dpi[i] = hidpp_cpu_to_le_u16(profile->dpi[i]); } for (i = 0; i < profiles_list->num_leds; i++) - hidpp20_onboard_profiles_write_led(&pdata.profile.leds[i], &profile->leds[i]); + hidpp20_onboard_profiles_write_led(&pdata->profile.leds[i], &profile->leds[i]); - hidpp20_buttons_from_cpu(profile, pdata.profile.buttons, profiles_list->num_buttons); + hidpp20_buttons_from_cpu(profile, pdata->profile.buttons, profiles_list->num_buttons); - memcpy(pdata.profile.name.txt, profile->name, sizeof(profile->name)); + memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name)); - rc = hidpp20_onboard_profiles_write_page(device, index + 1, data); + rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data); if (rc < 0) return rc; - if (rc != sizeof(pdata.data)) - return -EIO; - return 0; } diff --git a/src/hidpp20.h b/src/hidpp20.h index 3870a138..9bd64e07 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -31,6 +31,7 @@ #include #include "hidpp-generic.h" +#include "libratbag-util.h" struct _hidpp20_message { uint8_t report_id; @@ -506,7 +507,7 @@ struct hidpp20_profiles { uint8_t wireless; uint8_t sector_count; uint16_t sector_size; - struct hidpp20_profile profiles[0]; + struct hidpp20_profile *profiles; }; /** @@ -593,11 +594,16 @@ uint8_t hidpp20_onboard_profiles_get_code_from_special(enum ratbag_button_action_special special); int -hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device, - uint8_t read_rom, - uint8_t page, - uint16_t section, - uint8_t result[16]); +hidpp20_onboard_profiles_read_sector(struct hidpp20_device *device, + uint16_t sector, + uint16_t sector_size, + uint8_t *data); + +static inline uint8_t * +hidpp20_onboard_profiles_allocate_sector(struct hidpp20_profiles *profiles) +{ + return zalloc(profiles->sector_size); +} /* -------------------------------------------------------------------------- */ /* 0x8110 - Mouse Button Spy */ diff --git a/tools/hidpp20-dump-page.c b/tools/hidpp20-dump-page.c index 7140b118..7ac88668 100644 --- a/tools/hidpp20-dump-page.c +++ b/tools/hidpp20-dump-page.c @@ -30,32 +30,36 @@ #include static inline int -dump_page(struct hidpp20_device *dev, uint8_t rom, size_t page, size_t offset) +dump_page(struct hidpp20_device *dev, uint16_t sector_size, uint8_t rom, size_t page, size_t offset) { int rc = 0; - uint8_t bytes[16]; + uint16_t sector = (rom << 8) | page; + uint8_t *data = zalloc(sector_size); + + rc = hidpp20_onboard_profiles_read_sector(dev, sector, sector_size, data); + if (rc != 0) + goto out; 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)); + hidpp_log_buffer(&dev->base, HIDPP_LOG_PRIORITY_INFO, " ", data + offset, 16); offset += 16; } + out: + free(data); return rc; } static inline int -dump_all_pages(struct hidpp20_device *dev, uint8_t rom) +dump_all_pages(struct hidpp20_device *dev, uint16_t sector_size, uint8_t rom) { uint8_t page; int rc = 0; for (page = 0; page < 31; page++) { - rc = dump_page(dev, rom, page, 0); + rc = dump_page(dev, sector_size, rom, page, 0); if (rc != 0) break; } @@ -72,15 +76,15 @@ dump_all_pages(struct hidpp20_device *dev, uint8_t rom) } static inline int -dump_everything(struct hidpp20_device *dev) +dump_everything(struct hidpp20_device *dev, uint16_t sector_size) { int rc; - rc = dump_all_pages(dev, 0); + rc = dump_all_pages(dev, sector_size, 0); if (rc) return rc; - return dump_all_pages(dev, 1); + return dump_all_pages(dev, sector_size, 1); } static void @@ -97,6 +101,7 @@ main(int argc, char **argv) size_t page = 0, offset = 0; struct hidpp20_device *dev = NULL; struct hidpp_device base; + struct hidpp20_onboard_profiles_info info = { 0 }; int rc; if (argc < 2 || argc > 4) { @@ -114,13 +119,15 @@ main(int argc, char **argv) if (!dev) error(1, 0, "Failed to open %s as a HID++ 2.0 device", path); + hidpp20_onboard_profiles_get_profiles_desc(dev, &info); + if (argc == 2) - rc = dump_everything(dev); + rc = dump_everything(dev, info.sector_size); else { page = atoi(argv[1]); if (argc > 3) offset = atoi(argv[2]); - rc = dump_page(dev, 0, page, offset); + rc = dump_page(dev, info.sector_size, 0, page, offset); } hidpp20_device_destroy(dev);