From 1bfcc97d036ea73da87ee39fe70194380efe333e Mon Sep 17 00:00:00 2001 From: rexy712 Date: Fri, 12 Jan 2018 16:06:48 -0800 Subject: [PATCH] Works with multiple backlights now --- TODO | 3 + brightness | 1 + makefile | 2 + rexbacklight.c | 213 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 151 insertions(+), 68 deletions(-) create mode 100644 TODO create mode 100644 brightness diff --git a/TODO b/TODO new file mode 100644 index 0000000..6fec1b4 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +Individual device control +Query backlight percentage (get) +allow fade in and fade out diff --git a/brightness b/brightness new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/brightness @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/makefile b/makefile index afb1a7c..f1706cf 100644 --- a/makefile +++ b/makefile @@ -9,6 +9,8 @@ rexbacklight: rexbacklight.c install: install -m4711 -o root -g root -s rexbacklight /usr/bin/rexbacklight +.PHONY: uninstall + rm /usr/bin/rexbacklight .PHONY: clean clean: rm rexbacklight diff --git a/rexbacklight.c b/rexbacklight.c index a0334da..83f28db 100644 --- a/rexbacklight.c +++ b/rexbacklight.c @@ -21,8 +21,12 @@ #include #include #include +#include +#include -void usage(void){ +static const char* backlight_dir = "/sys/class/backlight/"; + +void usage(int exit_val){ fprintf(stderr, "Usage: rexbacklight [option]\n\n"); fprintf(stderr, "Options:\n"); @@ -33,13 +37,15 @@ void usage(void){ fprintf(stderr, " max\n"); fprintf(stderr, " min\n"); - fprintf(stderr, "\nrexbacklight Copyright (C) 2018 rexy712\n"); - fprintf(stderr, "This program comes with ABSOLUTELY NO WARRANTY.\n"); - fprintf(stderr, "This is free software, and you are welcome to redistribute it\n"); - fprintf(stderr, "under certain conditions; see the GNU GPLv3 for details.\n"); - fprintf(stderr, "A copy of the GPLv3 is available with the source in the file 'LICENSE'\n"); + if(!exit_val){ + fprintf(stderr, "\nrexbacklight Copyright (C) 2018 rexy712\n"); + fprintf(stderr, "This program comes with ABSOLUTELY NO WARRANTY.\n"); + fprintf(stderr, "This is free software, and you are welcome to redistribute it\n"); + fprintf(stderr, "under certain conditions; see the GNU GPLv3 for details.\n"); + fprintf(stderr, "A copy of the GPLv3 is available with the source in the file 'LICENSE'\n"); + } - exit(-1); + exit(exit_val); } int check_valid_files(const char* f1, const char* f2){ @@ -63,6 +69,47 @@ int check_valid_files(const char* f1, const char* f2){ return 0; } +struct string_array{ + char** list; + int size; +}; + +//Get a list of backlight devices in sysfs +struct string_array get_backlight_sources(void){ + + DIR* fd; + struct dirent* dir; + + fd = opendir(backlight_dir); + if(!fd){ + fprintf(stderr, "Unable to open '%s' for reading!\n", backlight_dir); + return (struct string_array){.list = NULL, .size = 0}; + } + + char** list = malloc(sizeof(const char*) * 8); + int i; + + for(i = 0;(dir = readdir(fd));){ + if(!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")){ + continue; + } + list[i] = malloc(strlen(dir->d_name) + 1); + strcpy(list[i], dir->d_name); + i++; + } + + closedir(fd); + + return (struct string_array){.list = list, .size = i}; +} + + +void free_string_array(struct string_array* s){ + for(int i = 0;i < s->size;i++) + free(s->list[i]); + free(s->list); +} + int get_brightness(const char* file){ FILE* bright = fopen(file, "r"); char buff[127]; @@ -79,89 +126,119 @@ int get_brightness(const char* file){ return atof(buff); } +int process_arg(char* arg, float min, float current, float max){ + //Amount to inc/dec + int delta = delta = max * atof(arg + 1) / 100.0; + + //Increment + if(arg[0] == '+'){ + delta = delta + current; + if(delta >= max) + return max; + else{ + return delta; + } + + //Decrement + }else if(arg[0] == '-'){ + delta = current - delta; + if(delta <= min) + return min; + else + return delta; + + //Directly set + }else if(arg[0] == '='){ + if(delta >= max) + return max; + else if(delta <= min) + return min; + else + return delta; + + //Set to minimum plus one (so backlight is actually on!) + }else if(!strcmp("min", arg)){ + return min + 1; + + //Turn off backlight + }else if(!strcmp("off", arg)){ + return min; + + //Set to maximum + }else if(!strcmp("max", arg)){ + return max; + //Unknown option + }else{ + usage(-1); + } + return current; +} + //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"; + const char* backlight_file = "brightness"; + const char* max_backlight_file = "max_brightness"; //Make sure we have an argument and it is at least 2 characters long - if(argc < 2 || strlen(argv[1]) < 2) - usage(); - else if(!strcmp(argv[1], "--help")) - usage(); + if(argc < 2 || !strcmp(argv[1], "--help")) + usage(0); + else if(strlen(argv[1]) < 2) + usage(-1); + //Gain access to sysfs files if(setuid(0)){ fprintf(stderr, "Unable to setuid to 0!\n"); return -3; } + //Make sure we aren't in a chroot environment (prevents writing to a file we don't want to!) 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); + //Now that we've verified we're in a safe environment to do the work, + //Let's get everything set up! - //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; + //Acquire a list of backlight devices in sysfs + struct string_array backlight_names = get_backlight_sources(); + if(backlight_names.size == 0){ + fprintf(stderr, "No backlights devices found!\n"); + 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); + //save our starting directory so we can change to each backlight directory + const char* starting_dir = getcwd(NULL, 0); + + if(chdir(backlight_dir)){ + fprintf(stderr, "Unable to read backlight sysfs directory!\n"); + return -2; + } + + //Set all backlight sources to the requested percentage + for(int i = 0;i < backlight_names.size;i++){ + if(chdir(backlight_names.list[i])){ + fprintf(stderr, "Unable to open backlight directory \"%s%s\"!\n", backlight_dir, backlight_names.list[i]); + continue; } - //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); + //Open brightness file for writing + int out = process_arg(argv[1], 0, get_brightness(backlight_file), get_brightness(max_backlight_file)); + FILE* bright = fopen(backlight_file, "w+"); + if(!bright){ + fprintf(stderr, "Unable to open brightness file \"%s\" for writing!\n", backlight_file); + continue; + } + fprintf(bright, "%d", out); - //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); + free_string_array(&backlight_names); + if(chdir(starting_dir)){ + fprintf(stderr, "Could not return to starting directory!\nWas the directory moved/deleted?\n"); + if(chdir(getenv("HOME")) || chdir("/")){ + return -5; + } + } return 0; }