From 5842dccc2a3e311018ea40f03c59e18b73c4346d Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 12 Sep 2017 10:01:49 +0200 Subject: [PATCH] hidpp20: check if crcs are valid once on plug To check if device is using ROM or Flash settings. Signed-off-by: Benjamin Tissoires --- src/driver-hidpp20.c | 18 -------- src/hidpp20.c | 99 ++++++++++++++++++++++++++++++++++++-------- src/hidpp20.h | 10 ----- 3 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index 264b82b9..12ac9088 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -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; diff --git a/src/hidpp20.c b/src/hidpp20.c index 4f68646d..b0a18e5f 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -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; } diff --git a/src/hidpp20.h b/src/hidpp20.h index 9bd64e07..d063f23f 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -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);