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
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "(gdb) Starten",
|
"name": "tibridge",
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/build/ticat",
|
"program": "${workspaceFolder}/build/tibridge",
|
||||||
"args": [],
|
"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}",
|
"cwd": "${workspaceFolder}",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
|
|
|
@ -1,6 +1,55 @@
|
||||||
cmake_minimum_required(VERSION 3.16)
|
project(tibridge)
|
||||||
find_package (ticables2)
|
|
||||||
find_package (pthread)
|
cmake_minimum_required(VERSION 3.1.0)
|
||||||
add_executable (tibridge main.c)
|
|
||||||
target_link_libraries (tibridge LINK_PUBLIC ticables2)
|
find_package(PkgConfig REQUIRED)
|
||||||
target_link_libraries (tibridge LINK_PUBLIC pthread)
|
|
||||||
|
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 <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
static CableDeviceInfo EmptyInfo;
|
static CableDeviceInfo EmptyInfo;
|
||||||
|
|
||||||
static pthread_t tid;
|
static pthread_t tid;
|
||||||
|
|
||||||
static CableHandle* handle;
|
static CableHandle* handle;
|
||||||
|
|
||||||
static pthread_mutex_t lock;
|
|
||||||
|
|
||||||
static CablePort port;
|
static CablePort port;
|
||||||
|
static CableModel model;
|
||||||
|
|
||||||
void reset_cable(void) {
|
void reset_cable(void) {
|
||||||
unsigned char err;
|
unsigned char err;
|
||||||
ticables_cable_reset(handle);
|
ticables_cable_reset(handle);
|
||||||
ticables_cable_close(handle);
|
ticables_cable_close(handle);
|
||||||
ticables_handle_del(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_delay(handle, 1);
|
||||||
ticables_options_set_timeout(handle, 5);
|
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) {
|
void retry_send(unsigned char* send, int sendCount) {
|
||||||
unsigned char err = 0;
|
unsigned char err = 0;
|
||||||
log(LEVEL_DEBUG, "SENDING %d BYTES \n", sendCount);
|
log(LEVEL_DEBUG, "%d->", sendCount);
|
||||||
log(LEVEL_TRACE, "%.*s\n", sendCount, send);
|
log(LEVEL_TRACE, "%.*s\n", sendCount, send);
|
||||||
while(err = ticables_cable_send(handle, send, sendCount)) {
|
while(err = ticables_cable_send(handle, send, sendCount)) {
|
||||||
log(LEVEL_ERROR, "Error sending: %d", err);
|
log(LEVEL_ERROR, "Error sending: %d", err);
|
||||||
|
@ -63,63 +52,32 @@ void nack() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void retry_recv(unsigned char* recv, int recvCount) {
|
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)
|
log(LEVEL_TRACE, "%.*s\n", recvCount, recv)
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while((c += fwrite(&recv[c], 1, recvCount - c, stdout)) < recvCount);
|
while((c += fwrite(&recv[c], 1, recvCount - c, stdout)) < recvCount);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INThandler(int sig) {
|
int main(int argc, char *argv[]) {
|
||||||
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 err;
|
int err;
|
||||||
|
|
||||||
/*
|
|
||||||
signal(SIGINT, INThandler);
|
|
||||||
signal(SIGSTOP, INThandler);
|
|
||||||
signal(SIGTERM, INThandler);
|
|
||||||
signal(SIGQUIT, INThandler);
|
|
||||||
*/
|
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
setvbuf(stdin, NULL, _IONBF, 0);
|
setvbuf(stdin, NULL, _IONBF, 0);
|
||||||
|
|
||||||
log(LEVEL_INFO, "PROCESS ID: %d\n", getpid());
|
utils_parse_args(argc, argv);
|
||||||
|
|
||||||
if (pthread_mutex_init(&lock, NULL) != 0) {
|
|
||||||
fprintf(stderr, "mutex init has failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ticables_library_init();
|
ticables_library_init();
|
||||||
|
|
||||||
// search for all USB cables (faster)
|
log(LEVEL_INFO, "PROCESS ID: %d\n", getpid());
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int *ports = cables[CABLE_SLV];
|
handle = utils_setup_cable();
|
||||||
int i;
|
if(handle == NULL) {
|
||||||
for(i = 0; !ports[i] && i < 5; i++);
|
log(LEVEL_ERROR, "Cable not found!\n");
|
||||||
|
return 1;
|
||||||
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);
|
err = ticables_cable_open(handle);
|
||||||
if(err) {
|
if(err) {
|
||||||
log(LEVEL_ERROR, "Could not open cable: %d\n", err);
|
log(LEVEL_ERROR, "Could not open cable: %d\n", err);
|
||||||
|
@ -133,7 +91,8 @@ int main(void) {
|
||||||
return 1;
|
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 handle_acks = true;
|
||||||
bool handled_first_recv = false;
|
bool handled_first_recv = false;
|
||||||
|
@ -144,6 +103,7 @@ int main(void) {
|
||||||
int recvCount = 0;
|
int recvCount = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
log(LEVEL_INFO, "<");
|
||||||
log(LEVEL_DEBUG, "RECEIVE PHASE\n");
|
log(LEVEL_DEBUG, "RECEIVE PHASE\n");
|
||||||
while(true) {
|
while(true) {
|
||||||
do {
|
do {
|
||||||
|
@ -201,6 +161,7 @@ int main(void) {
|
||||||
FD_SET(0, &set);
|
FD_SET(0, &set);
|
||||||
struct timeval timeout = { 1, 0 };
|
struct timeval timeout = { 1, 0 };
|
||||||
|
|
||||||
|
log(LEVEL_INFO, ">");
|
||||||
log(LEVEL_DEBUG, "SEND PHASE\n");
|
log(LEVEL_DEBUG, "SEND PHASE\n");
|
||||||
while(true) {
|
while(true) {
|
||||||
unsigned char send[255];
|
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