summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2010-09-09 13:27:56 -0400
committerMatthew Garrett <mjg@redhat.com>2010-09-09 13:27:56 -0400
commit4c65b46f10b2195ba813838f329b52ced7f15421 (patch)
tree79f58e00669a0b938425959a7e28b7414208ea87
Initial commit
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac15
-rw-r--r--libbacklight.c231
-rw-r--r--libbacklight.h20
-rw-r--r--libbacklight.pc.in11
5 files changed, 282 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..8983232
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,5 @@
+lib_LTLIBRARIES = libbacklight.la
+libbacklight_la_SOURCES = libbacklight.c libbacklight.h
+libatasmart_la_CFLAGS = $(PCIACCESS_CFLAGS)
+
+ACLOCAL_AMFLAGS = -I m4 \ No newline at end of file
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..f37d0f3
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,15 @@
+AC_PREREQ(2.63)
+
+AC_INIT([libbacklight], 0.01, [mjg@redhat.com])
+AC_CONFIG_SRCDIR([libbacklight.c])
+AC_CONFIG_MACRO_DIR(m4)
+
+AM_INIT_AUTOMAKE([foreign 1.11 -Wall])
+
+AC_CANONICAL_HOST
+AM_SILENT_RULES([yes])
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.11.0])
+AC_CONFIG_FILES([Makefile libbacklight.pc]) \ No newline at end of file
diff --git a/libbacklight.c b/libbacklight.c
new file mode 100644
index 0000000..2354829
--- /dev/null
+++ b/libbacklight.c
@@ -0,0 +1,231 @@
+#define _GNU_SOURCE
+
+#include <libbacklight.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <string.h>
+
+static const char *output_names[] = { "None",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "TV",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+};
+
+static long backlight_get(struct backlight *backlight, char *node)
+{
+ char buffer[100];
+ char *path;
+ int fd;
+ long value, ret;
+
+ asprintf(&path, "%s/%s", backlight->path, node);
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = read(fd, &buffer, sizeof(buffer));
+ if (ret < 1) {
+ ret = -1;
+ goto out;
+ }
+
+ value = strtol(buffer, NULL, 10);
+ ret = value;
+out:
+ close(fd);
+ if (path)
+ free(path);
+ return ret;
+}
+
+long backlight_get_brightness(struct backlight *backlight)
+{
+ return backlight_get(backlight, "brightness");
+}
+
+long backlight_get_max_brightness(struct backlight *backlight)
+{
+ return backlight_get(backlight, "max_brightness");
+}
+
+long backlight_get_actual_brightness(struct backlight *backlight)
+{
+ return backlight_get(backlight, "actual_brightness");
+}
+
+long backlight_set_brightness(struct backlight *backlight, long brightness)
+{
+ char *path;
+ char *buffer = NULL;
+ int fd;
+ long value, ret;
+
+ asprintf(&path, "%s/%s", backlight->path, "brightness");
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = read(fd, &buffer, sizeof(buffer));
+ if (ret < 1) {
+ ret = -1;
+ goto out;
+ }
+
+ asprintf(&buffer, "%ld", brightness);
+ ret = write(fd, buffer, strlen(buffer));
+ if (ret < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = backlight_get_brightness(backlight);
+out:
+ if (buffer)
+ free(buffer);
+ if (path)
+ free(path);
+ close(fd);
+ return ret;
+}
+
+struct backlight *backlight_init(struct pci_device *dev, int card,
+ int connector_type, int connector_type_id)
+{
+ char *pci_name;
+ char *drm_name;
+ char *chosen_path = NULL;
+ DIR *backlights;
+ struct dirent *entry;
+ enum backlight_type type = 0;
+ char buffer[100];
+ struct backlight *backlight;
+
+ asprintf(&pci_name, "%04x:%02x:%02x.%d", dev->domain, dev->bus,
+ dev->dev, dev->func);
+ asprintf(&drm_name, "card%d-%s-%d", card, output_names[connector_type],
+ connector_type_id);
+
+ backlights = opendir("/sys/class/backlight");
+
+ if (!backlights)
+ return NULL;
+
+ while ((entry = readdir(backlights))) {
+ char *backlight_path;
+ char *parent;
+ char *path;
+ enum backlight_type entry_type;
+ int fd, ret;
+
+ if (entry->d_name[0] == '.')
+ continue;
+
+ asprintf(&backlight_path, "%s/%s", "/sys/class/backlight",
+ entry->d_name);
+ asprintf(&path, "%s/%s", backlight_path, "type");
+ fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ goto out;
+
+ ret = read (fd, &buffer, sizeof(buffer));
+ close (fd);
+
+ if (ret < 1)
+ goto out;
+
+ buffer[ret] = '\0';
+
+ if (!strncmp(buffer, "raw\n", sizeof(buffer)))
+ entry_type = BACKLIGHT_RAW;
+ else if (!strncmp(buffer, "platform\n", sizeof(buffer)))
+ entry_type = BACKLIGHT_PLATFORM;
+ else if (!strncmp(buffer, "firmware\n", sizeof(buffer)))
+ entry_type = BACKLIGHT_FIRMWARE;
+ else
+ goto out;
+
+ free (path);
+ asprintf(&path, "%s/%s", backlight_path, "device");
+ ret = readlink(path, buffer, sizeof(buffer));
+
+ if (ret < 0)
+ goto out;
+
+ parent = basename(buffer);
+
+ if (entry_type == BACKLIGHT_RAW) {
+ if (strcmp(drm_name, parent) &&
+ strcmp(pci_name, parent)) {
+ goto out;
+ }
+ }
+
+ if (entry_type == BACKLIGHT_FIRMWARE) {
+ /* Older kernels won't provide a valid path here... */
+ unsigned int domain, bus, device, function;
+ ret = sscanf(parent, "%04x:%02x:%02x.%u", &domain, &bus,
+ &device, &function);
+ if (ret == 4) {
+ if (strcmp(pci_name, parent))
+ goto out;
+ }
+ }
+
+ if (entry_type < type)
+ goto out;
+
+ type = entry_type;
+
+ if (chosen_path)
+ free(chosen_path);
+ chosen_path = strdup(backlight_path);
+
+ out:
+ free(backlight_path);
+ free(path);
+ }
+
+ if (!chosen_path)
+ return NULL;
+
+ backlight = malloc(sizeof(struct backlight));
+
+ if (!backlight)
+ goto err;
+
+ backlight->path = chosen_path;
+ backlight->type = type;
+
+ backlight->max_brightness = backlight_get_max_brightness(backlight);
+ if (backlight->max_brightness < 0)
+ goto err;
+
+ backlight->brightness = backlight_get_actual_brightness(backlight);
+ if (backlight->brightness < 0)
+ goto err;
+
+ return backlight;
+err:
+ if (chosen_path)
+ free(chosen_path);
+ free (backlight);
+ return NULL;
+}
diff --git a/libbacklight.h b/libbacklight.h
new file mode 100644
index 0000000..20981bd
--- /dev/null
+++ b/libbacklight.h
@@ -0,0 +1,20 @@
+#include <pciaccess.h>
+
+enum backlight_type {
+ BACKLIGHT_RAW,
+ BACKLIGHT_PLATFORM,
+ BACKLIGHT_FIRMWARE,
+};
+
+struct backlight {
+ char *path;
+ int max_brightness;
+ int brightness;
+ enum backlight_type type;
+};
+
+struct backlight *backlight_init(struct pci_device *dev, int card,
+ int connector_type, int connector_type_id);
+long backlight_get_brightness(struct backlight *backlight);
+long backlight_get_max_brightness(struct backlight *backlight);
+long backlight_set_brightness(struct backlight *backlight, long brightness);
diff --git a/libbacklight.pc.in b/libbacklight.pc.in
new file mode 100644
index 0000000..f70bc0f
--- /dev/null
+++ b/libbacklight.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=${prefix}
+libdir=@libdir@
+includedir=${prefix}/include
+
+Name: libbacklight
+Description: Linux backlight interface library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lbacklight
+Cflags: -I${includedir}
+Requires: