mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 23:23:52 +01:00
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:
353
src/hidpp20.c
353
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user