#include "config.h"
#endif
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
+#include <dirent.h>
#include "backlight.h"
#include "fd.h"
+#define BACKLIGHT_CLASS "/sys/class/backlight"
+
/* Enough for 10 digits of backlight + '\n' + '\0' */
#define BACKLIGHT_VALUE_LEN 12
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
+#endif
+
/*
* Unfortunately this is not as simple as I would like it to be. If selinux is
* dropping dbus messages pkexec may block *forever*.
b->max = param.max;
b->fd = -1;
+ b->type = BL_PLATFORM;
return param.curval;
}
}
static int
-__backlight_read(const char *iface, const char *file)
+__backlight_open(const char *iface, const char *file, int mode)
{
char buf[1024];
- int fd, val;
+ int fd;
snprintf(buf, sizeof(buf), "%s/%s/%s", BACKLIGHT_CLASS, iface, file);
- fd = open(buf, O_RDONLY);
+ fd = open(buf, mode);
if (fd == -1)
return -1;
- if (is_sysfs_fd(fd)) {
- val = read(fd, buf, BACKLIGHT_VALUE_LEN - 1);
- if (val > 0) {
- buf[val] = '\0';
- val = atoi(buf);
- } else
- val = -1;
+ if (!is_sysfs_fd(fd)) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static int
+__backlight_read(const char *iface, const char *file)
+{
+ char buf[BACKLIGHT_VALUE_LEN];
+ int fd, val;
+
+ fd = __backlight_open(iface, file, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ val = read(fd, buf, BACKLIGHT_VALUE_LEN - 1);
+ if (val > 0) {
+ buf[val] = '\0';
+ val = atoi(buf);
} else
val = -1;
close(fd);
return val;
}
-int backlight_exists(const char *iface)
+/* List of available kernel interfaces in priority order */
+static const char *known_interfaces[] = {
+ "dell_backlight",
+ "gmux_backlight",
+ "asus-laptop",
+ "asus-nb-wmi",
+ "eeepc",
+ "thinkpad_screen",
+ "mbp_backlight",
+ "fujitsu-laptop",
+ "sony",
+ "samsung",
+ "acpi_video1",
+ "acpi_video0",
+ "intel_backlight",
+};
+
+static enum backlight_type __backlight_type(const char *iface)
+{
+ char buf[1024];
+ int fd, v;
+
+ v = -1;
+ fd = __backlight_open(iface, "type", O_RDONLY);
+ if (fd >= 0) {
+ v = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ }
+ if (v > 0) {
+ while (v > 0 && isspace(buf[v-1]))
+ v--;
+ buf[v] = '\0';
+
+ if (strcmp(buf, "raw") == 0)
+ v = BL_RAW;
+ else if (strcmp(buf, "platform") == 0)
+ v = BL_PLATFORM;
+ else if (strcmp(buf, "firmware") == 0)
+ v = BL_FIRMWARE;
+ else
+ v = BL_NAMED;
+ } else
+ v = BL_NAMED;
+
+ if (v == BL_NAMED) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
+ if (strcmp(iface, known_interfaces[i]) == 0)
+ break;
+ }
+ v += i;
+ }
+
+ return v;
+}
+
+enum backlight_type backlight_exists(const char *iface)
{
if (__backlight_read(iface, "brightness") < 0)
- return 0;
+ return BL_NONE;
if (__backlight_read(iface, "max_brightness") <= 0)
- return 0;
+ return BL_NONE;
- return 1;
+ return __backlight_type(iface);
}
static int __backlight_init(struct backlight *b, char *iface, int fd)
static int __backlight_direct_init(struct backlight *b, char *iface)
{
- char path[1024];
int fd;
- snprintf(path, sizeof(path), "%s/%s/brightness", BACKLIGHT_CLASS, iface);
- fd = open(path, O_RDWR);
+ fd = __backlight_open(iface, "brightness", O_RDWR);
if (fd < 0)
return 0;
- if (!is_sysfs_fd(fd)) {
- close(fd);
- return 0;
- }
-
return __backlight_init(b, iface, fd);
}
#endif
}
+static char *
+__backlight_find(void)
+{
+ char *best_iface = NULL;
+ unsigned best_type = INT_MAX;
+ DIR *dir;
+ struct dirent *de;
+
+ dir = opendir(BACKLIGHT_CLASS);
+ if (dir == NULL)
+ return NULL;
+
+ while ((de = readdir(dir))) {
+ int v;
+
+ if (*de->d_name == '.')
+ continue;
+
+ /* Fallback to priority list of known iface for old kernels */
+ v = backlight_exists(de->d_name);
+ if (v < best_type) {
+ char *copy = strdup(de->d_name);
+ if (copy) {
+ free(best_iface);
+ best_iface = copy;
+ best_type = v;
+ }
+ }
+ }
+ closedir(dir);
+
+ return best_iface;
+}
+
int backlight_open(struct backlight *b, char *iface)
{
int level;
if (iface == NULL)
+ iface = __backlight_find();
+ if (iface == NULL)
return -1;
+ b->type = __backlight_type(iface);
+
b->max = __backlight_read(iface, "max_brightness");
if (b->max <= 0)
return -1;
#ifndef BACKLIGHT_H
#define BACKLIGHT_H
+enum backlight_type {
+ BL_NONE = -1,
+ BL_PLATFORM,
+ BL_FIRMWARE,
+ BL_RAW,
+ BL_NAMED,
+};
+
struct backlight {
char *iface;
+ enum backlight_type type;
int max;
int pid, fd;
};
-#define BACKLIGHT_CLASS "/sys/class/backlight"
-
-int backlight_exists(const char *iface);
+enum backlight_type backlight_exists(const char *iface);
int backlight_open(struct backlight *backlight, char *iface);
int backlight_set(struct backlight *backlight, int level);
return level;
}
-enum {
- PLATFORM,
- FIRMWARE,
- RAW,
- NAMED,
-};
-
static char *
has_user_backlight_override(xf86OutputPtr output)
{
if (str == NULL)
return NULL;
- if (!backlight_exists(str)) {
+ DBG(("%s(s) requested %s\n", __FUNCTION__, output->name, str));
+
+ if (backlight_exists(str) == BL_NONE) {
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
"Unrecognised backlight control interface '%s'\n",
str);
}
static char *
-has_device_backlight(xf86OutputPtr output, int *best_type)
+has_device_backlight(xf86OutputPtr output)
{
struct sna *sna = to_sna(output->scrn);
struct pci_device *pci;
char path[1024];
+ unsigned best_type = INT_MAX;
char *best_iface = NULL;
DIR *dir;
struct dirent *de;
return NULL;
while ((de = readdir(dir))) {
- char buf[100];
- int fd, v;
-
- if (*de->d_name == '.')
- continue;
-
- DBG(("%s: %s\n", __FUNCTION__, de->d_name));
- snprintf(path, sizeof(path), "%s/%s/type",
- BACKLIGHT_CLASS, de->d_name);
-
- v = -1;
- fd = open(path, O_RDONLY);
- if (fd >= 0) {
- v = read(fd, buf, sizeof(buf)-1);
- close(fd);
- }
- if (v > 0) {
- while (v > 0 && isspace(buf[v-1]))
- v--;
- buf[v] = '\0';
-
- if (strcmp(buf, "raw") == 0)
- v = RAW;
- else if (strcmp(buf, "platform") == 0)
- v = PLATFORM;
- else if (strcmp(buf, "firmware") == 0)
- v = FIRMWARE;
- else
- v = INT_MAX;
- } else
- v = INT_MAX;
-
- if (v < *best_type) {
- char *copy;
-
- if (!backlight_exists(de->d_name))
- continue;
-
- copy = strdup(de->d_name);
- if (copy) {
- free(best_iface);
- best_iface = copy;
- *best_type = v;
- }
- }
- }
- closedir(dir);
-
- return best_iface;
-}
-
-static char *
-has_backlight(xf86OutputPtr output, int *best_type)
-{
- static const char *known_interfaces[] = {
- "dell_backlight",
- "gmux_backlight",
- "asus-laptop",
- "asus-nb-wmi",
- "eeepc",
- "thinkpad_screen",
- "mbp_backlight",
- "fujitsu-laptop",
- "sony",
- "samsung",
- "acpi_video1",
- "acpi_video0",
- "intel_backlight",
- };
- char *best_iface = NULL;
- DIR *dir;
- struct dirent *de;
-
- dir = opendir(BACKLIGHT_CLASS);
- if (dir == NULL)
- return NULL;
-
- while ((de = readdir(dir))) {
- char path[1024];
- char buf[100];
- int fd, v;
+ int v;
if (*de->d_name == '.')
continue;
- snprintf(path, sizeof(path), "%s/%s/type",
- BACKLIGHT_CLASS, de->d_name);
+ v = backlight_exists(de->d_name);
+ DBG(("%s: %s: exists=%d\n", __FUNCTION__, de->d_name, v));
- v = -1;
- fd = open(path, O_RDONLY);
- if (fd >= 0) {
- v = read(fd, buf, sizeof(buf)-1);
- close(fd);
- }
- if (v > 0) {
- while (v > 0 && isspace(buf[v-1]))
- v--;
- buf[v] = '\0';
-
- if (strcmp(buf, "raw") == 0)
- v = RAW;
- else if (strcmp(buf, "platform") == 0)
- v = PLATFORM;
- else if (strcmp(buf, "firmware") == 0)
- v = FIRMWARE;
- else
- v = NAMED;
- } else
- v = NAMED;
-
- /* Fallback to priority list of known iface for old kernels */
- if (v == NAMED) {
- int i;
- for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
- if (strcmp(de->d_name, known_interfaces[i]) == 0)
- break;
- }
- v += i;
- }
-
- if (v < *best_type) {
- char *copy;
-
- /* XXX detect right backlight for multi-GPU/panels */
-
- if (!backlight_exists(de->d_name))
- continue;
-
- copy = strdup(de->d_name);
+ if (v < best_type) {
+ char *copy = strdup(de->d_name);
if (copy) {
free(best_iface);
best_iface = copy;
- *best_type = v;
+ best_type = v;
}
}
}
sna_output_backlight_init(xf86OutputPtr output)
{
struct sna_output *sna_output = output->driver_private;
- MessageType from = X_PROBED;
+ MessageType from;
char *best_iface;
- int best_type;
- best_type = INT_MAX;
+ from = X_CONFIG;
best_iface = has_user_backlight_override(output);
if (best_iface)
goto done;
- best_iface = has_device_backlight(output, &best_type);
- if (best_iface)
- goto done;
-
- best_iface = has_backlight(output, &best_type);
+ /* XXX detect right backlight for multi-GPU/panels */
+ from = X_PROBED;
+ best_iface = has_device_backlight(output);
if (best_iface)
goto done;
- best_type = PLATFORM;
best_iface = NULL;
done:
+ DBG(("%s(%s) opening backlight %s\n", __FUNCTION__,
+ output->name, best_iface ?: "none"));
sna_output->backlight_active_level =
backlight_open(&sna_output->backlight, best_iface);
if (sna_output->backlight_active_level < 0)
return;
- switch (best_type) {
- case INT_MAX: best_iface = (char *)"user"; from = X_CONFIG; break;
- case FIRMWARE: best_iface = (char *)"firmware"; break;
- case PLATFORM: best_iface = (char *)"platform"; break;
- case RAW: best_iface = (char *)"raw"; break;
+ switch (sna_output->backlight.type) {
+ case BL_FIRMWARE: best_iface = (char *)"firmware"; break;
+ case BL_PLATFORM: best_iface = (char *)"platform"; break;
+ case BL_RAW: best_iface = (char *)"raw"; break;
default: best_iface = (char *)"unknown"; break;
}
xf86DrvMsg(output->scrn->scrnIndex, from,
return crtc->mode_crtc->crtc_id;
}
-/*
- * List of available kernel interfaces in priority order
- */
-static const char *backlight_interfaces[] = {
- "dell_backlight",
- "gmux_backlight",
- "asus-laptop",
- "asus-nb-wmi",
- "eeepc",
- "thinkpad_screen",
- "mbp_backlight",
- "fujitsu-laptop",
- "sony",
- "samsung",
- "acpi_video1", /* finally fallback to the generic acpi drivers */
- "acpi_video0",
- "intel_backlight",
- NULL,
-};
-
static void
intel_output_backlight_set(xf86OutputPtr output, int level)
{
static void
intel_output_backlight_init(xf86OutputPtr output)
{
-#ifdef __OpenBSD__
- intel_output->backlight_active_level =
- backlight_init(&intel_output->backlight, NULL);
- if (intel_output->backlight_active_level != -1) {
- xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
- "found backlight control interface\n");
- }
-#else
struct intel_output *intel_output = output->driver_private;
intel_screen_private *intel = intel_get_screen_private(output->scrn);
char *str;
- int i;
str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
if (str != NULL) {
- if (backlight_exists(str)) {
+ if (backlight_exists(str) != BL_NONE) {
intel_output->backlight_active_level =
- backlight_open(&intel_output->backlight, strdup(str));
+ backlight_open(&intel_output->backlight,
+ strdup(str));
if (intel_output->backlight_active_level != -1) {
xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
"found backlight control interface %s\n", str);
return;
}
}
+
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
"unrecognised backlight control interface %s\n", str);
}
- for (i = 0; backlight_interfaces[i] != NULL; i++) {
- if (backlight_exists(backlight_interfaces[i])) {
- intel_output->backlight_active_level =
- backlight_open(&intel_output->backlight, strdup(backlight_interfaces[i]));
- if (intel_output->backlight_active_level != -1) {
- xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
- "found backlight control interface %s\n", backlight_interfaces[i]);
- return;
- }
- }
+ intel_output->backlight_active_level =
+ backlight_open(&intel_output->backlight, NULL);
+ if (intel_output->backlight_active_level != -1) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
+ "found backlight control interface %s\n",
+ intel_output->backlight.iface);
+ return;
}
-#endif
}
static void