From b951d83a64d778179e440bad339e8e10ca4d41b7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 1 Sep 2017 14:11:17 +1000 Subject: [PATCH] Add ratbagd_led_has_mode() and the required dbus additions To be able to query which modes are available. Exposed via ratbagctl as ./build/ratbagctl.devel led 0 capabilities event4 Signed-off-by: Peter Hutterer --- doc/dbus.rst | 7 +++++++ ratbagd/ratbagd-led.c | 27 +++++++++++++++++++++++++++ src/driver-hidpp20.c | 9 +++++++++ src/driver-test.c | 5 +++++ src/libratbag-private.h | 11 +++++++++++ src/libratbag.c | 12 ++++++++++++ src/libratbag.h | 17 +++++++++++++++++ tools/ratbagctl.in | 19 +++++++++++++++++++ tools/ratbagctl.test.in | 5 +++++ tools/ratbagd.py | 5 +++++ 10 files changed, 117 insertions(+) diff --git a/doc/dbus.rst b/doc/dbus.rst index 8250429d..f05fc6ae 100644 --- a/doc/dbus.rst +++ b/doc/dbus.rst @@ -383,6 +383,13 @@ org.freedesktop.ratbag1.Led uint mapping to the mode enum from libratbag + .. js:attribute:: Modes + + :type: au + :flags: read-only, constant + + A list of modes supported by this LED + .. js:attribute:: Type :type: u diff --git a/ratbagd/ratbagd-led.c b/ratbagd/ratbagd-led.c index e87d6624..469fca3d 100644 --- a/ratbagd/ratbagd-led.c +++ b/ratbagd/ratbagd-led.c @@ -40,6 +40,32 @@ struct ratbagd_led { enum ratbag_led_colordepth colordepth; }; +static int ratbagd_led_get_modes(sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) +{ + struct ratbagd_led *led = userdata; + enum ratbag_led_mode mode = 0; + int r; + + r = sd_bus_message_open_container(reply, 'a', "u"); + if (r < 0) + return r; + + + while (mode <= RATBAG_LED_BREATHING) { + if (ratbag_led_has_mode(led->lib_led, mode)) + sd_bus_message_append(reply, "u", mode); + mode++; + } + + return sd_bus_message_close_container(reply); +} + static int ratbagd_led_get_mode(sd_bus *bus, const char *path, const char *interface, @@ -254,6 +280,7 @@ static int ratbagd_led_set_brightness(sd_bus *bus, const sd_bus_vtable ratbagd_led_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_led, index), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Modes", "au", ratbagd_led_get_modes, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_WRITABLE_PROPERTY("Mode", "u", ratbagd_led_get_mode, ratbagd_led_set_mode, 0, diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index bf800aa4..818ed139 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -295,6 +295,10 @@ hidpp20drv_read_led_1300(struct ratbag_led *led, struct hidpp20drv_data* data) default: led->mode = RATBAG_LED_ON; } + + ratbag_led_set_mode_capability(led, RATBAG_LED_ON); + ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING); + ratbag_led_set_mode_capability(led, RATBAG_LED_OFF); } static void @@ -332,6 +336,11 @@ hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_dat led->hz = h_led->period; /* FIXME: should be ceil(1000.0 / h_led->period), but that would be very small */ led->brightness = h_led->brightness * 255 / 100; led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888; + + ratbag_led_set_mode_capability(led, RATBAG_LED_ON); + ratbag_led_set_mode_capability(led, RATBAG_LED_CYCLE); + ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING); + ratbag_led_set_mode_capability(led, RATBAG_LED_OFF); } static void diff --git a/src/driver-test.c b/src/driver-test.c index 759e7fe7..49095b68 100644 --- a/src/driver-test.c +++ b/src/driver-test.c @@ -106,6 +106,11 @@ test_read_led(struct ratbag_led *led) struct ratbag_test_profile *p = &d->profiles[led->profile->index]; struct ratbag_test_led t_led = p->leds[led->index]; + ratbag_led_set_mode_capability(led, RATBAG_LED_ON); + ratbag_led_set_mode_capability(led, RATBAG_LED_CYCLE); + ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING); + ratbag_led_set_mode_capability(led, RATBAG_LED_OFF); + switch (t_led.mode) { case RATBAG_LED_ON: led->mode = RATBAG_LED_ON; diff --git a/src/libratbag-private.h b/src/libratbag-private.h index 60bcd55c..bc2517d4 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -274,6 +274,7 @@ struct ratbag_led { unsigned index; enum ratbag_led_type type; enum ratbag_led_mode mode; + uint32_t modes; /**< supported modes */ struct ratbag_color color; enum ratbag_led_colordepth colordepth; unsigned int hz; /**< rate of action in hz */ @@ -535,6 +536,16 @@ ratbag_resolution_set_cap(struct ratbag_resolution *res, res->capabilities = (1 << cap); } +static inline void +ratbag_led_set_mode_capability(struct ratbag_led *led, + enum ratbag_led_mode mode) +{ + assert(mode <= RATBAG_LED_BREATHING); + assert(mode < sizeof(led->modes) * 8); + + led->modes |= (1 << mode); +} + /* list of all supported drivers */ struct ratbag_driver etekcity_driver; struct ratbag_driver hidpp20_driver; diff --git a/src/libratbag.c b/src/libratbag.c index a9d22c1e..0db50e31 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -1458,6 +1458,18 @@ ratbag_led_get_type(struct ratbag_led *led) return led->type; } +LIBRATBAG_EXPORT int +ratbag_led_has_mode(struct ratbag_led *led, + enum ratbag_led_mode mode) +{ + assert(mode <= RATBAG_LED_BREATHING); + + if (mode == RATBAG_LED_OFF) + return 1; + + return (led->modes & (1 << mode)); +} + LIBRATBAG_EXPORT struct ratbag_color ratbag_led_get_color(struct ratbag_led *led) { diff --git a/src/libratbag.h b/src/libratbag.h index 992e5f47..aa2823b4 100644 --- a/src/libratbag.h +++ b/src/libratbag.h @@ -1182,6 +1182,23 @@ ratbag_profile_get_led(struct ratbag_profile *profile, unsigned int index); */ enum ratbag_led_type ratbag_led_get_type(struct ratbag_led *led); + +/** + * @ingroup led + * + * This function returns true if the given mode is supported by the LED, or + * false otherwise. + * + * @param led A previously initialized ratbag LED + * @param mode The LED mode @ref ratbag_led_mode to check for + * @return True if supported, false otherwise + * + * @see ratbag_led_set_mode + */ +int +ratbag_led_has_mode(struct ratbag_led *led, + enum ratbag_led_mode mode); + /** * @ingroup led * diff --git a/tools/ratbagctl.in b/tools/ratbagctl.in index 2e7a26f1..5b976723 100755 --- a/tools/ratbagctl.in +++ b/tools/ratbagctl.in @@ -167,6 +167,16 @@ def print_led(d, p, l, level): l.effect_rate, l.brightness)) +def print_led_caps(d, p, l, level): + leds = { + RatbagdLed.MODE_BREATHING: "breathing", + RatbagdLed.MODE_CYCLE: "cycle", + RatbagdLed.MODE_OFF: "off", + RatbagdLed.MODE_ON: "on", + } + supported = sorted([ v for k, v in leds.items() if k in l.modes ]) + print(" " * level + "Modes: {}".format(", ".join(supported))) + def print_button(d, p, b, level): types = { @@ -305,6 +315,9 @@ def func_led_get(r, args): l, p, d = find_led(r, args) print_led(d, p, l, 0) +def func_led_caps(r, args): + l, p, d = find_led(r, args) + print_led_caps(d, p, l, 0) def func_led_set(r, args): l, p, d = find_led(r, args) @@ -1074,6 +1087,12 @@ active profile if none is given.""", help_str: 'Show current LED value', func: func_led_get, }, + { + of_type: command, + name: 'capabilities', + help_str: 'Show LED capabilities', + func: func_led_caps, + }, { of_type: set, name: 'set', diff --git a/tools/ratbagctl.test.in b/tools/ratbagctl.test.in index 0a5e2dcb..f3634ddd 100755 --- a/tools/ratbagctl.test.in +++ b/tools/ratbagctl.test.in @@ -567,6 +567,11 @@ class TestRatbagCtlLED(TestRatbagCtl): self.launch_fail_test("Profile 1 Profile 2 Led 1 get test_device") self.launch_fail_test("Profile 1 Resolution 2 Led 1 get test_device") + def test_led_capabilities(self): + r = self.launch_good_test("led 0 capabilities test_device") + self.assertEqual(r, "Modes: breathing, cycle, off, on") + r = self.launch_good_test("led 1 capabilities test_device") + self.assertEqual(r, "Modes: breathing, cycle, off, on") def setUpModule(): global ratbagd_process, ratbagd, parser diff --git a/tools/ratbagd.py b/tools/ratbagd.py index 9e4000a1..559a52aa 100644 --- a/tools/ratbagd.py +++ b/tools/ratbagd.py @@ -924,6 +924,11 @@ class RatbagdLed(_RatbagdDBus): """ self._set_dbus_property("Mode", "u", mode) + @GObject.Property + def modes(self): + """The supported modes as a list""" + return self._get_dbus_property("Modes") + @GObject.Property def type(self): """An enum describing this led's type,