/* * This file is part of fwm-sysdaemon * backlight.c * * Copyright (c) 2019, 2022 firk (firk@cantconnect.ru) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. * 4. Altered versions in any form must be plainly marked as such, and * must not be misinterpreted as being the original software. * * This software is provided by the author and contributors `as is' * without any express or implied warranty. */ #include #include #include #include #include #include #include #include "config.h" #include "util.h" #include "backlight.h" typedef struct { int valid; char path[256]; int min; int range; int values[101]; } bl_dev; static bl_dev bl; static char const *bl_find(void) { static char name[200]; DIR *dp; struct dirent *de; int found; size_t len; found = 0; dp = opendir("/sys/class/backlight"); while(de=readdir(dp)) { if(de->d_name[0]=='.') continue; if((len = strlen(de->d_name))>100) continue; if(!found) { found = 1; bcopy(de->d_name, name, len); name[len] = 0; } else if(found==1) { found = 2; printlog("multiple backlight devices found, you may select needed one manually if you want"); printlog("backlight device: %S", name); printlog("backlight device: %S", de->d_name); } else { printlog("backlight device: %S", de->d_name); } } closedir(dp); return (found?name:NULL); } extern int bl_init(char const *name, int raw_max, int max, int linear) { char path[256]; int fd, i, raw_cur, raw_new, rem; if(!name && !(name = bl_find()) || !*name) { printlog("can't find backlight device, you may try to specify one manually"); return -1; } if(strlen(name)>100) { printlog("backlight device %\"S name too long", name); return -1; } snprintf(bl.path, sizeof(bl.path), "/sys/class/backlight/%s/brightness", name); if(raw_max<=0) { snprintf(path, sizeof(path), "/sys/class/backlight/%s/max_brightness", name); if((fd = open(path,O_RDONLY))<0) { printlog("can't open %\"S", path); return -1; } raw_max = fd_get_int_S(fd); close(fd); if(raw_max<=0) { printlog("can't read %\"S or it is malformed", path); return -1; } } if(max<=0 || max>100) max = 100; printlog("using backlight device %\"S raw values 0..%d for 0..%d", name, raw_max, max); bl.min = 0; bl.range = max+1; bl.values[0] = raw_cur = 1; for(i=1; i<=max; i++) { if(i==max) raw_cur = raw_max; else { rem = max-i; raw_new = (int)(pow(((double)raw_cur)/raw_max, ((double)rem)/(rem+1))*raw_max); if(raw_new>raw_cur && raw_new<=raw_max) raw_cur = raw_new; else raw_cur++; } bl.values[i] = raw_cur; } bl.valid = 1; return 0; } extern int bl_set(int v) { int fd; if(!bl.valid) return -1; if(vbl.range) v = bl.range; v = bl.values[v]; if((fd = open(bl.path,O_WRONLY))<0) return -1; if(fd_set_int_S(fd, v)<0) { close(fd); return -1; } close(fd); return 0; } extern int bl_get(void) { int fd, v, j; if(!bl.valid) return -1; if((fd = open(bl.path,O_RDONLY))<0) return -1; if((v=fd_get_int_S(fd))<0) { close(fd); return -1; } close(fd); j = bl.range-1; while(j && v<(bl.values[j-1] + (bl.values[j] - bl.values[j-1] + 1)/2)) j--; return j+bl.min; }