backlight: search for card in Linux

Fri, 20 Sep 2019 07:19:30 +0200

author
David Demelier <markand@malikania.fr>
date
Fri, 20 Sep 2019 07:19:30 +0200
changeset 10
2b12d8bee90d
parent 9
bd47bd0c977a
child 11
637ef49be6c9

backlight: search for card in Linux

backlight.c file | annotate | diff | comparison | revisions
--- a/backlight.c	Thu Sep 19 21:05:00 2019 +0200
+++ b/backlight.c	Fri Sep 20 07:19:30 2019 +0200
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define _POSIX_C_SOURCE 200809L
+
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -111,72 +113,100 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#define SYS_PATH "/sys/class/backlight"
 
 static int
-read_int(const char *path)
+read_int(int dfd, const char *file)
 {
-	FILE *fp;
-	int value = 0;
+	char buf[32] = {0};
+	int fd;
 
-	if ((fp = fopen(path, "r")) == NULL)
+	if ((fd = openat(dfd, file, O_RDONLY)) < 0)
 		die("open: %s\n", strerror(errno));
-	if (fscanf(fp, "%d", &value) != 1)
-		die("could not read value from %s\n", path);
+	if (read(fd, &buf[0], sizeof (buf) - 1) < 0)
+		die("read: %s\n", strerror(errno));
+
+	close(fd);
+
+	return atoi(buf);
+}
 
-	fclose(fp);
+static int
+write_int(int dfd, const char *file, int value)
+{
+	char buf[32] = {0};
+	int length;
+	int fd;
 
-	return value;
+	if ((fd = openat(dfd, file, O_WRONLY)) < 0)
+		die("open: %s\n", strerror(errno));
+	if ((length = snprintf(buf, sizeof (buf), "%d\n", value)) < 0)
+		die("snprintf: %s\n", strerror(errno));
+	if (write(fd, buf, length) != length)
+		die("write: %s\n", strerror(errno));
+
+	/* Re-read in case kernel change the value. */
+	return read_int(dfd, "brightness");
 }
 
 static int
-write_int(const char *path, int value)
+try_adaptor(int parent_fd, const char *path)
 {
-	FILE *fp;
+	int dfd;
+	struct stat st;
 
-	if ((fp = fopen(path, "w+")) == NULL)
-		die("open: %s\n", strerror(errno));
+	if ((dfd = openat(parent_fd, path, O_RDONLY)) < 0)
+		return -1;
+	if (fstatat(dfd, "brightness", &st, 0) < 0) {
+		close(dfd);
+		return -1;
+	}
 
-	fprintf(fp, "%d", value);
-
-	return value;
+	return dfd;
 }
 
-static const char *
-find_card(void)
+static int
+find_adaptor(void)
 {
-	static const char *list[] = {
-		"/sys/class/backlight/acpi_video0",
-		"/sys/class/backlight/intel_backlight",
-		NULL
-	};
+	int dfd, adaptorfd = -1;
+	DIR *dirp;
+	struct dirent *dirent;
+
+	if ((dfd = open(SYS_PATH, O_RDONLY)) < 0)
+		die("open: %s: %s\n", SYS_PATH, strerror(errno));
+	if (!(dirp = fdopendir(dfd)))
+		die("fdopendir: %s: %s\n", SYS_PATH, strerror(errno));
 
-	struct stat st;
+	while ((dirent = readdir(dirp))) {
+		if (strcmp(dirent->d_name, ".") == 0 ||
+		    strcmp(dirent->d_name, "..") == 0)
+			continue;
 
-	for (const char **ptr = list; *ptr != NULL; ++ptr)
-		if (stat(*ptr, &st) >= 0)
-			return *ptr;
+		if ((adaptorfd = try_adaptor(dfd, dirent->d_name)) >= 0)
+			break;
+	}
 
-	return NULL;
+	closedir(dirp);
+	close(dfd);
+
+	return adaptorfd;
 }
 
 static int
 set(int type)
 {
 	int current, max;
-	char file[BUFSIZ];
-	const char *card = find_card();
+	int dfd;
 
-	/* Find a card adaptor */
-	if (!card)
+	if ((dfd = find_adaptor()) < 0)
 		die("could not find card adaptor\n");
 
-	/* Read actual */
-	snprintf(file, sizeof (file), "%s/actual_brightness", card);
-	current = read_int(file);
-
-	/* Read max */
-	snprintf(file, sizeof (file), "%s/max_brightness", card);
-	max = read_int(file);
+	current = read_int(dfd, "actual_brightness");
+	max = read_int(dfd, "max_brightness");
 
 	if (type == Up) {
 		current += max / 100;
@@ -190,9 +220,7 @@
 			return 0;
 	}
 
-	snprintf(file, sizeof (file), "%s/brightness", card);
-
-	return write_int(file, current);
+	return write_int(dfd, "brightness", current);
 }
 
 #else
@@ -229,6 +257,4 @@
 		return 1;
 
 	printf("switching to %d\n", st);
-
-	return 0;
 }

mercurial