backlight support for non randr (go right to /sys via suid root tool).

test keybindings too and make brightness be 0->100 to avoid float
parsing issues



SVN revision: 60350
This commit is contained in:
Carsten Haitzler 2011-06-15 14:18:23 +00:00
parent 1be8366a35
commit 411f75319d
4 changed files with 350 additions and 218 deletions

View File

@ -29,7 +29,8 @@ internal_bin_PROGRAMS = \
enlightenment_fm_op \
enlightenment_init \
enlightenment_sys \
enlightenment_thumb
enlightenment_thumb \
enlightenment_backlight
ENLIGHTENMENTHEADERS = \
e_about.h \
@ -361,6 +362,11 @@ e_sys_main.c
enlightenment_sys_LDADD = @E_SYS_LIBS@
enlightenment_backlight_SOURCES = \
e_backlight_main.c
enlightenment_backlight_LDADD =
enlightenment_init_SOURCES = \
e_init_main.c \
e_xinerama.c
@ -373,6 +379,7 @@ enlightenment_init_LDADD = @E_INIT_LIBS@
setuid_root_mode = a=rx,u+xs
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
installed_headersdir = $(prefix)/include/enlightenment
installed_headers_DATA = $(ENLIGHTENMENTHEADERS)

View File

@ -2644,20 +2644,20 @@ ACT_FN_GO_ACPI(undim_screen, __UNUSED__)
e_backlight_mode_set(zone, E_BACKLIGHT_MODE_NORMAL);
}
ACT_FN_GO_ACPI(backlight_set, )
ACT_FN_GO(backlight_set, )
{
E_Zone *zone = _e_actions_zone_get(obj);
double v = atof(params);
int v = atoi(params);
e_backlight_mode_set(zone, E_BACKLIGHT_MODE_NORMAL);
e_backlight_level_set(zone, v, -1.0);
e_backlight_level_set(zone, ((double)v / 100.0), -1.0);
}
ACT_FN_GO_ACPI(backlight_adjust, )
ACT_FN_GO(backlight_adjust, )
{
E_Zone *zone = _e_actions_zone_get(obj);
double v = atof(params);
int v = atoi(params);
e_backlight_mode_set(zone, E_BACKLIGHT_MODE_NORMAL);
e_backlight_level_set(zone, e_backlight_level_get(zone) + v, -1.0);
e_backlight_level_set(zone, e_backlight_level_get(zone) + ((double)v / 100.0), -1.0);
}
/* local subsystem globals */
@ -2956,22 +2956,22 @@ e_actions_init(void)
ACT_GO_ACPI(undim_screen);
e_action_predef_name_set(N_("Screen"), N_("Undim"), "undim_screen",
NULL, NULL, 0);
ACT_GO_ACPI(backlight_set);
ACT_GO(backlight_set);
e_action_predef_name_set(N_("Screen"), N_("Backlight Set"), "backlight_set",
NULL, "syntax: brightness(0.0 - 1.0), example: 0.5", 1);
NULL, "syntax: brightness(0 - 100), example: 50", 1);
e_action_predef_name_set(N_("Screen"), N_("Backlight Min"), "backlight_set",
"0.0", NULL, 0);
"0", NULL, 0);
e_action_predef_name_set(N_("Screen"), N_("Backlight Mid"), "backlight_set",
"0.5", NULL, 0);
"50", NULL, 0);
e_action_predef_name_set(N_("Screen"), N_("Backlight Max"), "backlight_set",
"1.0", NULL, 0);
ACT_GO_ACPI(backlight_adjust);
"100", NULL, 0);
ACT_GO(backlight_adjust);
e_action_predef_name_set(N_("Screen"), N_("Backlight Adjust"), "backlight_adjust",
NULL, "syntax: brightness(-1.0 - 1.0), example: -0.2", 1);
NULL, "syntax: brightness(-100 - 100), example: -20", 1);
e_action_predef_name_set(N_("Screen"), N_("Backlight Up"), "backlight_adjust",
"0.1", NULL, 0);
"10", NULL, 0);
e_action_predef_name_set(N_("Screen"), N_("Backlight Down"), "backlight_adjust",
"-0.1", NULL, 0);
"-10", NULL, 0);
/* window_move_to_center */
ACT_GO(window_move_to_center);

View File

@ -1,40 +1,31 @@
#include "e.h"
#include <E_DBus.h>
#ifdef HAVE_HAL
#include <E_Hal.h>
#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
// doing more. for now make it work in the singleton
// FIXME: backlight should have config values for:
// 1. normal mode (eg on login/ start of e)
// 2. dim level (eg 0.5)
// 3. anim slide time (eg 0.5)
// FIXME: tried using hal backlight stuff... doesn't work
//#define HAL_BL 1
#define MODE_RANDR 0
#define MODE_HAL 1
#define MODE_SYS 1
static double bl_val = 1.0;
static double bl_animval = 1.0;
static E_Backlight_Mode bl_mode = E_BACKLIGHT_MODE_NORMAL;
static int sysmode = MODE_RANDR;
static Ecore_Animator *bl_anim = NULL;
#ifdef HAL_BL
static E_DBus_Connection *_hal_conn = NULL;
static const char *_hal_bl_dev = NULL;
static const char *_hal_bl_iface = NULL;
static int _hal_nlevels = 1;
#endif
static const char *bl_sysval = NULL;
static Ecore_Event_Handler *bl_sys_exit_handler = NULL;
static Ecore_Exe *bl_sys_set_exe = NULL;
static Eina_Bool bl_sys_pending_set = EINA_FALSE;
static void _e_backlight_update(E_Zone *zone);
static void _e_backlight_set(E_Zone *zone, double val);
static Eina_Bool _bl_anim(void *data, double pos);
static char *_bl_read_file(const char *file);
static int _bl_sys_num_get(const char *file);
static void _bl_sys_find(void);
static void _bl_sys_level_get(void);
static Eina_Bool _e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event);
static void _bl_sys_level_set(double val);
EINTERN int
e_backlight_init(void)
@ -48,29 +39,14 @@ e_backlight_init(void)
EINTERN int
e_backlight_shutdown(void)
{
#ifdef HAL_BL
if (_hal_conn)
{
e_dbus_connection_close(_hal_conn);
_hal_conn = NULL;
#ifdef HAVE_HAL
e_hal_shutdown();
#endif
e_dbus_shutdown();
if (_hal_bl_dev)
{
eina_stringshare_del(_hal_bl_dev);
_hal_bl_dev = NULL;
}
if (_hal_bl_iface)
{
eina_stringshare_del(_hal_bl_iface);
_hal_bl_iface = NULL;
}
}
#endif
if (bl_anim) ecore_animator_del(bl_anim);
bl_anim = NULL;
if (bl_sysval) eina_stringshare_del(bl_sysval);
bl_sysval = NULL;
if (bl_sys_exit_handler) ecore_event_handler_del(bl_sys_exit_handler);
bl_sys_exit_handler = NULL;
bl_sys_set_exe = NULL;
bl_sys_pending_set = EINA_FALSE;
return 1;
}
@ -81,7 +57,7 @@ e_backlight_update(void)
E_Manager *man;
E_Container *con;
E_Zone *zone;
EINA_LIST_FOREACH(e_manager_list(), m, man)
{
EINA_LIST_FOREACH(man->containers, c, con)
@ -102,15 +78,14 @@ e_backlight_level_set(E_Zone *zone, double val, double tim)
// set backlight associated with zone to val over period of tim
// if tim == 0.0 - then do it instantnly, if time == -1 use some default
// transition time
if (!zone) e_backlight_update();
else _e_backlight_update(zone);
if (val < 0.0) val = 0.0;
else if (val > 1.0) val = 1.0;
if (val == bl_val) return;
if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
bl_now = bl_val;
bl_val = val;
if (bl_mode != E_BACKLIGHT_MODE_NORMAL) return;
if (tim < 0.0) tim = e_config->backlight.transition;
// FIXME: save bl level for normal
if (tim == 0.0)
{
if (bl_anim)
@ -130,8 +105,6 @@ EAPI double
e_backlight_level_get(E_Zone *zone)
{
// zone == NULL == everything
if (!zone) e_backlight_update();
else _e_backlight_update(zone);
return bl_val;
}
@ -161,139 +134,6 @@ e_backlight_mode_get(E_Zone *zone __UNUSED__)
}
/* local subsystem functions */
#ifdef HAL_BL
#ifdef HAVE_HAL
void
_e_backlight_hal_val_reply(void *data __UNUSED__,
DBusMessage *reply,
DBusError *error)
{
dbus_uint32_t val;
if (dbus_error_is_set(error))
{
printf("Error: %s - %s\n", error->name, error->message);
return;
}
dbus_message_get_args(reply, error, DBUS_TYPE_UINT32,
&val, DBUS_TYPE_INVALID);
printf("Received: %i\n", val);
}
static void
_e_backlight_hal_val_get(void)
{
DBusMessage *msg;
if (!_hal_bl_dev) return;
msg = dbus_message_new_method_call
("org.freedesktop.Hal",
_hal_bl_dev,
_hal_bl_iface,
"GetBrightness"
);
e_dbus_message_send(_hal_conn, msg, _e_backlight_hal_val_reply, -1, NULL);
dbus_message_unref(msg);
}
static void
_e_backlight_hal_val_set(double val)
{
DBusMessage *msg;
dbus_uint32_t ival = 0;
if (!_hal_bl_dev) return;
msg = dbus_message_new_method_call
("org.freedesktop.Hal",
_hal_bl_dev,
_hal_bl_iface,
"SetBrightness"
);
ival = val * (_hal_nlevels - 1);
printf("hal set %i\n", ival);
dbus_message_append_args(msg, DBUS_TYPE_UINT32, &ival, DBUS_TYPE_INVALID);
dbus_message_set_no_reply(msg, EINA_TRUE);
e_dbus_message_send(_hal_conn, msg, NULL, -1, NULL);
dbus_message_unref(msg);
}
static void
_e_backlight_prop(void *data __UNUSED__,
void *reply_data,
DBusError *error)
{
E_Hal_Properties *ret = reply_data;
int err;
int nlevels;
const Eina_List *sl;
if (!ret) goto error;
if (dbus_error_is_set(error))
{
dbus_error_free(error);
goto error;
}
nlevels = e_hal_property_bool_get(ret, "laptop_panel.num_levels", &err);
if (err) goto error;
_hal_nlevels = nlevels;
printf("nlevels: %i\n", nlevels);
sl = e_hal_property_strlist_get(ret, "info.interfaces", &err);
if (err) goto error;
if (sl)
{
if (_hal_bl_iface) eina_stringshare_del(_hal_bl_iface);
_hal_bl_iface = eina_stringshare_add(sl->data);
printf("%s\n", _hal_bl_iface);
}
_e_backlight_hal_val_get();
return;
error:
if (_hal_bl_dev)
{
eina_stringshare_del(_hal_bl_dev);
_hal_bl_dev = NULL;
}
if (_hal_bl_iface)
{
eina_stringshare_del(_hal_bl_iface);
_hal_bl_iface = NULL;
}
}
static void
_e_backlight_panel_found(void *user_data __UNUSED__,
void *reply_data,
DBusError *error)
{
E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply_data;
Eina_List *l;
char *device;
if (!ret || !ret->strings) return;
if (dbus_error_is_set(error))
{
dbus_error_free(error);
return;
}
if (!_hal_bl_dev)
{
EINA_LIST_FOREACH(ret->strings, l, device)
{
printf("BL+: %s\n", device);
if (!_hal_bl_dev) _hal_bl_dev = eina_stringshare_add(device);
}
}
if (_hal_bl_dev)
{
e_hal_device_get_all_properties(_hal_conn, _hal_bl_dev,
_e_backlight_prop, NULL);
}
}
#endif
#endif
static void
_e_backlight_update(E_Zone *zone)
@ -316,24 +156,12 @@ _e_backlight_update(E_Zone *zone)
}
else
{
#ifdef HAL_BL
#ifdef HAVE_HAL
sysmode = MODE_HAL;
if (!_hal_conn)
{
e_dbus_init();
e_hal_init();
_hal_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
}
if (_hal_conn)
_bl_sys_find();
if (bl_sysval)
{
if (!_hal_bl_dev)
e_hal_manager_find_device_by_capability
(_hal_conn, "laptop_panel",
_e_backlight_panel_found, NULL);
sysmode = MODE_SYS;
_bl_sys_level_get();
}
#endif
#endif
}
}
@ -354,13 +182,12 @@ _e_backlight_set(E_Zone *zone, double val)
}
if (out) free(out);
}
else if (sysmode == MODE_HAL)
else if (sysmode == MODE_SYS)
{
#ifdef HAL_BL
#ifdef HAVE_HAL
_e_backlight_hal_val_set(val);
#endif
#endif
if (bl_sysval)
{
_bl_sys_level_set(val);
}
}
}
@ -381,3 +208,143 @@ _bl_anim(void *data, double pos)
}
return EINA_TRUE;
}
static char *
_bl_read_file(const char *file)
{
FILE *f = fopen(file, "r");
size_t len;
char buf[4096], *p;
if (!f) return NULL;
len = fread(buf, 1, sizeof(buf) - 1, f);
if (len == 0)
{
fclose(f);
return NULL;
}
buf[len] = 0;
for (p = buf; *p; p++)
{
if (p[0] == '\n') p[0] = 0;
}
fclose(f);
return strdup(buf);
}
static int
_bl_sys_num_get(const char *file)
{
char *max;
int maxval = -1;
max = _bl_read_file(file);
if (max)
{
maxval = atoi(max);
free(max);
}
return maxval;
}
static void
_bl_sys_find(void)
{
int maxval = 0;
const char *tryfile;
if (bl_sysval) return;
tryfile = "/sys/devices/virtual/backlight/acpi_video0/max_brightness";
maxval = _bl_sys_num_get(tryfile);
if (maxval > 0)
{
bl_sysval = eina_stringshare_add(tryfile);
return;
}
else
{
Eina_List *files;
const char *dir = "/sys/devices/virtual/backlight";
files = ecore_file_ls(dir);
if (files)
{
char *file;
EINA_LIST_FREE(files, file)
{
if (!bl_sysval)
{
char buf[PATH_MAX];
snprintf(buf, sizeof(buf),
"%s/%s/max_brightness", dir, file);
maxval = _bl_sys_num_get(buf);
if (maxval > 0)
bl_sysval = eina_stringshare_add(buf);
}
free(file);
}
}
}
}
static void
_bl_sys_level_get(void)
{
const char *maxfile = bl_sysval;
char *valfile, *p;
int maxval, val;
if (!bl_sysval) return;
valfile = strdup(maxfile);
p = strrchr(valfile, '/');
if (p)
{
p[1] = 0;
strcat(p, "brightness");
}
maxval = _bl_sys_num_get(maxfile);
if (maxval > 0)
{
val = _bl_sys_num_get(valfile);
if ((val >= 0) && (val <= maxval))
bl_val = (double)val / (double)maxval;
}
}
static Eina_Bool
_e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Exe_Event_Del *ev;
ev = event;
if (ev->exe == bl_sys_set_exe)
{
bl_sys_set_exe = NULL;
if (bl_sys_pending_set)
{
bl_sys_pending_set = EINA_FALSE;
_bl_sys_level_set(bl_val);
}
}
return ECORE_CALLBACK_RENEW;
}
static void
_bl_sys_level_set(double val)
{
char buf[PATH_MAX];
if (!bl_sys_exit_handler)
bl_sys_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_e_bl_cb_exit, NULL);
if (bl_sys_set_exe)
{
bl_sys_pending_set = EINA_TRUE;
return;
}
snprintf(buf, sizeof(buf),
"%s/enlightenment/utils/enlightenment_backlight %i",
e_prefix_lib_get(), (int)(val * 1000.0));
bl_sys_set_exe = ecore_exe_run(buf, NULL);
}

158
src/bin/e_backlight_main.c Normal file
View File

@ -0,0 +1,158 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
/* local subsystem functions */
static char *
read_file(const char *file)
{
FILE *f = fopen(file, "r");
size_t len;
char buf[4096], *p;
if (!f) return NULL;
len = fread(buf, 1, sizeof(buf) - 1, f);
if (len == 0)
{
fclose(f);
return NULL;
}
buf[len] = 0;
for (p = buf; *p; p++)
{
if (p[0] == '\n') p[0] = 0;
}
fclose(f);
return strdup(buf);
}
static int
write_file(const char *file, int val)
{
char buf[256];
int fd = open(file, O_WRONLY);
if (fd < 0)
{
perror("open");
return -1;
}
snprintf(buf, sizeof(buf), "%i", val);
if (write(fd, buf, strlen(buf)) != (int)strlen(buf))
{
perror("write");
close(fd);
return -1;
}
close(fd);
return 0;
}
/* local subsystem globals */
/* externally accessible functions */
int
main(int argc,
char **argv)
{
int i;
int level;
char *maxstr;
int maxlevel = 0, curlevel;
char file[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 == 2)
{
level = atoi(argv[1]);
}
else
{
exit(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);
}
maxstr = read_file("/sys/devices/virtual/backlight/acpi_video0/max_brightness_max");
if (maxstr)
{
maxlevel = atoi(maxstr);
if (maxlevel <= 0)
{
free(maxstr);
maxstr = NULL;
}
else
{
snprintf(file, sizeof(file), "/sys/devices/virtual/backlight/acpi_video0/brightness");
free(maxstr);
maxstr = NULL;
}
}
if (maxlevel <= 0)
{
DIR *dirp = opendir("/sys/devices/virtual/backlight");
struct dirent *dp;
if (!dirp) return 1;
while ((dp = readdir(dirp)))
{
if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
{
char buf[4096];
snprintf(buf, sizeof(buf), "/sys/devices/virtual/backlight/%s/max_brightness", dp->d_name);
maxstr = read_file(buf);
if (maxstr)
{
maxlevel = atoi(maxstr);
if (maxlevel <= 0)
{
free(maxstr);
maxstr = NULL;
}
else
{
snprintf(file, sizeof(file), "/sys/devices/virtual/backlight/%s/brightness", dp->d_name);
free(maxstr);
maxstr = NULL;
break;
}
}
}
}
closedir(dirp);
}
if (maxlevel > 0)
{
curlevel = (maxlevel * level) / 1000;
return write_file(file, curlevel);
}
return -1;
}