diff --git a/include/cmd.h b/include/cmd.h
new file mode 100644
index 0000000..1e860a8
--- /dev/null
+++ b/include/cmd.h
@@ -0,0 +1,69 @@
+/**
+ rexbacklight
+ Copyright (C) 2018 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef RECBACKLIGHT_CMD_H
+#define REXBACKLIGHT_CMD_H
+
+#define OP_SET 4
+#define OP_LIST 8
+#define OP_GET 128
+#define OP_NONE 0
+
+#define GET_LONG_OPT "--get"
+#define GET_SHORT_OPT "-g"
+#define FADE_LONG_OPT "--fade"
+#define FADE_SHORT_OPT "-f"
+#define DEVICE_LONG_OPT "--device"
+#define DEVICE_SHORT_OPT "-d"
+#define LIST_LONG_OPT "--list"
+#define LIST_SHORT_OPT "-l"
+#define HELP_LONG_OPT "--help"
+#define HELP_SHORT_OPT "-h"
+
+struct cmd_arg{
+ const char* lopt;
+ const char* sopt;
+ const char* desc;
+};
+
+extern struct cmd_arg rexbacklight_args[];
+extern int rexbacklight_args_length;
+
+struct arg_values{
+ struct arg_values* next;
+
+ //Specific device to control
+ //NULL means all devices
+ const char* device;
+
+ //What value to put in the backlight file
+ char* delta;
+
+ //How many seconds to transition
+ int fade_duration;
+
+ unsigned char operation;
+};
+
+
+
+void free_cmd_args(struct arg_values* a);
+struct arg_values process_cmd_args(int argc, char** argv);
+int process_op(char* arg, float min, float current, float max);
+
+#endif
diff --git a/include/common.h b/include/common.h
new file mode 100644
index 0000000..c49bb5c
--- /dev/null
+++ b/include/common.h
@@ -0,0 +1,34 @@
+/**
+ rexbacklight
+ Copyright (C) 2018 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#ifndef REXBACKLIGHT_COMMON_H
+#define REXBACKLIGHT_COMMON_H
+
+#define RETVAL_INVALID_FILE 1
+#define RETVAL_INVALID_DIR 2
+#define RETVAL_UNRECOGNIZED_OPTION 3
+#define RETVAL_MISSING_OPTION 4
+#define RETVAL_INVALID_DEVICE -5
+#define RETVAL_SUCCESS EXIT_SUCCESS
+
+_Noreturn void usage(int exit_val);
+
+
+#endif
diff --git a/makefile b/makefile
index 61e9be7..52474c1 100644
--- a/makefile
+++ b/makefile
@@ -1,25 +1,72 @@
-.PHONY: all
-all: rexbacklight
+#Copyright 2018 rexy712 of Rexy & Co
+#Makefile for project 'rexbacklight'
-rexbacklight: src/rexbacklight.c
- gcc -std=c11 -g -Wall -Wextra -pedantic src/rexbacklight.c -o rexbacklight
+#Project directory and file setup
+SOURCE_DIRS:=src
+OBJDIR:=obj
+DEPDIR:=obj/dep
+INCLUDE_DIRS:=include
+EXT:=c
+MAIN_EXECUTABLE:=rexbacklight
+
+#Compiler/Linker setup
+CC:=gcc
+CFLAGS:=-g -std=c11 -Wall -pedantic -Wextra
+release: CFLAGS:=-std=c11 -Wall -pedantic -Wextra -O2
+LDFLAGS=
+LDLIBS:=
+STRIP:=strip
+
+#Windows workarounds
+ifeq ($(OS),Windows_NT)
+ mkdir=mkdir $(subst /,\,$(1)) > NUL 2>&1
+ rm=del /F $(1) > NUL 2>&1
+ rmdir=rd /s /q $(1) > NUL 2>&1
+ move=move /y $(subst /,\,$(1)) $(subst /,\,$(2)) > NUL 2>&1
+ MAIN_EXECUTABLE:=$(MAIN_EXECUTABLE).exe
+ LDLIBS:=
+else
+ mkdir=mkdir -p $(1)
+ rm=rm -f $(1)
+ rmdir=rm -rf $(1)
+ move=mv $(1) $(2)
+endif
+
+#Internal management of sources/objects and additional cflags
+INTERNAL_CFLAGS=-c $(foreach dir,$(INCLUDE_DIRS),-I"$(dir)") -MMD -MP -MF"$(DEPDIR)/$*.d"
+SOURCES:=$(foreach source,$(SOURCE_DIRS),$(foreach ext,$(EXT),$(wildcard $(source)/*.$(ext))))
+OBJECTS:=$(addprefix $(OBJDIR)/,$(subst \,.,$(subst /,.,$(addsuffix .o,$(SOURCES)))))
+
+all: $(MAIN_EXECUTABLE)
+
+$(MAIN_EXECUTABLE): $(OBJECTS)
+ $(CC) $(LDFLAGS) $^ -o "$(basename $@)" $(LDLIBS)
.PHONY: release
-release: src/rexbacklight.c
- gcc -std=c11 -O2 -Wall -Wextra -pedantic src/rexbacklight.c -o rexbacklight
- strip --strip-all rexbacklight
+release: $(OBJECTS)
+ $(CC) $(LDFLAGS) $^ -o "$(basename $(MAIN_EXECUTABLE))" $(LDLIBS)
+ $(STRIP) --strip-all "$(MAIN_EXECUTABLE)"
-.PHONY: install
-install: rexbacklight
- install -m755 -o root -g root -s rexbacklight /usr/bin/rexbacklight
- install -m600 -o root -g root rules/91-backlight.rules /etc/udev/rules.d/91-backlight.rules
- install -m755 -o root -g root rules/backlight /etc/init.d/backlight
+define GENERATE_OBJECTS
+
+$$(OBJDIR)/$(subst \,.,$(subst /,.,$(1))).%.o: $(1)/%
+ $$(CC) $$(CFLAGS) $$(INTERNAL_CFLAGS) "$$<" -o "$$@"
+
+endef
+
+$(foreach dir,$(SOURCE_DIRS),$(eval $(call GENERATE_OBJECTS,$(dir))))
+$(OBJECTS): | $(OBJDIR) $(DEPDIR)
+
+$(OBJDIR):
+ $(call mkdir,"$@")
+$(DEPDIR):
+ $(call mkdir,"$@")
-.PHONY: uninstall
-uninstall:
- rm /usr/bin/rexbacklight
- rm /etc/udev/rules.d/91-backlight.rules
- rm /etc/init.d/backlight
.PHONY: clean
clean:
- rm rexbacklight
+ $(call rmdir,"$(DEPDIR)")
+ $(call rmdir,"$(OBJDIR)")
+ $(call rm,"$(MAIN_EXECUTABLE)")
+-include $(wildcard $(DEPDIR)/*.d)
+
+
diff --git a/src/cmd.c b/src/cmd.c
new file mode 100644
index 0000000..54ce680
--- /dev/null
+++ b/src/cmd.c
@@ -0,0 +1,196 @@
+/**
+ rexbacklight
+ Copyright (C) 2018 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "cmd.h"
+#include "common.h"
+
+#define CHECK_OPTION(opt, arg) (!strcmp(opt##_LONG_OPT, arg) || !strcmp(opt##_SHORT_OPT, arg))
+
+struct cmd_arg rexbacklight_args[] = {
+ {DEVICE_LONG_OPT, DEVICE_SHORT_OPT, "select which device to control"},
+ {FADE_LONG_OPT, FADE_SHORT_OPT, "TODO: change brightness over time interval"},
+ {GET_LONG_OPT, GET_SHORT_OPT, "TODO: print current brightness level to stdout"},
+ {LIST_LONG_OPT, LIST_SHORT_OPT, "TODO: print device names to stdout and exit"},
+ {HELP_LONG_OPT, HELP_SHORT_OPT, "print this help message and exit"}
+};
+int rexbacklight_args_length = sizeof(rexbacklight_args) / sizeof(rexbacklight_args[0]);
+
+void free_cmd_args(struct arg_values* a){
+ if(!a->next)
+ return;
+ free_cmd_args(a->next);
+ free(a->next);
+}
+
+#define CHECK_NEXT_ARG(rval) \
+ do{ \
+ if(i == argc - 1){ \
+ fprintf(stderr, "Missing argument to '%s'\n\n", argv[i]); \
+ free_cmd_args(&ret); \
+ usage(rval); \
+ } \
+ }while(0)
+#define UNRECOGNIZED_OPTION(rval) \
+ do{ \
+ fprintf(stderr, "Unrecognized command line option '%s'\n\n", argv[i]); \
+ free_cmd_args(&ret); \
+ usage(rval); \
+ }while(0);
+
+//Convert command line arguments to flags
+struct arg_values process_cmd_args(int argc, char** argv){
+ struct arg_values ret = {0};
+ struct arg_values* curr = &ret;
+
+ //Skip argv[0]
+ for(int i = 1;i < argc;i++){
+
+ //Check for switches
+ if(CHECK_OPTION(GET, argv[i])){
+ curr->operation |= OP_GET;
+ continue;
+
+ }else if(CHECK_OPTION(FADE, argv[i])){
+ CHECK_NEXT_ARG(-5);
+ curr->fade_duration = strtol(argv[++i], NULL, 0);
+ continue;
+ }
+
+ else if(CHECK_OPTION(DEVICE, argv[i])){
+ CHECK_NEXT_ARG(-5);
+ curr->next = calloc(1, sizeof(struct arg_values));
+ curr = curr->next;
+ curr->device = argv[++i];
+ continue;
+ }
+ else if(CHECK_OPTION(LIST, argv[i])){
+ free_cmd_args(&ret);
+ ret.operation = OP_LIST;
+ ret.next = NULL;
+ return ret;
+ }
+ else if(CHECK_OPTION(HELP, argv[i])){
+ free_cmd_args(&ret);
+ usage(RETVAL_SUCCESS);
+ }
+
+ else if(!strcmp(argv[i], "max")){
+ curr->operation = OP_SET;
+ curr->delta = argv[i];
+ }
+ else if(!strcmp(argv[i], "min")){
+ curr->operation = OP_SET;
+ curr->delta = argv[i];
+ }
+ else if(!strcmp(argv[i], "off")){
+ curr->operation = OP_SET;
+ curr->delta = argv[i];
+ }
+
+ //If we get a '-' followed by not a number, it's not a known option
+ else if(argv[i][1] < '0' || argv[i][1] > '9'){
+ UNRECOGNIZED_OPTION(RETVAL_UNRECOGNIZED_OPTION);
+ }
+
+ //If we get a '-' followed by a number, it's a decrement request
+ else{
+ curr->operation = OP_SET;
+ curr->delta = argv[i];
+ }
+ }
+
+ //If there isn't an operation defined in the global context and there is no specified device, there's nothing to do
+ if(!ret.operation){
+ if(!ret.next){
+ fprintf(stderr, "No operation requested!\n\n");
+ usage(RETVAL_MISSING_OPTION);
+ }
+ //if there is a device specified, make sure each one has a requested operation
+ for(curr = ret.next;curr;curr = curr->next){
+ if(!curr->operation){
+ fprintf(stderr, "No operation requested for device '%s'!\n\n", curr->device);
+ free_cmd_args(&ret);
+ usage(RETVAL_MISSING_OPTION);
+ }
+ }
+ //If there is a globally defined operation, apply it to the devices with no operation request
+ }else{
+ for(curr = ret.next;curr;curr = curr->next){
+ if(curr->operation == OP_NONE){
+ curr->operation = ret.operation;
+ if(!curr->delta)
+ curr->delta = ret.delta;
+
+ }
+ }
+ }
+ return ret;
+}
+#undef CHECK_OPTION
+#undef UNRECOGNIZED_OPTION
+
+//Process an operation
+int process_op(char* arg, float min, float current, float max){
+ //Amount to inc/dec
+ int delta = delta = max * atof(arg + 1) / 100.0;
+
+ //Increment
+ if(arg[0] == '+'){
+ delta = delta + current;
+ if(delta >= max)
+ return max;
+ else{
+ return delta;
+ }
+
+ //Decrement
+ }else if(arg[0] == '-'){
+ delta = current - delta;
+ if(delta <= min)
+ return min;
+ else
+ return delta;
+
+ //Directly set
+ }else if(arg[0] == '='){
+ if(delta >= max)
+ return max;
+ else if(delta <= min)
+ return min;
+ else
+ return delta;
+
+ //Set to minimum plus one (so backlight is actually on!)
+ }else if(!strcmp("min", arg)){
+ return min + 1;
+
+ //Turn off backlight
+ }else if(!strcmp("off", arg)){
+ return min;
+
+ //Set to maximum
+ }else if(!strcmp("max", arg)){
+ return max;
+ }
+ return current;
+}
+
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..6e5c228
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,50 @@
+/**
+ rexbacklight
+ Copyright (C) 2018 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "common.h"
+#include "cmd.h"
+
+#include
+
+_Noreturn void usage(int exit_val){
+ fprintf(stderr, "Usage: rexbacklight [argument] [options] [argument]\n\n");
+
+ fprintf(stderr, "Options:\n");
+ for(int i = 0;i < rexbacklight_args_length;i++){
+ fprintf(stderr, " %s|%s\n", rexbacklight_args[i].lopt, rexbacklight_args[i].sopt);
+ fprintf(stderr, " %s\n", rexbacklight_args[i].desc);
+ }
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Arguments:\n");
+ fprintf(stderr, " =\n");
+ fprintf(stderr, " -\n");
+ fprintf(stderr, " +\n");
+ fprintf(stderr, " off\n");
+ fprintf(stderr, " max\n");
+ fprintf(stderr, " min\n");
+
+ if(exit_val == RETVAL_SUCCESS){
+ fprintf(stderr, "\nrexbacklight Copyright (C) 2018 rexy712\n");
+ fprintf(stderr, "This program comes with ABSOLUTELY NO WARRANTY.\n");
+ fprintf(stderr, "This is free software, and you are welcome to redistribute it\n");
+ fprintf(stderr, "under certain conditions; see the GNU GPLv3 for details.\n");
+ fprintf(stderr, "A copy of the GPLv3 is available with the source in the file 'LICENSE'\n");
+ }
+
+ exit(exit_val);
+}
diff --git a/src/rexbacklight.c b/src/rexbacklight.c
index b4232ff..b9ba1e5 100644
--- a/src/rexbacklight.c
+++ b/src/rexbacklight.c
@@ -19,247 +19,20 @@
#include
#include
#include
-#include
-#include
#include
-#include
-
-#define OP_SET 4
-#define OP_GET 128
-#define OP_NONE 0
-
-#define GET_LONG_OPT "--get"
-#define GET_SHORT_OPT "-g"
-#define FADE_LONG_OPT "--fade"
-#define FADE_SHORT_OPT "-f"
-#define DEVICE_LONG_OPT "--device"
-#define DEVICE_SHORT_OPT "-d"
-#define HELP_LONG_OPT "--help"
-#define HELP_SHORT_OPT "-h"
-
-#define CHECK_OPTION(opt, arg) (!strcmp(opt##_LONG_OPT, arg) || !strcmp(opt##_SHORT_OPT, arg))
-
-#define RETVAL_INVALID_FILE -1
-#define RETVAL_INVALID_DIR -2
-#define RETVAL_UNRECOGNIZED_OPTION -3
-#define RETVAL_MISSING_OPTION -4
-#define RETVAL_INVALID_DEVICE -5
-#define RETVAL_SUCCESS EXIT_SUCCESS
-
-struct string_array{
- char** list;
- int size;
-};
-
-struct arg_values{
- struct arg_values* next;
-
- //Specific device to control
- //NULL means all devices
- const char* device;
-
- //What value to put in the backlight file
- char* delta;
-
- //How many seconds to transition
- int fade_duration;
-
- unsigned char operation;
-};
-
+#include "common.h"
+#include "cmd.h"
//This is where backlight devices can be found in sysfs
static const char* backlight_dir = "/sys/class/backlight/";
static const char* backlight_file = "brightness";
static const char* max_backlight_file = "max_brightness";
-//Print out usage message and GPL message if not caused by an error
-_Noreturn void usage(int exit_val){
- fprintf(stderr, "Usage: rexbacklight [argument] [options] [argument]\n\n");
-
- fprintf(stderr, "Options:\n");
- fprintf(stderr, " %s|%s\n", DEVICE_SHORT_OPT, DEVICE_LONG_OPT);
- fprintf(stderr, " select which device to control\n");
- fprintf(stderr, " %s|%s\n", FADE_SHORT_OPT, FADE_LONG_OPT);
- fprintf(stderr, " TODO: change brightness over time interval\n");
- fprintf(stderr, " %s|%s\n", GET_SHORT_OPT, GET_LONG_OPT);
- fprintf(stderr, " TODO: print the current brightness level to stdout\n");
- fprintf(stderr, " %s|%s\n", HELP_SHORT_OPT, HELP_LONG_OPT);
- fprintf(stderr, " print this help message and exit\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Arguments:\n");
- fprintf(stderr, " =\n");
- fprintf(stderr, " -\n");
- fprintf(stderr, " +\n");
- fprintf(stderr, " off\n");
- fprintf(stderr, " max\n");
- fprintf(stderr, " min\n");
-
- if(exit_val == RETVAL_SUCCESS){
- fprintf(stderr, "\nrexbacklight Copyright (C) 2018 rexy712\n");
- fprintf(stderr, "This program comes with ABSOLUTELY NO WARRANTY.\n");
- fprintf(stderr, "This is free software, and you are welcome to redistribute it\n");
- fprintf(stderr, "under certain conditions; see the GNU GPLv3 for details.\n");
- fprintf(stderr, "A copy of the GPLv3 is available with the source in the file 'LICENSE'\n");
- }
-
- exit(exit_val);
-}
-
-void free_cmd_args(struct arg_values* a){
- if(!a->next)
- return;
- free_cmd_args(a->next);
- free(a->next);
-}
-
-#define CHECK_NEXT_ARG(rval) \
- do{ \
- if(i == argc - 1){ \
- fprintf(stderr, "Missing argument to '%s'\n\n", argv[i]); \
- free_cmd_args(&ret); \
- usage(rval); \
- } \
- }while(0)
-#define UNRECOGNIZED_OPTION(rval) \
- do{ \
- fprintf(stderr, "Unrecognized command line option '%s'\n\n", argv[i]); \
- free_cmd_args(&ret); \
- usage(rval); \
- }while(0);
-
-//Convert command line arguments to flags
-struct arg_values process_cmd_args(int argc, char** argv){
- struct arg_values ret = {0};
- struct arg_values* curr = &ret;
-
- //Skip argv[0]
- for(int i = 1;i < argc;i++){
-
- //Check for switches
- if(CHECK_OPTION(GET, argv[i])){
- curr->operation |= OP_GET;
- continue;
-
- }else if(CHECK_OPTION(FADE, argv[i])){
- CHECK_NEXT_ARG(-5);
- curr->fade_duration = strtol(argv[++i], NULL, 0);
- continue;
- }
-
- else if(CHECK_OPTION(DEVICE, argv[i])){
- CHECK_NEXT_ARG(-5);
- curr->next = calloc(1, sizeof(struct arg_values));
- curr = curr->next;
- curr->device = argv[++i];
- continue;
- }
- else if(CHECK_OPTION(HELP, argv[i])){
- free_cmd_args(&ret);
- usage(RETVAL_SUCCESS);
- }
-
- else if(!strcmp(argv[i], "max")){
- curr->operation = OP_SET;
- curr->delta = argv[i];
- }
- else if(!strcmp(argv[i], "min")){
- curr->operation = OP_SET;
- curr->delta = argv[i];
- }
- else if(!strcmp(argv[i], "off")){
- curr->operation = OP_SET;
- curr->delta = argv[i];
- }
-
- //If we get a '-' followed by not a number, it's not a known option
- else if(argv[i][1] < '0' || argv[i][1] > '9'){
- UNRECOGNIZED_OPTION(RETVAL_UNRECOGNIZED_OPTION);
- }
-
- //If we get a '-' followed by a number, it's a decrement request
- else{
- curr->operation = OP_SET;
- curr->delta = argv[i];
- }
- }
-
- //If there isn't an operation defined in the global context and there is no specified device, there's nothing to do
- if(!ret.operation){
- if(!ret.next){
- fprintf(stderr, "No operation requested!\n\n");
- usage(RETVAL_MISSING_OPTION);
- }
- //if there is a device specified, make sure each one has a requested operation
- for(curr = ret.next;curr;curr = curr->next){
- if(!curr->operation){
- fprintf(stderr, "No operation requested for device '%s'!\n\n", curr->device);
- free_cmd_args(&ret);
- usage(RETVAL_MISSING_OPTION);
- }
- }
- //If there is a globally defined operation, apply it to the devices with no operation request
- }else{
- for(curr = ret.next;curr;curr = curr->next){
- if(curr->operation == OP_NONE){
- curr->operation = ret.operation;
- if(!curr->delta)
- curr->delta = ret.delta;
-
- }
- }
- }
- return ret;
-}
-#undef CHECK_OPTION
-#undef UNRECOGNIZED_OPTION
-
-//Process an operation
-int process_op(char* arg, float min, float current, float max){
- //Amount to inc/dec
- int delta = delta = max * atof(arg + 1) / 100.0;
-
- //Increment
- if(arg[0] == '+'){
- delta = delta + current;
- if(delta >= max)
- return max;
- else{
- return delta;
- }
-
- //Decrement
- }else if(arg[0] == '-'){
- delta = current - delta;
- if(delta <= min)
- return min;
- else
- return delta;
-
- //Directly set
- }else if(arg[0] == '='){
- if(delta >= max)
- return max;
- else if(delta <= min)
- return min;
- else
- return delta;
-
- //Set to minimum plus one (so backlight is actually on!)
- }else if(!strcmp("min", arg)){
- return min + 1;
-
- //Turn off backlight
- }else if(!strcmp("off", arg)){
- return min;
-
- //Set to maximum
- }else if(!strcmp("max", arg)){
- return max;
- }
- return current;
-}
+struct string_array{
+ char** list;
+ int size;
+};
//Delete the list of backlight devices
void free_string_array(struct string_array* s){