hidpp20: check if crcs are valid once on plug

To check if device is using ROM or Flash settings.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
Benjamin Tissoires
2017-09-12 10:01:49 +02:00
parent 0c5b1998a5
commit 5842dccc2a
3 changed files with 82 additions and 45 deletions

View File

@@ -684,22 +684,6 @@ hidpp20drv_read_color_leds(struct ratbag_device *device)
return rc;
}
static int
hidpp20drv_read_onboard_profile(struct ratbag_device *device, unsigned index)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
int rc;
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
return 0;
rc = hidpp20_onboard_profiles_read(drv_data->dev, index, drv_data->profiles);
if (rc < 0)
return rc;
return 0;
}
static void
hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
{
@@ -712,8 +696,6 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
profile->is_enabled = drv_data->profiles->profiles[index].enabled;
hidpp20drv_read_onboard_profile(device, profile->index);
profile->is_active = false;
if ((int)index == hidpp20drv_current_profile(device))
profile->is_active = true;

View File

@@ -1941,13 +1941,16 @@ hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
led->brightness = brightness;
}
int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
unsigned int index,
struct hidpp20_profiles *profiles_list)
static int
hidpp20_onboard_profiles_parse_profile(struct hidpp20_device *device,
struct hidpp20_profiles *profiles_list,
unsigned index,
bool check_crc)
{
union hidpp20_internal_profile *pdata;
_cleanup_free_ uint8_t *data = NULL;
struct hidpp20_profile *profile = &profiles_list->profiles[index];
uint16_t sector = index + 1;
_cleanup_free_ uint8_t *data = NULL;
unsigned i;
int rc;
@@ -1957,14 +1960,21 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
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)
rc = hidpp20_onboard_profiles_read_sector(device,
sector,
profiles_list->sector_size,
data);
if (rc < 0)
return rc;
if (check_crc) {
if (!hidpp20_onboard_profiles_is_sector_valid(device,
profiles_list->sector_size,
data)) {
return -EAGAIN;
}
}
profile->report_rate = 1000 / max(1, pdata->profile.report_rate);
profile->default_dpi = pdata->profile.default_dpi;
profile->switched_dpi = pdata->profile.switched_dpi;
@@ -1993,22 +2003,37 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
return 0;
}
int
hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
struct hidpp20_profiles *profiles)
static int
hidpp20_onboard_profiles_parse(struct hidpp20_device *device,
struct hidpp20_profiles *profiles,
uint16_t dict_address,
bool check_crc)
{
unsigned i;
int rc;
_cleanup_free_ uint8_t *data = NULL;
int rc;
unsigned i;
assert(profiles);
for (i = 0; i < profiles->num_profiles; i++) {
profiles->profiles[i].index = 0;
profiles->profiles[i].enabled = 0;
}
data = hidpp20_onboard_profiles_allocate_sector(profiles);
rc = hidpp20_onboard_profiles_read_sector(device, 0, profiles->sector_size, data);
rc = hidpp20_onboard_profiles_read_sector(device,
dict_address,
profiles->sector_size,
data);
if (rc < 0)
return rc;
if (check_crc) {
if (!hidpp20_onboard_profiles_is_sector_valid(device,
profiles->sector_size,
data)) {
return -EAGAIN;
}
}
for (i = 0; i < profiles->num_profiles; i++) {
uint8_t *d = data + 4 * i;
@@ -2017,8 +2042,48 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
profiles->profiles[i].index = d[1];
profiles->profiles[i].enabled = !!d[2];
rc = hidpp20_onboard_profiles_parse_profile(device,
profiles,
i,
check_crc);
if (rc < 0)
return rc;
}
return 0;
}
int
hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
struct hidpp20_profiles *profiles)
{
int rc;
assert(profiles);
rc = hidpp20_onboard_profiles_parse(device, profiles, 0x0000, true);
if (rc == 0)
return profiles->num_profiles;
if (rc != -EAGAIN) {
/* something went wrong */
return rc;
}
/*
* One of the used sector has a bad crc, the device is using the ROM
* profiles.
*/
hidpp_log_debug(&device->base, "device is using ROM settings\n");
rc = hidpp20_onboard_profiles_parse(device, profiles, 0x0100, false);
if (rc < 0)
return rc;
hidpp_log_debug(&device->base, "ROM settings loaded\n");
return profiles->num_profiles;
}

View File

@@ -573,16 +573,6 @@ int
hidpp20_onboard_profiles_set_current_dpi_index(struct hidpp20_device *device,
uint8_t index);
/**
* parse a given profile from the mouse and fill in the right profile in
* profiles_list.
*
* return 0 or a negative error.
*/
int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
unsigned int index,
struct hidpp20_profiles *profiles_list);
int hidpp20_onboard_profiles_write(struct hidpp20_device *device,
unsigned int index,
struct hidpp20_profiles *profiles_list);