From f56cbd847de2ad40240128ec3fb14625daa53e58 Mon Sep 17 00:00:00 2001
From: zoltanvb <101990835+zoltanvb@users.noreply.github.com>
Date: Tue, 14 Feb 2023 23:00:35 +0100
Subject: [PATCH] LED driver for Linux /sys/class/leds (#14981)
New driver for controlling system LEDs offered via /sys/class/leds.
Currently it handles led0, led1 etc. type of entries, which are
present on e.g. Raspberry Pi's.
---
Makefile.common | 3 +-
griffin/griffin.c | 1 +
led/drivers/led_sys_linux.c | 114 ++++++++++++++++++++++++++++++++++++
led/led_driver.c | 3 +
led/led_driver.h | 1 +
5 files changed, 121 insertions(+), 1 deletion(-)
create mode 100644 led/drivers/led_sys_linux.c
diff --git a/Makefile.common b/Makefile.common
index 6455f7bc48..ca952f3f0b 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -2416,7 +2416,8 @@ ifeq ($(HAVE_STATIC_AUDIO_FILTERS), 1)
endif
ifeq ($(HAVE_RPILED), 1)
- OBJ += led/drivers/led_rpi.o
+ OBJ += led/drivers/led_rpi.o \
+ led/drivers/led_sys_linux.o
endif
ifneq ($(findstring Win32,$(OS)),)
diff --git a/griffin/griffin.c b/griffin/griffin.c
index ea6af34702..59b90addb8 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -904,6 +904,7 @@ LEDS
#if defined(HAVE_RPILED)
#include "../led/drivers/led_rpi.c"
+#include "../led/drivers/led_sys_linux.c"
#endif
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
diff --git a/led/drivers/led_sys_linux.c b/led/drivers/led_sys_linux.c
new file mode 100644
index 0000000000..4562e34337
--- /dev/null
+++ b/led/drivers/led_sys_linux.c
@@ -0,0 +1,114 @@
+/* RetroArch - A frontend for libretro.
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+
+#include "../led_driver.h"
+#include "../led_defines.h"
+
+#include "../../configuration.h"
+
+typedef struct
+{
+ int setup[MAX_LEDS];
+ int map[MAX_LEDS];
+} sysled_t;
+
+/* TODO/FIXME - static globals */
+static sysled_t sys_curins;
+static sysled_t *sys_cur = &sys_curins;
+
+static void sys_led_init(void)
+{
+ int i;
+ settings_t *settings = config_get_ptr();
+
+ if (!settings)
+ return;
+
+ for (i = 0; i < MAX_LEDS; i++)
+ {
+ sys_cur->setup[i] = 0;
+ sys_cur->map[i] = settings->uints.led_map[i];
+ }
+}
+
+static void sys_led_free(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_LEDS; i++)
+ {
+ sys_cur->setup[i] = 0;
+ sys_cur->map[i] = 0;
+ }
+}
+
+static int set_sysled(int sysled, int value)
+{
+ FILE *fp;
+ char buf[256];
+ snprintf(buf, sizeof(buf), "/sys/class/leds/led%d/brightness", sysled);
+
+ /* Failed to set LED? */
+ if (!(fp = fopen(buf, "w")))
+ return -1;
+
+ /* Simplified: max_brightness could be taken into account */
+ /* Pi Zero may have reversed brightness? */
+ fprintf(fp, "%d\n", value ? 1 : 0);
+ fclose(fp);
+ return 1;
+}
+
+static int setup_sysled(int sysled)
+{
+ FILE *fp;
+ char buf[256];
+ snprintf(buf, sizeof(buf), "/sys/class/leds/led%d/trigger", sysled);
+
+ if (!(fp = fopen(buf, "w")))
+ return -1;
+
+ /* TODO: read actual trigger in [] and restore on exit */
+ fprintf(fp, "none");
+ fclose(fp);
+ return 1;
+}
+
+static void sys_led_set(int led, int state)
+{
+ int sysled = 0;
+
+ /* Invalid LED? */
+ if((led < 0) || (led >= MAX_LEDS))
+ return;
+
+ sysled = sys_cur->map[led];
+ if(sysled < 0)
+ return;
+
+ if(sys_cur->setup[led] == 0)
+ sys_cur->setup[led] = setup_sysled(sysled);
+ if(sys_cur->setup[led] > 0)
+ set_sysled(sysled, state);
+}
+
+const led_driver_t sys_led_driver = {
+ sys_led_init,
+ sys_led_free,
+ sys_led_set,
+ "sysled"
+};
diff --git a/led/led_driver.c b/led/led_driver.c
index c7a6987d1c..805eadcf85 100644
--- a/led/led_driver.c
+++ b/led/led_driver.c
@@ -47,6 +47,8 @@ void led_driver_init(const char *led_driver)
#ifdef HAVE_RPILED
if (string_is_equal("rpi", drivername))
current_led_driver = &rpi_led_driver;
+ if (string_is_equal("sysled", drivername))
+ current_led_driver = &sys_led_driver;
#endif
#if (defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)) || defined(HAVE_X11)
@@ -54,6 +56,7 @@ void led_driver_init(const char *led_driver)
current_led_driver = &keyboard_led_driver;
#endif
+
if (current_led_driver)
(*current_led_driver->init)();
diff --git a/led/led_driver.h b/led/led_driver.h
index cd04a5cfc0..aeffb4941a 100644
--- a/led/led_driver.h
+++ b/led/led_driver.h
@@ -44,6 +44,7 @@ void led_driver_set_led(int led, int value);
extern const led_driver_t overlay_led_driver;
extern const led_driver_t rpi_led_driver;
extern const led_driver_t keyboard_led_driver;
+extern const led_driver_t sys_led_driver;
RETRO_END_DECLS