Add ability to send debug messages over GDB

This commit is contained in:
Empathic Qubit 2022-12-27 20:31:52 +01:00
parent e26ea540e7
commit ea9665a100
6 changed files with 305 additions and 67 deletions

2
.vscode/launch.json vendored
View file

@ -30,7 +30,7 @@
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/tikeys",
"args": ["--subtype=mirage", "--log-level=trace"],
"args": ["--program=u1BERSHRD", "--log-level=trace"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],

31
.vscode/settings.json vendored
View file

@ -4,7 +4,36 @@
"ticalcs.h": "c",
"ticables.h": "c",
"vector": "c",
"random": "c"
"random": "c",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cmath": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"optional": "cpp",
"string_view": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"functional": "cpp",
"fstream": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"streambuf": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"typeinfo": "cpp",
"cstddef": "c"
},
"cmake.configureOnOpen": true
}

View file

@ -7,9 +7,12 @@ find_package(PkgConfig REQUIRED)
PKG_CHECK_MODULES(GLIB REQUIRED glib-2.0)
PKG_CHECK_MODULES(TICABLES REQUIRED ticables2)
PKG_CHECK_MODULES(TICALCS REQUIRED ticalcs2)
PKG_CHECK_MODULES(TIFILES REQUIRED tifiles2)
file(GLOB COMMON_SRC src/common/*.c)
####################################### TIBRIDGE ###############################
file(GLOB TIBRIDGE_SRC src/tibridge.c)
add_executable(tibridge ${COMMON_SRC} ${TIBRIDGE_SRC})
@ -30,6 +33,8 @@ target_link_directories(tibridge PRIVATE ${TICABLES_LIBRARIES})
PKG_CHECK_MODULES(READLINE REQUIRED readline)
####################################### TIKEYS ###############################
file(GLOB TIKEYS_SRC src/tikeys.c)
add_executable(tikeys ${COMMON_SRC} ${TIKEYS_SRC})
@ -41,15 +46,18 @@ target_include_directories(tikeys
PRIVATE ${GLIB_INCLUDE_DIRS}
PRIVATE ${TICABLES_INCLUDE_DIRS}
PRIVATE ${TICALCS_INCLUDE_DIRS}
PRIVATE ${TIFILES_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 ${TIFILES_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 ${TIFILES_LIBRARIES})
target_link_directories(tikeys PRIVATE ${READLINE_LIBRARIES})

View file

@ -42,6 +42,7 @@ void utils_parse_args(int argc, char *argv[]) {
{0,0,0,0}
};
opterr = 0;
optind = 0;
int opt_index = 0;
int opt;
@ -64,4 +65,6 @@ void utils_parse_args(int argc, char *argv[]) {
}
}
}
opterr = 1;
}

View file

@ -2,35 +2,53 @@
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include <error.h>
#include <unistd.h>
#include <signal.h>
#include <getopt.h>
#include <stdbool.h>
#include <string.h>
#include "common/utils.h"
static CableDeviceInfo EmptyInfo;
static pthread_t tid;
static CableHandle* handle;
static CableHandle* cable_handle;
static CablePort port;
static CableModel model;
int hex(char ch) {
if ((ch >= 'a') && (ch <= 'f'))
return (ch - 'a' + 10);
if ((ch >= '0') && (ch <= '9'))
return (ch - '0');
if ((ch >= 'A') && (ch <= 'F'))
return (ch - 'A' + 10);
return (-1);
}
uint8_t *hex2mem(const char *buf, uint8_t *mem, uint32_t count) {
unsigned char ch;
for (int i = 0; i < count; i++)
{
ch = hex(*buf++) << 4;
ch = ch + hex(*buf++);
*(mem++) = (char)ch;
}
return (mem);
}
void reset_cable(void) {
unsigned char err;
ticables_cable_reset(handle);
ticables_cable_close(handle);
ticables_handle_del(handle);
handle = ticables_handle_new(model, port);
ticables_options_set_delay(handle, 1);
ticables_options_set_timeout(handle, 5);
CablePort port;
CableModel model;
port = cable_handle->port;
model = cable_handle->model;
int err;
ticables_cable_reset(cable_handle);
ticables_cable_close(cable_handle);
ticables_handle_del(cable_handle);
cable_handle = ticables_handle_new(model, port);
ticables_options_set_delay(cable_handle, 1);
ticables_options_set_timeout(cable_handle, 5);
while(err = ticables_cable_open(handle)) {
fprintf(stderr, "Could not open cable: %d\n", err);
while(err = ticables_cable_open(cable_handle)) {
log(LEVEL_ERROR, "Could not open cable: %d\n", err);
}
}
@ -38,7 +56,7 @@ void retry_send(unsigned char* send, int sendCount) {
unsigned char err = 0;
log(LEVEL_DEBUG, "%d->", sendCount);
log(LEVEL_TRACE, "%.*s\n", sendCount, send);
while(err = ticables_cable_send(handle, send, sendCount)) {
while(err = ticables_cable_send(cable_handle, send, sendCount)) {
log(LEVEL_ERROR, "Error sending: %d", err);
reset_cable();
}
@ -61,7 +79,6 @@ void retry_recv(unsigned char* recv, int recvCount) {
}
int main(int argc, char *argv[]) {
int err;
// z88dk-gdb doesn't like the ACKs -/+, so we just hide them
int handle_acks = 1;
@ -87,30 +104,33 @@ int main(int argc, char *argv[]) {
log(LEVEL_DEBUG, "handle acks: %d\n", handle_acks);
int err;
ticables_library_init();
log(LEVEL_INFO, "PROCESS ID: %d\n", getpid());
handle = utils_setup_cable();
if(handle == NULL) {
cable_handle = utils_setup_cable();
if(cable_handle == NULL) {
log(LEVEL_ERROR, "Cable not found!\n");
return 1;
}
err = ticables_cable_open(handle);
//ticables_options_set_timeout(cable_handle , 1 * 60 * 60 * 10);
err = ticables_cable_open(cable_handle);
if(err) {
log(LEVEL_ERROR, "Could not open cable: %d\n", err);
return 1;
}
CableDeviceInfo info = EmptyInfo;
err = ticables_cable_get_device_info(handle, &info);
CableDeviceInfo info;
err = ticables_cable_get_device_info(cable_handle, &info);
if(err) {
log(LEVEL_ERROR, "Could not read device info: %d\n", err);
return 1;
}
log(LEVEL_INFO, "INFO: Model %d, Port:%d, Family %d, Variant %d\n", model, port, info.family, info.variant);
log(LEVEL_INFO, "Cable Family %d, Variant %d\n", info.family, info.variant);
bool handled_first_recv = false;
@ -124,7 +144,7 @@ int main(int argc, char *argv[]) {
log(LEVEL_DEBUG, "RECEIVE PHASE\n");
while(true) {
do {
if(err = ticables_cable_recv(handle, &recv[recvCount], 1)) {
if(err = ticables_cable_recv(cable_handle, &recv[recvCount], 1)) {
log(LEVEL_ERROR, "error receiving: %d\n", err);
}
} while(err);
@ -132,12 +152,14 @@ int main(int argc, char *argv[]) {
recvCount++;
if(current == '#') {
do {
if(err = ticables_cable_recv(handle, &recv[recvCount], 2)) {
if(err = ticables_cable_recv(cable_handle, &recv[recvCount], 2)) {
log(LEVEL_ERROR, "error receiving: %d\n", err);
}
} while(err);
recvCount += 2;
recv[recvCount] = '\0';
if(!handle_acks || handled_first_recv) {
retry_recv(recv, recvCount);
}
@ -145,6 +167,20 @@ int main(int argc, char *argv[]) {
log(LEVEL_DEBUG, "Discarded the first packet\n");
}
char *packet_char = strchr(recv, '$');
if(packet_char) {
packet_char++;
if(*packet_char == 'O') {
int data_size = (recvCount - 5) / 2;
char buf[data_size];
hex2mem(&packet_char[1], buf, data_size);
log(LEVEL_INFO, "\n%.*s", data_size, buf);
recvCount = 0;
continue;
}
}
if(handle_acks) {
log(LEVEL_DEBUG, "Injecting an ACK\n");
ack();

View file

@ -1,39 +1,115 @@
#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>
#include <stdlib.h>
static char *subtype = "mirage";
#include <readline/readline.h>
#include <glib-2.0/glib.h>
#include <tilp2/ticables.h>
#include <tilp2/ticalcs.h>
#include <tilp2/tifiles.h>
#include <tilp2/keys83p.h>
#include "common/utils.h"
static char *subtype = "";
static char *program = "";
static char *keys = "";
static int reset_ram = 0;
static CalcHandle *calc_handle = NULL;
static CalcModel model = CALC_NONE;
void send_key(uint32_t key, int retry) {
usleep(250000);
static void send_key(uint32_t key, int retry) {
usleep(100000);
int err;
while(err = ticalcs_calc_send_key(calc_handle, key) && retry);
}
static int compare(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}
static int get_program_index(GNode *tree, char* program) {
char *names[1024];
int n = 0;
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;
for (int j = 0; j < (int)g_node_n_children(parent); j++) {
GNode *child = g_node_nth_child(parent, j);
ve = child->data;
if(ve != NULL) {
const char *str_type = tifiles_vartype2string(model, ve->type);
if (strlen(str_type) >= 4
&& (
strcmp(&str_type[strlen(str_type) - 4], "PRGM") == 0
|| strcmp(str_type, "APPL") == 0
)
) {
names[n++] = ve->name;
}
}
}
}
qsort(names, n, sizeof(names[0]), compare);
for(int i = 0; i < n; i++) {
if(strcmp(names[i], program) == 0) {
return i+1; // Finance is always at the beginning
}
}
return -1;
}
void show_help() {
log(LEVEL_INFO, "Syntax: tikeys [--reset-ram] [--keys=ABCDEFG123456789] [--subtype=mirage --program=PROGNAME]\n");
}
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'},
{"program", required_argument, 0, 'p'},
{"keys", required_argument, 0, 'k'},
{"reset-ram", no_argument, &reset_ram, 1},
{"help", no_argument, 0, 'h'},
{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') {
while((opt = getopt_long(argc, argv, "s:p:", long_opts, &opt_index)) != -1) {
if(opt == 0 && long_opts[opt_index].flag) {
// Do nothing
}
else if(opt == 's') {
subtype = optarg;
}
else if(opt == 'p') {
program = optarg;
}
else if(opt == 'k') {
keys = optarg;
}
else if(opt == 'r') {
reset_ram = 1;
}
else if(opt == 'h') {
show_help();
return 0;
}
}
int err;
ticables_library_init();
CableHandle *cable_handle = utils_setup_cable();
@ -42,42 +118,128 @@ int main(int argc, char *argv[]) {
return 1;
}
err = ticables_cable_open(cable_handle);
if(err) {
log(LEVEL_ERROR, "Could not open cable: %d\n", err);
return 1;
}
CableDeviceInfo info;
err = ticables_cable_get_device_info(cable_handle, &info);
if(err) {
log(LEVEL_ERROR, "Could not read device info: %d\n", err);
return 1;
}
err = ticables_cable_close(cable_handle);
if(err) {
log(LEVEL_ERROR, "Could not close cable: %d\n", err);
return 1;
}
ticables_handle_del(cable_handle);
cable_handle = utils_setup_cable();
ticables_options_set_timeout(cable_handle, 20);
calc_handle = ticalcs_handle_new(CALC_TI83P);
model = CALC_TI83P;
calc_handle = ticalcs_handle_new(model);
ticalcs_cable_attach(calc_handle, cable_handle);
send_key(KEY83P_Quit, 1);
send_key(KEY83P_Clear, 1);
if(reset_ram) {
send_key(KEY83P_Quit, 1);
send_key(KEY83P_Clear, 1);
log(LEVEL_WARN, "Resetting RAM...\n");
send_key(KEY83P_ResetMem, 0);
}
if(strlen(keys) > 0) {
for(int i = 0; i < strlen(keys); i++) {
send_key(ticalcs_keys_83p(keys[i])->normal.value, 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");
if(strlen(subtype) > 0 || strlen(program) > 0) {
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");
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 if(strlen(program) > 0) {
if(strcmp(subtype, "noshell") != 0) {
log(LEVEL_WARN, "Subtype was not recognized! It will be started with noshell!\n");
}
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));
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");
return 1;
}
send_key(KEY83P_AppsMenu, 1);
for(int i = 0; i < noshell_idx; i++) {
send_key(KEY83P_Down, 1);
}
//send_key(KEY83P_Enter, 0);
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
send_key(KEY83P_Prgm, 1);
send_key(KEY83P_Enter, 1);
send_key(KEY83P_Up, 1);
send_key(KEY83P_Right, 1);
for(int i = 0; i < 16; i++) {
send_key(KEY83P_Del, 1);
}
// Actually input the name
for(int i = 0; i < strlen(program); i++) {
send_key(ticalcs_keys_83p(program[i])->normal.value, 1);
}
send_key(KEY83P_Enter, 0);
}
}
ticalcs_cable_detach(calc_handle);
ticalcs_handle_del(calc_handle);
ticables_cable_close(cable_handle);
ticables_handle_del(cable_handle);
ticables_library_exit();
return 0;
}