Mercurial > backlight
view backlight.c @ 16:0d923f0155dd
doc: improve documentation
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 11 Oct 2019 13:12:26 +0200 |
parents | 282ec7c30c04 |
children | 37d1b7dd73ee |
line wrap: on
line source
/* * main.c -- adjust laptop backlight using ACPI * * Copyright (c) 2010-2019 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* * Functions to implement for your system: * * All of these functions are allowed to exit on failures. */ /* Increase to the nearest upper level */ static void increase(void); /* Decrease to the nearest lower level */ static void decrease(void); /* Set the level explicitly to the nearest value */ static void set(unsigned int); /* Get the current value */ static unsigned int get(void); static void usage(const char *name) { fprintf(stderr, "usage: %s decrease\n", name); fprintf(stderr, " %s get\n", name); fprintf(stderr, " %s increase\n", name); fprintf(stderr, " %s set percentage\n", name); exit(1); } static void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "abort: "); vfprintf(stderr, fmt, ap); va_end(ap); exit(1); } /* {{{ Support for FreeBSD */ #if defined(__FreeBSD__) #include <sys/types.h> #include <sys/sysctl.h> static int set(enum action type) { int current, next = 0, i; int msg[100]; size_t len, nextlen; /* First, get all values availables */ len = sizeof (msg); if (sysctlbyname("hw.acpi.video.lcd0.levels", msg, &len, NULL, 0) == -1) die("sysctl: %s\n", strerror(errno)); /* Get the current value */ len = sizeof (current); if (sysctlbyname("hw.acpi.video.lcd0.brightness", ¤t, &len, NULL, 0) == -1) die("sysctl: %s\n", strerror(errno)); /* First find the index of 0 */ for (i = 0; msg[i] != 0; ++i) continue; /* Find the current value index in msg */ for (; msg[i] != current; ++i) continue; if (type == Up) { if (msg[i] >= 100) return msg[i]; next = msg[i + 1]; } else { if (msg[i] == 0) return 0; next = msg[i - 1]; } nextlen = sizeof (next); if (sysctlbyname("hw.acpi.video.lcd0.brightness", ¤t, &len, &next, nextlen) == -1) die("sysctl: %s\n", strerror(errno)); return next; } /* }}} */ /* {{{ Support for Linux */ #elif defined(__linux__) #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <fcntl.h> #include <unistd.h> #define SYS_PATH "/sys/class/backlight" static unsigned int read_int(int dfd, const char *file) { char buf[32] = {0}; int fd; if ((fd = openat(dfd, file, O_RDONLY)) < 0) die("open: %s\n", strerror(errno)); if (read(fd, &buf[0], sizeof (buf) - 1) < 0) die("read: %s\n", strerror(errno)); close(fd); return atoi(buf); } static int write_int(int dfd, const char *file, unsigned int value) { char buf[32] = {0}; int length; int fd; 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 try_adaptor(int parent_fd, const char *path) { int dfd; struct stat st; if ((dfd = openat(parent_fd, path, O_RDONLY)) < 0) return -1; if (fstatat(dfd, "brightness", &st, 0) < 0) { close(dfd); return -1; } return dfd; } static int find_adaptor(void) { 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)); while ((dirent = readdir(dirp))) { if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) continue; if ((adaptorfd = try_adaptor(dfd, dirent->d_name)) >= 0) break; } closedir(dirp); close(dfd); if (adaptorfd < 0) die("could not find card adaptor\n"); return adaptorfd; } static unsigned int downscale(int dfd, unsigned int value) { return value * 100 / read_int(dfd, "max_brightness"); } static unsigned int upscale(int dfd, unsigned int value) { return value * read_int(dfd, "max_brightness") / 100; } static void set(unsigned int percent) { int dfd = find_adaptor(); unsigned int value = upscale(dfd, percent); write_int(dfd, "brightness", value); } static void increase(void) { unsigned int value = get(); if (value + 2 > 100) value = 100; else value += 2; set(value); } static void decrease(void) { unsigned int value = get(); if ((int)value - 2 < 0) value = 0; else value -= 2; set(value); } static unsigned int get(void) { int dfd = find_adaptor(); int value = read_int(dfd, "brightness"); return downscale(dfd, value); } /* }}} */ /* {{{ Non supported shims */ #else static void notsupported(void) { die("backlight is not supported on this system\n"); } static void increase(void) { notsupported(); } static void decrease(void) { notsupported(); } static void set(unsigned int v) { (void)v; notsupported(); } static unsigned int get(void) { notsupported(); return -1; } #endif /* }}} */ int main(int argc, char *argv[]) { -- argc; ++ argv; if (argc < 1) usage(argv[0]); if (strcmp(argv[0], "get") == 0) printf("%d\n", get()); else if (strcmp(argv[0], "set") == 0) { if (argc != 2) usage(argv[0]); set(atoi(argv[1])); } else if (strcmp(argv[0], "increase") == 0) increase(); else if (strcmp(argv[0], "decrease") == 0) decrease(); }