From f9980385de8ba5bb33391cf3bc8b283db0fb1de2 Mon Sep 17 00:00:00 2001 From: Olivier Duchateau <duchateau.olivier@gmail.com> Date: Wed, 31 Dec 2014 11:52:52 +0100 Subject: [PATCH] Use sysctl(3) to get or set brightness level on FreeBSD and DragonFly systems Signed-off-by: Eric Koegel <eric.koegel@gmail.com> --- common/xfpm-brightness.c | 10 +- src/xfpm-backlight-helper.c | 323 +++++++++++++++++++++++++++++++++++- 2 files changed, 331 insertions(+), 2 deletions(-) diff --git a/common/xfpm-brightness.c b/common/xfpm-brightness.c index 823b0547..9680aa36 100644 --- a/common/xfpm-brightness.c +++ b/common/xfpm-brightness.c @@ -333,12 +333,16 @@ xfpm_brightness_helper_get_value (const gchar *argument) if ( exit_status != 0 ) goto out; +#if !defined(BACKEND_TYPE_FREEBSD) if ( stdout_data[0] == 'N' ) value = 0; else if ( stdout_data[0] == 'Y' ) value = 1; else value = atoi (stdout_data); +#else + value = atoi (stdout_data); +#endif out: g_free (command); @@ -606,7 +610,11 @@ xfpm_brightness_setup (XfpmBrightness *brightness) else { if ( xfpm_brightness_setup_helper (brightness) ) { - g_debug ("xrandr not available, brightness controlled by sysfs helper; min_level=%d max_level=%d", +#if defined(BACKEND_TYPE_FREEBSD) + g_debug ("xrandr not available, brightness controlled by sysctl helper; min_level=%d max_level=%d", +#else + g_debug ("xrandr not available, brightness controlled by sysfs helper; min_level=%d max_level=%d", +#endif brightness->priv->min_level, brightness->priv->max_level); return TRUE; diff --git a/src/xfpm-backlight-helper.c b/src/xfpm-backlight-helper.c index 5f23d524..4584edc2 100644 --- a/src/xfpm-backlight-helper.c +++ b/src/xfpm-backlight-helper.c @@ -19,7 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -36,6 +38,10 @@ #include <string.h> #endif #include <stdio.h> +#include <stdlib.h> +#if defined(BACKEND_TYPE_FREEBSD) +#include <sys/sysctl.h> +#endif #define EXIT_CODE_SUCCESS 0 #define EXIT_CODE_FAILED 1 @@ -43,10 +49,325 @@ #define EXIT_CODE_INVALID_USER 4 #define EXIT_CODE_NO_BRIGHTNESS_SWITCH 5 +#if !defined(BACKEND_TYPE_FREEBSD) #define BACKLIGHT_SYSFS_LOCATION "/sys/class/backlight" #define BRIGHTNESS_SWITCH_LOCATION "/sys/module/video/parameters/brightness_switch_enabled" +#endif + + +#if defined(BACKEND_TYPE_FREEBSD) +gboolean +acpi_video_is_enabled (gchar *device) +{ + return (backlight_helper_get_switch (device) == 1) ? TRUE : FALSE; +} + +gint +backlight_helper_get_switch (gchar *device) +{ + size_t size; + gint buf, res = -1; + gchar *name; + + name = g_strdup_printf ("hw.acpi.video.%s.active", device); + size = sizeof (buf); + + if (sysctlbyname (name, &buf, &size, NULL, 0) == 0) + res = buf; + + g_free (name); + return res; +} + +gint +backlight_helper_get_brightness (gchar *device) +{ + size_t size; + gint buf, res = -1; + gchar *name; + + name = g_strdup_printf ("hw.acpi.video.%s.brightness", device); + size = sizeof (buf); + + if (sysctlbyname (name, &buf, &size, NULL, 0) == 0) + res = buf; + + g_free (name); + return res; +} + +gint +int_cmp (gconstpointer a, gconstpointer b) +{ + return (gint) a < (gint) b ? -1 : ((gint) a == (gint) b ? 0 : 1); +} + +GList * +backlight_helper_get_levels (gchar *device) +{ + size_t size; + gint *levels; + gint nlevels, i; + GList *list = NULL, *item; + gchar *name; + + name = g_strdup_printf ("hw.acpi.video.%s.levels", device); + + /* allocate memory */ + sysctlbyname (name, NULL, &size, NULL, 0); + levels = (int *) malloc (size); + + if (sysctlbyname (name, levels, &size, NULL, 0) == 0) { + nlevels = size / sizeof (gint); + + for (i = 0; i < nlevels; i++) { + /* no duplicate item */ + item = g_list_find (list, GINT_TO_POINTER (levels[i])); + if (item == NULL) + list = g_list_append (list, + GINT_TO_POINTER (levels[i])); + } + } + + g_free (levels); + g_free (name); + + if (list != NULL) + list = g_list_sort (list, int_cmp); + + return list; +} + +gboolean +backlight_helper_set_switch (gchar *device, gint value) +{ + size_t size; + gint buf, old_buf; + gchar *name; + gint res = -1; + gboolean result = FALSE; + + name = g_strdup_printf ("hw.acpi.video.%s.active", device); + + res = backlight_helper_get_switch (device); + if (res != -1) { + old_buf = res; + size = sizeof (buf); + + /* we change value and check if it's really different */ + if (sysctlbyname (name, &buf, &size, &value, sizeof (value)) == 0) { + res = backlight_helper_get_switch (device); + if (res != -1 && res != old_buf) + result = TRUE; + } + } + g_free (name); + + return result; +} + +gboolean +backlight_helper_set_brightness (gchar *device, gint value) +{ + size_t size; + gint buf, old_buf; + gchar *name; + gint res = -1; + gboolean result = FALSE; + + name = g_strdup_printf ("hw.acpi.video.%s.brightness", device); + + res = backlight_helper_get_brightness (device); + if (res != -1) { + old_buf = res; + size = sizeof (buf); + + /* we change value, and check if it's really different */ + if (sysctlbyname (name, &buf, &size, &value, sizeof (value)) == 0) { + res = backlight_helper_get_brightness (device); + if (res != -1 && res != old_buf) + result = TRUE; + } + } + + g_free (name); + + return result; +} + +/* + * Find device which supports backlight brightness + */ +static gchar * +backlight_helper_get_device (void) +{ + /* 'tv' device is also available */ + gchar *types[] = { "lcd", "crt", "out", "ext", NULL }; + gchar *device = NULL; + gint i; + + device = (gchar *) g_malloc (sizeof (gchar)); + + for (i = 0; types[i] != NULL; i++) { + g_snprintf (device, 5, "%s0", types[i]); + + /* stop, when first device is found */ + if (acpi_video_is_enabled (device)) + break; + } + + return device; +} + +/* + * Backlight helper main function + */ +gint +main (gint argc, gchar *argv[]) +{ + GOptionContext *context; + gint uid; + gint euid; + guint retval = 0; + const gchar *pkexec_uid_str; + gint ret = -1; + gint set_brightness = -1; + gboolean get_brightness = FALSE; + gboolean get_max_brightness = FALSE; + gint set_brightness_switch = -1; + gboolean get_brightness_switch = FALSE; + gchar *device = NULL; + GList *list = NULL; + + const GOptionEntry options[] = { + { "set-brightness", '\0', 0, G_OPTION_ARG_INT, &set_brightness, + /* command line argument */ + "Set the current brightness", NULL }, + { "get-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_brightness, + /* command line argument */ + "Get the current brightness", NULL }, + { "get-max-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_max_brightness, + /* command line argument */ + "Get the number of brightness levels supported", NULL }, + { "set-brightness-switch", '\0', 0, G_OPTION_ARG_INT, &set_brightness_switch, + /* command line argument */ + "Enable or disable ACPI video brightness switch handling", NULL }, + { "get-brightness-switch", '\0', 0, G_OPTION_ARG_NONE, &get_brightness_switch, + /* command line argument */ + "Get the current setting of the ACPI video brightness switch handling", NULL }, + { NULL } + }; + + context = g_option_context_new (NULL); + g_option_context_set_summary (context, "XFCE Power Manager Backlight Helper"); + g_option_context_add_main_entries (context, options, NULL); + g_option_context_parse (context, &argc, &argv, NULL); + g_option_context_free (context); + /* no input */ + if (set_brightness == -1 && !get_brightness && !get_max_brightness && + set_brightness_switch == -1 && !get_brightness_switch) { + g_print ("No valid option was specifiedi\n"); + retval = EXIT_CODE_ARGUMENTS_INVALID; + goto out; + } + + /* find backlight device */ + device = backlight_helper_get_device (); + + if (device != NULL) { + /* get the current setting of the ACPI video brightness switch handling */ + if (get_brightness_switch) { + ret = backlight_helper_get_switch (device); + /* just print result to stdout */ + g_print ("%d", ret); + if (ret == -1) + retval = EXIT_CODE_FAILED; + else + retval = EXIT_CODE_SUCCESS; + goto out; + } + /* get current brightness level */ + if (get_brightness) { + ret = backlight_helper_get_brightness (device); + /* just print result to stdout */ + g_print ("%d", ret); + if (ret == -1) + retval = EXIT_CODE_FAILED; + else + retval = EXIT_CODE_SUCCESS; + goto out; + } + + /* get maximum brightness level */ + if (get_max_brightness) { + list = backlight_helper_get_levels (device); + if (list != NULL) { + /* just print result to stdout */ + g_print ("%d", (gint) g_list_last (list)->data); + g_list_free (list); + retval = EXIT_CODE_SUCCESS; + goto out; + } + else { + g_print ("Could not get the maximum value of the backlight\n"); + retval = EXIT_CODE_FAILED; + goto out; + } + } + + /* get calling process */ + uid = getuid (); + euid = geteuid (); + if (uid != 0 || euid != 0) { + g_print ("This program can only be used by the root user\n"); + retval = EXIT_CODE_ARGUMENTS_INVALID; + goto out; + } + + /* check we're not being spoofed */ + pkexec_uid_str = g_getenv ("PKEXEC_UID"); + if (pkexec_uid_str == NULL) { + g_print ("This program must only be run through pkexec\n"); + retval = EXIT_CODE_INVALID_USER; + goto out; + } + + /* set the brightness level */ + if (set_brightness != -1) { + if (backlight_helper_set_brightness (device, set_brightness)) { + retval = EXIT_CODE_SUCCESS; + goto out; + } + else { + g_print ("Could not set the value of the backlight\n"); + retval = EXIT_CODE_FAILED; + goto out; + } + } + + /* enable or disable ACPI video brightness switch handling */ + if (set_brightness_switch != -1) { + if (backlight_helper_set_switch (device, set_brightness_switch)) { + retval = EXIT_CODE_SUCCESS; + goto out; + } + else { + g_print ("Could not set the value of the brightness switch\n"); + retval = EXIT_CODE_FAILED; + goto out; + } + } + } + else { + retval = ret; + goto out; + } +out: + return retval; +} +#else /* * Find best backlight using an ordered interface list */ @@ -323,4 +644,4 @@ out: g_free (contents); return retval; } - +#endif -- GitLab