fbd-dev-leds: support for multicolor LEDs
Add support for multicolor LEDs as supported by the kernel. Used by Qualcomm devices such as SHIFT 6mq, OnePlus 6, etc. Documentation: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-class-led-multicolor Co-Developed-by: Dylan Van Assche <me@dylanvanassche.be>
This commit is contained in:
+72
-5
@@ -25,14 +25,22 @@
|
||||
* It currently only supports one pattern per led at a time.
|
||||
*/
|
||||
|
||||
#define LED_BRIGHTNESS_ATTR "brightness"
|
||||
#define LED_MAX_BRIGHTNESS_ATTR "max_brightness"
|
||||
#define LED_PATTERN_ATTR "pattern"
|
||||
#define LED_SUBSYSTEM "leds"
|
||||
#define LED_BRIGHTNESS_ATTR "brightness"
|
||||
#define LED_MAX_BRIGHTNESS_ATTR "max_brightness"
|
||||
#define LED_MULTI_INDEX_ATTR "multi_index"
|
||||
#define LED_MULTI_INTENSITY_ATTR "multi_intensity"
|
||||
#define LED_MULTI_INDEX_RED "red"
|
||||
#define LED_MULTI_INDEX_GREEN "green"
|
||||
#define LED_MULTI_INDEX_BLUE "blue"
|
||||
#define LED_PATTERN_ATTR "pattern"
|
||||
#define LED_SUBSYSTEM "leds"
|
||||
|
||||
typedef struct _FbdDevLed {
|
||||
GUdevDevice *dev;
|
||||
guint max_brightness;
|
||||
guint red_index;
|
||||
guint green_index;
|
||||
guint blue_index;
|
||||
/*
|
||||
* We just use the colors from the feedback until we
|
||||
* do rgb mixing, etc
|
||||
@@ -80,7 +88,7 @@ find_led_by_color (FbdDevLeds *self, FbdFeedbackLedColor color)
|
||||
|
||||
for (GSList *l = self->leds; l != NULL; l = l->next) {
|
||||
FbdDevLed *led = l->data;
|
||||
if (led->color == color)
|
||||
if (led->color == FBD_FEEDBACK_LED_COLOR_RGB || led->color == color)
|
||||
return led;
|
||||
}
|
||||
|
||||
@@ -119,6 +127,8 @@ initable_init (GInitable *initable,
|
||||
for (int i = 0; i <= FBD_FEEDBACK_LED_COLOR_LAST; i++) {
|
||||
g_autofree char *color = NULL;
|
||||
g_autofree char *enum_name = NULL;
|
||||
const gchar * const *index;
|
||||
guint counter = 0;
|
||||
gchar *c;
|
||||
|
||||
enum_name = g_enum_to_string (FBD_TYPE_FEEDBACK_LED_COLOR, i);
|
||||
@@ -127,6 +137,7 @@ initable_init (GInitable *initable,
|
||||
if (g_strstr_len (name, -1, color)) {
|
||||
g_autoptr (GError) err = NULL;
|
||||
guint brightness = g_udev_device_get_sysfs_attr_as_int (dev, LED_MAX_BRIGHTNESS_ATTR);
|
||||
index = g_udev_device_get_sysfs_attr_as_strv (dev, LED_MULTI_INDEX_ATTR);
|
||||
|
||||
if (!brightness)
|
||||
continue;
|
||||
@@ -135,6 +146,25 @@ initable_init (GInitable *initable,
|
||||
led->dev = g_object_ref (dev);
|
||||
led->color = i;
|
||||
led->max_brightness = brightness;
|
||||
|
||||
if (index) {
|
||||
for (int j = 0; j < g_strv_length ((gchar **) index); j++) {
|
||||
g_debug ("Index: %s", index[j]);
|
||||
if (g_strcmp0 (index[j], LED_MULTI_INDEX_RED) == 0) {
|
||||
led->red_index = counter;
|
||||
counter++;
|
||||
} else if (g_strcmp0 (index[j], LED_MULTI_INDEX_GREEN) == 0) {
|
||||
led->green_index = counter;
|
||||
counter++;
|
||||
} else if (g_strcmp0 (index[j], LED_MULTI_INDEX_BLUE) == 0) {
|
||||
led->blue_index = counter;
|
||||
counter++;
|
||||
} else {
|
||||
g_warning ("Unsupport LED color index: %d %s", counter, index[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path = g_udev_device_get_sysfs_path (dev);
|
||||
g_debug ("LED at '%s' usable", path);
|
||||
self->leds = g_slist_append (self->leds, led);
|
||||
@@ -221,6 +251,43 @@ fbd_dev_leds_start_periodic (FbdDevLeds *self, FbdFeedbackLedColor color,
|
||||
led = find_led_by_color (self, color);
|
||||
g_return_val_if_fail (led, FALSE);
|
||||
|
||||
if (led->color == FBD_FEEDBACK_LED_COLOR_RGB) {
|
||||
g_autofree char *intensity = NULL;
|
||||
guint colors[] = { 0, 0, 0 };
|
||||
switch (color) {
|
||||
case FBD_FEEDBACK_LED_COLOR_WHITE:
|
||||
colors[led->red_index] = led->max_brightness;
|
||||
colors[led->green_index] = led->max_brightness;
|
||||
colors[led->blue_index] = led->max_brightness;
|
||||
break;
|
||||
case FBD_FEEDBACK_LED_COLOR_RED:
|
||||
colors[led->red_index] = led->max_brightness;
|
||||
colors[led->green_index] = 0;
|
||||
colors[led->blue_index] = 0;
|
||||
break;
|
||||
case FBD_FEEDBACK_LED_COLOR_GREEN:
|
||||
colors[led->red_index] = 0;
|
||||
colors[led->green_index] = led->max_brightness;
|
||||
colors[led->blue_index] = 0;
|
||||
break;
|
||||
case FBD_FEEDBACK_LED_COLOR_BLUE:
|
||||
colors[led->red_index] = 0;
|
||||
colors[led->green_index] = 0;
|
||||
colors[led->blue_index] = led->max_brightness;
|
||||
break;
|
||||
default:
|
||||
g_warning("Unhandled color: %d\n", color);
|
||||
return FALSE;
|
||||
}
|
||||
intensity = g_strdup_printf ("%d %d %d\n", colors[0], colors[1], colors[2]);
|
||||
fbd_dev_led_set_brightness (led, led->max_brightness);
|
||||
success = fbd_udev_set_sysfs_path_attr_as_string (led->dev, LED_MULTI_INTENSITY_ATTR, intensity, &err);
|
||||
if (!success) {
|
||||
g_warning ("Failed to set multi intensity: %s", err->message);
|
||||
g_clear_error (&err);
|
||||
}
|
||||
}
|
||||
|
||||
max = led->max_brightness * (max_brightness_percentage / 100.0);
|
||||
/* ms mHz T/2 */
|
||||
t = 1000.0 * 1000.0 / freq / 2.0;
|
||||
|
||||
@@ -14,7 +14,8 @@ typedef enum _FbdFeedbackLedColor {
|
||||
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,
|
||||
FBD_FEEDBACK_LED_COLOR_RGB = 4,
|
||||
FBD_FEEDBACK_LED_COLOR_LAST = FBD_FEEDBACK_LED_COLOR_RGB,
|
||||
} FbdFeedbackLedColor;
|
||||
|
||||
#define FBD_TYPE_FEEDBACK_LED (fbd_feedback_led_get_type ())
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#define LED_BRIGHTNESS_ATTR "brightness"
|
||||
#define LED_MULTI_INTENSITY_ATTR "multi_intensity"
|
||||
#define LED_PATTERN_ATTR "pattern"
|
||||
#define LED_REPEAT_ATTR "repeat"
|
||||
#define LED_TRIGGER_ATTR "trigger"
|
||||
@@ -126,6 +127,9 @@ 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))
|
||||
return FALSE;
|
||||
|
||||
// Attribute is optional
|
||||
set_sysfs_attr_perm (sysfs_path, LED_MULTI_INTENSITY_ATTR, group->gr_gid);
|
||||
|
||||
if (!g_strcmp0 (trigger, LED_TRIGGER_PATTERN)) {
|
||||
if (!set_sysfs_attr_perm (sysfs_path, LED_PATTERN_ATTR, group->gr_gid))
|
||||
success = FALSE;
|
||||
|
||||
Reference in New Issue
Block a user