From ea7adeb30f9229271c02eadf76b3df6e928d1267 Mon Sep 17 00:00:00 2001 From: empathicqubit Date: Tue, 27 Dec 2022 23:35:23 +0100 Subject: [PATCH] Logging and warning cleanup. Fully start program with Noshell! --- CMakeLists.txt | 4 +- src/common/utils.h | 45 ++++++++++++++- src/tibridge.c | 27 ++++----- src/tikeys.c | 134 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 165 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a29f462..1f55ce5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ file(GLOB TIBRIDGE_SRC src/tibridge.c) add_executable(tibridge ${COMMON_SRC} ${TIBRIDGE_SRC}) -target_compile_options(tibridge PRIVATE -Werror) +target_compile_options(tibridge PRIVATE -Wall -Wno-format-security) target_include_directories(tibridge PRIVATE src/include/ @@ -39,7 +39,7 @@ file(GLOB TIKEYS_SRC src/tikeys.c) add_executable(tikeys ${COMMON_SRC} ${TIKEYS_SRC}) -target_compile_options(tikeys PRIVATE -Werror) +target_compile_options(tikeys PRIVATE -Wall -Wno-format-security) target_include_directories(tikeys PRIVATE src/include/ diff --git a/src/common/utils.h b/src/common/utils.h index 2f1775e..280b691 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -3,6 +3,8 @@ #include #include +#include +#include typedef enum { LEVEL_ERROR, @@ -12,7 +14,48 @@ typedef enum { LEVEL_TRACE, } LOG_LEVEL; -#define log(level, fmt, values...) if(level <= current_log_level) { fprintf(stderr, fmt, ## values); fflush(stderr); } +#define COLOR_RESET "\x1b[00m" +#define COLOR_BLACK "\x1b[30m" +#define COLOR_RED "\x1b[31m" +#define COLOR_GREEN "\x1b[32m" +#define COLOR_YELLOW "\x1b[33m" +#define COLOR_BLUE "\x1b[34m" +#define COLOR_MAGENTA "\x1b[35m" +#define COLOR_CYAN "\x1b[36m" +#define COLOR_WHITE "\x1b[37m" + +static char* get_fullfmt(LOG_LEVEL level, const char* fmt) { + char* color; + if(level == LEVEL_ERROR) { + color = COLOR_RED; + } + else if(level == LEVEL_WARN) { + color = COLOR_YELLOW; + } + else if(level == LEVEL_DEBUG) { + color = COLOR_MAGENTA; + } + else if(level == LEVEL_TRACE) { + color = COLOR_CYAN; + } + else { + color = COLOR_RESET; + } + + char *fullfmt = malloc(10 + strlen(fmt)); \ + sprintf(fullfmt, "%s%s%s", color, fmt, COLOR_RESET); \ + + return fullfmt; +} + +#define log(level, fmt, values...) { \ + if(level <= current_log_level) { \ + char *fullfmt = get_fullfmt(level, fmt ""); \ + fprintf(stderr, fullfmt , ## values); \ + fflush(stderr); \ + free(fullfmt); \ + } \ +} extern LOG_LEVEL current_log_level; diff --git a/src/tibridge.c b/src/tibridge.c index c798e76..94306b0 100644 --- a/src/tibridge.c +++ b/src/tibridge.c @@ -9,8 +9,6 @@ #include "common/utils.h" -static pthread_t tid; - static CableHandle* cable_handle; void show_help() { @@ -32,7 +30,7 @@ int hex(char ch) { return (-1); } -uint8_t *hex2mem(const char *buf, uint8_t *mem, uint32_t count) { +char *hex2mem(const char *buf, char *mem, uint32_t count) { unsigned char ch; for (int i = 0; i < count; i++) { @@ -56,30 +54,30 @@ void reset_cable(void) { ticables_options_set_delay(cable_handle, 1); ticables_options_set_timeout(cable_handle, 5); - while(err = ticables_cable_open(cable_handle)) { + while((err = ticables_cable_open(cable_handle))) { log(LEVEL_ERROR, "Could not open cable: %d\n", err); } } -void retry_send(unsigned char* send, int sendCount) { +void retry_send(uint8_t* send, int sendCount) { unsigned char err = 0; log(LEVEL_DEBUG, "%d->", sendCount); log(LEVEL_TRACE, "%.*s\n", sendCount, send); - while(err = ticables_cable_send(cable_handle, send, sendCount)) { + while((err = ticables_cable_send(cable_handle, send, sendCount))) { log(LEVEL_ERROR, "Error sending: %d", err); reset_cable(); } } void ack() { - retry_send("+", 1); + retry_send((uint8_t*)"+", 1); } void nack() { - retry_send("-", 1); + retry_send((uint8_t*)"-", 1); } -void retry_recv(unsigned char* recv, int recvCount) { +void retry_recv(uint8_t* recv, int recvCount) { log(LEVEL_DEBUG, "%d<-", recvCount); log(LEVEL_TRACE, "%.*s\n", recvCount, recv) int c = 0; @@ -150,7 +148,7 @@ int main(int argc, char *argv[]) { bool handled_first_recv = false; while(true) { - unsigned char recv[1023]; + uint8_t recv[1023]; unsigned char current = 0; int recvCount = 0; int c; @@ -159,7 +157,7 @@ int main(int argc, char *argv[]) { log(LEVEL_DEBUG, "RECEIVE PHASE\n"); while(true) { do { - if(err = ticables_cable_recv(cable_handle, &recv[recvCount], 1)) { + if((err = ticables_cable_recv(cable_handle, &recv[recvCount], 1))) { log(LEVEL_ERROR, "error receiving: %d\n", err); } } while(err); @@ -167,7 +165,7 @@ int main(int argc, char *argv[]) { recvCount++; if(current == '#') { do { - if(err = ticables_cable_recv(cable_handle, &recv[recvCount], 2)) { + if((err = ticables_cable_recv(cable_handle, &recv[recvCount], 2))) { log(LEVEL_ERROR, "error receiving: %d\n", err); } } while(err); @@ -182,7 +180,7 @@ int main(int argc, char *argv[]) { log(LEVEL_DEBUG, "Discarded the first packet\n"); } - char *packet_char = strchr(recv, '$'); + char *packet_char = strchr((const char*)recv, '$'); if(packet_char) { packet_char++; @@ -227,12 +225,11 @@ int main(int argc, char *argv[]) { fd_set set; FD_ZERO(&set); FD_SET(0, &set); - struct timeval timeout = { 1, 0 }; log(LEVEL_INFO, ">"); log(LEVEL_DEBUG, "SEND PHASE\n"); while(true) { - unsigned char send[255]; + uint8_t send[255]; int sendCount = 0; while(true) { diff --git a/src/tikeys.c b/src/tikeys.c index 69a8ccb..c546064 100644 --- a/src/tikeys.c +++ b/src/tikeys.c @@ -9,25 +9,42 @@ #include #include #include +#include #include "common/utils.h" +#define CABLE_TIMEOUT 20 +#define CABLE_FAST_TIMEOUT 2 + static char *subtype = ""; static char *program = ""; static char *keys = ""; static int reset_ram = 0; static CalcHandle *calc_handle = NULL; +static CableHandle *cable_handle = NULL; static CalcModel model = CALC_NONE; void show_help() { log(LEVEL_INFO, "Syntax: tikeys [--reset-ram] [--keys=ABCDEFG123456789] [--subtype=mirage --program=PROGNAME]\n"); } +void cleanup() { + if(calc_handle) { + ticalcs_cable_detach(calc_handle); + ticalcs_handle_del(calc_handle); + } + if(cable_handle) { + ticables_cable_close(cable_handle); + ticables_handle_del(cable_handle); + } + ticables_library_exit(); +} + static void send_key(uint32_t key, int retry) { usleep(100000); int err; - while(err = ticalcs_calc_send_key(calc_handle, key) && retry); + while((err = ticalcs_calc_send_key(calc_handle, key) && retry)); } static int compare(const void *a, const void *b) { @@ -37,8 +54,8 @@ static int compare(const void *a, const void *b) { static int get_program_index(GNode *tree, char* program) { char *names[1024]; int n = 0; + bool has_program = false; - TreeInfo *info = tree->data; for (int i = 0; i < (int)g_node_n_children(tree); i++) { GNode *parent = g_node_nth_child(tree, i); VarEntry *ve = parent->data; @@ -50,29 +67,72 @@ static int get_program_index(GNode *tree, char* program) { if(ve != NULL) { const char *str_type = tifiles_vartype2string(model, ve->type); + bool is_program = strcmp(&str_type[strlen(str_type) - 4], "PRGM") == 0; if (strlen(str_type) >= 4 && ( - strcmp(&str_type[strlen(str_type) - 4], "PRGM") == 0 - || strcmp(str_type, "APPL") == 0 + is_program || strcmp(str_type, "APPL") == 0 ) ) { + if(is_program && strcmp(ve->name, program) == 0) { + has_program = true; + } + names[n++] = ve->name; + log(LEVEL_TRACE, "%s\n", names[n-1]); } } } } + log(LEVEL_TRACE, "Sorting\n"); + qsort(names, n, sizeof(names[0]), compare); for(int i = 0; i < n; i++) { + log(LEVEL_TRACE, "%s\n", names[i]); if(strcmp(names[i], program) == 0) { - return i+1; // Finance is always at the beginning + // Finance is always at the beginning for apps + return has_program ? i : i+1; } } return -1; } +int start_app(GNode *apps, char *app_name, int is_program) { + int noshell_idx = get_program_index(apps, app_name); + if(noshell_idx == -1) { + log(LEVEL_ERROR, "Could not find %s.\n", app_name); + return 1; + } + + if(is_program) { + send_key(KEY83P_Prgm, 1); + } + else { + send_key(KEY83P_AppsMenu, 1); + } + + for(int i = 0; i < noshell_idx; i++) { + send_key(KEY83P_Down, 1); + } + send_key(KEY83P_Enter, 0); + + if(is_program) { + send_key(KEY83P_Enter, 0); + } + + return 0; +} + +void handle_sigint(int code) { + cleanup(); +} + int main(int argc, char *argv[]) { + struct sigaction sa; + sa.sa_handler = handle_sigint; + sigaction(SIGINT, &sa, NULL); + utils_parse_args(argc, argv); const struct option long_opts[] = { @@ -106,22 +166,29 @@ int main(int argc, char *argv[]) { } else if(opt == 'h') { show_help(); + cleanup(); return 0; } } + log(LEVEL_TRACE, "Subtype: %s\n", subtype); + log(LEVEL_TRACE, "Keys: %s\n", keys); + log(LEVEL_TRACE, "Reset RAM: %d\n", reset_ram); + int err; ticables_library_init(); - CableHandle *cable_handle = utils_setup_cable(); + cable_handle = utils_setup_cable(); if(cable_handle == NULL) { log(LEVEL_ERROR, "Cable not found!\n"); + cleanup(); return 1; } err = ticables_cable_open(cable_handle); if(err) { log(LEVEL_ERROR, "Could not open cable: %d\n", err); + cleanup(); return 1; } @@ -129,12 +196,14 @@ int main(int argc, char *argv[]) { err = ticables_cable_get_device_info(cable_handle, &info); if(err) { log(LEVEL_ERROR, "Could not read device info: %d\n", err); + cleanup(); return 1; } err = ticables_cable_close(cable_handle); if(err) { log(LEVEL_ERROR, "Could not close cable: %d\n", err); + cleanup(); return 1; } @@ -142,7 +211,7 @@ int main(int argc, char *argv[]) { cable_handle = utils_setup_cable(); - ticables_options_set_timeout(cable_handle, 20); + ticables_options_set_timeout(cable_handle, CABLE_TIMEOUT); model = CALC_TI83P; @@ -164,15 +233,19 @@ int main(int argc, char *argv[]) { } if(strlen(subtype) > 0 || strlen(program) > 0) { + log(LEVEL_DEBUG, "Got a program startup request.\n"); + send_key(KEY83P_Quit, 1); send_key(KEY83P_Clear, 1); if(strcmp(subtype, "asm") == 0) { log(LEVEL_ERROR, "asm is not supported! Start it manually!\n"); + cleanup(); return 1; } else if(strcmp(subtype, "tse") == 0) { log(LEVEL_ERROR, "tse is not supported! Start it manually!\n"); + cleanup(); return 1; } else if(strcmp(subtype, "ion") == 0) { @@ -184,9 +257,17 @@ int main(int argc, char *argv[]) { } else if(strcmp(subtype, "mirage") == 0) { log(LEVEL_WARN, "Mirage will be started, but you still need to start the program yourself.\n"); - send_key(KEY83P_AppsMenu, 1); - send_key(ticalcs_keys_83p('M')->normal.value, 1); - send_key(KEY83P_Enter, 0); + + GNode *vars, *apps; + while((err = ticalcs_calc_get_dirlist(calc_handle, &vars, &apps))); + + log(LEVEL_DEBUG, "Got dirlist\n"); + + if((err = start_app(apps, "MirageOS", 0))) { + log(LEVEL_ERROR, "Could not start MirageOS. Is it installed?\n"); + cleanup(); + return 1; + } } else if(strlen(program) > 0) { if(strcmp(subtype, "noshell") != 0) { @@ -195,28 +276,32 @@ int main(int argc, char *argv[]) { log(LEVEL_INFO, "Verifying that noshell is correctly hooked.\n"); - int err; GNode *vars, *apps; - while(err = ticalcs_calc_get_dirlist(calc_handle, &vars, &apps)); + while((err = ticalcs_calc_get_dirlist(calc_handle, &vars, &apps))); log(LEVEL_DEBUG, "Got dirlist\n"); - int noshell_idx = get_program_index(apps, "Noshell "); - if(noshell_idx == -1) { - log(LEVEL_ERROR, "Could not find noshell. Exiting\n"); + if((err = start_app(apps, "Noshell ", 0))) { + log(LEVEL_ERROR, "Could not start Noshell. Is it installed?\n"); + cleanup(); return 1; } - send_key(KEY83P_AppsMenu, 1); - for(int i = 0; i < noshell_idx; i++) { - send_key(KEY83P_Down, 1); + ticables_options_set_timeout(cable_handle, CABLE_FAST_TIMEOUT); + send_key(ticalcs_keys_83p('1')->normal.value, 0); + send_key(KEY83P_Enter, 0); + send_key(ticalcs_keys_83p('6')->normal.value, 0); + ticables_options_set_timeout(cable_handle, CABLE_TIMEOUT); + + if((err = start_app(vars, program, 1))) { + log(LEVEL_ERROR, "Could not start %s. Is it installed?\n", program); + cleanup(); + return 1; } - //send_key(KEY83P_Enter, 0); + cleanup(); return 1; - get_program_index(vars, program); - // There has to be a better way to do this... // Select a program then delete the name, // keeping only the pgrm token @@ -236,11 +321,6 @@ int main(int argc, char *argv[]) { } } - ticalcs_cable_detach(calc_handle); - ticalcs_handle_del(calc_handle); - ticables_cable_close(cable_handle); - ticables_handle_del(cable_handle); - ticables_library_exit(); - + cleanup(); return 0; } \ No newline at end of file