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.
This commit is contained in:
committed by
Sebastian Krzyszkowiak
parent
2f083ea5ae
commit
a5b4f99412
@@ -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
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*
|
||||
* 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 <gio/gio.h>
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "fbd-feedback-led.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
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
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 <glib-object.h>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "fbd-udev"
|
||||
|
||||
#include "fbd-udev.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
|
||||
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
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
Reference in New Issue
Block a user