Add keypressing program to automatically start different shells
This commit is contained in:
parent
52e3f1630d
commit
c97fa6d38b
6 changed files with 272 additions and 67 deletions
27
.vscode/launch.json
vendored
27
.vscode/launch.json
vendored
|
@ -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,
|
||||
|
|
|
@ -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})
|
66
src/common/utils.c
Normal file
66
src/common/utils.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "utils.h"
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
src/common/utils.h
Normal file
23
src/common/utils.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef __COMMON_UTILS_H__
|
||||
#define __COMMON_UTILS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tilp2/ticables.h>
|
||||
|
||||
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
|
|
@ -8,22 +8,23 @@
|
|||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#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);
|
||||
log(LEVEL_INFO, "PROCESS ID: %d\n", getpid());
|
||||
|
||||
handle = utils_setup_cable();
|
||||
if(handle == NULL) {
|
||||
log(LEVEL_ERROR, "Cable not found!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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[]);
|
83
src/tikeys.c
Normal file
83
src/tikeys.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include <tilp2/ticables.h>
|
||||
#include <tilp2/ticalcs.h>
|
||||
#include "common/utils.h"
|
||||
#include <readline/readline.h>
|
||||
#include <tilp2/keys83p.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Add table
Reference in a new issue