From 5f5e2945985229bdf1679f69629536c71422cffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Fri, 3 Jan 2020 22:09:14 +0000 Subject: [PATCH] hidpp20: add support for reading/writing the report rate via 0x8060 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe LaĆ­ns --- src/driver-hidpp20.c | 60 ++++++++++++++++++++++++++++++++++++++++++-- src/hidpp20.c | 56 +++++++++++++++++++++++++++++++++++++++++ src/hidpp20.h | 6 +++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index e9f5b05e..78b8daed 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -822,9 +822,12 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device) { struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct ratbag *ratbag = device->ratbag; + struct ratbag_profile *profile; uint8_t bitflags_ms; int nrates = 0; int rc; + uint8_t rate_ms; + unsigned rate_hz; rc = hidpp20_adjustable_report_rate_get_report_rate_list(drv_data->dev, &bitflags_ms); @@ -843,6 +846,37 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device) drv_data->num_report_rates = nrates; + if (!hidpp20_adjustable_report_rate_get_report_rate(drv_data->dev, &rate_ms)) { + switch (rate_ms) + { + case 1: + rate_hz = 1000; + break; + case 2: + case 3: /* 3ms = 333.(3)Hz, we round to 500Hz */ + rate_hz = 500; + break; + case 4: + case 5: /* 5ms = 200Hz, we round to 250Hz */ + rate_hz = 250; + break; + case 6: /* 6ms = 166.(6)Hz, we round to 125Hz */ + case 7: /* 7ms = 142Hz, we round to 125Hz */ + case 8: + rate_hz = 125; + break; + default: + rate_hz = 0; + break; + } + + if (rate_hz) { + log_debug(ratbag, "report rate is %u\n", rate_hz); + ratbag_device_for_each_profile(device, profile) + profile->hz = rate_hz; + } + } + log_debug(ratbag, "device has %d report rates\n", nrates); return 0; @@ -983,6 +1017,20 @@ out: return rc; } +static int +hidpp20drv_update_report_rate_8060(struct ratbag_profile *profile, int hz) +{ + struct ratbag_device *device = profile->device; + struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); + int rc; + + rc = hidpp20_adjustable_report_rate_set_report_rate(drv_data->dev, 1000/hz); + if (rc) + return rc; + + return RATBAG_SUCCESS; +} + static int hidpp20drv_update_report_rate_8100(struct ratbag_profile *profile, int hz) { @@ -1001,12 +1049,20 @@ hidpp20drv_update_report_rate(struct ratbag_profile *profile, int hz) { struct ratbag_device *device = profile->device; struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); + int rc; if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) return hidpp20drv_update_report_rate_8100(profile, hz); - if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060) - return -ENOTSUP; + if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060) { + rc = hidpp20drv_update_report_rate_8060(profile, hz); + + /* re-populate the profile with the correct value if we fail */ + if (rc) + hidpp20drv_read_report_rate_8060(profile->device); + + return rc; + } return -ENOTSUP; } diff --git a/src/hidpp20.c b/src/hidpp20.c index baafceaa..d4ea49a1 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -1612,6 +1612,8 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, /* -------------------------------------------------------------------------- */ #define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE_LIST 0x00 +#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE 0x10 +#define CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE 0x20 int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device, uint8_t *bitflags_ms) @@ -1641,6 +1643,60 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d return 0; } +int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device, + uint8_t *rate_ms) +{ + uint8_t feature_index; + int rc; + union hidpp20_message msg = { + .msg.report_id = REPORT_ID_SHORT, + .msg.device_idx = device->index, + .msg.address = CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE, + .msg.parameters[0] = 0, + }; + + feature_index = hidpp_root_get_feature_idx(device, + HIDPP_PAGE_ADJUSTABLE_REPORT_RATE); + if (feature_index == 0) + return -ENOTSUP; + + msg.msg.sub_id = feature_index; + + rc = hidpp20_request_command(device, &msg); + if (rc) + return rc; + + *rate_ms = msg.msg.parameters[0]; + + return 0; +} + +int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device, + uint8_t rate_ms) +{ + uint8_t feature_index; + int rc; + union hidpp20_message msg = { + .msg.report_id = REPORT_ID_SHORT, + .msg.device_idx = device->index, + .msg.address = CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE, + .msg.parameters[0] = rate_ms, + }; + + feature_index = hidpp_root_get_feature_idx(device, + HIDPP_PAGE_ADJUSTABLE_REPORT_RATE); + if (feature_index == 0) + return -ENOTSUP; + + msg.msg.sub_id = feature_index; + + rc = hidpp20_request_command(device, &msg); + if (rc) + return rc; + + return 0; +} + /* -------------------------------------------------------------------------- */ /* 0x8100 - Onboard Profiles */ /* -------------------------------------------------------------------------- */ diff --git a/src/hidpp20.h b/src/hidpp20.h index aa7bc30e..61a60f52 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -432,6 +432,12 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device, uint8_t *bitflags_ms); +int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device, + uint8_t *rate_ms); + +int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device, + uint8_t rate_ms); + /* -------------------------------------------------------------------------- */ /* 0x8070v4 - Color LED effects */ /* -------------------------------------------------------------------------- */