From ec7bb2f63a931aa58d8b15b91478110d0427c5fe Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 16 Oct 2017 17:49:26 +1000 Subject: [PATCH] Add list of report rates to the resolutions Same blueprint as the list of DPI values Signed-off-by: Peter Hutterer --- doc/dbus.rst | 12 ++++++++++++ ratbagd/ratbagd-resolution.c | 34 ++++++++++++++++++++++++++++++++++ src/driver-etekcity.c | 13 +++++++------ src/driver-gskill.c | 4 ++++ src/driver-hidpp10.c | 7 +++++++ src/driver-hidpp20.c | 5 ++++- src/driver-logitech-g300.c | 1 + src/driver-roccat.c | 13 +++++++------ src/driver-test.c | 12 ++++++++++++ src/libratbag-private.h | 20 ++++++++++++++++++++ src/libratbag-test.h | 1 + src/libratbag.c | 18 ++++++++++++++++++ src/libratbag.h | 23 +++++++++++++++++++++++ tools/ratbagd.py | 5 +++++ 14 files changed, 155 insertions(+), 13 deletions(-) diff --git a/doc/dbus.rst b/doc/dbus.rst index be89ef62..131561e3 100644 --- a/doc/dbus.rst +++ b/doc/dbus.rst @@ -292,6 +292,18 @@ org.freedesktop.ratbag1.Resolution capability, changing the report rate on one resolution will change the report rate on all resolutions. + .. js:attribute:: ReportRates + + :type: au + :flags: read-write, constant + + A list of permitted report rates. Values in this list may be used + in the :js:attr:`ReportRate` property. This list is always sorted + ascending, the lowest report rate is the first item in the list. + + This list may be empty if the device does not support reading and/or + writing to resolutions. + .. js:function:: SetDefault() → () Set this resolution to be the default diff --git a/ratbagd/ratbagd-resolution.c b/ratbagd/ratbagd-resolution.c index a0959ba4..396f3dae 100644 --- a/ratbagd/ratbagd-resolution.c +++ b/ratbagd/ratbagd-resolution.c @@ -296,6 +296,39 @@ ratbagd_resolution_get_report_rate(sd_bus *bus, return sd_bus_message_append(reply, "u", rate); } +static int +ratbagd_resolution_get_report_rates(sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) +{ + struct ratbagd_resolution *resolution = userdata; + struct ratbag_resolution *lib_resolution = resolution->lib_resolution; + unsigned int rates[5]; + unsigned int nrates = ARRAY_LENGTH(rates); + int r; + + r = sd_bus_message_open_container(reply, 'a', "u"); + if (r < 0) + return r; + + nrates = ratbag_resolution_get_report_rate_list(lib_resolution, + rates, nrates); + assert(nrates <= ARRAY_LENGTH(rates)); + + for (unsigned int i = 0; i < nrates; i++) { + r = sd_bus_message_append(reply, "u", rates[i]); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + + static int ratbagd_resolution_set_report_rate(sd_bus *bus, const char *path, @@ -348,6 +381,7 @@ const sd_bus_vtable ratbagd_resolution_vtable[] = { ratbagd_resolution_get_report_rate, ratbagd_resolution_set_report_rate, 0, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("ReportRates", "au", ratbagd_resolution_get_report_rates, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("SetActive", "", "u", ratbagd_resolution_set_active, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetDefault", "", "u", ratbagd_resolution_set_default, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, diff --git a/src/driver-etekcity.c b/src/driver-etekcity.c index 91a18d87..737742a4 100644 --- a/src/driver-etekcity.c +++ b/src/driver-etekcity.c @@ -430,6 +430,7 @@ etekcity_read_profile(struct ratbag_profile *profile) unsigned int report_rate; int dpi_x, dpi_y, hz; int rc; + unsigned int report_rates[] = { 125, 250, 500, 1000 }; assert(profile->index <= ETEKCITY_PROFILE_MAX); @@ -446,12 +447,9 @@ etekcity_read_profile(struct ratbag_profile *profile) return; /* first retrieve the report rate, it is set per profile */ - switch (setting_report->report_rate) { - case 0x00: report_rate = 125; break; - case 0x01: report_rate = 250; break; - case 0x02: report_rate = 500; break; - case 0x03: report_rate = 1000; break; - default: + if (setting_report->report_rate < ARRAY_LENGTH(report_rates)) { + report_rate = report_rates[setting_report->report_rate]; + } else { log_error(device->ratbag, "error while reading the report rate of the mouse (0x%02x)\n", buf[26]); @@ -473,6 +471,9 @@ etekcity_read_profile(struct ratbag_profile *profile) ratbag_resolution_set_cap(resolution, RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION); resolution->is_active = (resolution->index == setting_report->current_dpi); + + ratbag_resolution_set_report_rate_list(resolution, report_rates, + ARRAY_LENGTH(report_rates)); } ratbag_profile_for_each_button(profile, button) diff --git a/src/driver-gskill.c b/src/driver-gskill.c index 6d455632..527aab77 100644 --- a/src/driver-gskill.c +++ b/src/driver-gskill.c @@ -988,6 +988,8 @@ gskill_read_resolutions(struct ratbag_profile *profile, for (i = 0; i < report->dpi_num; i++) { _cleanup_resolution_ struct ratbag_resolution *resolution; + unsigned int rates[] = { 500, 1000 }; /* let's assume that is true */ + dpi_x = report->dpi_levels[i].x * GSKILL_DPI_UNIT; dpi_y = report->dpi_levels[i].y * GSKILL_DPI_UNIT; @@ -1001,6 +1003,8 @@ gskill_read_resolutions(struct ratbag_profile *profile, ratbag_resolution_set_dpi_list_from_range(resolution, GSKILL_MIN_DPI, GSKILL_MAX_DPI); + ratbag_resolution_set_report_rate_list(resolution, rates, + ARRAY_LENGTH(rates)); } } diff --git a/src/driver-hidpp10.c b/src/driver-hidpp10.c index 4fbb1cd1..5c300ceb 100644 --- a/src/driver-hidpp10.c +++ b/src/driver-hidpp10.c @@ -397,6 +397,10 @@ hidpp10drv_read_profile(struct ratbag_profile *profile) uint16_t xres, yres; uint8_t idx; + /* 0x64 USB_REFRESH_RATE has time between reports in ms. so let's + * assume the 1000/500/250 rates exist on the devices */ + unsigned int rates[] = {250, 500, 1000}; + drv_data = ratbag_get_drv_data(device); hidpp10 = drv_data->dev; rc = hidpp10_get_profile(hidpp10, profile->index, &p); @@ -449,6 +453,9 @@ hidpp10drv_read_profile(struct ratbag_profile *profile) ratbag_resolution_set_dpi_list(res, dpis, hidpp10->dpi_count); } + + ratbag_resolution_set_report_rate_list(res, rates, + ARRAY_LENGTH(rates)); } ratbag_profile_for_each_button(profile, button) diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index 8f9915d9..edd69eb8 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -669,6 +669,7 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile) ratbag_profile_for_each_resolution(profile, res) { struct hidpp20_sensor *sensor; + unsigned int rate = 500; /* let's assume that one is just present */ /* We only look at the first sensor. Multiple * sensors is too niche to care about right now */ @@ -679,6 +680,7 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile) ratbag_resolution_set_dpi_list_from_range(res, sensor->dpi_min, sensor->dpi_max); + ratbag_resolution_set_report_rate_list(res, &rate, 1); /* FIXME: we mark all resolutions as active because * they are from different sensors */ @@ -866,6 +868,7 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile) ratbag_profile_for_each_resolution(profile, res) { struct hidpp20_sensor *sensor; + unsigned int rate = p->report_rate; /* We only look at the first sensor. Multiple * sensors is too niche to care about right now */ @@ -888,7 +891,7 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile) ratbag_resolution_set_dpi_list_from_range(res, sensor->dpi_min, sensor->dpi_max); - + ratbag_resolution_set_report_rate_list(res, &rate, 1); } } diff --git a/src/driver-logitech-g300.c b/src/driver-logitech-g300.c index 57bc9a45..dc52ee96 100644 --- a/src/driver-logitech-g300.c +++ b/src/driver-logitech-g300.c @@ -396,6 +396,7 @@ logitech_g300_read_profile(struct ratbag_profile *profile) ratbag_resolution_set_dpi_list_from_range(resolution, LOGITECH_G300_DPI_MIN, LOGITECH_G300_DPI_MAX); + ratbag_resolution_set_report_rate_list(resolution, &hz, 1); } ratbag_profile_for_each_button(profile, button) diff --git a/src/driver-roccat.c b/src/driver-roccat.c index 0479b292..644a751b 100644 --- a/src/driver-roccat.c +++ b/src/driver-roccat.c @@ -704,6 +704,7 @@ roccat_read_profile(struct ratbag_profile *profile) unsigned int report_rate; int dpi_x, dpi_y, hz; int rc; + unsigned int report_rates[] = { 125, 250, 500, 1000 }; assert(profile->index <= ROCCAT_PROFILE_MAX); @@ -720,12 +721,9 @@ roccat_read_profile(struct ratbag_profile *profile) return; /* first retrieve the report rate, it is set per profile */ - switch (setting_report->report_rate) { - case 0x00: report_rate = 125; break; - case 0x01: report_rate = 250; break; - case 0x02: report_rate = 500; break; - case 0x03: report_rate = 1000; break; - default: + if (setting_report->report_rate < ARRAY_LENGTH(report_rates)) { + report_rate = report_rates[setting_report->report_rate]; + } else { log_error(device->ratbag, "error while reading the report rate of the mouse (0x%02x)\n", buf[26]); @@ -747,6 +745,9 @@ roccat_read_profile(struct ratbag_profile *profile) ratbag_resolution_set_cap(resolution, RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION); resolution->is_active = (resolution->index == setting_report->current_dpi); + + ratbag_resolution_set_report_rate_list(resolution, report_rates, + ARRAY_LENGTH(report_rates)); } ratbag_profile_for_each_button(profile, button) diff --git a/src/driver-test.c b/src/driver-test.c index 49095b68..48c432be 100644 --- a/src/driver-test.c +++ b/src/driver-test.c @@ -191,6 +191,7 @@ test_read_profile(struct ratbag_profile *profile) for (i = 0; i < d->num_resolutions; i++) { _cleanup_resolution_ struct ratbag_resolution *res; + size_t nrates = 0; r = &p->resolutions[i]; @@ -201,6 +202,17 @@ test_read_profile(struct ratbag_profile *profile) ratbag_resolution_set_dpi_list_from_range(res, r0->dpi_min, r0->dpi_max); + + for (size_t r = 0; r < ARRAY_LENGTH(r0->report_rates); r++) { + if (r0->report_rates[r] > 0) + nrates++; + } + + if (nrates > 0) + ratbag_resolution_set_report_rate_list(res, + r0->report_rates, + nrates); + res->is_active = r->active; if (r->active) active_set = true; diff --git a/src/libratbag-private.h b/src/libratbag-private.h index 71fd72a4..dfb184c6 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -261,6 +261,10 @@ struct ratbag_resolution { unsigned int dpi_x; /**< x resolution in dpi */ unsigned int dpi_y; /**< y resolution in dpi */ unsigned int hz; /**< report rate in Hz */ + + unsigned int rates[5]; + size_t nrates; + bool is_active; bool is_default; uint32_t capabilities; @@ -528,6 +532,22 @@ ratbag_resolution_set_dpi_list(struct ratbag_resolution *res, res->ndpis = ndpis; } +static inline void +ratbag_resolution_set_report_rate_list(struct ratbag_resolution *res, + unsigned int *rates, + size_t nrates) +{ + assert(nrates <= ARRAY_LENGTH(res->rates)); + _Static_assert(sizeof(*rates) == sizeof(*res->rates), "Mismatching size"); + + for (size_t i = 0; i < nrates; i++) { + res->rates[i] = rates[i]; + if (i > 0) + assert(rates[i] > rates[i - 1]); + } + res->nrates = nrates; +} + static inline void ratbag_resolution_set_cap(struct ratbag_resolution *res, enum ratbag_resolution_capability cap) diff --git a/src/libratbag-test.h b/src/libratbag-test.h index 06e62d77..d7543bdb 100644 --- a/src/libratbag-test.h +++ b/src/libratbag-test.h @@ -57,6 +57,7 @@ struct ratbag_test_resolution { uint32_t caps; int dpi_min, dpi_max; + unsigned int report_rates[5]; }; struct ratbag_test_color { diff --git a/src/libratbag.c b/src/libratbag.c index b3e39661..e2e32bde 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -1158,6 +1158,24 @@ ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution) return resolution->hz; } +LIBRATBAG_EXPORT size_t +ratbag_resolution_get_report_rate_list(struct ratbag_resolution *resolution, + unsigned int *rates, + size_t nrates) +{ + _Static_assert(sizeof(*rates) == sizeof(*resolution->rates), "type mismatch"); + + assert(nrates > 0); + + if (resolution->nrates == 0) + return 0; + + memcpy(rates, resolution->rates, + sizeof(unsigned int) * min(nrates, resolution->nrates)); + + return resolution->nrates; +} + LIBRATBAG_EXPORT int ratbag_resolution_is_active(const struct ratbag_resolution *resolution) { diff --git a/src/libratbag.h b/src/libratbag.h index aa2823b4..787b4831 100644 --- a/src/libratbag.h +++ b/src/libratbag.h @@ -936,6 +936,29 @@ ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution, int ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution); +/** + * @ingroup resolution + * + * Get the number of report rates in Hz available for this resolution. + * The list of report rates is sorted in ascending order but may be filtered + * by libratbag and does not necessarily reflect all report rates supported by + * the physical device. + * + * This function writes at most nrates values but returns the number of + * report rates available on this resolution. In other words, if it returns a + * number larger than nrates, call it again with an array the size of the + * return value. + * + * @param[out] rates Set to the supported report rates in ascending order + * @param[in] nrates The number of elements in resolutions + * + * @return The number of valid items in rates. If the returned value + * is larger than nrates, the list was truncated. + */ +size_t +ratbag_resolution_get_report_rate_list(struct ratbag_resolution *resolution, + unsigned int *rates, + size_t nrates); /** * @ingroup resolution * diff --git a/tools/ratbagd.py b/tools/ratbagd.py index 455ed435..4775c3d9 100644 --- a/tools/ratbagd.py +++ b/tools/ratbagd.py @@ -598,6 +598,11 @@ class RatbagdResolution(_RatbagdDBus): """The list of supported DPI values""" return self._get_dbus_property("Resolutions") + @GObject.Property + def report_rates(self): + """The list of supported report rates""" + return self._get_dbus_property("ReportRates") + @GObject.Property def is_active(self): """True if this is the currently active resolution, False