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.
This commit is contained in:
committed by
Guido Gunther
parent
ca712e9a32
commit
995d21b587
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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-led"
|
||||
|
||||
#include "fbd-dev-led-priv.h"
|
||||
#include "fbd-dev-led-multicolor.h"
|
||||
#include "fbd-enums.h"
|
||||
#include "fbd-udev.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 <gudev/gudev.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
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
|
||||
+54
-66
@@ -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 <gio/gio.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"
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+10
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user