#include #include #include #include #include #include #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define ABS(x) ((x) < 0 ? -(x) : (x)) #define MEDIAN_SAMPLES 4 const char *LUMINANCE_DEV = "/sys/bus/iio/devices/iio:device0/in_illuminance_raw"; const char *MAX_BRIGHTNESS_DEV = "/sys/class/backlight/intel_backlight/max_brightness"; const char *BRIGHTNESS_DEV = "/sys/class/backlight/intel_backlight/brightness"; const char *ACTUAL_BRIGHTNESS_DEV = "/sys/class/backlight/intel_backlight/actual_brightness"; char STR_BUFFER[128] = {0}; // file pointer to the luminance device FILE *luminance_fp = NULL; // max luminance that the display can output int max_luminance = 400; // minimum display brightness in percent float min_brightness_percent = 0.05; // returns the luminance value in percentage between 0 and 1 int get_luminance_raw (void) { const char *x = fgets(STR_BUFFER, sizeof(STR_BUFFER), luminance_fp); if (x == NULL) { fprintf(stderr, "Could not read luminance value: %s\n", strerror(errno)); return -1; } int luminance = strtol(STR_BUFFER, NULL, 10); rewind(luminance_fp); return luminance; } int read_int(FILE *fp) { fflush(fp); const char *p = fgets(STR_BUFFER, sizeof(STR_BUFFER), fp); if (p == NULL) { return -1; } long r = strtol(STR_BUFFER, NULL, 10); if (r == LONG_MIN || r == LONG_MAX) { return -1; } rewind(fp); return r; } int main (void) { // open the luminance device luminance_fp = fopen(LUMINANCE_DEV, "r"); if (luminance_fp == NULL) { fprintf(stderr, "Could not open luminance device '%s': %s\n", LUMINANCE_DEV, strerror(errno)); return 1; } // get max and min brightness FILE *fp = fopen(MAX_BRIGHTNESS_DEV, "r"); if (fp == NULL) { fprintf(stderr, "Could not open max_brightness file '%s': %s\n", MAX_BRIGHTNESS_DEV, strerror(errno)); return 1; } int max_brightness = read_int(fp); if (max_brightness < 0) { fprintf(stderr, "Could not read max brightness value: %s\n", strerror(errno)); return 1; } int min_brightness = max_brightness * min_brightness_percent; fclose(fp); // open brightness device FILE *brightness_fp = fopen(BRIGHTNESS_DEV, "w"); if (brightness_fp == NULL) { fprintf(stderr, "Could not open brightness device '%s': %s\n", BRIGHTNESS_DEV, strerror(errno)); return 1; } // open actual brightness device FILE *actual_brightness_fp = fopen(ACTUAL_BRIGHTNESS_DEV, "r"); if (brightness_fp == NULL) { fprintf(stderr, "Could not open actual brightness device '%s': %s\n", ACTUAL_BRIGHTNESS_DEV, strerror(errno)); return 1; } int x = get_luminance_raw(); int luminance_samples[MEDIAN_SAMPLES] = {x, x, x, x}; int idx = 0; int user_offset = 0; int brightness_target = min_brightness; int brightness_old = min_brightness; int brightness_adjusted = min_brightness; int brightness_delta = 0; while (1) { static float luminance; static float luminance_percent; x = get_luminance_raw(); if (x >= 0) luminance_samples[idx] = x; idx = (idx + 1) % MEDIAN_SAMPLES; luminance = 0; for (int i = 0; i < MEDIAN_SAMPLES; i++) { luminance += luminance_samples[i] / MEDIAN_SAMPLES; } luminance_percent = MIN(luminance/max_luminance, 1.0); brightness_old = brightness_target; brightness_target = MAX((int)(luminance_percent * max_brightness), min_brightness); brightness_delta = ABS((float)(brightness_target - brightness_old)/brightness_old); // if the brightness changes by more than 10% reduce the user offset, scaling // with the delta, this accounts for large changes in brightness no longer // corresponding to the adjustments that the user made to the brightness if (brightness_delta > 0.1) { user_offset = user_offset * MAX(MIN(1-(brightness_delta*1.2), 1), 0); } brightness_adjusted = MIN(MAX(brightness_target + user_offset, min_brightness), max_brightness); x = snprintf(STR_BUFFER, sizeof(STR_BUFFER), "%d", brightness_adjusted); if (x <= 0) { fprintf(stderr, "Error in snprintf(): %s\n", strerror(errno)); } if (fputs(STR_BUFFER, brightness_fp) == EOF) { fprintf(stderr, "error writing brightness: %s\n", strerror(errno)); } rewind(brightness_fp); sleep(3); // read actual brightness to get the user offset int actual_brightness = 0; int off = 0; actual_brightness = read_int(actual_brightness_fp); if (actual_brightness < 0) { fprintf(stderr, "error reading actual brightness: %s\n", strerror(errno)); actual_brightness = brightness_adjusted; } off = actual_brightness - brightness_target; if (brightness_target != max_brightness || off < 0){ user_offset = off; } printf("brightness target: %d; user offset: %d; brightness adjusted: %d\n", brightness_target, user_offset, brightness_adjusted); } return 0; }