From 10139749583953979ce55efac3a0e6dfb58ad2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:08 +0100 Subject: [PATCH 01/11] theme: Fix some indentation --- src/fbd-feedback-theme.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/fbd-feedback-theme.c b/src/fbd-feedback-theme.c index 6d1bc22..3274920 100644 --- a/src/fbd-feedback-theme.c +++ b/src/fbd-feedback-theme.c @@ -42,9 +42,9 @@ G_DEFINE_TYPE_WITH_CODE (FbdFeedbackTheme, fbd_feedback_theme, G_TYPE_OBJECT, static JsonNode * fbd_theme_serializable_serialize_property (JsonSerializable *serializable, - const gchar *property_name, - const GValue *value, - GParamSpec *pspec) + const gchar *property_name, + const GValue *value, + GParamSpec *pspec) { FbdFeedbackTheme *self = FBD_FEEDBACK_THEME (serializable); JsonNode *node = NULL; @@ -71,10 +71,10 @@ fbd_theme_serializable_serialize_property (JsonSerializable *serializable, static gboolean fbd_theme_serializable_deserialize_property (JsonSerializable *serializable, - const gchar *property_name, - GValue *value, - GParamSpec *pspec, - JsonNode *property_node) + const gchar *property_name, + GValue *value, + GParamSpec *pspec, + JsonNode *property_node) { if (g_strcmp0 (property_name, "profiles") == 0) { if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) { @@ -117,7 +117,7 @@ fbd_theme_serializable_deserialize_property (JsonSerializable *serializable, } static void -fbd_feedback_theme_set_property (GObject *object, +fbd_feedback_theme_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) From 253d178cfc0c74c0af945c80c1b820da9376d9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:09 +0100 Subject: [PATCH 02/11] fbd-dev-leds: Use gi-docgen compatible format We don't document the server classes via gi-docgen atm but as we use it for the lib update classes we touch. --- src/fbd-dev-leds.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index bd498e2..4e7195b 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -16,15 +16,6 @@ #include -/** - * SECTION:fbd-dev-led - * @short_description: LED device interface - * @Title: FbdDevLeds - * - * #FbdDevLeds is used to interface with LEDS via sysfs - * It currently only supports one pattern per led at a time. - */ - #define LED_BRIGHTNESS_ATTR "brightness" #define LED_MAX_BRIGHTNESS_ATTR "max_brightness" #define LED_MULTI_INDEX_ATTR "multi_index" @@ -48,6 +39,14 @@ typedef struct _FbdDevLed { FbdFeedbackLedColor color; } FbdDevLed; +/** + * FbdDevLeds: + * + * LED device interface + * + * #FbdDevLeds is used to interface with LEDS via sysfs + * It currently only supports one pattern per led at a time. + */ typedef struct _FbdDevLeds { GObject parent; From 5fc0372b453038f2dd75558b71bb429c46dcb6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:10 +0100 Subject: [PATCH 03/11] Move LED device to separate file We separate out the led as different LED types have different ways to set patterns, etc --- src/fbd-dev-led.c | 34 ++++++++++++++++++++++++++++++++++ src/fbd-dev-led.h | 32 ++++++++++++++++++++++++++++++++ src/fbd-dev-leds.c | 36 +----------------------------------- src/fbd-dev-leds.h | 2 +- src/meson.build | 1 + 5 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 src/fbd-dev-led.c create mode 100644 src/fbd-dev-led.h diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c new file mode 100644 index 0000000..0df3354 --- /dev/null +++ b/src/fbd-dev-led.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + * Author: Guido Günther + * + * See Documentation/ABI/testing/sysfs-class-led-trigger-pattern + */ + +#define G_LOG_DOMAIN "fbd-dev-led" + +#include "fbd-dev-led.h" +#include "fbd-udev.h" + +#define LED_BRIGHTNESS_ATTR "brightness" + +void +fbd_dev_led_free (FbdDevLed *led) +{ + g_object_unref (led->dev); + g_free (led); +} + +gboolean +fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) +{ + g_autoptr (GError) err = NULL; + + if (!fbd_udev_set_sysfs_path_attr_as_int (led->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { + g_warning ("Failed to setup brightness: %s", err->message); + return FALSE; + } + + return TRUE; +} diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h new file mode 100644 index 0000000..43644c9 --- /dev/null +++ b/src/fbd-dev-led.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include "fbd-feedback-led.h" + +#include + +#include + +G_BEGIN_DECLS + +typedef struct _FbdDevLed { + GUdevDevice *dev; + guint max_brightness; + guint red_index; + guint green_index; + guint blue_index; + /* + * We just use the colors from the feedback until we + * do rgb mixing, etc + */ + FbdFeedbackLedColor color; +} FbdDevLed; + +void fbd_dev_led_free (FbdDevLed *led); +gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); + +G_END_DECLS diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index 4e7195b..66bd443 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -10,13 +10,13 @@ #include "fbd.h" #include "fbd-enums.h" +#include "fbd-dev-led.h" #include "fbd-dev-leds.h" #include "fbd-feedback-led.h" #include "fbd-udev.h" #include -#define LED_BRIGHTNESS_ATTR "brightness" #define LED_MAX_BRIGHTNESS_ATTR "max_brightness" #define LED_MULTI_INDEX_ATTR "multi_index" #define LED_MULTI_INTENSITY_ATTR "multi_intensity" @@ -26,19 +26,6 @@ #define LED_PATTERN_ATTR "pattern" #define LED_SUBSYSTEM "leds" -typedef struct _FbdDevLed { - GUdevDevice *dev; - guint max_brightness; - guint red_index; - guint green_index; - guint blue_index; - /* - * We just use the colors from the feedback until we - * do rgb mixing, etc - */ - FbdFeedbackLedColor color; -} FbdDevLed; - /** * FbdDevLeds: * @@ -59,27 +46,6 @@ static void initable_iface_init (GInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (FbdDevLeds, fbd_dev_leds, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)); - -static void -fbd_dev_led_free (FbdDevLed *led) -{ - g_object_unref (led->dev); - g_free (led); -} - -static gboolean -fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) -{ - g_autoptr (GError) err = NULL; - - if (!fbd_udev_set_sysfs_path_attr_as_int (led->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { - g_warning ("Failed to setup brightness: %s", err->message); - return FALSE; - } - - return TRUE; -} - static FbdDevLed * find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color) { diff --git a/src/fbd-dev-leds.h b/src/fbd-dev-leds.h index 479be88..999dbd9 100644 --- a/src/fbd-dev-leds.h +++ b/src/fbd-dev-leds.h @@ -6,9 +6,9 @@ #pragma once #include "fbd-feedback-led.h" +#include "fbd-udev.h" #include -#include G_BEGIN_DECLS diff --git a/src/meson.build b/src/meson.build index a75cf6d..510306f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,6 +15,7 @@ sources = [ 'fbd-error.c', 'fbd-dev-vibra.c', 'fbd-dev-sound.c', + 'fbd-dev-led.c', 'fbd-dev-leds.c', 'fbd-event.c', 'fbd-feedback-base.c', From fd852c6f69f4c06e7f9cb6f2591db56d26144f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:10 +0100 Subject: [PATCH 04/11] fbd-dev-leds: Move led creation into fbd-dev-led This will allow us to separate the different led types --- src/fbd-dev-led.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ src/fbd-dev-led.h | 1 + src/fbd-dev-leds.c | 63 ++++-------------------------------------- 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 0df3354..a42f5e8 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -9,9 +9,15 @@ #define G_LOG_DOMAIN "fbd-dev-led" #include "fbd-dev-led.h" +#include "fbd-enums.h" #include "fbd-udev.h" #define LED_BRIGHTNESS_ATTR "brightness" +#define LED_MAX_BRIGHTNESS_ATTR "max_brightness" +#define LED_MULTI_INDEX_ATTR "multi_index" +#define LED_MULTI_INDEX_RED "red" +#define LED_MULTI_INDEX_GREEN "green" +#define LED_MULTI_INDEX_BLUE "blue" void fbd_dev_led_free (FbdDevLed *led) @@ -20,6 +26,69 @@ fbd_dev_led_free (FbdDevLed *led) g_free (led); } + +FbdDevLed * +fbd_dev_led_new (GUdevDevice *dev) +{ + + FbdDevLed *led = NULL; + const gchar *name, *path; + + name = g_udev_device_get_name (dev); + /* We don't know anything about diffusors that can combine different + color LEDSs so go with fixed colors until the kernel gives us + enough information */ + for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) { + g_autofree char *color = NULL; + g_autofree char *enum_name = NULL; + const gchar * const *index; + guint counter = 0; + gchar *c; + + enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i); + c = strrchr (enum_name, '_'); + color = g_ascii_strdown (c+1, -1); + if (g_strstr_len (name, -1, color)) { + g_autoptr (GError) err = NULL; + guint brightness = g_udev_device_get_sysfs_attr_as_int (dev, LED_MAX_BRIGHTNESS_ATTR); + index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_MULTI_INDEX_ATTR); + + if (!brightness) + continue; + + led = g_malloc0 (sizeof(FbdDevLed)); + led->dev = g_object_ref (dev); + led->color = i; + led->max_brightness = brightness; + + if (index) { + for (int j = 0; j < g_strv_length ((gchar **) index); j++) { + g_debug ("Index: %s", index[j]); + if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { + led->red_index = counter; + counter++; + } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { + led->green_index = counter; + counter++; + } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { + led->blue_index = counter; + counter++; + } else { + g_warning ("Unsupport LED color index: %d %s", counter, index[j]); + } + } + } + + path = g_udev_device_get_sysfs_path (dev); + g_debug ("LED at '%s' usable", path); + break; + } + } + + return led; +} + + gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) { diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index 43644c9..b46e766 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -28,5 +28,6 @@ typedef struct _FbdDevLed { void fbd_dev_led_free (FbdDevLed *led); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); +FbdDevLed *fbd_dev_led_new (GUdevDevice *dev); G_END_DECLS diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index 66bd443..14f2ff9 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -17,12 +17,7 @@ #include -#define LED_MAX_BRIGHTNESS_ATTR "max_brightness" -#define LED_MULTI_INDEX_ATTR "multi_index" #define LED_MULTI_INTENSITY_ATTR "multi_intensity" -#define LED_MULTI_INDEX_RED "red" -#define LED_MULTI_INDEX_GREEN "green" -#define LED_MULTI_INDEX_BLUE "blue" #define LED_PATTERN_ATTR "pattern" #define LED_SUBSYSTEM "leds" @@ -77,65 +72,17 @@ initable_init (GInitable *initable, for (GList *l = leds; l != NULL; l = l->next) { GUdevDevice *dev = G_UDEV_DEVICE (l->data); - const gchar *name, *path; - FbdDevLed *led = NULL; + FbdDevLed *led; if (g_strcmp0 (g_udev_device_get_property (dev, FEEDBACKD_UDEV_ATTR), FEEDBACKD_UDEV_VAL_LED)) { continue; } - name = g_udev_device_get_name (dev); - /* We don't know anything about diffusors that can combine different - color LEDSs so go with fixed colors until the kernel gives us - enough information */ - for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) { - g_autofree char *color = NULL; - g_autofree char *enum_name = NULL; - const gchar * const *index; - guint counter = 0; - gchar *c; - - enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i); - c = strrchr (enum_name, '_'); - color = g_ascii_strdown (c+1, -1); - if (g_strstr_len (name, -1, color)) { - g_autoptr (GError) err = NULL; - guint brightness = g_udev_device_get_sysfs_attr_as_int (dev, LED_MAX_BRIGHTNESS_ATTR); - index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_MULTI_INDEX_ATTR); - - if (!brightness) - continue; - - led = g_malloc0 (sizeof(FbdDevLed)); - led->dev = g_object_ref (dev); - led->color = i; - led->max_brightness = brightness; - - if (index) { - for (int j = 0; j < g_strv_length ((gchar **) index); j++) { - g_debug ("Index: %s", index[j]); - if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { - led->red_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { - led->green_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { - led->blue_index = counter; - counter++; - } else { - g_warning ("Unsupport LED color index: %d %s", counter, index[j]); - } - } - } - - path = g_udev_device_get_sysfs_path (dev); - g_debug ("LED at '%s' usable", path); - self->leds = g_slist_append (self->leds, led); - found = TRUE; - break; - } + led = fbd_dev_led_new (dev); + if (led) { + self->leds = g_slist_append (self->leds, led); + found = TRUE; } } From 8ad1c43ff1b49813c7f5bc0fc2b1058258e7ee71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:11 +0100 Subject: [PATCH 05/11] fbd-dev-leds: Move pattern trigger into fbd-dev-led --- src/fbd-dev-led.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ src/fbd-dev-led.h | 4 +++ src/fbd-dev-leds.c | 56 +--------------------------------------- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index a42f5e8..9dc3cd1 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -18,6 +18,8 @@ #define LED_MULTI_INDEX_RED "red" #define LED_MULTI_INDEX_GREEN "green" #define LED_MULTI_INDEX_BLUE "blue" +#define LED_MULTI_INTENSITY_ATTR "multi_intensity" +#define LED_PATTERN_ATTR "pattern" void fbd_dev_led_free (FbdDevLed *led) @@ -100,4 +102,66 @@ fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) } return TRUE; +} + + +gboolean +fbd_dev_led_start_periodic (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq) +{ + g_autoptr (GError) err = NULL; + g_autofree gchar *str = NULL; + gboolean success = FALSE; + gdouble max; + gdouble t; + + if (led->color == FBD_FEEDBACK_LED_COLOR_RGB) { + g_autofree char *intensity = NULL; + guint colors[] = { 0, 0, 0 }; + switch (color) { + case FBD_FEEDBACK_LED_COLOR_WHITE: + colors[led->red_index] = led->max_brightness; + colors[led->green_index] = led->max_brightness; + colors[led->blue_index] = led->max_brightness; + break; + case FBD_FEEDBACK_LED_COLOR_RED: + colors[led->red_index] = led->max_brightness; + colors[led->green_index] = 0; + colors[led->blue_index] = 0; + break; + case FBD_FEEDBACK_LED_COLOR_GREEN: + colors[led->red_index] = 0; + colors[led->green_index] = led->max_brightness; + colors[led->blue_index] = 0; + break; + case FBD_FEEDBACK_LED_COLOR_BLUE: + colors[led->red_index] = 0; + colors[led->green_index] = 0; + colors[led->blue_index] = led->max_brightness; + break; + default: + g_warning("Unhandled color: %d\n", color); + return FALSE; + } + intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]); + fbd_dev_led_set_brightness (led, led->max_brightness); + success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err); + if (!success) { + g_warning ("Failed to set multi intensity: %s", err->message); + g_clear_error (&err); + } + } + + max = led->max_brightness * (max_brightness_percentage / 100.0); + /* ms mHz T/2 */ + t = 1000.0 * 1000.0 / freq / 2.0; + str = g_strdup_printf ("0 %d %d %d\n", (gint)t, (gint)max, (gint)t); + g_debug ("Freq %d mHz, Brightness: %d%%, Blink pattern: %s", freq, max_brightness_percentage, str); + success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_PATTERN_ATTR, str, &err); + if (!success) + g_warning ("Failed to set led pattern: %s", err->message); + + return success; } diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index b46e766..e4af3e3 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -29,5 +29,9 @@ typedef struct _FbdDevLed { void fbd_dev_led_free (FbdDevLed *led); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); FbdDevLed *fbd_dev_led_new (GUdevDevice *dev); +gboolean fbd_dev_led_start_periodic (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq); G_END_DECLS diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index 14f2ff9..b66b5f0 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -17,8 +17,6 @@ #include -#define LED_MULTI_INTENSITY_ATTR "multi_intensity" -#define LED_PATTERN_ATTR "pattern" #define LED_SUBSYSTEM "leds" /** @@ -151,65 +149,13 @@ fbd_dev_leds_start_periodic (FbdDevLeds *self, FbdFeedbackLedColor color, guint max_brightness_percentage, guint freq) { FbdDevLed *led; - gdouble max; - gdouble t; - g_autofree gchar *str = NULL; - - g_autoptr (GError) err = NULL; - gboolean success; g_return_val_if_fail (FBD_IS_DEV_LEDS (self), FALSE); g_return_val_if_fail (max_brightness_percentage <= 100.0, FALSE); led = find_led_by_color (self, color); g_return_val_if_fail (led, FALSE); - if (led->color == FBD_FEEDBACK_LED_COLOR_RGB) { - g_autofree char *intensity = NULL; - guint colors[] = { 0, 0, 0 }; - switch (color) { - case FBD_FEEDBACK_LED_COLOR_WHITE: - colors[led->red_index] = led->max_brightness; - colors[led->green_index] = led->max_brightness; - colors[led->blue_index] = led->max_brightness; - break; - case FBD_FEEDBACK_LED_COLOR_RED: - colors[led->red_index] = led->max_brightness; - colors[led->green_index] = 0; - colors[led->blue_index] = 0; - break; - case FBD_FEEDBACK_LED_COLOR_GREEN: - colors[led->red_index] = 0; - colors[led->green_index] = led->max_brightness; - colors[led->blue_index] = 0; - break; - case FBD_FEEDBACK_LED_COLOR_BLUE: - colors[led->red_index] = 0; - colors[led->green_index] = 0; - colors[led->blue_index] = led->max_brightness; - break; - default: - g_warning("Unhandled color: %d\n", color); - return FALSE; - } - intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]); - fbd_dev_led_set_brightness (led, led->max_brightness); - success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err); - if (!success) { - g_warning ("Failed to set multi intensity: %s", err->message); - g_clear_error (&err); - } - } - - max = led->max_brightness * (max_brightness_percentage / 100.0); - /* ms mHz T/2 */ - t = 1000.0 * 1000.0 / freq / 2.0; - str = g_strdup_printf ("0 %d %d %d\n", (gint)t, (gint)max, (gint)t); - g_debug ("Freq %d mHz, Brightness: %d%%, Blink pattern: %s", freq, max_brightness_percentage, str); - success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_PATTERN_ATTR, str, &err); - if (!success) - g_warning ("Failed to set led pattern: %s", err->message); - - return success; + return fbd_dev_led_start_periodic (led, color, max_brightness_percentage, freq); } gboolean From 5d8b2e5fe486a73f232bfdb523fea5d2b668a478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:12 +0100 Subject: [PATCH 06/11] fbd-dev-led: Allow to lookup color This allows us to make the led structure into an opaque in the next commit --- src/fbd-dev-led.c | 7 +++++++ src/fbd-dev-led.h | 1 + src/fbd-dev-leds.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 9dc3cd1..8ccd3ed 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -165,3 +165,10 @@ fbd_dev_led_start_periodic (FbdDevLed *led, return success; } + + +gboolean +fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) +{ + return (led->color == FBD_FEEDBACK_LED_COLOR_RGB || led->color == color); +} diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index e4af3e3..bf45d16 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -33,5 +33,6 @@ gboolean fbd_dev_led_start_periodic (FbdDevLed *led, FbdFeedbackLedColor color, guint max_brightness_percentage, guint freq); +gboolean fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color); G_END_DECLS diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index b66b5f0..d4f048b 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -46,7 +46,7 @@ find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color) for (GSList *l = self->leds; l != NULL; l = l->next) { FbdDevLed *led = l->data; - if (led->color == FBD_FEEDBACK_LED_COLOR_RGB || led->color == color) + if (fbd_dev_led_has_color (led, color)) return led; } From f17ca72c1bc13824e4afdd9bbff3d823558cf9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:12 +0100 Subject: [PATCH 07/11] fbd-dev-led: Make structure opaque This will allow us to turn it into a GObject --- src/fbd-dev-led.c | 15 +++++++++++++++ src/fbd-dev-led.h | 13 +------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 8ccd3ed..2badd62 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -21,6 +21,21 @@ #define LED_MULTI_INTENSITY_ATTR "multi_intensity" #define LED_PATTERN_ATTR "pattern" + +struct _FbdDevLed { + GUdevDevice *dev; + guint max_brightness; + guint red_index; + guint green_index; + guint blue_index; + /* + * We just use the colors from the feedback until we + * do rgb mixing, etc + */ + FbdFeedbackLedColor color; +}; + + void fbd_dev_led_free (FbdDevLed *led) { diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index bf45d16..c709f75 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -13,18 +13,7 @@ G_BEGIN_DECLS -typedef struct _FbdDevLed { - GUdevDevice *dev; - guint max_brightness; - guint red_index; - guint green_index; - guint blue_index; - /* - * We just use the colors from the feedback until we - * do rgb mixing, etc - */ - FbdFeedbackLedColor color; -} FbdDevLed; +typedef struct _FbdDevLed FbdDevLed; void fbd_dev_led_free (FbdDevLed *led); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); From f7ec08497ed6a34220324b2e0f98c52a7e6372b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:13 +0100 Subject: [PATCH 08/11] fbd-dev-led: Turn into a GObject This is just the minimal changes to switch to a derivable GObject --- src/fbd-dev-led.c | 159 +++++++++++++++++++++++++++++++++++---------- src/fbd-dev-led.h | 9 ++- src/fbd-dev-leds.c | 2 +- 3 files changed, 133 insertions(+), 37 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 2badd62..e437d6d 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -21,8 +21,14 @@ #define LED_MULTI_INTENSITY_ATTR "multi_intensity" #define LED_PATTERN_ATTR "pattern" +enum { + PROP_0, + PROP_DEV, + PROP_LAST_PROP +}; +static GParamSpec *props[PROP_LAST_PROP]; -struct _FbdDevLed { +typedef struct _FbdDevLedPrivate { GUdevDevice *dev; guint max_brightness; guint red_index; @@ -33,22 +39,93 @@ struct _FbdDevLed { * do rgb mixing, etc */ FbdFeedbackLedColor color; -}; +} FbdDevLedPrivate; -void -fbd_dev_led_free (FbdDevLed *led) +G_DEFINE_TYPE_WITH_PRIVATE (FbdDevLed, fbd_dev_led, G_TYPE_OBJECT) + + +static void +fbd_dev_led_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + FbdDevLed *led = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); + + switch (property_id) { + case PROP_DEV: + priv->dev = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +fbd_dev_led_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + FbdDevLed *led = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); + + switch (property_id) { + case PROP_DEV: + g_value_set_object (value, priv->dev); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +fbd_dev_led_finalize (GObject *object) +{ + FbdDevLed *self = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (self); + + g_clear_object (&priv->dev); + + G_OBJECT_CLASS (fbd_dev_led_parent_class)->finalize (object); +} + + +static void +fbd_dev_led_class_init (FbdDevLedClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = fbd_dev_led_get_property; + object_class->set_property = fbd_dev_led_set_property; + object_class->finalize = fbd_dev_led_finalize; + + props[PROP_DEV] = + g_param_spec_object ("dev", "", "", + G_UDEV_TYPE_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST_PROP, props); +} + + +static void +fbd_dev_led_init (FbdDevLed *self) { - g_object_unref (led->dev); - g_free (led); } FbdDevLed * fbd_dev_led_new (GUdevDevice *dev) { - FbdDevLed *led = NULL; + FbdDevLedPrivate *priv; const gchar *name, *path; name = g_udev_device_get_name (dev); @@ -73,22 +150,23 @@ fbd_dev_led_new (GUdevDevice *dev) if (!brightness) continue; - led = g_malloc0 (sizeof(FbdDevLed)); - led->dev = g_object_ref (dev); - led->color = i; - led->max_brightness = brightness; + led = g_object_new (FBD_TYPE_DEV_LED, NULL); + priv = fbd_dev_led_get_instance_private (led); + priv->dev = g_object_ref (dev); + priv->color = i; + priv->max_brightness = brightness; if (index) { for (int j = 0; j < g_strv_length ((gchar **) index); j++) { g_debug ("Index: %s", index[j]); if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { - led->red_index = counter; + priv->red_index = counter; counter++; } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { - led->green_index = counter; + priv->green_index = counter; counter++; } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { - led->blue_index = counter; + priv->blue_index = counter; counter++; } else { g_warning ("Unsupport LED color index: %d %s", counter, index[j]); @@ -109,15 +187,19 @@ fbd_dev_led_new (GUdevDevice *dev) gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) { + FbdDevLedPrivate *priv; g_autoptr (GError) err = NULL; - if (!fbd_udev_set_sysfs_path_attr_as_int (led->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + priv = fbd_dev_led_get_instance_private (led); + + if (!fbd_udev_set_sysfs_path_attr_as_int (priv->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { g_warning ("Failed to setup brightness: %s", err->message); return FALSE; } return TRUE; -} +} gboolean @@ -126,55 +208,59 @@ fbd_dev_led_start_periodic (FbdDevLed *led, guint max_brightness_percentage, guint freq) { + FbdDevLedPrivate *priv; g_autoptr (GError) err = NULL; g_autofree gchar *str = NULL; gboolean success = FALSE; gdouble max; gdouble t; - if (led->color == FBD_FEEDBACK_LED_COLOR_RGB) { + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + priv = fbd_dev_led_get_instance_private (led); + + if (priv->color == FBD_FEEDBACK_LED_COLOR_RGB) { g_autofree char *intensity = NULL; guint colors[] = { 0, 0, 0 }; switch (color) { case FBD_FEEDBACK_LED_COLOR_WHITE: - colors[led->red_index] = led->max_brightness; - colors[led->green_index] = led->max_brightness; - colors[led->blue_index] = led->max_brightness; + colors[priv->red_index] = priv->max_brightness; + colors[priv->green_index] = priv->max_brightness; + colors[priv->blue_index] = priv->max_brightness; break; case FBD_FEEDBACK_LED_COLOR_RED: - colors[led->red_index] = led->max_brightness; - colors[led->green_index] = 0; - colors[led->blue_index] = 0; + colors[priv->red_index] = priv->max_brightness; + colors[priv->green_index] = 0; + colors[priv->blue_index] = 0; break; case FBD_FEEDBACK_LED_COLOR_GREEN: - colors[led->red_index] = 0; - colors[led->green_index] = led->max_brightness; - colors[led->blue_index] = 0; + colors[priv->red_index] = 0; + colors[priv->green_index] = priv->max_brightness; + colors[priv->blue_index] = 0; break; case FBD_FEEDBACK_LED_COLOR_BLUE: - colors[led->red_index] = 0; - colors[led->green_index] = 0; - colors[led->blue_index] = led->max_brightness; + colors[priv->red_index] = 0; + colors[priv->green_index] = 0; + colors[priv->blue_index] = priv->max_brightness; break; default: g_warning("Unhandled color: %d\n", color); return FALSE; } intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]); - fbd_dev_led_set_brightness (led, led->max_brightness); - success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err); + fbd_dev_led_set_brightness (led, priv->max_brightness); + success = fbd_udev_set_sysfs_path_attr_as_string (priv->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err); if (!success) { g_warning ("Failed to set multi intensity: %s", err->message); g_clear_error (&err); } } - max = led->max_brightness * (max_brightness_percentage / 100.0); + max = priv->max_brightness * (max_brightness_percentage / 100.0); /* ms mHz T/2 */ t = 1000.0 * 1000.0 / freq / 2.0; str = g_strdup_printf ("0 %d %d %d\n", (gint)t, (gint)max, (gint)t); g_debug ("Freq %d mHz, Brightness: %d%%, Blink pattern: %s", freq, max_brightness_percentage, str); - success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_PATTERN_ATTR, str, &err); + success = fbd_udev_set_sysfs_path_attr_as_string (priv->dev, LED_PATTERN_ATTR, str, &err); if (!success) g_warning ("Failed to set led pattern: %s", err->message); @@ -185,5 +271,10 @@ fbd_dev_led_start_periodic (FbdDevLed *led, gboolean fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) { - return (led->color == FBD_FEEDBACK_LED_COLOR_RGB || led->color == color); + FbdDevLedPrivate *priv; + + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + priv = fbd_dev_led_get_instance_private (led); + + return (priv->color == FBD_FEEDBACK_LED_COLOR_RGB || priv->color == color); } diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index c709f75..d1fe99b 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -13,9 +13,10 @@ G_BEGIN_DECLS -typedef struct _FbdDevLed FbdDevLed; +#define FBD_TYPE_DEV_LED fbd_dev_led_get_type() + +G_DECLARE_DERIVABLE_TYPE (FbdDevLed, fbd_dev_led, FBD, DEV_LED, GObject) -void fbd_dev_led_free (FbdDevLed *led); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); FbdDevLed *fbd_dev_led_new (GUdevDevice *dev); gboolean fbd_dev_led_start_periodic (FbdDevLed *led, @@ -24,4 +25,8 @@ gboolean fbd_dev_led_start_periodic (FbdDevLed *led, guint freq); gboolean fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color); +struct _FbdDevLedClass { + GObjectClass parent_class; +}; + G_END_DECLS diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index d4f048b..a17ddfe 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -107,7 +107,7 @@ fbd_dev_leds_dispose (GObject *object) FbdDevLeds *self = FBD_DEV_LEDS (object); g_clear_object (&self->client); - g_slist_free_full (self->leds, (GDestroyNotify)fbd_dev_led_free); + g_slist_free_full (self->leds, (GDestroyNotify)g_object_unref); self->leds = NULL; G_OBJECT_CLASS (fbd_dev_leds_parent_class)->dispose (object); From ac0516329cb7de91b708f388672ab604f41b552a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:14 +0100 Subject: [PATCH 09/11] fbd-dev-led: Use GInitable Use default GObject patterns instead of stuffing things into the fbd_dev_led_new () so derived classes can override it. --- src/fbd-dev-led.c | 146 +++++++++++++++++++++++++++------------------ src/fbd-dev-led.h | 2 +- src/fbd-dev-leds.c | 5 +- 3 files changed, 92 insertions(+), 61 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index e437d6d..00b8dd1 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -12,6 +12,8 @@ #include "fbd-enums.h" #include "fbd-udev.h" +#include + #define LED_BRIGHTNESS_ATTR "brightness" #define LED_MAX_BRIGHTNESS_ATTR "max_brightness" #define LED_MULTI_INDEX_ATTR "multi_index" @@ -42,7 +44,11 @@ typedef struct _FbdDevLedPrivate { } FbdDevLedPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (FbdDevLed, fbd_dev_led, G_TYPE_OBJECT) +static void initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (FbdDevLed, fbd_dev_led, G_TYPE_OBJECT, + G_ADD_PRIVATE (FbdDevLed) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)) static void @@ -97,6 +103,83 @@ fbd_dev_led_finalize (GObject *object) } +static gboolean +initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + FbdDevLed *led = FBD_DEV_LED (initable); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); + const gchar *name, *path; + gboolean success; + + name = g_udev_device_get_name (priv->dev); + /* We don't know anything about diffusors that can combine different + color LEDSs so go with fixed colors until the kernel gives us + enough information */ + for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) { + g_autofree char *color = NULL; + g_autofree char *enum_name = NULL; + const gchar * const *index; + guint counter = 0; + gchar *c; + + enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i); + c = strrchr (enum_name, '_'); + color = g_ascii_strdown (c+1, -1); + if (g_strstr_len (name, -1, color)) { + g_autoptr (GError) err = NULL; + guint brightness = g_udev_device_get_sysfs_attr_as_int (priv->dev, LED_MAX_BRIGHTNESS_ATTR); + index = g_udev_device_get_sysfs_attr_as_strv (priv->dev, LED_MULTI_INDEX_ATTR); + + if (!brightness) + continue; + + priv->color = i; + priv->max_brightness = brightness; + + if (index) { + for (int j = 0; j < g_strv_length ((gchar **) index); j++) { + g_debug ("Index: %s", index[j]); + if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { + priv->red_index = counter; + counter++; + } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { + priv->green_index = counter; + counter++; + } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { + priv->blue_index = counter; + counter++; + } else { + g_warning ("Unsupport LED color index: %d %s", counter, index[j]); + } + } + } + + path = g_udev_device_get_sysfs_path (priv->dev); + g_debug ("LED at '%s' usable", path); + success = TRUE; + break; + } + } + + if (!success) { + g_set_error (error, + G_FILE_ERROR, G_FILE_ERROR_FAILED, + "%s not usable as RBG LED", name); + } + + return success; +} + + +static void +initable_iface_init (GInitableIface *iface) +{ + iface->init = initable_init; +} + + static void fbd_dev_led_class_init (FbdDevLedClass *klass) { @@ -122,65 +205,9 @@ fbd_dev_led_init (FbdDevLed *self) FbdDevLed * -fbd_dev_led_new (GUdevDevice *dev) +fbd_dev_led_new (GUdevDevice *dev, GError **err) { - FbdDevLed *led = NULL; - FbdDevLedPrivate *priv; - const gchar *name, *path; - - name = g_udev_device_get_name (dev); - /* We don't know anything about diffusors that can combine different - color LEDSs so go with fixed colors until the kernel gives us - enough information */ - for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) { - g_autofree char *color = NULL; - g_autofree char *enum_name = NULL; - const gchar * const *index; - guint counter = 0; - gchar *c; - - enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i); - c = strrchr (enum_name, '_'); - color = g_ascii_strdown (c+1, -1); - if (g_strstr_len (name, -1, color)) { - g_autoptr (GError) err = NULL; - guint brightness = g_udev_device_get_sysfs_attr_as_int (dev, LED_MAX_BRIGHTNESS_ATTR); - index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_MULTI_INDEX_ATTR); - - if (!brightness) - continue; - - led = g_object_new (FBD_TYPE_DEV_LED, NULL); - priv = fbd_dev_led_get_instance_private (led); - priv->dev = g_object_ref (dev); - priv->color = i; - priv->max_brightness = brightness; - - if (index) { - for (int j = 0; j < g_strv_length ((gchar **) index); j++) { - g_debug ("Index: %s", index[j]); - if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { - priv->red_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { - priv->green_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { - priv->blue_index = counter; - counter++; - } else { - g_warning ("Unsupport LED color index: %d %s", counter, index[j]); - } - } - } - - path = g_udev_device_get_sysfs_path (dev); - g_debug ("LED at '%s' usable", path); - break; - } - } - - return led; + return g_initable_new (FBD_TYPE_DEV_LED, NULL, err, "dev", dev, NULL); } @@ -260,6 +287,7 @@ fbd_dev_led_start_periodic (FbdDevLed *led, t = 1000.0 * 1000.0 / freq / 2.0; str = g_strdup_printf ("0 %d %d %d\n", (gint)t, (gint)max, (gint)t); g_debug ("Freq %d mHz, Brightness: %d%%, Blink pattern: %s", freq, max_brightness_percentage, str); + success = fbd_udev_set_sysfs_path_attr_as_string (priv->dev, LED_PATTERN_ATTR, str, &err); if (!success) g_warning ("Failed to set led pattern: %s", err->message); diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index d1fe99b..66228d3 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -17,8 +17,8 @@ G_BEGIN_DECLS G_DECLARE_DERIVABLE_TYPE (FbdDevLed, fbd_dev_led, FBD, DEV_LED, GObject) +FbdDevLed *fbd_dev_led_new (GUdevDevice *dev, GError **err); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); -FbdDevLed *fbd_dev_led_new (GUdevDevice *dev); gboolean fbd_dev_led_start_periodic (FbdDevLed *led, FbdFeedbackLedColor color, guint max_brightness_percentage, diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index a17ddfe..75a6c7a 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -69,6 +69,7 @@ initable_init (GInitable *initable, leds = g_udev_client_query_by_subsystem (self->client, LED_SUBSYSTEM); for (GList *l = leds; l != NULL; l = l->next) { + g_autoptr (GError) err = NULL; GUdevDevice *dev = G_UDEV_DEVICE (l->data); FbdDevLed *led; @@ -77,10 +78,12 @@ initable_init (GInitable *initable, continue; } - led = fbd_dev_led_new (dev); + led = fbd_dev_led_new (dev, &err); if (led) { self->leds = g_slist_append (self->leds, led); found = TRUE; + } else { + g_debug ("Led not usable: %s", err->message); } } From ca712e9a32af11b45f714b86be8043d12c70734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:16 +0100 Subject: [PATCH 10/11] fbd-dev-led: Add class methods so derived classes can override functionality --- src/fbd-dev-led.c | 277 ++++++++++++++++++++++++++-------------------- src/fbd-dev-led.h | 8 ++ 2 files changed, 165 insertions(+), 120 deletions(-) diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 00b8dd1..25705c4 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -50,65 +50,9 @@ G_DEFINE_TYPE_WITH_CODE (FbdDevLed, fbd_dev_led, G_TYPE_OBJECT, G_ADD_PRIVATE (FbdDevLed) G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)) - -static void -fbd_dev_led_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - FbdDevLed *led = FBD_DEV_LED (object); - FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); - - switch (property_id) { - case PROP_DEV: - priv->dev = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - - -static void -fbd_dev_led_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - FbdDevLed *led = FBD_DEV_LED (object); - FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); - - switch (property_id) { - case PROP_DEV: - g_value_set_object (value, priv->dev); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - - -static void -fbd_dev_led_finalize (GObject *object) -{ - FbdDevLed *self = FBD_DEV_LED (object); - FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (self); - - g_clear_object (&priv->dev); - - G_OBJECT_CLASS (fbd_dev_led_parent_class)->finalize (object); -} - - static gboolean -initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) +fbd_dev_led_probe_default (FbdDevLed *led, GError **error) { - FbdDevLed *led = FBD_DEV_LED (initable); FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); const gchar *name, *path; gboolean success; @@ -173,67 +117,11 @@ initable_init (GInitable *initable, } -static void -initable_iface_init (GInitableIface *iface) -{ - iface->init = initable_init; -} - - -static void -fbd_dev_led_class_init (FbdDevLedClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = fbd_dev_led_get_property; - object_class->set_property = fbd_dev_led_set_property; - object_class->finalize = fbd_dev_led_finalize; - - props[PROP_DEV] = - g_param_spec_object ("dev", "", "", - G_UDEV_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST_PROP, props); -} - - -static void -fbd_dev_led_init (FbdDevLed *self) -{ -} - - -FbdDevLed * -fbd_dev_led_new (GUdevDevice *dev, GError **err) -{ - return g_initable_new (FBD_TYPE_DEV_LED, NULL, err, "dev", dev, NULL); -} - - -gboolean -fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) -{ - FbdDevLedPrivate *priv; - g_autoptr (GError) err = NULL; - - g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); - priv = fbd_dev_led_get_instance_private (led); - - if (!fbd_udev_set_sysfs_path_attr_as_int (priv->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { - g_warning ("Failed to setup brightness: %s", err->message); - return FALSE; - } - - return TRUE; -} - - -gboolean -fbd_dev_led_start_periodic (FbdDevLed *led, - FbdFeedbackLedColor color, - guint max_brightness_percentage, - guint freq) +static gboolean +fbd_dev_led_start_periodic_default (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq) { FbdDevLedPrivate *priv; g_autoptr (GError) err = NULL; @@ -296,8 +184,8 @@ fbd_dev_led_start_periodic (FbdDevLed *led, } -gboolean -fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) +static gboolean +fbd_dev_led_has_color_default (FbdDevLed *led, FbdFeedbackLedColor color) { FbdDevLedPrivate *priv; @@ -306,3 +194,152 @@ fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) return (priv->color == FBD_FEEDBACK_LED_COLOR_RGB || priv->color == color); } + + +static void +fbd_dev_led_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + FbdDevLed *led = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); + + switch (property_id) { + case PROP_DEV: + priv->dev = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +fbd_dev_led_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + FbdDevLed *led = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); + + switch (property_id) { + case PROP_DEV: + g_value_set_object (value, priv->dev); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +fbd_dev_led_finalize (GObject *object) +{ + FbdDevLed *self = FBD_DEV_LED (object); + FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (self); + + g_clear_object (&priv->dev); + + G_OBJECT_CLASS (fbd_dev_led_parent_class)->finalize (object); +} + + +static gboolean +initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_GET_CLASS (initable); + + return fbd_dev_led_class->probe (FBD_DEV_LED (initable), error); +} + + +static void +initable_iface_init (GInitableIface *iface) +{ + iface->init = initable_init; +} + + +static void +fbd_dev_led_class_init (FbdDevLedClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_CLASS (klass); + + object_class->get_property = fbd_dev_led_get_property; + object_class->set_property = fbd_dev_led_set_property; + object_class->finalize = fbd_dev_led_finalize; + + fbd_dev_led_class->probe = fbd_dev_led_probe_default; + fbd_dev_led_class->start_periodic = fbd_dev_led_start_periodic_default; + fbd_dev_led_class->has_color = fbd_dev_led_has_color_default; + + props[PROP_DEV] = + g_param_spec_object ("dev", "", "", + G_UDEV_TYPE_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST_PROP, props); +} + + +static void +fbd_dev_led_init (FbdDevLed *self) +{ +} + + +FbdDevLed * +fbd_dev_led_new (GUdevDevice *dev, GError **err) +{ + return g_initable_new (FBD_TYPE_DEV_LED, NULL, err, "dev", dev, NULL); +} + + +gboolean +fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness) +{ + FbdDevLedPrivate *priv; + g_autoptr (GError) err = NULL; + + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + priv = fbd_dev_led_get_instance_private (led); + + if (!fbd_udev_set_sysfs_path_attr_as_int (priv->dev, LED_BRIGHTNESS_ATTR, brightness, &err)) { + g_warning ("Failed to setup brightness: %s", err->message); + return FALSE; + } + + return TRUE; +} + + +gboolean +fbd_dev_led_start_periodic (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq) +{ + FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_GET_CLASS (led); + + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + + return fbd_dev_led_class->start_periodic (led, color, max_brightness_percentage, freq); +} + + +gboolean +fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) +{ + FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_GET_CLASS (led); + + g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); + + return fbd_dev_led_class->has_color (led, color); +} diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index 66228d3..cddfad9 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -27,6 +27,14 @@ gboolean fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor c struct _FbdDevLedClass { GObjectClass parent_class; + + gboolean (*probe) (FbdDevLed *led, GError **error); + gboolean (*start_periodic) (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq); + gboolean (*has_color) (FbdDevLed *led, + FbdFeedbackLedColor color); }; G_END_DECLS From 995d21b5879511f113cc694e3f3450dd500f0272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 21 Jan 2023 14:47:16 +0100 Subject: [PATCH 11/11] fbd-dev-led: Move multicolor handling to separate class Everything related to multicolor moves into the new class and we add the necessary getters and setters so derived classes can access the parent classes attributes where needed. --- src/fbd-dev-led-multicolor.c | 177 +++++++++++++++++++++++++++++++++++ src/fbd-dev-led-multicolor.h | 18 ++++ src/fbd-dev-led-priv.h | 22 +++++ src/fbd-dev-led.c | 120 +++++++++++------------- src/fbd-dev-led.h | 1 + src/fbd-dev-leds.c | 13 ++- src/meson.build | 1 + 7 files changed, 283 insertions(+), 69 deletions(-) create mode 100644 src/fbd-dev-led-multicolor.c create mode 100644 src/fbd-dev-led-multicolor.h create mode 100644 src/fbd-dev-led-priv.h diff --git a/src/fbd-dev-led-multicolor.c b/src/fbd-dev-led-multicolor.c new file mode 100644 index 0000000..e0732aa --- /dev/null +++ b/src/fbd-dev-led-multicolor.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2023 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + * Author: Guido Günther + * + * See Documentation/ABI/testing/sysfs-class-led-trigger-pattern + */ + +#define G_LOG_DOMAIN "fbd-dev-led" + +#include "fbd-dev-led-priv.h" +#include "fbd-dev-led-multicolor.h" +#include "fbd-enums.h" +#include "fbd-udev.h" + +#include + +#define LED_MULTI_INDEX_ATTR "multi_index" +#define LED_MULTI_INDEX_RED "red" +#define LED_MULTI_INDEX_GREEN "green" +#define LED_MULTI_INDEX_BLUE "blue" +#define LED_MULTI_INTENSITY_ATTR "multi_intensity" + + +typedef struct _FbdDevLedMulticolor { + FbdDevLed parent; + + guint red_index; + guint green_index; + guint blue_index; +} FbdDevLedMulticolor; + + +G_DEFINE_TYPE (FbdDevLedMulticolor, fbd_dev_led_multicolor, FBD_TYPE_DEV_LED) + + +static gboolean +fbd_dev_led_probe_multicolor (FbdDevLed *led, GError **error) +{ + g_autoptr (GError) err = NULL; + FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led); + GUdevDevice *dev = fbd_dev_led_get_device (led); + const gchar *name, *path; + const gchar * const *index; + guint counter = 0; + guint max_brightness; + + name = g_udev_device_get_name (dev); + + index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_MULTI_INDEX_ATTR); + if (index == NULL) { + g_set_error (error, + G_FILE_ERROR, G_FILE_ERROR_FAILED, + "%s is no multicololor LED", name); + return FALSE; + } + + max_brightness = g_udev_device_get_sysfs_attr_as_int (dev, LED_MAX_BRIGHTNESS_ATTR); + if (!max_brightness) { + g_set_error (error, + G_FILE_ERROR, G_FILE_ERROR_FAILED, + "%s has no max_brightness", name); + return FALSE; + } + fbd_dev_led_set_max_brightness (led, max_brightness); + fbd_dev_led_set_color (led, FBD_FEEDBACK_LED_COLOR_RGB); + + for (int i = 0; index[i] != NULL; i++) { + g_debug ("Index: %s", index[i]); + if (g_strcmp0 (index[i], LED_MULTI_INDEX_RED) == 0) { + self->red_index = counter; + counter++; + } else if (g_strcmp0 (index[i], LED_MULTI_INDEX_GREEN) == 0) { + self->green_index = counter; + counter++; + } else if (g_strcmp0 (index[i], LED_MULTI_INDEX_BLUE) == 0) { + self->blue_index = counter; + counter++; + } else { + g_warning ("Unsupport LED color index: %d %s", counter, index[i]); + } + } + + path = g_udev_device_get_sysfs_path (dev); + g_debug ("LED at '%s' usable as multicolor", path); + return TRUE; +} + + +static gboolean +fbd_dev_led_start_periodic_multicolor (FbdDevLed *led, + FbdFeedbackLedColor color, + guint max_brightness_percentage, + guint freq) +{ + FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led); + GUdevDevice *dev = fbd_dev_led_get_device (led); + g_autofree char *intensity = NULL; + g_autoptr (GError) err = NULL; + g_autofree gchar *str = NULL; + gboolean success = FALSE; + guint max_brightness; + guint colors[] = { 0, 0, 0 }; + + max_brightness = fbd_dev_led_get_max_brightness (led); + switch (color) { + case FBD_FEEDBACK_LED_COLOR_WHITE: + colors[self->red_index] = max_brightness; + colors[self->green_index] = max_brightness; + colors[self->blue_index] = max_brightness; + break; + case FBD_FEEDBACK_LED_COLOR_RED: + colors[self->red_index] = max_brightness; + colors[self->green_index] = 0; + colors[self->blue_index] = 0; + break; + case FBD_FEEDBACK_LED_COLOR_GREEN: + colors[self->red_index] = 0; + colors[self->green_index] = max_brightness; + colors[self->blue_index] = 0; + break; + case FBD_FEEDBACK_LED_COLOR_BLUE: + colors[self->red_index] = 0; + colors[self->green_index] = 0; + colors[self->blue_index] = max_brightness; + break; + default: + g_warning("Unhandled color: %d\n", color); + return FALSE; + } + + intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]); + fbd_dev_led_set_brightness (led, max_brightness); + success = fbd_udev_set_sysfs_path_attr_as_string (dev, + LED_MULTI_INTENSITY_ATTR, + intensity, + &err); + if (!success) { + g_warning ("Failed to set multi intensity: %s", err->message); + return FALSE; + } + + /* Chain up to parent class to set the pattern */ + return FBD_DEV_LED_CLASS (fbd_dev_led_multicolor_parent_class)->start_periodic ( + led, color, max_brightness_percentage, freq); +} + + +static gboolean +fbd_dev_led_has_color_multicolor (FbdDevLed *led, FbdFeedbackLedColor color) +{ + return color == FBD_FEEDBACK_LED_COLOR_RGB; +} + + +static void +fbd_dev_led_multicolor_class_init (FbdDevLedMulticolorClass *klass) +{ + FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_CLASS (klass); + + fbd_dev_led_class->probe = fbd_dev_led_probe_multicolor; + fbd_dev_led_class->start_periodic = fbd_dev_led_start_periodic_multicolor; + fbd_dev_led_class->has_color = fbd_dev_led_has_color_multicolor; +} + + +static void +fbd_dev_led_multicolor_init (FbdDevLedMulticolor *self) +{ +} + + +FbdDevLed * +fbd_dev_led_multicolor_new (GUdevDevice *dev, GError **err) +{ + return g_initable_new (FBD_TYPE_DEV_LED_MULTICOLOR, NULL, err, "dev", dev, NULL); +} diff --git a/src/fbd-dev-led-multicolor.h b/src/fbd-dev-led-multicolor.h new file mode 100644 index 0000000..79f17fe --- /dev/null +++ b/src/fbd-dev-led-multicolor.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2023 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include "fbd-dev-led.h" + +G_BEGIN_DECLS + +#define FBD_TYPE_DEV_LED_MULTICOLOR fbd_dev_led_multicolor_get_type() + +G_DECLARE_FINAL_TYPE (FbdDevLedMulticolor, fbd_dev_led_multicolor, FBD, DEV_LED_MULTICOLOR, FbdDevLed) + +FbdDevLed *fbd_dev_led_multicolor_new (GUdevDevice *dev, GError **err); + +G_END_DECLS diff --git a/src/fbd-dev-led-priv.h b/src/fbd-dev-led-priv.h new file mode 100644 index 0000000..32b34e1 --- /dev/null +++ b/src/fbd-dev-led-priv.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include "fbd-dev-led.h" +#include "fbd-feedback-led.h" + +#include +#include + +G_BEGIN_DECLS + +#define LED_MAX_BRIGHTNESS_ATTR "max_brightness" + +GUdevDevice *fbd_dev_led_get_device (FbdDevLed *led); +void fbd_dev_led_set_max_brightness (FbdDevLed *led, guint max_brightness); +void fbd_dev_led_set_color (FbdDevLed *led, FbdFeedbackLedColor color); + +G_END_DECLS diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index 25705c4..a68b3da 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -9,13 +9,13 @@ #define G_LOG_DOMAIN "fbd-dev-led" #include "fbd-dev-led.h" +#include "fbd-dev-led-priv.h" #include "fbd-enums.h" #include "fbd-udev.h" #include #define LED_BRIGHTNESS_ATTR "brightness" -#define LED_MAX_BRIGHTNESS_ATTR "max_brightness" #define LED_MULTI_INDEX_ATTR "multi_index" #define LED_MULTI_INDEX_RED "red" #define LED_MULTI_INDEX_GREEN "green" @@ -33,9 +33,6 @@ static GParamSpec *props[PROP_LAST_PROP]; typedef struct _FbdDevLedPrivate { GUdevDevice *dev; guint max_brightness; - guint red_index; - guint green_index; - guint blue_index; /* * We just use the colors from the feedback until we * do rgb mixing, etc @@ -61,11 +58,9 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error) /* We don't know anything about diffusors that can combine different color LEDSs so go with fixed colors until the kernel gives us enough information */ - for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) { + for (int i = 0; i < FBD_FEEDBACK_LED_COLOR_RGB; i++) { g_autofree char *color = NULL; g_autofree char *enum_name = NULL; - const gchar * const *index; - guint counter = 0; gchar *c; enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i); @@ -74,34 +69,15 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error) if (g_strstr_len (name, -1, color)) { g_autoptr (GError) err = NULL; guint brightness = g_udev_device_get_sysfs_attr_as_int (priv->dev, LED_MAX_BRIGHTNESS_ATTR); - index = g_udev_device_get_sysfs_attr_as_strv (priv->dev, LED_MULTI_INDEX_ATTR); if (!brightness) continue; priv->color = i; - priv->max_brightness = brightness; - - if (index) { - for (int j = 0; j < g_strv_length ((gchar **) index); j++) { - g_debug ("Index: %s", index[j]); - if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) { - priv->red_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) { - priv->green_index = counter; - counter++; - } else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) { - priv->blue_index = counter; - counter++; - } else { - g_warning ("Unsupport LED color index: %d %s", counter, index[j]); - } - } - } + fbd_dev_led_set_max_brightness (led, brightness); path = g_udev_device_get_sysfs_path (priv->dev); - g_debug ("LED at '%s' usable", path); + g_debug ("LED at '%s' usable for %s", path, color); success = TRUE; break; } @@ -133,43 +109,6 @@ fbd_dev_led_start_periodic_default (FbdDevLed *led, g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); priv = fbd_dev_led_get_instance_private (led); - if (priv->color == FBD_FEEDBACK_LED_COLOR_RGB) { - g_autofree char *intensity = NULL; - guint colors[] = { 0, 0, 0 }; - switch (color) { - case FBD_FEEDBACK_LED_COLOR_WHITE: - colors[priv->red_index] = priv->max_brightness; - colors[priv->green_index] = priv->max_brightness; - colors[priv->blue_index] = priv->max_brightness; - break; - case FBD_FEEDBACK_LED_COLOR_RED: - colors[priv->red_index] = priv->max_brightness; - colors[priv->green_index] = 0; - colors[priv->blue_index] = 0; - break; - case FBD_FEEDBACK_LED_COLOR_GREEN: - colors[priv->red_index] = 0; - colors[priv->green_index] = priv->max_brightness; - colors[priv->blue_index] = 0; - break; - case FBD_FEEDBACK_LED_COLOR_BLUE: - colors[priv->red_index] = 0; - colors[priv->green_index] = 0; - colors[priv->blue_index] = priv->max_brightness; - break; - default: - g_warning("Unhandled color: %d\n", color); - return FALSE; - } - intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]); - fbd_dev_led_set_brightness (led, priv->max_brightness); - success = fbd_udev_set_sysfs_path_attr_as_string (priv->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err); - if (!success) { - g_warning ("Failed to set multi intensity: %s", err->message); - g_clear_error (&err); - } - } - max = priv->max_brightness * (max_brightness_percentage / 100.0); /* ms mHz T/2 */ t = 1000.0 * 1000.0 / freq / 2.0; @@ -192,7 +131,7 @@ fbd_dev_led_has_color_default (FbdDevLed *led, FbdFeedbackLedColor color) g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); priv = fbd_dev_led_get_instance_private (led); - return (priv->color == FBD_FEEDBACK_LED_COLOR_RGB || priv->color == color); + return priv->color == color; } @@ -343,3 +282,52 @@ fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) return fbd_dev_led_class->has_color (led, color); } + + +guint +fbd_dev_led_get_max_brightness (FbdDevLed *led) +{ + FbdDevLedPrivate *priv; + + g_return_val_if_fail (FBD_IS_DEV_LED (led), 0); + priv = fbd_dev_led_get_instance_private (led); + + return priv->max_brightness; +} + +/* Functions for derived classes */ + +GUdevDevice * +fbd_dev_led_get_device (FbdDevLed *led) +{ + FbdDevLedPrivate *priv; + + g_return_val_if_fail (FBD_IS_DEV_LED (led), NULL); + priv = fbd_dev_led_get_instance_private (led); + + return priv->dev; +} + + +void +fbd_dev_led_set_color (FbdDevLed *led, FbdFeedbackLedColor color) +{ + FbdDevLedPrivate *priv; + + g_return_if_fail (FBD_IS_DEV_LED (led)); + priv = fbd_dev_led_get_instance_private (led); + + priv->color = color; +} + + +void +fbd_dev_led_set_max_brightness (FbdDevLed *led, guint max_brightness) +{ + FbdDevLedPrivate *priv; + + g_return_if_fail (FBD_IS_DEV_LED (led)); + priv = fbd_dev_led_get_instance_private (led); + + priv->max_brightness = max_brightness; +} diff --git a/src/fbd-dev-led.h b/src/fbd-dev-led.h index cddfad9..139deec 100644 --- a/src/fbd-dev-led.h +++ b/src/fbd-dev-led.h @@ -19,6 +19,7 @@ G_DECLARE_DERIVABLE_TYPE (FbdDevLed, fbd_dev_led, FBD, DEV_LED, GObject) FbdDevLed *fbd_dev_led_new (GUdevDevice *dev, GError **err); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); +guint fbd_dev_led_get_max_brightness (FbdDevLed *led); gboolean fbd_dev_led_start_periodic (FbdDevLed *led, FbdFeedbackLedColor color, guint max_brightness_percentage, diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c index 75a6c7a..34b4314 100644 --- a/src/fbd-dev-leds.c +++ b/src/fbd-dev-leds.c @@ -11,6 +11,7 @@ #include "fbd.h" #include "fbd-enums.h" #include "fbd-dev-led.h" +#include "fbd-dev-led-multicolor.h" #include "fbd-dev-leds.h" #include "fbd-feedback-led.h" #include "fbd-udev.h" @@ -78,12 +79,18 @@ initable_init (GInitable *initable, continue; } - led = fbd_dev_led_new (dev, &err); + /* Try multicolor first, fall back to single color */ + led = fbd_dev_led_multicolor_new (dev, &err); + if (led == NULL) { + g_debug ("Led not usable as multicolor: '%s'", err->message); + led = fbd_dev_led_new (dev, &err); + if (led == NULL) + g_debug ("Led not usable as single color: '%s'", err->message); + } + if (led) { self->leds = g_slist_append (self->leds, led); found = TRUE; - } else { - g_debug ("Led not usable: %s", err->message); } } diff --git a/src/meson.build b/src/meson.build index 510306f..8d2dcdb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,6 +16,7 @@ sources = [ 'fbd-dev-vibra.c', 'fbd-dev-sound.c', 'fbd-dev-led.c', + 'fbd-dev-led-multicolor.c', 'fbd-dev-leds.c', 'fbd-event.c', 'fbd-feedback-base.c',