Some cleanup work
This commit is contained in:
parent
dbfa9b9d12
commit
04dcd0684a
@ -38,6 +38,8 @@ else()
|
||||
set(enable_RESTORE_FILE "")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DREXBACKLIGHT_DEBUG")
|
||||
|
||||
configure_file(
|
||||
"${INCLUDE_PATH}/config.h.in"
|
||||
"${INCLUDE_PATH}/config.h"
|
||||
|
||||
@ -56,7 +56,10 @@ struct arg_values{
|
||||
|
||||
int fade_steps;
|
||||
|
||||
unsigned char operation;
|
||||
union{
|
||||
int operation;
|
||||
int num_values;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -19,6 +19,12 @@
|
||||
#ifndef REXBACKLIGHT_COMMON_H
|
||||
#define REXBACKLIGHT_COMMON_H
|
||||
|
||||
#ifdef REXBACKLIGHT_DEBUG
|
||||
#define DEBUG_PRINT(s, ...) printf(s, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINT(s, ...)
|
||||
#endif
|
||||
|
||||
#define RETVAL_INVALID_FILE 1
|
||||
#define RETVAL_INVALID_DIR 2
|
||||
#define RETVAL_UNRECOGNIZED_OPTION 3
|
||||
@ -45,6 +51,7 @@ struct string_array{
|
||||
char** list;
|
||||
int size;
|
||||
};
|
||||
void free_string_array(struct string_array* s);
|
||||
|
||||
void mem_error(void);
|
||||
_Noreturn void version(void);
|
||||
|
||||
@ -155,6 +155,7 @@ struct arg_values init_arg_values(void){
|
||||
struct arg_values process_cmd_args(int argc, char** argv){
|
||||
struct arg_values ret = init_arg_values();
|
||||
struct arg_values* curr = &ret;
|
||||
int nvals = 0;
|
||||
int i;
|
||||
|
||||
//Skip argv[0]
|
||||
@ -189,6 +190,7 @@ struct arg_values process_cmd_args(int argc, char** argv){
|
||||
*(curr->next) = init_arg_values();
|
||||
curr = curr->next;
|
||||
curr->device = argv[++i];
|
||||
++nvals;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -305,6 +307,8 @@ struct arg_values process_cmd_args(int argc, char** argv){
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ret.next)
|
||||
ret.num_values = nvals;
|
||||
return ret;
|
||||
}
|
||||
#undef CHECK_OPTION
|
||||
|
||||
@ -36,6 +36,13 @@ void io_error_3(const char* error, const char* type, const char* name, const cha
|
||||
fprintf(stderr, "Unable to %s %s '%s%s%s'!\n", error, type, name, name2, name3);
|
||||
}
|
||||
|
||||
//Clean up a string array
|
||||
void free_string_array(struct string_array* s){
|
||||
int i;
|
||||
for(i = 0;i < s->size;++i)
|
||||
free(s->list[i]);
|
||||
free(s->list);
|
||||
}
|
||||
|
||||
void mem_error(void){
|
||||
fprintf(stderr, "Failed to allocate memory! Unable to continue!\n");
|
||||
|
||||
@ -53,14 +53,6 @@ const char* restore_file_suffix(void){return "/.config/rexledctl.json";}
|
||||
const char* brightness_file(void){return "brightness";}
|
||||
const char* max_brightness_file(void){return "max_brightness";}
|
||||
|
||||
//Clean up a string array
|
||||
void free_string_array(struct string_array* s){
|
||||
int i;
|
||||
for(i = 0;i < s->size;++i)
|
||||
free(s->list[i]);
|
||||
free(s->list);
|
||||
}
|
||||
|
||||
//Get a list of led/backlight devices in sysfs
|
||||
struct string_array get_device_sources(void){
|
||||
DIR* fd;
|
||||
@ -83,8 +75,6 @@ struct string_array get_device_sources(void){
|
||||
return arr;
|
||||
}
|
||||
|
||||
#define MEMORY_ERROR() do{mem_error();return_value = RETVAL_MEM_ERROR;free_string_array(&arr);closedir(fd);}while(0)
|
||||
|
||||
for(arr.size = 0;(dir = readdir(fd));){
|
||||
int slen;
|
||||
if(!strncmp(dir->d_name, ".", 1) || !strncmp(dir->d_name, "..", 2)){
|
||||
@ -93,13 +83,15 @@ struct string_array get_device_sources(void){
|
||||
|
||||
//Resize list if more than 8 led/backlight devices exist (not likely)
|
||||
if(arr.size >= list_size){
|
||||
int j;
|
||||
char** tmp = malloc(sizeof(const char*) * (list_size += 8));
|
||||
if(!tmp){
|
||||
MEMORY_ERROR();
|
||||
mem_error();
|
||||
return_value = RETVAL_MEM_ERROR;
|
||||
free_string_array(&arr);
|
||||
closedir(fd);
|
||||
return (struct string_array){0};
|
||||
}
|
||||
for(j = 0;j < arr.size;++j){
|
||||
for(int j = 0;j < arr.size;++j){
|
||||
tmp[j] = arr.list[j];
|
||||
}
|
||||
free(arr.list);
|
||||
@ -109,16 +101,17 @@ struct string_array get_device_sources(void){
|
||||
slen = strlen(dir->d_name);
|
||||
arr.list[arr.size] = malloc(slen + 1);
|
||||
if(!arr.list[arr.size]){
|
||||
MEMORY_ERROR();
|
||||
mem_error();
|
||||
return_value = RETVAL_MEM_ERROR;
|
||||
free_string_array(&arr);
|
||||
closedir(fd);
|
||||
return (struct string_array){0};
|
||||
}
|
||||
strcpy(arr.list[arr.size], dir->d_name);
|
||||
strncpy(arr.list[arr.size], dir->d_name, slen);
|
||||
arr.list[arr.size][slen] = 0;
|
||||
++arr.size;
|
||||
}
|
||||
|
||||
#undef MEMORY_ERROR
|
||||
|
||||
closedir(fd);
|
||||
return arr;
|
||||
}
|
||||
@ -142,42 +135,52 @@ float get_brightness(const char* file){
|
||||
fclose(bright);
|
||||
return atof(buff);
|
||||
}
|
||||
double get_time(void){
|
||||
struct timespec t;
|
||||
clock_gettime(CLOCK_BOOTTIME, &t);
|
||||
return ((t.tv_sec * 1000.0) + (t.tv_nsec * 0.0000001));
|
||||
}
|
||||
void sleep_for(double time){
|
||||
DEBUG_PRINT("sleeping for %lf milliseconds\n", time);
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (long)(time*0.0001);
|
||||
ts.tv_nsec = ((time) - ts.tv_sec*1000) * 1000*1000;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
//update brightness incrementally over requested millisecond time interval
|
||||
void fade_out(const char* device_name, int iv, int fv, int ms_duration, int steps){
|
||||
|
||||
void fade_out(struct arg_values* arg, int iv, int fv){
|
||||
FILE* fd;
|
||||
struct timeval start, end;
|
||||
double start, end;
|
||||
double tdelta = 0; //amount of time that has passed in ms
|
||||
float value = iv; //current value to write to file
|
||||
int step_delta = ms_duration / steps;
|
||||
int step_inc = step_delta;
|
||||
float brdelta = (float)(fv - iv) / steps; //amount brightness needs to change per iteration
|
||||
double step_delta = (double)arg->fade_duration / arg->fade_steps;
|
||||
double step_inc = step_delta;
|
||||
float brdelta = (float)(fv - iv) / arg->fade_steps; //amount brightness needs to change per iteration
|
||||
|
||||
while(ms_duration > tdelta){
|
||||
while(arg->fade_duration > tdelta){
|
||||
//write
|
||||
gettimeofday(&start, NULL);
|
||||
start = get_time();
|
||||
fd = fopen(brightness_file(), "w+");
|
||||
if(!fd){
|
||||
io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), device_name, brightness_file());
|
||||
io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), arg->device, brightness_file());
|
||||
return_value = RETVAL_INVALID_FILE;
|
||||
return;
|
||||
}
|
||||
fprintf(fd, "%d", (int)value);
|
||||
fclose(fd);
|
||||
gettimeofday(&end, NULL);
|
||||
end = get_time();
|
||||
|
||||
//calc time delta
|
||||
tdelta += (((end.tv_sec * 1000.0) + (end.tv_usec / 1000.0)) - ((start.tv_sec * 1000.0) + (start.tv_usec / 1000.0)));
|
||||
tdelta += end - start;
|
||||
|
||||
//calc next value to write
|
||||
value += brdelta;
|
||||
|
||||
//waste excess time until next step
|
||||
if(step_delta > tdelta){
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (long)((step_delta - tdelta)/1000);
|
||||
ts.tv_nsec = ((step_delta - tdelta) - ts.tv_sec*1000) * 1000*1000;
|
||||
nanosleep(&ts, NULL);
|
||||
sleep_for(step_delta - tdelta);
|
||||
tdelta = step_delta;
|
||||
}
|
||||
//calc end of next step
|
||||
@ -185,7 +188,7 @@ void fade_out(const char* device_name, int iv, int fv, int ms_duration, int step
|
||||
}
|
||||
fd = fopen(brightness_file(), "w+");
|
||||
if(!fd){
|
||||
io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), device_name, brightness_file());
|
||||
io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), arg->device, brightness_file());
|
||||
return_value = RETVAL_INVALID_FILE;
|
||||
return;
|
||||
}
|
||||
@ -198,7 +201,7 @@ void fade_out(const char* device_name, int iv, int fv, int ms_duration, int step
|
||||
void do_assignment(struct arg_values* arg, const char* device){
|
||||
int start = get_brightness(brightness_file());
|
||||
int out = process_op(arg, 0, start, get_brightness(max_brightness_file()));
|
||||
fade_out(device, start, out, arg->fade_duration, arg->fade_steps);
|
||||
fade_out(arg, start, out);
|
||||
}
|
||||
|
||||
//Run get operation
|
||||
@ -215,8 +218,7 @@ void do_get(const char* device){
|
||||
|
||||
//Run list operation
|
||||
void do_list(struct string_array* names){
|
||||
int i;
|
||||
for(i = 0;i < names->size;++i)
|
||||
for(int i = 0;i < names->size;++i)
|
||||
fprintf(stdout, "%s\n", names->list[i]);
|
||||
}
|
||||
|
||||
@ -234,6 +236,9 @@ int individual_device_op(struct arg_values* curr){
|
||||
case OP_GET:
|
||||
do_get(curr->device);
|
||||
break;
|
||||
case OP_LIST:
|
||||
printf("%s\n", curr->device);
|
||||
break;
|
||||
}
|
||||
if(chdir(device_dir())){
|
||||
io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir());
|
||||
@ -275,64 +280,26 @@ void individual_device_loop(struct arg_values* a){
|
||||
#endif
|
||||
|
||||
|
||||
//If no devices were specified, this function will run
|
||||
void all_device_loop(struct string_array* device_names, struct arg_values* args){
|
||||
int i;
|
||||
switch(args->operation){
|
||||
case OP_SET:
|
||||
case OP_INC:
|
||||
case OP_DEC:
|
||||
for(i = 0;i < device_names->size;++i){
|
||||
if(chdir(device_names->list[i])){
|
||||
io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), device_names->list[i]);
|
||||
return_value = RETVAL_INVALID_DIR;
|
||||
continue;
|
||||
}
|
||||
do_assignment(args, device_names->list[i]);
|
||||
if(chdir(device_dir())){
|
||||
io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir());
|
||||
return_value = RETVAL_INVALID_DIR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_RESTORE_FILE
|
||||
save_restore_file(device_names);
|
||||
#endif
|
||||
break;
|
||||
case OP_LIST:
|
||||
do_list(device_names);
|
||||
break;
|
||||
case OP_GET:
|
||||
for(i = 0;i < device_names->size;++i){
|
||||
if(chdir(device_names->list[i])){
|
||||
io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), device_names->list[i]);
|
||||
return_value = RETVAL_INVALID_DIR;
|
||||
continue;
|
||||
}
|
||||
do_get(device_names->list[i]);
|
||||
if(chdir(device_dir())){
|
||||
io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir());
|
||||
return_value = RETVAL_INVALID_DIR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef ENABLE_RESTORE_FILE
|
||||
case OP_RESTORE:;
|
||||
all_restore();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Internal processing error!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void populate_args(struct arg_values* arg, struct string_array* devices){
|
||||
struct arg_values* curr = arg;
|
||||
for(size_t i = 0;i < devices->size;++i){
|
||||
curr->next = malloc(sizeof(struct arg_values));
|
||||
curr->next->device = devices->list[i];
|
||||
curr->next->delta = arg->delta;
|
||||
curr->next->fade_duration = arg->fade_duration;
|
||||
curr->next->fade_steps = arg->fade_steps;
|
||||
curr->next->operation = arg->operation;
|
||||
curr = curr->next;
|
||||
}
|
||||
curr->next = NULL;
|
||||
arg->num_values = devices->size;
|
||||
}
|
||||
int main(int argc, char** argv){
|
||||
|
||||
struct arg_values args; //A linked list of devices and the requested settings.
|
||||
struct string_array device_names; //List of all led/backlight devices in sysfs.
|
||||
struct arg_values* curr;
|
||||
|
||||
args = process_cmd_args(argc, argv);
|
||||
if(args.operation == OP_USAGE){
|
||||
usage(return_value);
|
||||
@ -342,34 +309,28 @@ int main(int argc, char** argv){
|
||||
|
||||
device_names = get_device_sources();
|
||||
|
||||
//Macro for easy memory cleaning
|
||||
#define CLEANUP() do{free_string_array(&device_names);free_cmd_args(&args);}while(0)
|
||||
|
||||
|
||||
|
||||
//If there are no led/backlights, we can't do anything
|
||||
if(device_names.size == 0){
|
||||
#ifdef REXBACKLIGHT
|
||||
fprintf(stderr, "No backlights devices found!\n");
|
||||
#elif defined(REXLEDCTL)
|
||||
fprintf(stderr, "No led devices found!\n");
|
||||
#else
|
||||
#error "UNDEFINED PROGRAM NAME!"
|
||||
#endif
|
||||
CLEANUP();
|
||||
free_string_array(&device_names);
|
||||
free_cmd_args(&args);
|
||||
return RETVAL_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
//Make sure all explicit devices actually exist
|
||||
for(curr = args.next;curr;curr = curr->next){
|
||||
int i;
|
||||
for(i = 0;i < device_names.size;++i){
|
||||
for(struct arg_values* curr = args.next;curr;curr = curr->next){
|
||||
for(int i = 0;i < device_names.size;++i){
|
||||
if(!strcmp(curr->device, device_names.list[i])){
|
||||
goto continue_outer;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "No such device '%s'\n", curr->device);
|
||||
CLEANUP();
|
||||
free_string_array(&device_names);
|
||||
free_cmd_args(&args);
|
||||
return RETVAL_INVALID_DEVICE;
|
||||
continue_outer:;
|
||||
}
|
||||
@ -377,21 +338,23 @@ int main(int argc, char** argv){
|
||||
//Change to the base directory for all sysfs leds/backlights
|
||||
if(chdir(device_dir())){
|
||||
io_error(IO_ERROR_READ, IO_ERROR_DIR, device_dir());
|
||||
CLEANUP();
|
||||
free_string_array(&device_names);
|
||||
free_cmd_args(&args);
|
||||
return RETVAL_INVALID_DIR;
|
||||
}
|
||||
|
||||
//Run selected operation
|
||||
if(args.next){
|
||||
individual_device_loop(&args);
|
||||
}else{
|
||||
populate_args(&args, &device_names);
|
||||
individual_device_loop(&args);
|
||||
}
|
||||
#ifdef ENABLE_RESTORE_FILE
|
||||
save_restore_file(&device_names);
|
||||
#endif
|
||||
}else{
|
||||
all_device_loop(&device_names, &args);
|
||||
}
|
||||
|
||||
CLEANUP();
|
||||
free_string_array(&device_names);
|
||||
free_cmd_args(&args);
|
||||
return return_value;
|
||||
}
|
||||
#undef CLEANUP
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user