diff --git a/.vscode/launch.json b/.vscode/launch.json index 2ada58c..03f7772 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,13 +4,34 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { - "name": "(gdb) Starten", + "name": "tibridge", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/build/ticat", + "program": "${workspaceFolder}/build/tibridge", "args": [], - "stopAtEntry": false, + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "preLaunchTask": "build", + "setupCommands": [ + { + "description": "Automatische Strukturierung und Einrückung für \"gdb\" aktivieren", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "tikeys", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/tikeys", + "args": ["--subtype=mirage", "--log-level=trace"], + "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ce3b58..369a82a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,55 @@ -cmake_minimum_required(VERSION 3.16) -find_package (ticables2) -find_package (pthread) -add_executable (tibridge main.c) -target_link_libraries (tibridge LINK_PUBLIC ticables2) -target_link_libraries (tibridge LINK_PUBLIC pthread) +project(tibridge) + +cmake_minimum_required(VERSION 3.1.0) + +find_package(PkgConfig REQUIRED) + +PKG_CHECK_MODULES(GLIB REQUIRED glib-2.0) +PKG_CHECK_MODULES(TICABLES REQUIRED ticables2) +PKG_CHECK_MODULES(TICALCS REQUIRED ticalcs2) + +file(GLOB COMMON_SRC src/common/*.c) + +file(GLOB TIBRIDGE_SRC src/tibridge.c) + +add_executable(tibridge ${COMMON_SRC} ${TIBRIDGE_SRC}) + +target_compile_options(tibridge PRIVATE -Werror) + +target_include_directories(tibridge + PRIVATE src/include/ + PRIVATE ${GLIB_INCLUDE_DIRS} + PRIVATE ${TICABLES_INCLUDE_DIRS} +) + +target_link_libraries(tibridge PRIVATE ${GLIB_LIBRARIES}) +target_link_libraries(tibridge PRIVATE ${TICABLES_LIBRARIES}) + +target_link_directories(tibridge PRIVATE ${GLIB_LIBRARY_DIRS}) +target_link_directories(tibridge PRIVATE ${TICABLES_LIBRARIES}) + +PKG_CHECK_MODULES(READLINE REQUIRED readline) + +file(GLOB TIKEYS_SRC src/tikeys.c) + +add_executable(tikeys ${COMMON_SRC} ${TIKEYS_SRC}) + +target_compile_options(tikeys PRIVATE -Werror) + +target_include_directories(tikeys + PRIVATE src/include/ + PRIVATE ${GLIB_INCLUDE_DIRS} + PRIVATE ${TICABLES_INCLUDE_DIRS} + PRIVATE ${TICALCS_INCLUDE_DIRS} + PRIVATE ${READLINE_INCLUDE_DIRS} +) + +target_link_libraries(tikeys PRIVATE ${GLIB_LIBRARIES}) +target_link_libraries(tikeys PRIVATE ${TICABLES_LIBRARIES}) +target_link_libraries(tikeys PRIVATE ${TICALCS_LIBRARIES}) +target_link_libraries(tikeys PRIVATE ${READLINE_LIBRARIES}) + +target_link_directories(tikeys PRIVATE ${GLIB_LIBRARY_DIRS}) +target_link_directories(tikeys PRIVATE ${TICABLES_LIBRARIES}) +target_link_directories(tikeys PRIVATE ${TICALCS_LIBRARIES}) +target_link_directories(tikeys PRIVATE ${READLINE_LIBRARIES}) \ No newline at end of file diff --git a/src/common/utils.c b/src/common/utils.c new file mode 100644 index 0000000..e1469c4 --- /dev/null +++ b/src/common/utils.c @@ -0,0 +1,66 @@ +#include "utils.h" +#include +#include + +LOG_LEVEL current_log_level = LEVEL_INFO; + +CableHandle* utils_setup_cable() { + // search for all USB cables (faster) + log(LEVEL_INFO, "Searching for link cables...\n"); + int **cables = NULL; + int err = ticables_probing_do(&cables, 5, PROBE_ALL); + if(err) { + log(LEVEL_ERROR, "Could not probe cable: %d\n", err); + ticables_probing_finish(&cables); + return NULL; + } + + CableModel model; + int port; + for(model = CABLE_NUL; model < CABLE_MAX ; model++) { + int *ports = cables[model]; + int i; + for(i = 0; !ports[i] && i < 5; i++); + + port = ports[i]; + if(port) { + log(LEVEL_DEBUG, "Cable Model: %d, Port: %d\n", model, i); + break; + } + } + + CableHandle *handle = ticables_handle_new(model, port); + ticables_options_set_delay(handle, 1); + ticables_options_set_timeout(handle, 5); + + return handle; +} + +void utils_parse_args(int argc, char *argv[]) { + const struct option long_opts[] = { + {"log-level", required_argument, 0, 'L'}, + {0,0,0,0} + }; + + int opt_index = 0; + int opt; + while((opt = getopt_long(argc, argv, "L:", long_opts, &opt_index)) != -1) { + if(opt == 'L') { + if(strcmp(optarg, "warn") == 0) { + current_log_level = LEVEL_WARN; + } + else if(strcmp(optarg, "error") == 0) { + current_log_level = LEVEL_ERROR; + } + else if(strcmp(optarg, "debug") == 0) { + current_log_level = LEVEL_DEBUG; + } + else if(strcmp(optarg, "trace") == 0) { + current_log_level = LEVEL_TRACE; + } + else if(strcmp(optarg, "info") == 0) { + current_log_level = LEVEL_INFO; + } + } + } +} \ No newline at end of file diff --git a/src/common/utils.h b/src/common/utils.h new file mode 100644 index 0000000..2f1775e --- /dev/null +++ b/src/common/utils.h @@ -0,0 +1,23 @@ +#ifndef __COMMON_UTILS_H__ +#define __COMMON_UTILS_H__ + +#include +#include + +typedef enum { + LEVEL_ERROR, + LEVEL_WARN, + LEVEL_INFO, + LEVEL_DEBUG, + LEVEL_TRACE, +} LOG_LEVEL; + +#define log(level, fmt, values...) if(level <= current_log_level) { fprintf(stderr, fmt, ## values); fflush(stderr); } + +extern LOG_LEVEL current_log_level; + +CableHandle* utils_setup_cable(); + +void utils_parse_args(int argc, char *argv[]); + +#endif \ No newline at end of file diff --git a/main.c b/src/tibridge.c similarity index 74% rename from main.c rename to src/tibridge.c index 24fa0b3..e6f17a9 100644 --- a/main.c +++ b/src/tibridge.c @@ -8,22 +8,23 @@ #include #include +#include "common/utils.h" + static CableDeviceInfo EmptyInfo; static pthread_t tid; static CableHandle* handle; -static pthread_mutex_t lock; - static CablePort port; +static CableModel model; void reset_cable(void) { unsigned char err; ticables_cable_reset(handle); ticables_cable_close(handle); ticables_handle_del(handle); - handle = ticables_handle_new(CABLE_SLV, port); + handle = ticables_handle_new(model, port); ticables_options_set_delay(handle, 1); ticables_options_set_timeout(handle, 5); @@ -32,21 +33,9 @@ void reset_cable(void) { } } -typedef enum { - LEVEL_ERROR, - LEVEL_WARN, - LEVEL_INFO, - LEVEL_DEBUG, - LEVEL_TRACE, -} LOG_LEVEL; - -static LOG_LEVEL current_log_level = LEVEL_TRACE; - -#define log(level, fmt, values...) if(level <= current_log_level) { fprintf(stderr, fmt, ## values); fflush(stderr); } - void retry_send(unsigned char* send, int sendCount) { unsigned char err = 0; - log(LEVEL_DEBUG, "SENDING %d BYTES \n", sendCount); + log(LEVEL_DEBUG, "%d->", sendCount); log(LEVEL_TRACE, "%.*s\n", sendCount, send); while(err = ticables_cable_send(handle, send, sendCount)) { log(LEVEL_ERROR, "Error sending: %d", err); @@ -63,63 +52,32 @@ void nack() { } void retry_recv(unsigned char* recv, int recvCount) { - log(LEVEL_DEBUG, "RECEIVED %d BYTES\n", recvCount); + log(LEVEL_DEBUG, "%d<-", recvCount); log(LEVEL_TRACE, "%.*s\n", recvCount, recv) int c = 0; while((c += fwrite(&recv[c], 1, recvCount - c, stdout)) < recvCount); fflush(stdout); } -void INThandler(int sig) { - signal(sig, SIG_IGN); - char rest[1024]; - int count = read(0, rest, sizeof(rest)); - fwrite(rest, count, 1, stderr); - fflush(stderr); -} - -int main(void) { - int **cables = NULL; +int main(int argc, char *argv[]) { int err; -/* - signal(SIGINT, INThandler); - signal(SIGSTOP, INThandler); - signal(SIGTERM, INThandler); - signal(SIGQUIT, INThandler); - */ - setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0); - log(LEVEL_INFO, "PROCESS ID: %d\n", getpid()); - - if (pthread_mutex_init(&lock, NULL) != 0) { - fprintf(stderr, "mutex init has failed\n"); - return 1; - } + utils_parse_args(argc, argv); ticables_library_init(); - // search for all USB cables (faster) - log(LEVEL_INFO, "Searching for link cables...\n"); - err = ticables_probing_do(&cables, 5, PROBE_USB | PROBE_FIRST); - if(err) - { - log(LEVEL_ERROR, "Could not probe cable: %d\n", err); - ticables_probing_finish(&cables); - return 1; - } + log(LEVEL_INFO, "PROCESS ID: %d\n", getpid()); - int *ports = cables[CABLE_SLV]; - int i; - for(i = 0; !ports[i] && i < 5; i++); - - port = ports[i]; - handle = ticables_handle_new(CABLE_SLV, port); - ticables_options_set_delay(handle, 1); - ticables_options_set_timeout(handle, 5); + handle = utils_setup_cable(); + if(handle == NULL) { + log(LEVEL_ERROR, "Cable not found!\n"); + return 1; + } + // BEGIN DON'T DO THIS FOR TICALCS err = ticables_cable_open(handle); if(err) { log(LEVEL_ERROR, "Could not open cable: %d\n", err); @@ -133,7 +91,8 @@ int main(void) { return 1; } - log(LEVEL_INFO, "INFO: Family %d, Variant %d\n", info.family, info.variant); + log(LEVEL_INFO, "INFO: Model %d, Port:%d, Family %d, Variant %d\n", model, port, info.family, info.variant); + // END DON'T DO THIS FOR TICALCS bool handle_acks = true; bool handled_first_recv = false; @@ -144,6 +103,7 @@ int main(void) { int recvCount = 0; int c; + log(LEVEL_INFO, "<"); log(LEVEL_DEBUG, "RECEIVE PHASE\n"); while(true) { do { @@ -201,6 +161,7 @@ int main(void) { FD_SET(0, &set); struct timeval timeout = { 1, 0 }; + log(LEVEL_INFO, ">"); log(LEVEL_DEBUG, "SEND PHASE\n"); while(true) { unsigned char send[255]; @@ -225,3 +186,5 @@ int main(void) { } } } + +void utils_parse_args(int argc, char *argv[]); \ No newline at end of file diff --git a/src/tikeys.c b/src/tikeys.c new file mode 100644 index 0000000..663a857 --- /dev/null +++ b/src/tikeys.c @@ -0,0 +1,83 @@ +#include +#include +#include "common/utils.h" +#include +#include +#include +#include + +static char *subtype = "mirage"; + +static CalcHandle *calc_handle = NULL; + +void send_key(uint32_t key, int retry) { + usleep(250000); + int err; + while(err = ticalcs_calc_send_key(calc_handle, key) && retry); +} + +int main(int argc, char *argv[]) { + utils_parse_args(argc, argv); + + const struct option long_opts[] = { + //{name,arg,flag,val} + {"subtype", required_argument, 0, 's'}, + {0,0,0,0} + }; + + optind = 0; + int opt_index = 0; + int opt; + while((opt = getopt_long(argc, argv, "s:", long_opts, &opt_index)) != -1) { + if(opt == 's') { + subtype = optarg; + } + } + + ticables_library_init(); + + CableHandle *cable_handle = utils_setup_cable(); + if(cable_handle == NULL) { + log(LEVEL_ERROR, "Cable not found!\n"); + return 1; + } + + ticables_options_set_timeout(cable_handle, 20); + + calc_handle = ticalcs_handle_new(CALC_TI83P); + ticalcs_cable_attach(calc_handle, cable_handle); + + send_key(KEY83P_Quit, 1); + send_key(KEY83P_Clear, 1); + + int err; + if(strcmp(subtype, "asm") == 0) { + log(LEVEL_ERROR, "asm is not supported! Start it manually!\n"); + return 1; + } + else if(strcmp(subtype, "tse") == 0) { + log(LEVEL_ERROR, "tse is not supported! Start it manually!\n"); + return 1; + } + else if(strcmp(subtype, "ion") == 0) { + log(LEVEL_WARN, "ion will be started, but you still need to start the program yourself.\n"); + send_key(KEY83P_Prgm, 1); + send_key(ticalcs_keys_83p('A')->normal.value, 1); + send_key(KEY83P_Enter, 1); + send_key(KEY83P_Enter, 0); + } + 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); + } + else { + log(LEVEL_WARN, "Subtype was not recognized! Start it manually!\n"); + } + + ticalcs_cable_detach(calc_handle); + ticables_cable_close(cable_handle); + + return 0; +} \ No newline at end of file