From 4fc5495f4e1c227a6284375300a13848b2a8fffd Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Tue, 14 Apr 2015 14:20:33 +0100 Subject: [PATCH] backlight: Use basic ACPI sysctl knob on FreeBSD (kernel) Summary: Unconditionally build the suid-helper _backlight program; conditionalize behavior on Eeze, FreeBSD (doing nothing on neither). Add logic to set the FreeBSD sysctl in a similar manner to udev devices on Linux. Add _bl_sys_find/_get helpers for FreeBSD that check for and consult the video ACPI sysctl. Test Plan: Seems to work okay on my laptop (with EINA_CPU_FAKE=1 to workaround a threadq race that I believe is unrelated -- T2287). Reviewers: zmike, q66 Reviewed By: q66 Subscribers: cedric, seoz Differential Revision: https://phab.enlightenment.org/D2337 --- src/bin/Makefile.mk | 12 +---- src/bin/e_backlight.c | 80 +++++++++++++++++++++++++++-- src/bin/e_backlight_main.c | 125 +++++++++++++++++++++++++++++++-------------- 3 files changed, 163 insertions(+), 54 deletions(-) diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index 105c380..5afdb4a 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -27,6 +27,7 @@ src/bin/enlightenment_open internal_bindir = $(libdir)/enlightenment/utils internal_bin_PROGRAMS = \ +src/bin/enlightenment_backlight \ src/bin/enlightenment_fm_op \ src/bin/enlightenment_sys \ src/bin/enlightenment_thumb \ @@ -36,10 +37,6 @@ if ! HAVE_WAYLAND_ONLY internal_bin_PROGRAMS += src/bin/enlightenment_alert endif -if HAVE_EEZE -internal_bin_PROGRAMS += src/bin/enlightenment_backlight -endif - ENLIGHTENMENTHEADERS = \ src/bin/e_about.h \ src/bin/e_acpi.h \ @@ -420,13 +417,11 @@ src/bin/e_sys_l2ping.c src_bin_enlightenment_sys_LDADD = @SUID_LDFLAGS@ @E_SYS_LIBS@ @BLUEZ_LIBS@ src_bin_enlightenment_sys_CPPFLAGS = @SUID_CFLAGS@ @E_SYS_CFLAGS@ @BLUEZ_CFLAGS@ -DPACKAGE_SYSCONF_DIR=\"@PACKAGE_SYSCONF_DIR@\" -if HAVE_EEZE src_bin_enlightenment_backlight_SOURCES = \ src/bin/e_backlight_main.c src_bin_enlightenment_backlight_CPPFLAGS = @SUID_CFLAGS@ @EEZE_CFLAGS@ src_bin_enlightenment_backlight_LDADD = @SUID_LDFLAGS@ @EEZE_LIBS@ -endif src_bin_enlightenment_alert_SOURCES = \ src/bin/e_alert_main.c @@ -455,14 +450,9 @@ include src/bin/e_fm/Makefile.mk # and before internal_bin_PROGRAMS are installed. install-data-hook is # run after both setuid_root_mode = a=rx,u+xs -if HAVE_EEZE enlightenment-sys-install-data-hook: @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_sys$(EXEEXT) || true @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_backlight$(EXEEXT) || true -else -enlightenment-sys-install-data-hook: - @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_sys$(EXEEXT) || true -endif installed_headersdir = $(prefix)/include/enlightenment installed_headers_DATA = $(ENLIGHTENMENTHEADERS) src/bin/e_fm_shared_types.h INSTALL_DATA_HOOKS += enlightenment-sys-install-data-hook diff --git a/src/bin/e_backlight.c b/src/bin/e_backlight.c index 12e8db1..92c8a0d 100644 --- a/src/bin/e_backlight.c +++ b/src/bin/e_backlight.c @@ -2,6 +2,12 @@ #ifdef HAVE_EEZE # include #endif +#include +#ifdef __FreeBSD_kernel__ +# include +# include +# include +#endif // FIXME: backlight should be tied per zone but this implementation is just // a signleton right now as thats 99% of use cases. but api supports @@ -25,7 +31,7 @@ static Eina_Bool bl_avail = EINA_TRUE; #ifndef HAVE_WAYLAND_ONLY static Eina_Bool xbl_avail = EINA_FALSE; #endif -#ifdef HAVE_EEZE +#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) static double bl_delayval = 1.0; static const char *bl_sysval = NULL; static Ecore_Event_Handler *bl_sys_exit_handler = NULL; @@ -38,6 +44,11 @@ static void _bl_sys_level_get(void); static Eina_Bool _e_bl_cb_exit(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); static void _bl_sys_level_set(double val); #endif +#ifdef __FreeBSD_kernel__ +static const char *bl_acpi_sysctl = "hw.acpi.video.lcd0.brightness"; +static int bl_mib[CTL_MAXNAME]; +static int bl_mib_len = -1; +#endif EAPI int E_EVENT_BACKLIGHT_CHANGE = -1; @@ -240,7 +251,7 @@ _e_backlight_update(void) return; } #endif -#ifdef HAVE_EEZE +#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) _bl_sys_find(); if (bl_sysval) { @@ -299,7 +310,7 @@ _e_backlight_set(double val) free(out); } #endif -#ifdef HAVE_EEZE +#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) else if (sysmode == MODE_SYS) { if (bl_sysval) @@ -445,7 +456,9 @@ _bl_sys_level_get(void) e_bl_val = (double)val / (double)maxval; // fprintf(stderr, "GET: %i/%i (%1.3f)\n", val, maxval, e_bl_val); } +#endif // HAVE_EEZE +#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) static Eina_Bool _e_bl_cb_ext_delay(void *data EINA_UNUSED) { @@ -494,5 +507,64 @@ _bl_sys_level_set(double val) e_prefix_lib_get(), (int)(val * 1000.0), bl_sysval); bl_sys_set_exe = ecore_exe_run(buf, NULL); } +#endif // HAVE_EEZE || __FreeBSD_kernel__ -#endif +#ifdef __FreeBSD_kernel__ +static void +_bl_sys_find(void) +{ + int rc; + size_t mlen; + + if (!bl_avail) return; + if (bl_mib_len >= 0) return; + + mlen = sizeof(bl_mib) / sizeof(bl_mib[0]); + rc = sysctlnametomib(bl_acpi_sysctl, bl_mib, &mlen); + if (rc < 0) + { + if (errno == ENOENT) ERR("ACPI brightness sysctl '%s' not found, consider 'kldload acpi_video'", bl_acpi_sysctl); + else ERR("sysctlnametomib(%s): %s(%d)", bl_acpi_sysctl, strerror(errno), errno); + + bl_avail = EINA_FALSE; + return; + } + bl_mib_len = (int)mlen; + sysmode = MODE_SYS; + eina_stringshare_replace(&bl_sysval, bl_acpi_sysctl); +} + +static void +_bl_sys_level_get(void) +{ + int rc, brightness; + size_t oldlen; + + if (!bl_avail) return; + if (bl_mib_len < 0) return; + + oldlen = sizeof(brightness); + rc = sysctl(bl_mib, bl_mib_len, &brightness, &oldlen, NULL, 0); + if (rc < 0) + { + ERR("Could not retrieve ACPI brightness: %s(%d)", strerror(errno), errno); + bl_avail = EINA_FALSE; + return; + } + if (oldlen != sizeof(brightness)) + { + // This really should not happen. + ERR("!!! Brightness sysctl changed size !!!"); + bl_avail = EINA_FALSE; + return; + } + if (brightness < 0 || brightness > 100) + { + // This really should not happen either. + ERR("!!! Brightness sysctl out of range !!!"); + bl_avail = EINA_FALSE; + return; + } + e_bl_val = (double)brightness / 100.; +} +#endif // __FreeBSD_kernel__ diff --git a/src/bin/e_backlight_main.c b/src/bin/e_backlight_main.c index 4aadbab..d2f0e20 100644 --- a/src/bin/e_backlight_main.c +++ b/src/bin/e_backlight_main.c @@ -4,11 +4,13 @@ #include #include #include +#include #include #include #include #include +#if defined(HAVE_EEZE) #include /* local subsystem functions */ @@ -33,48 +35,15 @@ _bl_write_file(const char *file, int val) return 0; } -/* externally accessible functions */ -int -main(int argc, char **argv) +static int +_bl_set(const char *dev, int level) { - int i, level, devok = 0; - const char *f, *dev = NULL, *str; + const char *f, *str; int maxlevel = 0, curlevel = -1; Eina_List *devs, *l; + Eina_Bool devok = EINA_FALSE; char buf[4096] = ""; - for (i = 1; i < argc; i++) - { - if ((!strcmp(argv[i], "-h")) || - (!strcmp(argv[i], "-help")) || - (!strcmp(argv[i], "--help"))) - { - printf("This is an internal tool for Enlightenment.\n" - "do not use it.\n"); - exit(0); - } - } - if (argc == 3) - { - level = atoi(argv[1]); - dev = argv[2]; - } - else - exit(1); - - if (!dev) return -1; - - if (setuid(0) != 0) - { - printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n"); - exit(5); - } - if (setgid(0) != 0) - { - printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n"); - exit(7); - } - eeze_init(); devs = eeze_udev_find_by_filter("backlight", NULL, NULL); if (!devs) @@ -89,7 +58,7 @@ main(int argc, char **argv) if (!strcmp(f, dev)) { dev = f; - devok = 1; + devok = EINA_TRUE; break; } } @@ -123,7 +92,85 @@ main(int argc, char **argv) EINA_LIST_FREE(devs, f) eina_stringshare_del(f); +} +#elif defined(__FreeBSD_kernel__) // !HAVE_EEZE +#include +#include - return -1; +static const char *bl_acpi_sysctl = "hw.acpi.video.lcd0.brightness"; + +static int +_bl_set(const char *dev, int level) +{ + int rc; + + level = ((100 * level) + 500) / 1000; + if (level > 100) level = 100; + else if (level < 0) level = 0; + + // Be slightly careful if making this more permissive. We don't want to + // allow non-root users to set arbitrary integer sysctls between 0-100. + if (strcmp(bl_acpi_sysctl, dev) != 0) + { + printf("bad device: %s\n", dev); + return -1; + } + + rc = sysctlbyname(bl_acpi_sysctl, NULL, NULL, &level, sizeof(level)); + if (rc < 0) + { + perror("sysctlbyname"); + return -1; + } + return 0; } +#endif // __FreeBSD_kernel__ + +#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) +int +main(int argc, char **argv) +{ + const char *dev = NULL; + int i, level; + for (i = 1; i < argc; i++) + { + if ((!strcmp(argv[i], "-h")) || + (!strcmp(argv[i], "-help")) || + (!strcmp(argv[i], "--help"))) + { + printf("This is an internal tool for Enlightenment.\n" + "do not use it.\n"); + exit(0); + } + } + if (argc == 3) + { + level = atoi(argv[1]); + dev = argv[2]; + } + else + exit(1); + + if (!dev) return -1; + + if (setuid(0) != 0) + { + printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n"); + exit(5); + } + if (setgid(0) != 0) + { + printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n"); + exit(7); + } + + return _bl_set(dev, level); +} +#else // !HAVE_EEZE && !__FreeBSD_kernel__ +int +main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + return -1; +} +#endif -- 2.7.4