Merge branch 'qcom-lpg-hwpattern' into 'main'

fb-dev-leds: support hw_pattern for Qualcomm LPG

See merge request Librem5/feedbackd!100
This commit is contained in:
Guido Günther
2024-06-09 09:45:20 +00:00
15 changed files with 682 additions and 72 deletions
+25 -16
View File
@@ -6,7 +6,7 @@
* See Documentation/ABI/testing/sysfs-class-led-trigger-pattern * See Documentation/ABI/testing/sysfs-class-led-trigger-pattern
*/ */
#define G_LOG_DOMAIN "fbd-dev-led" #define G_LOG_DOMAIN "fbd-dev-led-multicolor"
#include "fbd-dev-led-priv.h" #include "fbd-dev-led-priv.h"
#include "fbd-dev-led-multicolor.h" #include "fbd-dev-led-multicolor.h"
@@ -37,7 +37,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (FbdDevLedMulticolor, fbd_dev_led_multicolor, FBD_TYP
static gboolean static gboolean
fbd_dev_led_probe_multicolor (FbdDevLed *led, GError **error) fbd_dev_led_multicolor_probe (FbdDevLed *led, GError **error)
{ {
FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led); FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led);
FbdDevLedMulticolorPrivate *priv = fbd_dev_led_multicolor_get_instance_private (self); FbdDevLedMulticolorPrivate *priv = fbd_dev_led_multicolor_get_instance_private (self);
@@ -53,7 +53,7 @@ fbd_dev_led_probe_multicolor (FbdDevLed *led, GError **error)
if (index == NULL) { if (index == NULL) {
g_set_error (error, g_set_error (error,
G_FILE_ERROR, G_FILE_ERROR_FAILED, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"%s is no multicololor LED", name); "%s is no multicolor LED", name);
return FALSE; return FALSE;
} }
@@ -65,7 +65,7 @@ fbd_dev_led_probe_multicolor (FbdDevLed *led, GError **error)
return FALSE; return FALSE;
} }
fbd_dev_led_set_max_brightness (led, max_brightness); fbd_dev_led_set_max_brightness (led, max_brightness);
fbd_dev_led_set_color (led, FBD_FEEDBACK_LED_COLOR_RGB); fbd_dev_led_set_supported_color (led, FBD_FEEDBACK_LED_COLOR_RGB);
for (int i = 0; index[i] != NULL; i++) { for (int i = 0; index[i] != NULL; i++) {
g_debug ("Index: %s", index[i]); g_debug ("Index: %s", index[i]);
@@ -90,10 +90,8 @@ fbd_dev_led_probe_multicolor (FbdDevLed *led, GError **error)
static gboolean static gboolean
fbd_dev_led_start_periodic_multicolor (FbdDevLed *led, fbd_dev_led_multicolor_set_color (FbdDevLed *led,
FbdFeedbackLedColor color, FbdFeedbackLedColor color)
guint max_brightness_percentage,
guint freq)
{ {
FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led); FbdDevLedMulticolor *self = FBD_DEV_LED_MULTICOLOR (led);
FbdDevLedMulticolorPrivate *priv = fbd_dev_led_multicolor_get_instance_private (self); FbdDevLedMulticolorPrivate *priv = fbd_dev_led_multicolor_get_instance_private (self);
@@ -142,16 +140,27 @@ fbd_dev_led_start_periodic_multicolor (FbdDevLed *led,
return FALSE; return FALSE;
} }
/* Chain up to parent class to set the pattern */ return TRUE;
return FBD_DEV_LED_CLASS (fbd_dev_led_multicolor_parent_class)->start_periodic (
led, color, max_brightness_percentage, freq);
} }
static gboolean static gboolean
fbd_dev_led_has_color_multicolor (FbdDevLed *led, FbdFeedbackLedColor color) fbd_dev_led_multicolor_supports_color (FbdDevLed *led,
FbdFeedbackLedColor color)
{ {
return color == FBD_FEEDBACK_LED_COLOR_RGB; switch(color) {
case FBD_FEEDBACK_LED_COLOR_WHITE:
return TRUE;
case FBD_FEEDBACK_LED_COLOR_RED:
return TRUE;
case FBD_FEEDBACK_LED_COLOR_GREEN:
return TRUE;
case FBD_FEEDBACK_LED_COLOR_BLUE:
return TRUE;
default:
g_warning ("Color unsupported: %d", color);
return FALSE;
}
} }
@@ -160,9 +169,9 @@ fbd_dev_led_multicolor_class_init (FbdDevLedMulticolorClass *klass)
{ {
FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_CLASS (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->probe = fbd_dev_led_multicolor_probe;
fbd_dev_led_class->start_periodic = fbd_dev_led_start_periodic_multicolor; fbd_dev_led_class->set_color = fbd_dev_led_multicolor_set_color;
fbd_dev_led_class->has_color = fbd_dev_led_has_color_multicolor; fbd_dev_led_class->supports_color = fbd_dev_led_multicolor_supports_color;
} }
+1 -1
View File
@@ -17,6 +17,6 @@ G_BEGIN_DECLS
GUdevDevice *fbd_dev_led_get_device (FbdDevLed *led); 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_max_brightness (FbdDevLed *led, guint max_brightness);
void fbd_dev_led_set_color (FbdDevLed *led, FbdFeedbackLedColor color); void fbd_dev_led_set_supported_color (FbdDevLed *led, FbdFeedbackLedColor color);
G_END_DECLS G_END_DECLS
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2023 Dylan Van Assche <me@dylanvanassche.be>
* SPDX-License-Identifier: GPL-3.0+
*/
#define G_LOG_DOMAIN "fbd-dev-led-qcom-multicolor"
#include "fbd-dev-led-priv.h"
#include "fbd-dev-led.h"
#include "fbd-dev-led-qcom.h"
#include "fbd-dev-led-qcom-priv.h"
#include "fbd-dev-led-qcom-multicolor.h"
#include "fbd-enums.h"
#include "fbd-udev.h"
#include <gio/gio.h>
#define LED_HW_PATTERN_ATTR "hw_pattern"
#define LED_REPEAT_ATTR "repeat"
typedef struct _FbdDevLedQcomMulticolor {
FbdDevLedMulticolor parent;
FbdDevLedQcom *qcom_led;
} FbdDevLedQcomMulticolor;
G_DEFINE_TYPE (FbdDevLedQcomMulticolor, fbd_dev_led_qcom_multicolor, FBD_TYPE_DEV_LED_MULTICOLOR)
static gboolean
fbd_dev_led_qcom_multicolor_probe (FbdDevLed *led, GError **error)
{
FbdDevLedQcomMulticolor *self = FBD_DEV_LED_QCOM_MULTICOLOR (led);
GUdevDevice *dev = fbd_dev_led_get_device (FBD_DEV_LED (led));
self->qcom_led = FBD_DEV_LED_QCOM (fbd_dev_led_qcom_new (dev, error));
if (!self->qcom_led)
return FALSE;
return FBD_DEV_LED_CLASS (fbd_dev_led_qcom_multicolor_parent_class)->probe(led, error);
}
static gboolean
fbd_dev_led_qcom_multicolor_start_periodic (FbdDevLed *led,
guint max_brightness_percentage,
guint freq)
{
FbdDevLedQcomMulticolor *self = FBD_DEV_LED_QCOM_MULTICOLOR (led);
return fbd_dev_led_start_periodic (FBD_DEV_LED (self->qcom_led), max_brightness_percentage, freq);
}
static void
fbd_dev_led_qcom_multicolor_class_init (FbdDevLedQcomMulticolorClass *klass)
{
FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_CLASS (klass);
fbd_dev_led_class->probe = fbd_dev_led_qcom_multicolor_probe;
fbd_dev_led_class->start_periodic = fbd_dev_led_qcom_multicolor_start_periodic;
}
static void
fbd_dev_led_qcom_multicolor_init (FbdDevLedQcomMulticolor *self)
{
}
FbdDevLed *
fbd_dev_led_qcom_multicolor_new (GUdevDevice *dev, GError **err)
{
return g_initable_new (FBD_TYPE_DEV_LED_QCOM_MULTICOLOR, NULL, err, "dev", dev, NULL);
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright (C) 2023 Dylan Van Assche <me@dylanvanassche.be>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#pragma once
#include "fbd-dev-led-multicolor.h"
G_BEGIN_DECLS
#define FBD_TYPE_DEV_LED_QCOM_MULTICOLOR fbd_dev_led_qcom_multicolor_get_type()
G_DECLARE_FINAL_TYPE (FbdDevLedQcomMulticolor, fbd_dev_led_qcom_multicolor, FBD, DEV_LED_QCOM_MULTICOLOR, FbdDevLedMulticolor)
FbdDevLed *fbd_dev_led_qcom_multicolor_new (GUdevDevice *dev, GError **err);
G_END_DECLS
+16
View File
@@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Dylan Van Assche <me@dylanvanassche.be>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#pragma once
#include "fbd-dev-led-qcom.h"
#include <glib-object.h>
G_BEGIN_DECLS
gboolean fbd_dev_led_probe_qcom (FbdDevLed *led, GError **error);
G_END_DECLS
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2023 Dylan Van Assche <me@dylanvanassche.be>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#define G_LOG_DOMAIN "fbd-dev-led-qcom"
#include "fbd-dev-led-priv.h"
#include "fbd-dev-led-qcom.h"
#include "fbd-dev-led-qcom-priv.h"
#include "fbd-enums.h"
#include "fbd-udev.h"
#include <gio/gio.h>
#define LED_HW_PATTERN_ATTR "hw_pattern"
#define LED_REPEAT_ATTR "repeat"
#define LED_REPEAT_INFINITY "-1"
#define QCOM_LPG_MAX_PAUSE_MS 511
typedef struct _FbdDevLedQcom {
FbdDevLed parent;
} FbdDevLedQcom;
G_DEFINE_TYPE (FbdDevLedQcom, fbd_dev_led_qcom, FBD_TYPE_DEV_LED)
static gboolean
fbd_dev_led_qcom_probe (FbdDevLed *led, GError **error)
{
GUdevDevice *dev = fbd_dev_led_get_device (led);
const gchar *name;
const gchar * const *index;
name = g_udev_device_get_name (dev);
index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_HW_PATTERN_ATTR);
if (index == NULL) {
g_set_error (error,
G_FILE_ERROR, G_FILE_ERROR_FAILED,
"%s is no QCOM LED with HW support", name);
return FALSE;
}
return FBD_DEV_LED_CLASS (fbd_dev_led_qcom_parent_class)->probe(led, error);
}
static gboolean
fbd_dev_led_qcom_start_periodic (FbdDevLed *led,
guint max_brightness_percentage,
guint freq)
{
GUdevDevice *dev = fbd_dev_led_get_device (led);
gdouble max;
gdouble t;
g_autofree gchar *str = NULL;
g_autoptr (GError) err = NULL;
gboolean success;
g_return_val_if_fail (max_brightness_percentage <= 100.0, FALSE);
max = fbd_dev_led_get_max_brightness (led) * (max_brightness_percentage / 100.0);
g_debug ("Using hw_pattern interface for QCOM LPG LED");
/* QCOM LPG LEDs can only pause up to 511ms */
/* ms mHz T/2 */
t = 1000.0 * 1000.0 / freq / 2.0;
if (t > QCOM_LPG_MAX_PAUSE_MS)
t = QCOM_LPG_MAX_PAUSE_MS;
str = g_strdup_printf ("0 %d 0 0 %d %d %d 0\n", (gint)t, (gint)max, (gint)t, (gint)max);
success = fbd_udev_set_sysfs_path_attr_as_string (dev, LED_REPEAT_ATTR, LED_REPEAT_INFINITY, &err);
if (!success) {
g_warning ("Failed to set LED repeat: %s", err->message);
goto failure;
}
success = fbd_udev_set_sysfs_path_attr_as_string (dev, LED_HW_PATTERN_ATTR, str, &err);
if (!success) {
g_warning ("Failed to set LED hw_pattern: %s", err->message);
goto failure;
}
g_debug ("Freq %d mHz, Brightness: %d%%, Blink pattern: %s, HW: yes", freq, max_brightness_percentage, str);
return TRUE;
failure:
g_warning("Falling back to software pattern");
return FBD_DEV_LED_CLASS (fbd_dev_led_qcom_parent_class)->start_periodic (
led, max_brightness_percentage, freq);
}
static void
fbd_dev_led_qcom_class_init (FbdDevLedQcomClass *klass)
{
FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_CLASS (klass);
fbd_dev_led_class->probe = fbd_dev_led_qcom_probe;
fbd_dev_led_class->start_periodic = fbd_dev_led_qcom_start_periodic;
}
static void
fbd_dev_led_qcom_init (FbdDevLedQcom *self)
{
}
FbdDevLed *
fbd_dev_led_qcom_new (GUdevDevice *dev, GError **err)
{
return g_initable_new (FBD_TYPE_DEV_LED_QCOM, NULL, err, "dev", dev, NULL);
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright (C) 2023 Dylan Van Assche <me@dylanvanassche.be>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#pragma once
#include "fbd-dev-led.h"
G_BEGIN_DECLS
#define FBD_TYPE_DEV_LED_QCOM fbd_dev_led_qcom_get_type()
G_DECLARE_FINAL_TYPE (FbdDevLedQcom, fbd_dev_led_qcom, FBD, DEV_LED_QCOM, FbdDevLed)
FbdDevLed *fbd_dev_led_qcom_new (GUdevDevice *dev, GError **err);
G_END_DECLS
+46 -29
View File
@@ -16,11 +16,6 @@
#include <gio/gio.h> #include <gio/gio.h>
#define LED_BRIGHTNESS_ATTR "brightness" #define LED_BRIGHTNESS_ATTR "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"
#define LED_MULTI_INTENSITY_ATTR "multi_intensity"
#define LED_PATTERN_ATTR "pattern" #define LED_PATTERN_ATTR "pattern"
enum { enum {
@@ -63,7 +58,7 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error)
/* We don't know anything about diffusors that can combine different /* We don't know anything about diffusors that can combine different
color LEDSs so go with fixed colors until the kernel gives us color LEDSs so go with fixed colors until the kernel gives us
enough information */ enough information */
for (int i = 0; i < FBD_FEEDBACK_LED_COLOR_RGB; i++) { for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) {
g_autofree char *color = NULL; g_autofree char *color = NULL;
g_autofree char *enum_name = NULL; g_autofree char *enum_name = NULL;
gchar *c; gchar *c;
@@ -90,7 +85,7 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error)
if (!success) { if (!success) {
g_set_error (error, g_set_error (error,
G_FILE_ERROR, G_FILE_ERROR_FAILED, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"%s not usable as RBG LED", name); "%s not usable as RGB LED", name);
} }
return success; return success;
@@ -98,10 +93,31 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error)
static gboolean static gboolean
fbd_dev_led_start_periodic_default (FbdDevLed *led, fbd_dev_led_set_color_default (FbdDevLed *led,
FbdFeedbackLedColor color, FbdFeedbackLedColor color)
guint max_brightness_percentage, {
guint freq) /* Ignore setting color as we have a single color only */
return TRUE;
}
static gboolean
fbd_dev_led_supports_color_default (FbdDevLed *led,
FbdFeedbackLedColor 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 == color;
}
static gboolean
fbd_dev_led_start_periodic_default (FbdDevLed *led,
guint max_brightness_percentage,
guint freq)
{ {
FbdDevLedPrivate *priv; FbdDevLedPrivate *priv;
g_autoptr (GError) err = NULL; g_autoptr (GError) err = NULL;
@@ -111,6 +127,7 @@ fbd_dev_led_start_periodic_default (FbdDevLed *led,
gdouble t; gdouble t;
g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE);
g_return_val_if_fail (max_brightness_percentage <= 100, FALSE);
priv = fbd_dev_led_get_instance_private (led); priv = fbd_dev_led_get_instance_private (led);
max = priv->max_brightness * (max_brightness_percentage / 100.0); max = priv->max_brightness * (max_brightness_percentage / 100.0);
@@ -127,18 +144,6 @@ fbd_dev_led_start_periodic_default (FbdDevLed *led,
} }
static gboolean
fbd_dev_led_has_color_default (FbdDevLed *led, FbdFeedbackLedColor 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 == color;
}
static void static void
fbd_dev_led_set_property (GObject *object, fbd_dev_led_set_property (GObject *object,
guint property_id, guint property_id,
@@ -221,7 +226,8 @@ fbd_dev_led_class_init (FbdDevLedClass *klass)
fbd_dev_led_class->probe = fbd_dev_led_probe_default; 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->start_periodic = fbd_dev_led_start_periodic_default;
fbd_dev_led_class->has_color = fbd_dev_led_has_color_default; fbd_dev_led_class->set_color = fbd_dev_led_set_color_default;
fbd_dev_led_class->supports_color = fbd_dev_led_supports_color_default;
props[PROP_DEV] = props[PROP_DEV] =
g_param_spec_object ("dev", "", "", g_param_spec_object ("dev", "", "",
@@ -265,7 +271,6 @@ fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness)
gboolean gboolean
fbd_dev_led_start_periodic (FbdDevLed *led, fbd_dev_led_start_periodic (FbdDevLed *led,
FbdFeedbackLedColor color,
guint max_brightness_percentage, guint max_brightness_percentage,
guint freq) guint freq)
{ {
@@ -273,18 +278,30 @@ fbd_dev_led_start_periodic (FbdDevLed *led,
g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE);
return fbd_dev_led_class->start_periodic (led, color, max_brightness_percentage, freq); return fbd_dev_led_class->start_periodic (led, max_brightness_percentage, freq);
} }
gboolean gboolean
fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color) fbd_dev_led_set_color (FbdDevLed *led,
FbdFeedbackLedColor color)
{ {
FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_GET_CLASS (led); FbdDevLedClass *fbd_dev_led_class = FBD_DEV_LED_GET_CLASS (led);
g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE); g_return_val_if_fail (FBD_IS_DEV_LED (led), FALSE);
return fbd_dev_led_class->has_color (led, color); return fbd_dev_led_class->set_color (led, color);
}
gboolean
fbd_dev_led_supports_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->supports_color (led, color);
} }
@@ -314,7 +331,7 @@ fbd_dev_led_get_device (FbdDevLed *led)
void void
fbd_dev_led_set_color (FbdDevLed *led, FbdFeedbackLedColor color) fbd_dev_led_set_supported_color (FbdDevLed *led, FbdFeedbackLedColor color)
{ {
FbdDevLedPrivate *priv; FbdDevLedPrivate *priv;
+7 -6
View File
@@ -20,22 +20,23 @@ G_DECLARE_DERIVABLE_TYPE (FbdDevLed, fbd_dev_led, FBD, DEV_LED, GObject)
FbdDevLed *fbd_dev_led_new (GUdevDevice *dev, GError **err); FbdDevLed *fbd_dev_led_new (GUdevDevice *dev, GError **err);
gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness); gboolean fbd_dev_led_set_brightness (FbdDevLed *led, guint brightness);
guint fbd_dev_led_get_max_brightness (FbdDevLed *led); guint fbd_dev_led_get_max_brightness (FbdDevLed *led);
gboolean fbd_dev_led_set_color (FbdDevLed *led, FbdFeedbackLedColor color);
gboolean fbd_dev_led_start_periodic (FbdDevLed *led, gboolean fbd_dev_led_start_periodic (FbdDevLed *led,
FbdFeedbackLedColor color,
guint max_brightness_percentage, guint max_brightness_percentage,
guint freq); guint freq);
gboolean fbd_dev_led_has_color (FbdDevLed *led, FbdFeedbackLedColor color); gboolean fbd_dev_led_supports_color (FbdDevLed *led, FbdFeedbackLedColor color);
struct _FbdDevLedClass { struct _FbdDevLedClass {
GObjectClass parent_class; GObjectClass parent_class;
gboolean (*probe) (FbdDevLed *led, GError **error); gboolean (*probe) (FbdDevLed *led, GError **error);
gboolean (*start_periodic) (FbdDevLed *led, gboolean (*start_periodic) (FbdDevLed *led,
FbdFeedbackLedColor color,
guint max_brightness_percentage, guint max_brightness_percentage,
guint freq); guint freq);
gboolean (*has_color) (FbdDevLed *led, gboolean (*set_color) (FbdDevLed *led,
FbdFeedbackLedColor color); FbdFeedbackLedColor color);
gboolean (*supports_color) (FbdDevLed *led,
FbdFeedbackLedColor color);
}; };
G_END_DECLS G_END_DECLS
+44 -10
View File
@@ -12,6 +12,8 @@
#include "fbd-enums.h" #include "fbd-enums.h"
#include "fbd-dev-led.h" #include "fbd-dev-led.h"
#include "fbd-dev-led-multicolor.h" #include "fbd-dev-led-multicolor.h"
#include "fbd-dev-led-qcom.h"
#include "fbd-dev-led-qcom-multicolor.h"
#include "fbd-dev-leds.h" #include "fbd-dev-leds.h"
#include "fbd-feedback-led.h" #include "fbd-feedback-led.h"
#include "fbd-udev.h" #include "fbd-udev.h"
@@ -47,7 +49,7 @@ find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color)
for (GSList *l = self->leds; l != NULL; l = l->next) { for (GSList *l = self->leds; l != NULL; l = l->next) {
FbdDevLed *led = l->data; FbdDevLed *led = l->data;
if (fbd_dev_led_has_color (led, color)) if (fbd_dev_led_supports_color (led, color))
return led; return led;
} }
@@ -55,6 +57,43 @@ find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color)
return self->leds->data; return self->leds->data;
} }
static FbdDevLed*
probe_led (GUdevDevice *dev, GError **error) {
FbdDevLed *led = NULL;
led = fbd_dev_led_qcom_multicolor_new (dev, error);
if (led != NULL) {
g_debug ("Discovered QCOM multicolor LED");
return led;
}
g_clear_error (error);
led = fbd_dev_led_qcom_new (dev, error);
if (led != NULL) {
g_debug ("Discovered QCOM single color LED");
return led;
}
g_clear_error (error);
led = fbd_dev_led_multicolor_new (dev, error);
if (led != NULL) {
g_debug ("Discovered multicolor LED");
return led;
}
g_clear_error (error);
led = fbd_dev_led_new (dev, error);
if (led != NULL) {
g_debug ("Discovered single color LED");
return led;
}
g_debug ("Unable to determine LED driver");
return NULL;
}
static gboolean static gboolean
initable_init (GInitable *initable, initable_init (GInitable *initable,
GCancellable *cancellable, GCancellable *cancellable,
@@ -79,14 +118,7 @@ initable_init (GInitable *initable,
continue; continue;
} }
/* Try multicolor first, fall back to single color */ led = probe_led (dev, &err);
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) { if (led) {
self->leds = g_slist_append (self->leds, led); self->leds = g_slist_append (self->leds, led);
@@ -165,7 +197,9 @@ fbd_dev_leds_start_periodic (FbdDevLeds *self, FbdFeedbackLedColor color,
led = find_led_by_color (self, color); led = find_led_by_color (self, color);
g_return_val_if_fail (led, FALSE); g_return_val_if_fail (led, FALSE);
return fbd_dev_led_start_periodic (led, color, max_brightness_percentage, freq); fbd_dev_led_set_color (led, color);
return fbd_dev_led_start_periodic (led, max_brightness_percentage, freq);
} }
gboolean gboolean
+10 -6
View File
@@ -16,12 +16,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#define LED_BRIGHTNESS_ATTR "brightness" #define LED_BRIGHTNESS_ATTR "brightness"
#define LED_MULTI_INTENSITY_ATTR "multi_intensity" #define LED_MULTI_INTENSITY_ATTR "multi_intensity"
#define LED_PATTERN_ATTR "pattern" #define LED_PATTERN_ATTR "pattern"
#define LED_REPEAT_ATTR "repeat" #define LED_REPEAT_ATTR "repeat"
#define LED_TRIGGER_ATTR "trigger" #define LED_TRIGGER_ATTR "trigger"
#define LED_TRIGGER_PATTERN "pattern" #define LED_TRIGGER_PATTERN "pattern"
#define LED_TRIGGER_HW_PATTERN "hw_pattern"
enum { enum {
FBD_LEDCTRL_ERR_CMDLINE = 1, FBD_LEDCTRL_ERR_CMDLINE = 1,
@@ -127,7 +128,7 @@ set_perms (const char *sysfs_path, const char *trigger, const char *gname)
if (!set_sysfs_attr_perm (sysfs_path, LED_BRIGHTNESS_ATTR, group->gr_gid)) if (!set_sysfs_attr_perm (sysfs_path, LED_BRIGHTNESS_ATTR, group->gr_gid))
return FALSE; return FALSE;
// Attribute is optional /* Attribute is optional */
set_sysfs_attr_perm (sysfs_path, LED_MULTI_INTENSITY_ATTR, group->gr_gid); set_sysfs_attr_perm (sysfs_path, LED_MULTI_INTENSITY_ATTR, group->gr_gid);
if (!g_strcmp0 (trigger, LED_TRIGGER_PATTERN)) { if (!g_strcmp0 (trigger, LED_TRIGGER_PATTERN)) {
@@ -135,6 +136,9 @@ set_perms (const char *sysfs_path, const char *trigger, const char *gname)
success = FALSE; success = FALSE;
if (!set_sysfs_attr_perm (sysfs_path, LED_REPEAT_ATTR, group->gr_gid)) if (!set_sysfs_attr_perm (sysfs_path, LED_REPEAT_ATTR, group->gr_gid))
success = FALSE; success = FALSE;
/* Attribute is optional */
set_sysfs_attr_perm (sysfs_path, LED_TRIGGER_HW_PATTERN, group->gr_gid);
} }
/* specific setup for other triggers goes here */ /* specific setup for other triggers goes here */
+2
View File
@@ -17,6 +17,8 @@ sources = [
'fbd-dev-sound.c', 'fbd-dev-sound.c',
'fbd-dev-led.c', 'fbd-dev-led.c',
'fbd-dev-led-multicolor.c', 'fbd-dev-led-multicolor.c',
'fbd-dev-led-qcom.c',
'fbd-dev-led-qcom-multicolor.c',
'fbd-dev-leds.c', 'fbd-dev-leds.c',
'fbd-event.c', 'fbd-event.c',
'fbd-feedback-base.c', 'fbd-feedback-base.c',
@@ -0,0 +1,118 @@
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03/c440000.spmi:pmic@3:pwm/leds/rgb:status
E: FEEDBACKD_TYPE=led
E: ID_FOR_SEAT=leds-platform-c440000_spmi-platform-c440000_spmi_pmic_3_pwm
E: ID_PATH=platform-c440000.spmi-platform-c440000.spmi:pmic@3:pwm
E: ID_PATH_TAG=platform-c440000_spmi-platform-c440000_spmi_pmic_3_pwm
E: OF_COMPATIBLE_N=0
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3/pwm/multi-led
E: OF_NAME=multi-led
E: SUBSYSTEM=leds
E: TAGS=:seat:
A: brightness=0\n
L: device=../../../c440000.spmi:pmic@3:pwm
A: hw_pattern=
A: max_brightness=511\n
A: multi_index=blue green red\n
A: multi_intensity=0 0 0\n
A: pattern=
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: repeat=-1\n
A: trigger=none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot heartbeat backlight cpu cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 activity default-on panic [pattern] mmc0 rfkill-any rfkill-none bluetooth-power hci0-power rfkill0 pmi8998-charger-online qcom-battery-charging-or-full qcom-battery-charging qcom-battery-full qcom-battery-charging-blink-full-solid\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03/c440000.spmi:pmic@3:pwm
E: DRIVER=qcom-spmi-lpg
E: MODALIAS=of:NpwmT(null)Cqcom,pmi8998-lpg
E: OF_COMPATIBLE_0=qcom,pmi8998-lpg
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3/pwm
E: OF_NAME=pwm
E: SUBSYSTEM=platform
L: driver=../../../../../../../bus/platform/drivers/qcom-spmi-lpg
A: driver_override=(null)\n
A: modalias=of:NpwmT(null)Cqcom,pmi8998-lpg\n
L: of_node=../../../../../../../firmware/devicetree/base/soc@0/spmi@c440000/pmic@3/pwm
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03
E: DRIVER=pmic-spmi
E: MODALIAS=of:NpmicT(null)Cqcom,pmi8998Cqcom,spmi-pmic
E: OF_COMPATIBLE_0=qcom,pmi8998
E: OF_COMPATIBLE_1=qcom,spmi-pmic
E: OF_COMPATIBLE_N=2
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3
E: OF_NAME=pmic
E: SUBSYSTEM=spmi
L: driver=../../../../../../bus/spmi/drivers/pmic-spmi
L: of_node=../../../../../../firmware/devicetree/base/soc@0/spmi@c440000/pmic@3
A: power/control=auto\n
A: power/runtime_active_time=7149472\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0
E: MODALIAS=of:NspmiT(null)Cqcom,spmi-pmic-arb
E: OF_COMPATIBLE_0=qcom,spmi-pmic-arb
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000
E: OF_NAME=spmi
E: SUBSYSTEM=spmi
L: of_node=../../../../../firmware/devicetree/base/soc@0/spmi@c440000
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi
E: DRIVER=spmi_pmic_arb
E: MODALIAS=of:NspmiT(null)Cqcom,spmi-pmic-arb
E: OF_COMPATIBLE_0=qcom,spmi-pmic-arb
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000
E: OF_NAME=spmi
E: SUBSYSTEM=platform
L: consumer:platform:c440000.spmi:pmic@0:adc@3100=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:adc@3100
L: consumer:platform:c440000.spmi:pmic@0:pon@800:pwrkey=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:pon@800:pwrkey
L: consumer:platform:c440000.spmi:pmic@0:pon@800:resin=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:pon@800:resin
L: consumer:platform:c440000.spmi:pmic@0:rtc@6000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:rtc@6000
L: consumer:platform:c440000.spmi:pmic@0:temp-alarm@2400=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:temp-alarm@2400
L: consumer:platform:c440000.spmi:pmic@2:charger@1000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@2:charger@1000
L: consumer:platform:c440000.spmi:pmic@2:fuel-gauge@4000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@2:fuel-gauge@4000
L: consumer:platform:c440000.spmi:pmic@3:haptics@c000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@3:haptics@c000
L: driver=../../../../bus/platform/drivers/spmi_pmic_arb
A: driver_override=(null)\n
A: modalias=of:NspmiT(null)Cqcom,spmi-pmic-arb\n
L: of_node=../../../../firmware/devicetree/base/soc@0/spmi@c440000
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0
E: DRIVER=simple-pm-bus
E: MODALIAS=of:NsocT(null)Csimple-bus
E: OF_COMPATIBLE_0=simple-bus
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0
E: OF_NAME=soc
E: SUBSYSTEM=platform
L: consumer:platform:17c90000.timer=../../virtual/devlink/platform:soc@0--platform:17c90000.timer
L: consumer:platform:894000.i2c=../../virtual/devlink/platform:soc@0--platform:894000.i2c
L: consumer:platform:898000.serial=../../virtual/devlink/platform:soc@0--platform:898000.serial
L: consumer:platform:a600000.usb=../../virtual/devlink/platform:soc@0--platform:a600000.usb
L: consumer:platform:a84000.serial=../../virtual/devlink/platform:soc@0--platform:a84000.serial
L: consumer:platform:a8c000.i2c=../../virtual/devlink/platform:soc@0--platform:a8c000.i2c
L: driver=../../../bus/platform/drivers/simple-pm-bus
A: driver_override=(null)\n
A: modalias=of:NsocT(null)Csimple-bus\n
L: of_node=../../../firmware/devicetree/base/soc@0
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
@@ -0,0 +1,118 @@
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03/c440000.spmi:pmic@3:pwm/leds/white:status
E: FEEDBACKD_TYPE=led
E: ID_FOR_SEAT=leds-platform-c440000_spmi-platform-c440000_spmi_pmic_3_pwm
E: ID_PATH=platform-c440000.spmi-platform-c440000.spmi:pmic@3:pwm
E: ID_PATH_TAG=platform-c440000_spmi-platform-c440000_spmi_pmic_3_pwm
E: OF_COMPATIBLE_N=0
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3/pwm/led@5
E: OF_NAME=led
E: SUBSYSTEM=leds
E: TAGS=:seat:
A: brightness=0\n
L: device=../../../c440000.spmi:pmic@3:pwm
A: hw_pattern=
A: max_brightness=511\n
A: pattern=
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: repeat=-1\n
A: trigger=none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot heartbeat backlight cpu cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 activity default-on panic [pattern] mmc0 rfkill-any rfkill-none bluetooth-power hci0-power rfkill0 pmi8998-charger-online qcom-battery-charging-or-full qcom-battery-charging qcom-battery-full qcom-battery-charging-blink-full-solid phy0rx phy0tx phy0assoc phy0radio rfkill1\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03/c440000.spmi:pmic@3:pwm
E: DRIVER=qcom-spmi-lpg
E: MODALIAS=of:NpwmT(null)Cqcom,pmi8998-lpg
E: OF_COMPATIBLE_0=qcom,pmi8998-lpg
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3/pwm
E: OF_NAME=pwm
E: SUBSYSTEM=platform
L: driver=../../../../../../../bus/platform/drivers/qcom-spmi-lpg
A: driver_override=(null)\n
A: modalias=of:NpwmT(null)Cqcom,pmi8998-lpg\n
L: of_node=../../../../../../../firmware/devicetree/base/soc@0/spmi@c440000/pmic@3/pwm
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0/0-03
E: DRIVER=pmic-spmi
E: MODALIAS=of:NpmicT(null)Cqcom,pmi8998Cqcom,spmi-pmic
E: OF_COMPATIBLE_0=qcom,pmi8998
E: OF_COMPATIBLE_1=qcom,spmi-pmic
E: OF_COMPATIBLE_N=2
E: OF_FULLNAME=/soc@0/spmi@c440000/pmic@3
E: OF_NAME=pmic
E: SUBSYSTEM=spmi
L: driver=../../../../../../bus/spmi/drivers/pmic-spmi
L: of_node=../../../../../../firmware/devicetree/base/soc@0/spmi@c440000/pmic@3
A: power/control=auto\n
A: power/runtime_active_time=124723680\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi/spmi-0
E: MODALIAS=of:NspmiT(null)Cqcom,spmi-pmic-arb
E: OF_COMPATIBLE_0=qcom,spmi-pmic-arb
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000
E: OF_NAME=spmi
E: SUBSYSTEM=spmi
L: of_node=../../../../../firmware/devicetree/base/soc@0/spmi@c440000
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0/c440000.spmi
E: DRIVER=spmi_pmic_arb
E: MODALIAS=of:NspmiT(null)Cqcom,spmi-pmic-arb
E: OF_COMPATIBLE_0=qcom,spmi-pmic-arb
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0/spmi@c440000
E: OF_NAME=spmi
E: SUBSYSTEM=platform
L: consumer:platform:c440000.spmi:pmic@0:adc@3100=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:adc@3100
L: consumer:platform:c440000.spmi:pmic@0:pon@800:pwrkey=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:pon@800:pwrkey
L: consumer:platform:c440000.spmi:pmic@0:pon@800:resin=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:pon@800:resin
L: consumer:platform:c440000.spmi:pmic@0:rtc@6000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:rtc@6000
L: consumer:platform:c440000.spmi:pmic@0:temp-alarm@2400=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@0:temp-alarm@2400
L: consumer:platform:c440000.spmi:pmic@2:charger@1000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@2:charger@1000
L: consumer:platform:c440000.spmi:pmic@2:fuel-gauge@4000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@2:fuel-gauge@4000
L: consumer:platform:c440000.spmi:pmic@3:haptics@c000=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@3:haptics@c000
L: consumer:platform:c440000.spmi:pmic@3:leds@d800=../../../virtual/devlink/platform:c440000.spmi--platform:c440000.spmi:pmic@3:leds@d800
L: driver=../../../../bus/platform/drivers/spmi_pmic_arb
A: driver_override=(null)\n
A: modalias=of:NspmiT(null)Cqcom,spmi-pmic-arb\n
L: of_node=../../../../firmware/devicetree/base/soc@0/spmi@c440000
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
P: /devices/platform/soc@0
E: DRIVER=simple-pm-bus
E: MODALIAS=of:NsocT(null)Csimple-bus
E: OF_COMPATIBLE_0=simple-bus
E: OF_COMPATIBLE_N=1
E: OF_FULLNAME=/soc@0
E: OF_NAME=soc
E: SUBSYSTEM=platform
L: consumer:platform:17c90000.timer=../../virtual/devlink/platform:soc@0--platform:17c90000.timer
L: consumer:platform:894000.i2c=../../virtual/devlink/platform:soc@0--platform:894000.i2c
L: consumer:platform:898000.serial=../../virtual/devlink/platform:soc@0--platform:898000.serial
L: consumer:platform:a600000.usb=../../virtual/devlink/platform:soc@0--platform:a600000.usb
L: consumer:platform:a84000.serial=../../virtual/devlink/platform:soc@0--platform:a84000.serial
L: consumer:platform:a98000.i2c=../../virtual/devlink/platform:soc@0--platform:a98000.i2c
L: driver=../../../bus/platform/drivers/simple-pm-bus
A: driver_override=(null)\n
A: modalias=of:NsocT(null)Csimple-bus\n
L: of_node=../../../firmware/devicetree/base/soc@0
A: power/control=auto\n
A: power/runtime_active_time=0\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
+67 -4
View File
@@ -8,6 +8,8 @@
#include "fbd-feedback-led.h" #include "fbd-feedback-led.h"
#include "fbd-dev-led.h" #include "fbd-dev-led.h"
#include "fbd-dev-led-multicolor.h" #include "fbd-dev-led-multicolor.h"
#include "fbd-dev-led-qcom.h"
#include "fbd-dev-led-qcom-multicolor.h"
#include "testlib.h" #include "testlib.h"
@@ -33,8 +35,8 @@ test_fbd_dev_led_simple (FbdUmockdevFixture *fixture, gconstpointer unused)
led = fbd_dev_led_new (dev, &err); led = fbd_dev_led_new (dev, &err);
g_assert_no_error (err); g_assert_no_error (err);
g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 255); g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 255);
g_assert_true (fbd_dev_led_has_color (led, FBD_FEEDBACK_LED_COLOR_BLUE)); g_assert_true (fbd_dev_led_supports_color (led, FBD_FEEDBACK_LED_COLOR_BLUE));
g_assert_true (fbd_dev_led_start_periodic (led, FBD_FEEDBACK_LED_COLOR_BLUE, 50, 50)); g_assert_true (fbd_dev_led_start_periodic (led, 50, 50));
g_assert_finalize_object (led); g_assert_finalize_object (led);
} }
@@ -60,8 +62,63 @@ test_fbd_dev_led_multicolor (FbdUmockdevFixture *fixture, gconstpointer unused)
led = fbd_dev_led_multicolor_new (dev, &err); led = fbd_dev_led_multicolor_new (dev, &err);
g_assert_no_error (err); g_assert_no_error (err);
g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 248); g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 248);
g_assert_true (fbd_dev_led_has_color (led, FBD_FEEDBACK_LED_COLOR_RGB)); g_assert_true (fbd_dev_led_supports_color (led, FBD_FEEDBACK_LED_COLOR_BLUE));
g_assert_true (fbd_dev_led_start_periodic (led, FBD_FEEDBACK_LED_COLOR_BLUE, 50, 50)); g_assert_true (fbd_dev_led_start_periodic (led, 50, 50));
g_assert_finalize_object (led);
}
static void
test_fbd_dev_led_qcom_simple (FbdUmockdevFixture *fixture, gconstpointer unused)
{
GUdevClient *client;
g_autolist (GUdevDevice) leds = NULL;
FbdDevLed *led;
g_autoptr (GError) err = NULL;
GUdevDevice *dev;
client = g_udev_client_new ((const char *const []){ "leds", NULL});
leds = g_udev_client_query_by_subsystem (client, "leds");
/* There should be a single device only */
g_assert_cmpint (g_list_length (leds), ==, 1);
dev = G_UDEV_DEVICE (leds->data);
g_assert_cmpstr (g_udev_device_get_property (dev, "FEEDBACKD_TYPE"), ==, "led");
led = fbd_dev_led_qcom_new (dev, &err);
g_assert_no_error (err);
g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 511);
g_assert_true (fbd_dev_led_supports_color (led, FBD_FEEDBACK_LED_COLOR_WHITE));
g_assert_true (fbd_dev_led_start_periodic (led, 50, 50));
g_assert_finalize_object (led);
}
static void
test_fbd_dev_led_qcom_multicolor (FbdUmockdevFixture *fixture, gconstpointer unused)
{
GUdevClient *client;
g_autolist (GUdevDevice) leds = NULL;
FbdDevLed *led;
g_autoptr (GError) err = NULL;
GUdevDevice *dev;
client = g_udev_client_new ((const char *const []){ "leds", NULL});
leds = g_udev_client_query_by_subsystem (client, "leds");
/* There should be a single device only */
g_assert_cmpint (g_list_length (leds), ==, 1);
dev = G_UDEV_DEVICE (leds->data);
g_assert_cmpstr (g_udev_device_get_property (dev, "FEEDBACKD_TYPE"), ==, "led");
led = fbd_dev_led_qcom_multicolor_new (dev, &err);
g_assert_no_error (err);
g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 511);
g_assert_true (fbd_dev_led_supports_color (led, FBD_FEEDBACK_LED_COLOR_BLUE));
g_assert_true (fbd_dev_led_start_periodic (led, 50, 50));
g_assert_finalize_object (led); g_assert_finalize_object (led);
} }
@@ -78,6 +135,12 @@ main (gint argc, gchar *argv[])
FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/multicolor", FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/multicolor",
test_fbd_dev_led_multicolor, test_fbd_dev_led_multicolor,
"led-multicolor"); "led-multicolor");
FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/qcom/simple",
test_fbd_dev_led_qcom_simple,
"led-qcom-simple");
FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/qcom/multicolor",
test_fbd_dev_led_qcom_multicolor,
"led-qcom-multicolor");
return g_test_run(); return g_test_run();
} }