Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,29 @@ exec >>"${LOG}" 2>&1

hydrate_probe_env

# Clara Colour (spaColour/393): snow protocol, needs mirror_x
if [ -z "${APP_TOUCH_MIRROR_X}" ] && \
{ [ "${APP_CODENAME}" = "spaColour" ] || [ "${APP_PRODUCT_ID}" = "393" ]; } && \
[ "${APP_TOUCH_PROTOCOL}" = "snow" ]; then
APP_TOUCH_MIRROR_X=1
fi

# Libra Colour (monza/390): standard multitouch, needs mirror_y (not mirror_x)
if [ -z "${APP_TOUCH_MIRROR_Y}" ] && \
{ [ "${APP_CODENAME}" = "monza" ] || [ "${APP_PRODUCT_ID}" = "390" ]; }; then
APP_TOUCH_MIRROR_Y=1
fi

# Elipsa 2E (condor/389): standard multitouch, needs mirror_y (not mirror_x)
if [ -z "${APP_TOUCH_MIRROR_Y}" ] && \
{ [ "${APP_CODENAME}" = "condor" ] || [ "${APP_PRODUCT_ID}" = "389" ]; }; then
APP_TOUCH_MIRROR_Y=1
fi

if [ -z "${APP_TOUCH_MIRROR_X}" ]; then
APP_TOUCH_MIRROR_X=0
fi

if [ -z "${APP_TOUCH_MIRROR_Y}" ]; then
APP_TOUCH_MIRROR_Y=0
fi
Expand Down
62 changes: 57 additions & 5 deletions src/kobo/bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,15 @@ bool file_exists(const char* path) {
}

Bsky::Session load_saved_session() {
const char* config_path = skeets_config_path();
std::fprintf(stderr, "bootstrap: load_saved_session: config_path='%s'\n", config_path);

Bsky::Session session;
config_t* config = config_open(skeets_config_path());
if (!config) return session;
config_t* config = config_open(config_path);
if (!config) {
std::fprintf(stderr, "bootstrap: load_saved_session: config_open returned NULL\n");
return session;
}

session.handle = config_get_str(config, "handle", "");
session.access_jwt = config_get_str(config, "access_jwt", "");
Expand All @@ -82,6 +88,14 @@ Bsky::Session load_saved_session() {
session.appview_url = config_get_str(config,
"appview_url",
config_get_str(config, "appview", kDefaultAppView));

std::fprintf(stderr, "bootstrap: load_saved_session: loaded handle='%s' did='%s' pds='%s' has_access=%zu has_refresh=%zu\n",
session.handle.empty() ? "(empty)" : session.handle.c_str(),
session.did.empty() ? "(empty)" : session.did.c_str(),
session.pds_url.empty() ? "(empty)" : session.pds_url.c_str(),
session.access_jwt.size(),
session.refresh_jwt.size());

config_free(config);
return session;
}
Expand All @@ -91,16 +105,36 @@ bool has_saved_session(const Bsky::Session& session) {
}

void save_session(const Bsky::Session& session) {
config_t* config = config_open(skeets_config_path());
if (!config) return;
const char* config_path = skeets_config_path();

if (session.handle.empty() && session.access_jwt.empty() && session.did.empty()) {
std::fprintf(stderr, "bootstrap: save_session: SKIPPING — session is empty (would overwrite valid config)\n");
return;
}

std::fprintf(stderr, "bootstrap: save_session: saving handle='%s' did='%s' pds='%s' access_len=%zu refresh_len=%zu\n",
session.handle.c_str(), session.did.c_str(), session.pds_url.c_str(),
session.access_jwt.size(), session.refresh_jwt.size());

config_t* config = config_open(config_path);
if (!config) {
std::fprintf(stderr, "bootstrap: save_session: config_open returned NULL for '%s'\n", config_path);
return;
}

config_set_str(config, "handle", session.handle.c_str());
config_set_str(config, "access_jwt", session.access_jwt.c_str());
config_set_str(config, "refresh_jwt", session.refresh_jwt.c_str());
config_set_str(config, "did", session.did.c_str());
config_set_str(config, "pds_url", session.pds_url.c_str());
config_set_str(config, "appview_url", session.appview_url.c_str());
config_save(config);

int result = config_save(config);
if (result != 0) {
std::fprintf(stderr, "bootstrap: save_session: config_save FAILED for '%s' (result=%d)\n", config_path, result);
} else {
std::fprintf(stderr, "bootstrap: save_session: config_save succeeded for '%s'\n", config_path);
}
config_free(config);
}

Expand Down Expand Up @@ -143,16 +177,22 @@ skeets_bootstrap_result_t make_error_result(const std::string& error_message, bo
} // namespace

skeets_bootstrap_result_t skeets_run_bootstrap() {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: starting\n");

if (skeets_ensure_data_dirs() != 0) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: failed to create data dirs\n");
return make_error_result("Failed to create rewrite data directories", false);
}

std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: loading saved session\n");
Bsky::Session saved_session = load_saved_session();

Bsky::Session restored_session;
std::string saved_session_error;
if (has_saved_session(saved_session)) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: found saved session, attempting restore\n");
if (restore_saved_session_with_retry(saved_session, restored_session, saved_session_error)) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: session restore succeeded\n");
save_session(restored_session);
skeets_bootstrap_result_t result;
result.state = skeets_bootstrap_state_t::session_restored;
Expand All @@ -163,21 +203,31 @@ skeets_bootstrap_result_t skeets_run_bootstrap() {
result.used_saved_session = true;
return result;
}
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: session restore failed: %s\n", saved_session_error.c_str());
} else {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: no saved session found\n");
}

std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: checking for login.txt\n");
bool found_login_file = false;
const skeets_login_txt_t login = read_login_txt(found_login_file);
if (!found_login_file) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: no login.txt found\n");
if (has_saved_session(saved_session)) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: returning error (had session but restore failed)\n");
return make_error_result(saved_session_error.empty() ? "Saved session resume failed" : saved_session_error, false);
}
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: returning waiting for login\n");
return make_waiting_result();
}

std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: login.txt found, handle='%s'\n", login.handle.c_str());
if (login.handle.empty() || login.password.empty()) {
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: login.txt missing handle or password\n");
return make_error_result("login.txt is missing required handle or password fields", true);
}

std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: attempting createSession\n");
bool created = false;
std::string error_message;
Bsky::Session created_session;
Expand All @@ -194,6 +244,7 @@ skeets_bootstrap_result_t skeets_run_bootstrap() {
return make_error_result(error_message.empty() ? "Login failed" : error_message, true);
}

std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: createSession succeeded, saving session\n");
created_session.appview_url = login.appview_url.empty() ? kDefaultAppView : login.appview_url;
save_session(created_session);

Expand All @@ -204,6 +255,7 @@ skeets_bootstrap_result_t skeets_run_bootstrap() {
result.detail = "Session tokens were saved under the rewrite app root.";
result.authenticated = true;
result.consumed_login_file = true;
std::fprintf(stderr, "bootstrap: skeets_run_bootstrap: returning success\n");
return result;
}

Expand Down
21 changes: 20 additions & 1 deletion src/kobo/diag_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,30 @@ skeets_input_protocol_t detect_input_protocol() {
int run_input_diag() {
std::fprintf(stderr, "rewrite diag: input.begin\n");

// Query actual framebuffer dimensions instead of hardcoding a single device's resolution.
int fb_width = 0;
int fb_height = 0;
{
skeets_framebuffer_t probe_fb;
std::string fb_err;
if (skeets_framebuffer_open(probe_fb, &fb_err)) {
fb_width = probe_fb.info.screen_width;
fb_height = probe_fb.info.screen_height;
skeets_framebuffer_close(probe_fb);
std::fprintf(stderr, "rewrite diag: input.detected_fb=%dx%d\n", fb_width, fb_height);
} else {
fb_width = 1072;
fb_height = 1448;
std::fprintf(stderr, "rewrite diag: input.fb_probe_failed=%s (using %dx%d fallback)\n",
fb_err.c_str(), fb_width, fb_height);
}
}

skeets_input_t input;
input.debug_raw_events = true;
input.raw_event_log_budget = 64;
std::string error_message;
if (!skeets_input_open(input, 1072, 1448, detect_input_protocol(), &error_message)) {
if (!skeets_input_open(input, fb_width, fb_height, detect_input_protocol(), &error_message)) {
std::fprintf(stderr, "rewrite diag: input.open_failed=%s\n", error_message.c_str());
return 5;
}
Expand Down
25 changes: 22 additions & 3 deletions src/kobo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,7 @@ void save_settings(const skeets_app_t& app) {
}

void clear_saved_session(skeets_app_t& app) {
std::fprintf(stderr, "clear_saved_session: CLEARING session from config\n");
config_t* config = config_open(skeets_config_path());
if (config) {
config_set_str(config, "handle", "");
Expand Down Expand Up @@ -1569,15 +1570,33 @@ void clear_saved_session(skeets_app_t& app) {
}

void persist_session(skeets_app_t& app, const Bsky::Session& session) {
config_t* config = config_open(skeets_config_path());
if (config) {
const char* config_path = skeets_config_path();

if (session.handle.empty() && session.access_jwt.empty() && session.did.empty()) {
std::fprintf(stderr, "persist_session: SKIPPING save — session is empty (would overwrite valid config)\n");
return;
}

std::fprintf(stderr, "persist_session: saving handle='%s' did='%s' pds='%s' access_len=%zu refresh_len=%zu\n",
session.handle.c_str(), session.did.c_str(), session.pds_url.c_str(),
session.access_jwt.size(), session.refresh_jwt.size());

config_t* config = config_open(config_path);
if (!config) {
std::fprintf(stderr, "persist_session: config_open returned NULL for '%s'\n", config_path);
} else {
config_set_str(config, "handle", session.handle.c_str());
config_set_str(config, "access_jwt", session.access_jwt.c_str());
config_set_str(config, "refresh_jwt", session.refresh_jwt.c_str());
config_set_str(config, "did", session.did.c_str());
config_set_str(config, "pds_url", session.pds_url.c_str());
config_set_str(config, "appview_url", session.appview_url.c_str());
config_save(config);
int result = config_save(config);
if (result != 0) {
std::fprintf(stderr, "persist_session: config_save FAILED (result=%d)\n", result);
} else {
std::fprintf(stderr, "persist_session: config_save succeeded\n");
}
config_free(config);
}
app.bootstrap.session = session;
Expand Down
55 changes: 47 additions & 8 deletions src/util/config.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "config.h"
#include "str.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <unistd.h>

#define CONFIG_MAX_ENTRIES 128

Expand All @@ -28,12 +30,19 @@ static config_entry_t *find_entry(config_t *cfg, const char *key) {

config_t *config_open(const char *path) {
config_t *cfg = (config_t *)calloc(1, sizeof(config_t));
if (!cfg) return NULL;
if (!cfg) {
std::fprintf(stderr, "config_open: calloc failed for '%s'\n", path ? path : "(null)");
return NULL;
}
str_safe_copy(cfg->path, path, sizeof(cfg->path));

FILE *f = fopen(path, "r");
if (!f) return cfg; /* new config, no file yet */
if (!f) {
std::fprintf(stderr, "config_open: file '%s' not found (errno=%d), returning empty config\n", path, errno);
return cfg; /* new config, no file yet */
}

std::fprintf(stderr, "config_open: reading '%s'\n", path);
char line[CONFIG_MAX_KEY + CONFIG_MAX_VALUE + 4];
while (fgets(line, sizeof(line), f)) {
str_trim(line);
Expand All @@ -49,6 +58,7 @@ config_t *config_open(const char *path) {
config_set_str(cfg, k, v);
}
fclose(f);
std::fprintf(stderr, "config_open: loaded %d entries from '%s'\n", cfg->count, path);
return cfg;
}

Expand All @@ -57,13 +67,42 @@ void config_free(config_t *cfg) {
}

int config_save(config_t *cfg) {
if (!cfg) return -1;
if (!cfg) {
std::fprintf(stderr, "config_save: cfg is NULL\n");
return -1;
}
FILE *f = fopen(cfg->path, "w");
if (!f) return -1;
if (!f) {
std::fprintf(stderr, "config_save: failed to open '%s' for writing: %s (errno=%d)\n",
cfg->path, std::strerror(errno), errno);
return -1;
}
fprintf(f, "# sKeets config\n");
for (int i = 0; i < cfg->count; i++)
fprintf(f, "%s=%s\n", cfg->entries[i].key, cfg->entries[i].value);
fclose(f);

// Flush to kernel buffers
if (fflush(f) != 0) {
std::fprintf(stderr, "config_save: fflush failed for '%s': %s (errno=%d)\n",
cfg->path, std::strerror(errno), errno);
fclose(f);
return -1;
}

// Sync to persistent storage (critical on embedded devices)
int fd = fileno(f);
if (fd >= 0 && fsync(fd) != 0) {
std::fprintf(stderr, "config_save: fsync failed for '%s': %s (errno=%d)\n",
cfg->path, std::strerror(errno), errno);
// Don't fail - data may still reach disk on fclose
}

if (fclose(f) != 0) {
std::fprintf(stderr, "config_save: fclose failed for '%s': %s (errno=%d)\n",
cfg->path, std::strerror(errno), errno);
return -1;
}
std::fprintf(stderr, "config_save: successfully wrote %d entries to '%s'\n", cfg->count, cfg->path);
return 0;
}

Expand Down
17 changes: 15 additions & 2 deletions src/util/paths.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "paths.h"

#include <cstdio>
#include <cstdlib>
#include <mutex>
#include <string>
Expand Down Expand Up @@ -84,8 +85,20 @@ const char *skeets_cache_dir() {

int skeets_ensure_data_dirs() {
const path_state_t &state = paths();
if (!mkdirs(state.data_dir)) return -1;
if (!mkdirs(state.cache_dir)) return -1;
fprintf(stderr, "paths: ensuring data directories exist\n");
fprintf(stderr, "paths: data_dir='%s'\n", state.data_dir.c_str());
fprintf(stderr, "paths: config_path='%s'\n", state.config_path.c_str());
fprintf(stderr, "paths: cache_dir='%s'\n", state.cache_dir.c_str());

if (!mkdirs(state.data_dir)) {
fprintf(stderr, "paths: FAILED to create data_dir='%s'\n", state.data_dir.c_str());
return -1;
}
if (!mkdirs(state.cache_dir)) {
fprintf(stderr, "paths: FAILED to create cache_dir='%s'\n", state.cache_dir.c_str());
return -1;
}
fprintf(stderr, "paths: data directories ready\n");
return 0;
}

Expand Down