From a5b4f994125a0150b8f78af731cf05f72ee1eaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Fri, 29 May 2020 15:42:54 +0200 Subject: [PATCH] feedbackd: Support visual feedback via LEDs Currently all LED feedbacks are infinite we can improve that later on by using the 'repeat' attribute of the LED pattern trigger. --- README.md | 1 + src/fbd-dev-leds.c | 245 +++++++++++++++++++++++++++++++++++++ src/fbd-dev-leds.h | 26 ++++ src/fbd-feedback-led.c | 190 ++++++++++++++++++++++++++++ src/fbd-feedback-led.h | 24 ++++ src/fbd-feedback-manager.c | 16 +++ src/fbd-feedback-manager.h | 3 + src/fbd-feedback-profile.c | 2 + src/fbd-udev.c | 86 +++++++++++++ src/fbd-udev.h | 19 +++ src/fbd.h | 7 ++ src/meson.build | 4 + 12 files changed, 623 insertions(+) create mode 100644 src/fbd-dev-leds.c create mode 100644 src/fbd-dev-leds.h create mode 100644 src/fbd-feedback-led.c create mode 100644 src/fbd-feedback-led.h create mode 100644 src/fbd-udev.c create mode 100644 src/fbd-udev.h diff --git a/README.md b/README.md index cd98535..9a8107a 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ available feedback types are: - Sound (an audible sound from the sound naming spec) - VibraRumble: haptic motor rumbling - VibraPeriodic: periodic feedback from the haptic motor +- Led: Feedback via blinking LEDs You can check the feedback theme and the classes (prefixed with Fbd) for available properties. Note that the feedback theme API (including diff --git a/src/fbd-dev-leds.c b/src/fbd-dev-leds.c new file mode 100644 index 0000000..5c842f7 --- /dev/null +++ b/src/fbd-dev-leds.c @@ -0,0 +1,245 @@ +/* + * 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-leds" + +#include "fbd.h" +#include "fbd-enums.h" +#include "fbd-dev-leds.h" +#include "fbd-feedback-led.h" +#include "fbd-udev.h" + +#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_PATTERN_ATTR "pattern" +#define LED_SUBSYSTEM "leds" + +typedef struct _FbdDevLed { + GUdevDevice *dev; + guint max_brightness; + /* + * We just use the colors from the feedback until we + * do rgb mixing, etc + */ + FbdFeedbackLedColor color; +} FbdDevLed; + +typedef struct _FbdDevLeds { + GObject parent; + + GUdevClient *client; + GSList *leds; +} FbdDevLeds; + +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); +} + +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, 0, &err)) { + g_warning ("Failed to setup brightness: %s", err->message); + return FALSE; + } + + return TRUE; +} + +static FbdDevLed * +find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color) +{ + g_return_val_if_fail (self->leds, NULL); + + for (GSList *l = self->leds; l != NULL; l = l->next) { + FbdDevLed *led = l->data; + if (led->color == color) + return led; + } + + /* If we did not match a color pick the first */ + return self->leds->data; +} + +static gboolean +initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + const gchar * const subsystems[] = { LED_SUBSYSTEM, NULL }; + FbdDevLeds *self = FBD_DEV_LEDS (initable); + + g_autoptr (GList) leds; + gboolean found = FALSE; + + self->client = g_udev_client_new (subsystems); + + leds = g_udev_client_query_by_subsystem (self->client, LED_SUBSYSTEM); + + for (GList *l = leds; l != NULL; l = l->next) { + GUdevDevice *dev = G_UDEV_DEVICE (l->data); + const gchar *name, *path; + FbdDevLed *led = NULL; + + 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 gchar *color; + gchar *c; + + c = strrchr (g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i), '_'); + color = g_strdup (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, "max_brightness"); + + if (!brightness) + continue; + + led = g_malloc0 (sizeof(FbdDevLed)); + led->dev = dev; + led->max_brightness = brightness; + 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; + } + } + + if (!led) + g_object_unref (dev); + } + + /* TODO: listen for new leds via udev events */ + + if (!found) { + g_set_error (error, + G_FILE_ERROR, G_FILE_ERROR_FAILED, + "No usable LEDs found"); + } + + return found; +} + +static void +initable_iface_init (GInitableIface *iface) +{ + iface->init = initable_init; +} + +static void +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); + self->leds = NULL; + + G_OBJECT_CLASS (fbd_dev_leds_parent_class)->dispose (object); +} + +static void +fbd_dev_leds_class_init (FbdDevLedsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = fbd_dev_leds_dispose; +} + +static void +fbd_dev_leds_init (FbdDevLeds *self) +{ +} + +FbdDevLeds * +fbd_dev_leds_new (GError **error) +{ + return FBD_DEV_LEDS (g_initable_new (FBD_TYPE_DEV_LEDS, + NULL, + error, + NULL)); +} + +/** + * fbd_dev_leds_start_periodic: + * @self: The #FbdDevLeds + * @color: The color to use for the LED pattern + * @max_brightness: The max brightness (in percent) to use for the pattern + * @freq: The pattern's frequency in mHz + * + * Start periodic feedback. + */ +gboolean +fbd_dev_leds_start_periodic (FbdDevLeds *self, FbdFeedbackLedColor color, + guint max_brightness, 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); + led = find_led_by_color (self, color); + g_return_val_if_fail (led, FALSE); + + max = led->max_brightness * (max_brightness / 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, 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; +} + +gboolean +fbd_dev_leds_stop (FbdDevLeds *self, FbdFeedbackLedColor color) +{ + FbdDevLed *led; + + g_return_val_if_fail (FBD_IS_DEV_LEDS (self), FALSE); + + led = find_led_by_color (self, color); + g_return_val_if_fail (led, FALSE); + + return fbd_dev_led_set_brightness (led, 0); +} diff --git a/src/fbd-dev-leds.h b/src/fbd-dev-leds.h new file mode 100644 index 0000000..479be88 --- /dev/null +++ b/src/fbd-dev-leds.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include "fbd-feedback-led.h" + +#include +#include + +G_BEGIN_DECLS + +#define FBD_TYPE_DEV_LEDS (fbd_dev_leds_get_type ()) + +G_DECLARE_FINAL_TYPE (FbdDevLeds, fbd_dev_leds, FBD, DEV_LEDS, GObject); + +FbdDevLeds *fbd_dev_leds_new (GError **error); +gboolean fbd_dev_leds_start_periodic (FbdDevLeds *self, + FbdFeedbackLedColor color, + guint max_brighness, guint freq); +gboolean fbd_dev_leds_stop (FbdDevLeds *self, + FbdFeedbackLedColor color); + +G_END_DECLS diff --git a/src/fbd-feedback-led.c b/src/fbd-feedback-led.c new file mode 100644 index 0000000..89fd207 --- /dev/null +++ b/src/fbd-feedback-led.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2020 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + * Author: Guido Günther + */ + +#define G_LOG_DOMAIN "fbd-feedback-led" + +#include "fbd-enums.h" +#include "fbd-dev-leds.h" +#include "fbd-feedback-led.h" +#include "fbd-feedback-manager.h" + +/** + * SECTION:fbd-feedback-led + * @short_description: Describes a led feedback + * @Title: FbdFeedbackLed + * + * The #FbdFeedbackLed describes a feedback via an LED. It currently + * only supports periodic patterns. + */ + +enum { + PROP_0, + PROP_FREQUENCY, + PROP_COLOR, + PROP_MAX_BRIGHTNESS, + PROP_PRIORITY, + PROP_LAST_PROP, +}; +static GParamSpec *props[PROP_LAST_PROP]; + +typedef struct _FbdFeedbackLed { + FbdFeedbackBase parent; + + guint frequency; + guint priority; + guint max_brightness; + FbdFeedbackLedColor color; +} FbdFeedbackLed; + +G_DEFINE_TYPE (FbdFeedbackLed, fbd_feedback_led, FBD_TYPE_FEEDBACK_BASE) + +static void +fbd_feedback_led_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + FbdFeedbackLed *self = FBD_FEEDBACK_LED (object); + + switch (property_id) { + case PROP_FREQUENCY: + self->frequency = g_value_get_uint (value); + break; + case PROP_PRIORITY: + self->priority = g_value_get_uint (value); + break; + case PROP_MAX_BRIGHTNESS: + self->max_brightness = g_value_get_uint (value); + break; + case PROP_COLOR: + self->color = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +fbd_feedback_led_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + FbdFeedbackLed *self = FBD_FEEDBACK_LED (object); + + switch (property_id) { + case PROP_FREQUENCY: + g_value_set_uint (value, self->frequency); + break; + case PROP_PRIORITY: + g_value_set_uint (value, self->priority); + break; + case PROP_MAX_BRIGHTNESS: + g_value_set_uint (value, self->max_brightness); + break; + case PROP_COLOR: + g_value_set_enum (value, self->color); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +fbd_feedback_led_run (FbdFeedbackBase *base) +{ + FbdFeedbackLed *self = FBD_FEEDBACK_LED (base); + FbdFeedbackManager *manager = fbd_feedback_manager_get_default (); + FbdDevLeds *dev = fbd_feedback_manager_get_dev_leds (manager); + + g_debug ("Periodic led feeedback: self->max_brightness, self->frequency"); + + /* FIXME: handle priority */ + fbd_dev_leds_start_periodic (dev, + self->color, + self->max_brightness, + self->frequency); +} + +static void +fbd_feedback_led_end (FbdFeedbackBase *base) +{ + FbdFeedbackLed *self = FBD_FEEDBACK_LED (base); + FbdFeedbackManager *manager = fbd_feedback_manager_get_default (); + FbdDevLeds *dev = fbd_feedback_manager_get_dev_leds (manager); + + fbd_dev_leds_stop (dev, FBD_FEEDBACK_LED_COLOR_BLUE); + fbd_feedback_base_done (FBD_FEEDBACK_BASE (self)); +} + +static void +fbd_feedback_led_class_init (FbdFeedbackLedClass *klass) +{ + FbdFeedbackBaseClass *base_class = FBD_FEEDBACK_BASE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = fbd_feedback_led_set_property; + object_class->get_property = fbd_feedback_led_get_property; + + base_class->run = fbd_feedback_led_run; + base_class->end = fbd_feedback_led_end; + + props[PROP_FREQUENCY] = + g_param_spec_uint ( + "frequency", + "Frequency", + "Led event frequency in mHz", + 0, G_MAXUINT, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + props[PROP_COLOR] = + g_param_spec_enum ( + "color", + "Color", + "The LED color", + FBD_TYPE_FEEDBACK_LED_COLOR, + FBD_FEEDBACK_LED_COLOR_WHITE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * FbdFeedbackLed:priority: + * + * Priority of the led pattern. Led devices can only display a limited + * amount of patterns at time. In this case the pattern with the highest + * priority wins. + */ + props[PROP_PRIORITY] = + g_param_spec_uint ( + "priority", + "Priority", + "The LED pattern priority", + 0, 255, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * FbdFeedbackLed:max-brightness: + * + * The maximum brightness in the LED pattern in percent of the LEDs + * maximum brightness. + */ + props[PROP_MAX_BRIGHTNESS] = + g_param_spec_uint ( + "max-brightness", + "Maximum brightness percentage", + "Maximum brightness in the LED pattern", + 1, 100, 100, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST_PROP, props); +} + +static void +fbd_feedback_led_init (FbdFeedbackLed *self) +{ + self->max_brightness = 100; +} diff --git a/src/fbd-feedback-led.h b/src/fbd-feedback-led.h new file mode 100644 index 0000000..85e076d --- /dev/null +++ b/src/fbd-feedback-led.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include "fbd-feedback-base.h" + +G_BEGIN_DECLS + +typedef enum _FbdFeedbackLedColor { + FBD_FEEDBACK_LED_COLOR_WHITE = 0, + FBD_FEEDBACK_LED_COLOR_RED = 1, + FBD_FEEDBACK_LED_COLOR_GREEN = 2, + FBD_FEEDBACK_LED_COLOR_BLUE = 3, + FBD_FEEDBACK_LED_COLOR_LAST = FBD_FEEDBACK_LED_COLOR_BLUE, +} FbdFeedbackLedColor; + +#define FBD_TYPE_FEEDBACK_LED (fbd_feedback_led_get_type ()) + +G_DECLARE_FINAL_TYPE (FbdFeedbackLed, fbd_feedback_led, FBD, FEEDBACK_LED, FbdFeedbackBase); + +G_END_DECLS diff --git a/src/fbd-feedback-manager.c b/src/fbd-feedback-manager.c index 8f052e0..063dc60 100644 --- a/src/fbd-feedback-manager.c +++ b/src/fbd-feedback-manager.c @@ -9,6 +9,7 @@ #include "lfb-names.h" #include "fbd.h" #include "fbd-dev-vibra.h" +#include "fbd-dev-leds.h" #include "fbd-event.h" #include "fbd-feedback-vibra.h" #include "fbd-feedback-manager.h" @@ -48,6 +49,7 @@ typedef struct _FbdFeedbackManager { GUdevClient *client; FbdDevVibra *vibra; FbdDevSound *sound; + FbdDevLeds *leds; } FbdFeedbackManager; static void fbd_feedback_manager_feedback_iface_init (LfbGdbusFeedbackIface *iface); @@ -141,6 +143,12 @@ init_devices (FbdFeedbackManager *self) if (!self->vibra) g_debug ("No vibra capable device found"); + self->leds = fbd_dev_leds_new (&err); + if (!self->leds) { + g_debug ("Failed to init leds device: %s", err->message); + g_clear_error (&err); + } + self->sound = fbd_dev_sound_new (&err); if (!self->sound) { g_warning ("Failed to init sound device: %s", err->message); @@ -409,6 +417,14 @@ fbd_feedback_manager_get_dev_sound (FbdFeedbackManager *self) return self->sound; } +FbdDevLeds * +fbd_feedback_manager_get_dev_leds (FbdFeedbackManager *self) +{ + g_return_val_if_fail (FBD_IS_FEEDBACK_MANAGER (self), NULL); + + return self->leds; +} + gboolean fbd_feedback_manager_set_profile (FbdFeedbackManager *self, const gchar *profile) { diff --git a/src/fbd-feedback-manager.h b/src/fbd-feedback-manager.h index 964dcc5..04c829c 100644 --- a/src/fbd-feedback-manager.h +++ b/src/fbd-feedback-manager.h @@ -6,7 +6,9 @@ #pragma once #include "fbd-dev-vibra.h" +#include "fbd-dev-leds.h" #include "fbd-dev-sound.h" + #include "lfb-gdbus.h" #include @@ -19,6 +21,7 @@ G_DECLARE_FINAL_TYPE (FbdFeedbackManager, fbd_feedback_manager, FBD, FEEDBACK_MA FbdFeedbackManager *fbd_feedback_manager_get_default (void); FbdDevVibra *fbd_feedback_manager_get_dev_vibra (FbdFeedbackManager *self); FbdDevSound *fbd_feedback_manager_get_dev_sound (FbdFeedbackManager *self); +FbdDevLeds *fbd_feedback_manager_get_dev_leds (FbdFeedbackManager *self); gboolean fbd_feedback_manager_set_profile (FbdFeedbackManager *self, const gchar *profile); G_END_DECLS diff --git a/src/fbd-feedback-profile.c b/src/fbd-feedback-profile.c index dbd1689..1ad4f34 100644 --- a/src/fbd-feedback-profile.c +++ b/src/fbd-feedback-profile.c @@ -9,6 +9,7 @@ #include "fbd-feedback-dummy.h" #include "fbd-feedback-profile.h" #include "fbd-feedback-sound.h" +#include "fbd-feedback-led.h" #include "fbd-feedback-vibra-periodic.h" #include "fbd-feedback-vibra-rumble.h" @@ -83,6 +84,7 @@ feedback_get_type (JsonNode *feedback_node) /* Ensure all feedback types so the json parsing can use them */ g_type_ensure (FBD_TYPE_FEEDBACK_DUMMY); + g_type_ensure (FBD_TYPE_FEEDBACK_LED); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_PERIODIC); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_RUMBLE); g_type_ensure (FBD_TYPE_FEEDBACK_SOUND); diff --git a/src/fbd-udev.c b/src/fbd-udev.c new file mode 100644 index 0000000..0f057de --- /dev/null +++ b/src/fbd-udev.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2020 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + * Author: Guido Günther + * + */ + +#define G_LOG_DOMAIN "fbd-udev" + +#include "fbd-udev.h" + +#include + +#include +#include +#include +#include + +gboolean +fbd_udev_set_sysfs_path_attr_as_string (GUdevDevice *dev, const gchar *attr, + const gchar *s, GError **err) +{ + gint fd; + int len; + g_autofree gchar *path = g_strjoin ("/", g_udev_device_get_sysfs_path (dev), + attr, NULL); + + fd = open (path, O_WRONLY|O_TRUNC, 0666); + if (fd < 0) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to open %s: %s", + path, strerror (errno)); + return FALSE; + } + + len = strlen (s); + if (write (fd, s, len) < 0) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to write %s to %s: %s", + s, path, strerror (errno)); + close (fd); + return FALSE; + } + + if (close (fd) < 0) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to close %s: %s", + path, strerror (errno)); + return FALSE; + } + + return TRUE; +} + +gboolean +fbd_udev_set_sysfs_path_attr_as_int (GUdevDevice *dev, const gchar *attr, + gint val, GError **err) +{ + gint fd; + int len; + g_autofree gchar *s = NULL; + + g_autofree gchar *path = g_strjoin ("/", g_udev_device_get_sysfs_path (dev), + attr, NULL); + + fd = open (path, O_WRONLY|O_TRUNC, 0666); + if (fd < 0) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to open %s: %s", + path, strerror (errno)); + return FALSE; + } + + s = g_strdup_printf ("%d", val); + len = strlen (s); + if (write (fd, s, len) < len) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to write %s: %s", + path, strerror (errno)); + close (fd); + return FALSE; + } + + if (close (fd) < 0) { + g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to close %s: %s", + path, strerror (errno)); + return FALSE; + } + + return TRUE; +} diff --git a/src/fbd-udev.h b/src/fbd-udev.h new file mode 100644 index 0000000..59365d0 --- /dev/null +++ b/src/fbd-udev.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 Purism SPC + * + * SPDX-License-Identifier: GPL-3.0+ + */ +#pragma once + +#include +#include + + +G_BEGIN_DECLS + +gboolean fbd_udev_set_sysfs_path_attr_as_string (GUdevDevice *dev, const gchar *attr, + const gchar *s, GError **err); +gboolean fbd_udev_set_sysfs_path_attr_as_int (GUdevDevice *dev, const gchar *attr, + gint val, GError **err); + +G_END_DECLS diff --git a/src/fbd.h b/src/fbd.h index edeb1fe..c5a1e12 100644 --- a/src/fbd.h +++ b/src/fbd.h @@ -4,6 +4,13 @@ G_BEGIN_DECLS +/* + * The udev attribute and values devices must have to be handled by + * fbd feedbackd + */ +#define FEEDBACKD_UDEV_ATTR "FEEDBACKD_TYPE" +#define FEEDBACKD_UDEV_VAL_LED "led" + typedef enum { FBD_ERROR_FAILED = 0, } FbdError; diff --git a/src/meson.build b/src/meson.build index 128d873..918c73f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,6 +3,7 @@ if get_option('daemon') fbd_enum_headers = files([ 'fbd-event.h', + 'fbd-feedback-led.h', 'fbd-feedback-vibra.h', ]) fbd_enum_sources = gnome.mkenums_simple('fbd-enums', @@ -14,9 +15,11 @@ sources = [ 'fbd.c', 'fbd-dev-vibra.c', 'fbd-dev-sound.c', + 'fbd-dev-leds.c', 'fbd-event.c', 'fbd-feedback-base.c', 'fbd-feedback-dummy.c', + 'fbd-feedback-led.c', 'fbd-feedback-manager.c', 'fbd-feedback-profile.c', 'fbd-feedback-sound.c', @@ -24,6 +27,7 @@ sources = [ 'fbd-feedback-vibra.c', 'fbd-feedback-vibra-periodic.c', 'fbd-feedback-vibra-rumble.c', + 'fbd-udev.c', ] fbd_deps = [