Some cleanup work

This commit is contained in:
rexy712 2018-12-09 04:28:21 -08:00
parent dbfa9b9d12
commit 04dcd0684a
6 changed files with 93 additions and 107 deletions

View File

@ -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"

View File

@ -56,7 +56,10 @@ struct arg_values{
int fade_steps;
unsigned char operation;
union{
int operation;
int num_values;
};
};

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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