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