From 904abe32940a57cdc047bd465d0be3d2b7b34c06 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Sat, 1 Dec 2018 08:36:56 -0800 Subject: [PATCH] Now can read from predefined restore file at /var/tmp/rexbacklight.json --- include/cmd.h | 1 + include/common.h | 1 + src/cmd.c | 42 +++++++++------ src/rexbacklight.c | 124 ++++++++++++++++++++++++++++++++++++++------- 4 files changed, 133 insertions(+), 35 deletions(-) diff --git a/include/cmd.h b/include/cmd.h index 1799902..23b0545 100644 --- a/include/cmd.h +++ b/include/cmd.h @@ -23,6 +23,7 @@ #define OP_DEC 2 #define OP_SET 4 #define OP_LIST 8 +#define OP_RESTORE 16 #define OP_GET 128 #define OP_NONE 0 #define OP_VERSION 254 diff --git a/include/common.h b/include/common.h index 0db7fef..6979d3d 100644 --- a/include/common.h +++ b/include/common.h @@ -29,6 +29,7 @@ #define RETVAL_MEM_ERROR 6 #define RETVAL_INTERNAL_ERROR 7 #define RETVAL_SUCCESS EXIT_SUCCESS + extern int return_value; void mem_error(void); diff --git a/src/cmd.c b/src/cmd.c index 506ebd5..aa9c43b 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -54,6 +54,9 @@ #define DEC_LONG_OPT NO_OPT #define DEC_SHORT_OPT NO_OPT #define DEC_XBACK_OPT "-dec" +#define RESTORE_LONG_OPT "--restore" +#define RESTORE_SHORT_OPT "-R" +#define RESTORE_XBACK_OPT NO_OPT #define DEVICE_DESC "select which device to control" #define FADE_DESC "change brightness over time interval" @@ -65,6 +68,7 @@ #define SET_DESC "set backlight device to specified value" #define INC_DESC "increase backlight device by specified value" #define DEC_DESC "decrease backlight device by specified value" +#define RESTORE_DESC "reassign previously saved backlight values" int strcmp_handle_null(const char* one, const char* two){ if(!one) @@ -82,28 +86,31 @@ int strcmp_handle_null(const char* one, const char* two){ #define CHECK_OPTION(opt, arg) (!strcmp_handle_null(opt##_LONG_OPT, arg) || !strcmp_handle_null(opt##_SHORT_OPT, arg) || !strcmp_handle_null(opt##_XBACK_OPT, arg)) struct cmd_arg rexbacklight_args[] = { - {DEVICE_LONG_OPT, DEVICE_SHORT_OPT, DEVICE_XBACK_OPT, DEVICE_DESC}, - {NO_OPT, NO_OPT, SET_XBACK_OPT, SET_DESC}, - {NO_OPT, NO_OPT, INC_XBACK_OPT, INC_DESC}, - {NO_OPT, NO_OPT, DEC_XBACK_OPT, DEC_DESC}, - {FADE_LONG_OPT, FADE_SHORT_OPT, FADE_XBACK_OPT, FADE_DESC}, - {STEPS_LONG_OPT, STEPS_SHORT_OPT, STEPS_XBACK_OPT, STEPS_DESC}, - {GET_LONG_OPT, GET_SHORT_OPT, GET_XBACK_OPT, GET_DESC}, - {HELP_LONG_OPT, HELP_SHORT_OPT, HELP_XBACK_OPT, HELP_DESC}, - {VERSION_LONG_OPT, NO_OPT, VERSION_XBACK_OPT, VERSION_DESC} + {DEVICE_LONG_OPT, DEVICE_SHORT_OPT, DEVICE_XBACK_OPT, DEVICE_DESC}, + {NO_OPT, NO_OPT, SET_XBACK_OPT, SET_DESC}, + {NO_OPT, NO_OPT, INC_XBACK_OPT, INC_DESC}, + {NO_OPT, NO_OPT, DEC_XBACK_OPT, DEC_DESC}, + {FADE_LONG_OPT, FADE_SHORT_OPT, FADE_XBACK_OPT, FADE_DESC}, + {STEPS_LONG_OPT, STEPS_SHORT_OPT, STEPS_XBACK_OPT, STEPS_DESC}, + {GET_LONG_OPT, GET_SHORT_OPT, GET_XBACK_OPT, GET_DESC}, + {LIST_LONG_OPT, LIST_SHORT_OPT, LIST_XBACK_OPT, LIST_DESC}, + {RESTORE_LONG_OPT, RESTORE_SHORT_OPT, RESTORE_XBACK_OPT, RESTORE_DESC}, + {HELP_LONG_OPT, HELP_SHORT_OPT, HELP_XBACK_OPT, HELP_DESC}, + {VERSION_LONG_OPT, NO_OPT, VERSION_XBACK_OPT, VERSION_DESC} }; #else //XBACKLIGHT_COMPAT_OPTIONS #define CHECK_OPTION(opt, arg) (!strcmp_handle_null(opt##_LONG_OPT, arg) || !strcmp_handle_null(opt##_SHORT_OPT, arg)) struct cmd_arg rexbacklight_args[] = { - {DEVICE_LONG_OPT, DEVICE_SHORT_OPT, DEVICE_DESC}, - {FADE_LONG_OPT, FADE_SHORT_OPT, FADE_DESC}, - {STEPS_LONG_OPT, STEPS_SHORT_OPT, STEPS_DESC}, - {GET_LONG_OPT, GET_SHORT_OPT, GET_DESC}, - {LIST_LONG_OPT, LIST_SHORT_OPT, LIST_DESC}, - {HELP_LONG_OPT, HELP_SHORT_OPT, HELP_DESC}, - {VERSION_LONG_OPT, NO_OPT, VERSION_DESC} + {DEVICE_LONG_OPT, DEVICE_SHORT_OPT, DEVICE_DESC}, + {FADE_LONG_OPT, FADE_SHORT_OPT, FADE_DESC}, + {STEPS_LONG_OPT, STEPS_SHORT_OPT, STEPS_DESC}, + {GET_LONG_OPT, GET_SHORT_OPT, GET_DESC}, + {LIST_LONG_OPT, LIST_SHORT_OPT, LIST_DESC}, + {RESTORE_LONG_OPT, RESTORE_SHORT_OPT, RESTORE_DESC}, + {HELP_LONG_OPT, HELP_SHORT_OPT, HELP_DESC}, + {VERSION_LONG_OPT, NO_OPT, VERSION_DESC} }; #endif //XBACKLIGHT_COMPAT_OPTIONS @@ -195,6 +202,9 @@ struct arg_values process_cmd_args(int argc, char** argv){ ret.next = NULL; return ret; } + else if(CHECK_OPTION(RESTORE, argv[i])){ + ret.operation = OP_RESTORE; + } else if(!strcmp(argv[i], "max")){ curr->operation = OP_SET; curr->delta = 100; diff --git a/src/rexbacklight.c b/src/rexbacklight.c index c89deb6..dee5bd1 100644 --- a/src/rexbacklight.c +++ b/src/rexbacklight.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "common.h" #include "cmd.h" @@ -36,10 +37,12 @@ //This is where backlight devices can be found in sysfs static const char* device_dir = "/sys/class/backlight/"; const char* executable_name = "rexbacklight"; +static const char* restore_file = "/var/tmp/rexbacklight.json"; #elif defined(REXLEDCTL) //This is where led devices can be found in sysfs static const char* device_dir = "/sys/class/leds"; const char* executable_name = "rexledctl"; +static const char* restore_file = "/var/tmp/rexledctl.json"; #else #error "UNDEFINED PROGRAM NAME!" #endif @@ -62,10 +65,10 @@ void io_error(const char* error, const char* type, const char* name){ fprintf(stderr, "Unable to %s %s '%s'!\n", error, type, name); } void io_error_2(const char* error, const char* type, const char* name, const char* name2){ - fprintf(stderr, "Unable to %s %s '%s/%s'!\n", error, type, name, name2); + fprintf(stderr, "Unable to %s %s '%s%s'!\n", error, type, name, name2); } void io_error_3(const char* error, const char* type, const char* name, const char* name2, const char* name3){ - fprintf(stderr, "Unable to %s %s '%s/%s/%s'!\n", error, type, name, name2, name3); + fprintf(stderr, "Unable to %s %s '%s%s%s'!\n", error, type, name, name2, name3); } //Clean up a string array @@ -235,31 +238,108 @@ void do_list(struct string_array* names){ fprintf(stdout, "%s\n", names->list[i]); } +RJP_value* read_restore_file(const char* file){ + size_t filesize; + char* file_contents; + int i; + FILE* fp = fopen(file, "r"); + if(!fp){ + fprintf(stderr, "Could not restore! No restore file found!\n"); + return NULL; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + file_contents = malloc(filesize+1); + i = fread(file_contents, filesize, 1, fp); + fclose(fp); + file_contents[filesize] = 0; + RJP_value* root = rjp_parse(file_contents); + free(file_contents); + return root; +} +int individual_device_op(struct arg_values* curr){ + if(chdir(curr->device)){ + io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, curr->device); + return RETVAL_INVALID_DIR; + } + switch(curr->operation){ + case OP_SET: + case OP_INC: + case OP_DEC: + do_assignment(curr, curr->device); + break; + case OP_GET: + do_get(curr->device); + break; + } + if(chdir(device_dir)){ + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); + return RETVAL_INTERNAL_ERROR; + } + return return_value; +} + +RJP_value* find_matching_json_device(const char* name, RJP_value* root){ + for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ + if(!strcmp(rjp_member_name(curr), name)){ + return curr; + } + } + return NULL; +} +int prep_restore(struct arg_values* curr, RJP_value** root, int* try_restore){ + if(!*root && *try_restore){ + *root = read_restore_file(restore_file); + if(!*root){ + *try_restore = 0; + return 0; + } + } + RJP_value* match = find_matching_json_device(curr->device, *root); + if(!match){ + fprintf(stderr, "No matching device '%s' in restore file!\n", curr->device); + return 0; + } + curr->operation = OP_SET; + curr->delta = rjp_value_dfloat(match); + return 1; +} //If devices were specified, this function will run void individual_device_loop(struct arg_values* a){ struct arg_values* curr; + RJP_value* root = 0; + int try_restore = 1; for(curr = a->next;curr;curr = curr->next){ - if(chdir(curr->device)){ - io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, curr->device); - return_value = RETVAL_INVALID_DIR; - continue; + if(curr->operation == OP_RESTORE){ + if(!prep_restore(curr, &root, &try_restore)) + continue; } - switch(curr->operation){ - case OP_SET: - case OP_INC: - case OP_DEC: - do_assignment(curr, curr->device); - break; - case OP_GET: - do_get(curr->device); - break; - } - if(chdir(device_dir)){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); - return_value = RETVAL_INVALID_DIR; + return_value = individual_device_op(curr); + if(return_value == RETVAL_INTERNAL_ERROR){ + rjp_free(root); return; } } + rjp_free(root); +} + +void process_restore_file(void){ + RJP_value* root = read_restore_file(restore_file); + if(!root) + return; + struct arg_values tmp = {.next = NULL, + .fade_duration = 0, + .fade_steps = 1, + .operation = OP_SET}; + for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ + tmp.device = rjp_member_name(curr); + tmp.delta = rjp_value_dfloat(curr); + individual_device_op(&tmp); + } + rjp_free(root); } //If no devices were specified, this function will run @@ -301,6 +381,12 @@ void all_device_loop(struct string_array* device_names, struct arg_values* args) } } break; + case OP_RESTORE:; + process_restore_file(); + break; + default: + fprintf(stderr, "Internal processing error!\n"); + break; } }