163 lines
4.8 KiB
C
163 lines
4.8 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
|
|
#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;
|
|
|
|
// retturns 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.0;
|
|
}
|
|
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;
|
|
|
|
luminance_samples[idx] = get_luminance_raw();
|
|
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_target;
|
|
}
|
|
|
|
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\n", brightness_target, user_offset, brightness_adjusted);
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|