backlight: Amalgamate hardcoded priority tables
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 15 Feb 2014 19:54:30 +0000 (19:54 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 15 Feb 2014 20:56:24 +0000 (20:56 +0000)
Our fallback path for finding the backlight interface uses a hardcoded
table of known backlight controllers in proirity order. Rather than
maintain this table twice in the midst of the KMS logic, push it to the
new set of common backlight routines.

This incorporates bugfixes from SNA to handle unknown backlights, but
usable, gracefully.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/backlight.c
src/backlight.h
src/sna/sna_display.c
src/uxa/intel_display.c

index b04b5f7..5011cb8 100644 (file)
 #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*.
@@ -110,6 +120,7 @@ int backlight_open(struct backlight *b, char *iface)
 
        b->max = param.max;
        b->fd = -1;
+       b->type = BL_PLATFORM;
 
        return param.curval;
 }
@@ -124,23 +135,38 @@ is_sysfs_fd(int fd)
 }
 
 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);
@@ -148,15 +174,71 @@ __backlight_read(const char *iface, const char *file)
        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)
@@ -168,19 +250,12 @@ 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);
 }
 
@@ -242,13 +317,51 @@ static int __backlight_helper_init(struct backlight *b, char *iface)
 #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;
index deecbd0..6eeaff6 100644 (file)
 #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);
index 83b043c..e769546 100644 (file)
@@ -327,13 +327,6 @@ sna_output_backlight_get(xf86OutputPtr output)
        return level;
 }
 
-enum {
-       PLATFORM,
-       FIRMWARE,
-       RAW,
-       NAMED,
-};
-
 static char *
 has_user_backlight_override(xf86OutputPtr output)
 {
@@ -344,7 +337,9 @@ 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);
@@ -355,11 +350,12 @@ has_user_backlight_override(xf86OutputPtr output)
 }
 
 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;
@@ -378,139 +374,20 @@ has_device_backlight(xf86OutputPtr output, int *best_type)
                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;
                        }
                }
        }
@@ -523,37 +400,34 @@ static void
 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,
index c7c2d7c..0f06793 100644 (file)
@@ -139,26 +139,6 @@ crtc_id(struct intel_crtc *crtc)
        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)
 {
@@ -181,46 +161,35 @@ intel_output_backlight_get(xf86OutputPtr output)
 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