Skip to content

Commit

Permalink
Interface with FBInk for visual feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
NiLuJe committed Jun 9, 2018
1 parent cbc202a commit cb23d5c
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -5,6 +5,8 @@ Kobo/
# Same, for our vendored SQLite
SQLiteBuild/
sqlite.built
# As well as FBInk
fbink.built
# KDevelop
kfmon.kdev4
.kdev4/
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -8,3 +8,6 @@
path = sqlite
url = git://repo.or.cz/sqlite.git
ignore = untracked
[submodule "FBInk"]
path = FBInk
url = https://github.com/NiLuJe/FBInk.git
1 change: 1 addition & 0 deletions FBInk
Submodule FBInk added at eb6bdf
23 changes: 20 additions & 3 deletions Makefile
Expand Up @@ -31,6 +31,8 @@ ifdef NILUJE
else
# We want to link to sqlite3 explicitly statically
LIBS=-l:libsqlite3.a
# We also want FBInk when targeting real devices ;).
LIBS+=-l:libfbink.a
endif

# NOTE: Remember to use gdb -ex 'set follow-fork-mode child' to debug, since we fork like wild bunnies...
Expand Down Expand Up @@ -77,6 +79,11 @@ ifeq "$(SQLITE)" "true"
EXTRA_LDFLAGS+=-static-libgcc
endif

# And pick up FBInk, too.
ifndef NILUJE
EXTRA_LDFLAGS+=-LFBInk/Release
endif

# We use pthreads, let GCC do its thing to do it right (c.f., gcc -dumpspecs | grep pthread).
# NOTE: It mostly consists of passing -D_REENTRANT to the preprocessor, -lpthread to the linker,
# and setting -fprofile-update to prefer-atomic instead of single.
Expand Down Expand Up @@ -152,12 +159,22 @@ sqlite.built:
$(MAKE) SHELL_OPT=""
touch sqlite.built

release: sqlite.built
fbink.built:
cd FBInk && \
$(MAKE) strip
touch fbink.built

release: sqlite.built fbink.built
$(MAKE) strip SQLITE=true

distclean: clean
fbinkclean:
cd FBInk && \
$(MAKE) clean

distclean: clean fbinkclean
rm -rf SQLiteBuild
rm -rf sqlite/manifest sqlite/manifest.uuid
rm -rf sqlite.built
rm -rf fbink.built

.PHONY: default outdir all kfmon strip kobo debug niluje nilujed clean release distclean
.PHONY: default outdir all kfmon strip kobo debug niluje nilujed clean release fbinkclean distclean
58 changes: 56 additions & 2 deletions kfmon.c
Expand Up @@ -18,6 +18,25 @@

#include "kfmon.h"

// Fake FBInk in my sandbox...
#ifdef NILUJE
const char* fbink_version(void) {
return "N/A";
}

int fbink_open(void) {
return EXIT_SUCCESS;
}

int fbink_init(int) {
return EXIT_SUCCESS;
}

int fbink_print(int, char*, FBInkConfig*) {
return EXIT_SUCCESS;
}
#endif

// Because daemon() only appeared in glibc 2.21 (and doesn't double-fork anyway)
static int
daemonize(void)
Expand Down Expand Up @@ -923,6 +942,7 @@ static pid_t
if (pid < 0) {
// Fork failed?
perror("[KFMon] [ERR!] Aborting: fork");
fbink_print(-1, "fork failed ?!", &fbink_config);
exit(EXIT_FAILURE);
} else if (pid == 0) {
// Sweet child o' mine!
Expand Down Expand Up @@ -964,6 +984,7 @@ static pid_t
LOG(LOG_ERR,
"Failed to find an available entry in our process table for pid %ld, aborting!",
(long) pid);
fbink_print(-1, "Can't spawn any more processes", &fbink_config);
exit(EXIT_FAILURE);
} else {
pthread_mutex_lock(&ptlock);
Expand All @@ -989,6 +1010,7 @@ static pid_t
int* arg = malloc(sizeof(*arg));
if (arg == NULL) {
LOG(LOG_ERR, "Couldn't allocate memory for thread arg, aborting!");
fbink_print(-1, "OOM ?!", &fbink_config);
exit(EXIT_FAILURE);
}
*arg = i;
Expand All @@ -999,10 +1021,12 @@ static pid_t
pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_attr_init");
fbink_print(-1, "pthread_attr_init failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_attr_setdetachstate");
fbink_print(-1, "pthread_attr_setdetachstate failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}

Expand All @@ -1013,10 +1037,12 @@ static pid_t
if (pthread_attr_setstacksize(&attr,
MAX(1 * 1024 * 1024 / 2, sizeof(void*) * 1024 * 1024 / 8)) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_attr_setstacksize");
fbink_print(-1, "pthread_attr_setstacksize failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}
if (pthread_create(&rthread, &attr, reaper_thread, arg) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_create");
fbink_print(-1, "pthread_create failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}

Expand All @@ -1025,11 +1051,13 @@ static pid_t
snprintf(thname, sizeof(thname), "Reaper:%ld", (long) pid);
if (pthread_setname_np(rthread, thname) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_setname_np");
fbink_print(-1, "pthread_setname_np failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}

if (pthread_attr_destroy(&attr) != 0) {
perror("[KFMon] [ERR!] Aborting: pthread_attr_destroy");
fbink_print(-1, "pthread_attr_destroy failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}
}
Expand Down Expand Up @@ -1115,6 +1143,7 @@ static bool
len = read(fd, buf, sizeof buf);
if (len == -1 && errno != EAGAIN) {
perror("[KFMon] [ERR!] Aborting: read");
fbink_print(-1, "read failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}

Expand Down Expand Up @@ -1200,13 +1229,15 @@ static bool
"%s is flagged as a spawn blocker, it will prevent *any* event from triggering a spawn while it is still running!",
watch_config[watch_idx].action);
}
fbink_print(-1, "Spawning something . . .", &fbink_config);
// We're using execvp()...
char* const cmd[] = { watch_config[watch_idx].action, NULL };
spawn(cmd, watch_idx);
} else {
LOG(LOG_NOTICE,
"Target icon '%s' might not have been fully processed by Nickel yet, don't launch anything.",
watch_config[watch_idx].filename);
fbink_print(-1, "Not spawning: still processing!", &fbink_config);
// NOTE: That, or we hit a SQLITE_BUSY timeout on OPEN,
// which tripped our 'pending processing' check.
}
Expand All @@ -1223,9 +1254,11 @@ static bool
watch_config[watch_idx].filename,
(long) spid,
watch_config[watch_idx].action);
fbink_print(-1, "Not spawning: still running!", &fbink_config);
} else if (is_reader_spawned) {
LOG(LOG_INFO,
"As a spawn blocker process is currently running, we won't be spawning anything else to prevent unwanted behavior!");
fbink_print(-1, "Not spawning: blocked!", &fbink_config);
}
}
}
Expand Down Expand Up @@ -1331,13 +1364,15 @@ int

// Say hello :)
LOG(LOG_INFO,
"[PID: %ld] Initializing KFMon %s | Built on %s @ %s | Using SQLite %s (built against version %s)",
"[PID: %ld] Initializing KFMon %s | Built on %s @ %s | Using SQLite %s (built against version %s) | With FBInk %s",
(long) getpid(),
KFMON_VERSION,
__DATE__,
__TIME__,
sqlite3_libversion(),
SQLITE_VERSION);
SQLITE_VERSION,
fbink_version()
);

// Load our configs
if (load_config() == -1) {
Expand Down Expand Up @@ -1366,6 +1401,22 @@ int
// Initialize the process table, to track our spawns
init_process_table();

// Initialize FBInk
fbink_config.row = 1;
fbink_config.col = -5;
fbink_config.is_inverted = false;
fbink_config.is_flashing = false;
fbink_config.is_cleared = false;
fbink_config.is_centered = true;
fbink_config.is_padded = true;
// Consider not being able to print on screen a hard pass...
// (Mostly, it's to avoid blowing up later in fbink_print).
if (fbink_init(-1) == EXIT_FAILURE) {
LOG(LOG_ERR, "Failed to initialize FBInk, aborting!");
exit(EXIT_FAILURE);
}
fbink_print(-1, "KFMon is starting up", &fbink_config);

// We pretty much want to loop forever...
while (1) {
LOG(LOG_INFO, "Beginning the main loop.");
Expand All @@ -1375,6 +1426,7 @@ int
fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (fd == -1) {
perror("[KFMon] [ERR!] Aborting: inotify_init1");
fbink_print(-1, "Failed to initialize inotify", &fbink_config);
exit(EXIT_FAILURE);
}

Expand Down Expand Up @@ -1407,6 +1459,7 @@ int
if (watch_config[watch_idx].inotify_wd == -1) {
perror("[KFMon] [CRIT] inotify_add_watch");
LOG(LOG_ERR, "Cannot watch '%s', aborting!", watch_config[watch_idx].filename);
fbink_print(-1, "Failed to setup a watch", &fbink_config);
exit(EXIT_FAILURE);
// NOTE: This effectively means we exit when any one of our target file cannot be found,
// which is not a bad thing, per se...
Expand All @@ -1432,6 +1485,7 @@ int
continue;
}
perror("[KFMon] [ERR!] Aborting: poll");
fbink_print(-1, "poll failed ?!", &fbink_config);
exit(EXIT_FAILURE);
}

Expand Down
23 changes: 23 additions & 0 deletions kfmon.h
Expand Up @@ -25,6 +25,9 @@
#endif

#include "inih/ini.h"
#ifndef NILUJE
#include "FBInk/fbink.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
Expand Down Expand Up @@ -71,6 +74,25 @@
# define KFMON_CONFIGPATH "/home/niluje/Kindle/Staging/kfmon"
#endif

// We also have to fake the FBInk API in my sandbox...
#ifdef NILUJE
typedef struct
{
short int row;
short int col;
bool is_inverted;
bool is_flashing;
bool is_cleared;
bool is_centered;
bool is_padded;
} FBInkConfig;

const char* fbink_version(void);
int fbink_open(void);
int fbink_init(int);
int fbink_print(int, const char*, FBInkConfig*);
#endif

// Log everything to stderr (which actually points to our logfile)
#define LOG(prio, fmt, ...) \
({ \
Expand Down Expand Up @@ -196,6 +218,7 @@ unsigned int watch_count = 0;
// Make our config global, because I'm terrible at C.
DaemonConfig daemon_config = { 0 };
WatchConfig watch_config[WATCH_MAX] = { 0 };
FBInkConfig fbink_config = { 0 };

static unsigned int qhash(const unsigned char*, size_t);
static bool is_target_processed(unsigned int, bool);
Expand Down

0 comments on commit cb23d5c

Please sign in to comment.