From a7233af252e6692ea407fbabf7a37daf197c4409 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Thu, 11 Jan 2018 17:26:36 -0800 Subject: [PATCH] Backlight control for thinkpad --- .gitignore | 4 ++ makefile | 14 ++++++ rexbacklight.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 .gitignore create mode 100644 makefile create mode 100644 rexbacklight.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..437da04 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.d +rexbacklight +*.swp diff --git a/makefile b/makefile new file mode 100644 index 0000000..afb1a7c --- /dev/null +++ b/makefile @@ -0,0 +1,14 @@ +.PHONY: all +all: rexbacklight + +rexbacklight: rexbacklight.c + gcc -std=c11 -O2 -Wall -Wextra -pedantic rexbacklight.c -o rexbacklight + strip --strip-all rexbacklight + +.PHONY: install +install: + install -m4711 -o root -g root -s rexbacklight /usr/bin/rexbacklight + +.PHONY: clean +clean: + rm rexbacklight diff --git a/rexbacklight.c b/rexbacklight.c new file mode 100644 index 0000000..587720a --- /dev/null +++ b/rexbacklight.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +void usage(void){ + fprintf(stderr, "TODO: usage\n"); + exit(-1); +} + +int check_valid_files(const char* f1, const char* f2){ + struct stat file1, file2; + if(stat(f1, &file1)){ + printf("failed to open '%s'\n", f1); + return -1; + } + if(stat(f2, &file2)){ + printf("failed to open '%s'\n", f2); + return -1; + } + //Same device and same inode means same file + + //device id + if(file1.st_dev != file2.st_dev) + return -2; + //inode number + if(file1.st_ino != file2.st_ino) + return -2; + return 0; +} + +int get_brightness(const char* file){ + FILE* bright = fopen(file, "r"); + char buff[127]; + if(!bright){ + fprintf(stderr, "Unable to open brightness file \"%s\"!\n", file); + return 0; + } + if(!fgets(buff, sizeof(buff), bright)){ + fprintf(stderr, "Unable to read file \"%s\"!\n", file); + fclose(bright); + return 0; + } + fclose(bright); + return atof(buff); +} + +//argv[1] shall be [+-=]|min|max|off +int main(int argc, char** argv){ + const char* backlight_file = "/sys/class/backlight/intel_backlight/brightness"; + const char* max_backlight_file = "/sys/class/backlight/intel_backlight/max_brightness"; + + //Make sure we have an argument and it is at least 2 characters long + if(argc < 2 || strlen(argv[1]) < 2) + usage(); + + if(setuid(0)){ + fprintf(stderr, "Unable to setuid to 0!\n"); + return -3; + } + + if(check_valid_files("/", "/proc/1/root")){ + fprintf(stderr, "No chroot today\n"); + return -4; + } + + //Min brightness is just 0, so set it up front + float min_brightness = 0; + float max_brightness = get_brightness(max_backlight_file); + float current_brightness = get_brightness(backlight_file); + + //Amount to inc/dec + int delta; + if(strlen(argv[1]) > 0) + delta = max_brightness * atof(argv[1] + 1) / 100.0; + else + delta = 0; + + //Open brightness file for writing + FILE* bright = fopen(backlight_file, "w+"); + if(!bright){ + fprintf(stderr, "Unable to open brightness file \"%s\" for writing!\n", backlight_file); + return 1; + } + + //Increment + if(argv[1][0] == '+'){ + delta = delta + current_brightness; + if(delta >= max_brightness) + fprintf(bright, "%d", (int)max_brightness); + else{ + fprintf(bright, "%d", delta); + } + + //Decrement + }else if(argv[1][0] == '-'){ + delta = current_brightness - delta; + if(delta <= min_brightness) + fprintf(bright, "%d", (int)min_brightness); + else + fprintf(bright, "%d", delta); + + //Directly set + }else if(argv[1][0] == '='){ + if(delta >= max_brightness) + fprintf(bright, "%d", (int)max_brightness); + else if(delta <= min_brightness) + fprintf(bright, "%d", (int)min_brightness); + else + fprintf(bright, "%d", delta); + + //Set to minimum plus one (so backlight is actually on!) + }else if(!strcmp("min", argv[1])){ + fprintf(bright, "%d", (int)(min_brightness + 1)); + + //Turn off backlight + }else if(!strcmp("off", argv[1])){ + fprintf(bright, "%d", (int)min_brightness); + + //Set to maximum + }else if(!strcmp("max", argv[1])){ + fprintf(bright, "%d", (int)max_brightness); + + //Unknown option + }else{ + fclose(bright); + usage(); + } + fclose(bright); + return 0; +}