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 <benjamin.tissoires@gmail.com>
This commit is contained in:
Benjamin Tissoires
2017-09-05 14:06:59 +02:00
parent d2600583bb
commit 1857378a76
3 changed files with 205 additions and 199 deletions

View File

@@ -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,
&macro[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, &macro);
rc = hidpp20_onboard_profiles_read_macro(device, profiles, page, offset, &macro);
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;
}

View File

@@ -31,6 +31,7 @@
#include <stdint.h>
#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 */

View File

@@ -30,32 +30,36 @@
#include <libratbag-util.h>
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);