From 056ce41c9e39ddd87189b4316e49cfcbe783555e Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 30 Mar 2024 09:34:52 +0100 Subject: [PATCH] gdb: style, messages, add option to wait for gdb:start --- fxsdk/gdb-bridge.c | 210 ++++++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 86 deletions(-) diff --git a/fxsdk/gdb-bridge.c b/fxsdk/gdb-bridge.c index 6eb2904..f9a9705 100644 --- a/fxsdk/gdb-bridge.c +++ b/fxsdk/gdb-bridge.c @@ -12,32 +12,62 @@ #include #include -static struct fxlink_device* setup_calc(libusb_context* context) { - struct fxlink_filter filter = { - .intf_fxlink = true, - }; - delay_t delay = delay_infinite(); +/* Establish a connection to the calculator. If nostart is set, assume the + calculator is ready immediately; otherwise, wait for a message of type + gdb:start. The latter can be useful is the calculator is using USB prior to + starting a debugging session. */ +static struct fxlink_device *setup_calc(libusb_context *context, bool nostart) +{ + struct fxlink_filter filter = { 0 }; + filter.intf_fxlink = true; fxlink_filter_clean_libusb(&filter); hlog("calculators"); - log_("wating for fxlink capable device...\n"); - struct fxlink_device* dev = fxlink_device_find_wait(context, &filter, &delay); - if (!dev) { - elog("unable to open fxlink_device\n"); + log_("waiting for calculator to connect...\n"); + delay_t delay = delay_infinite(); + struct fxlink_device *fdev = + fxlink_device_find_wait(context, &filter, &delay); + + if(!fdev) { + elog("unable to open calculator\n"); + return NULL; + } + if(!fxlink_device_claim_fxlink(fdev)) { + elog("unable to claim fxlink interface\n"); return NULL; } - if (!fxlink_device_claim_fxlink(dev)) { - elog("unable to claim fxlink\n"); - return NULL; + fxlink_device_start_bulk_IN(fdev); + + if(nostart) + return fdev; + + hlog("gdb"); + log_("waiting for gdb init message...\n"); + while(true) { + libusb_handle_events(context); + + struct fxlink_message *msg = fxlink_device_finish_bulk_IN(fdev); + if(!msg) + continue; + if(fxlink_message_is_apptype(msg, "gdb", "start")) { + hlog("gdb"); + log_("got start message\n"); + break; + } + wlog("dropped a message of type %.16s:%.16s\n", + msg->application, msg->type); + + fxlink_device_start_bulk_IN(fdev); } - return dev; + return fdev; } -static int setup_socket(const char* listen_path) { +static int setup_socket(char const *listen_path) +{ int listen_socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (listen_socket < 0) { + if(listen_socket < 0) { perror("socket"); return -1; } @@ -46,23 +76,24 @@ static int setup_socket(const char* listen_path) { .sun_family = AF_UNIX, .sun_path = {0}, }; - strncpy(listen_address.sun_path, listen_path, sizeof(listen_address.sun_path) - 1); - if (bind(listen_socket, (struct sockaddr*)&listen_address, sizeof(listen_address)) < 0) { + strncpy(listen_address.sun_path, listen_path, + sizeof(listen_address.sun_path) - 1); + if(bind(listen_socket, (struct sockaddr *)&listen_address, sizeof(listen_address)) < 0) { close(listen_socket); perror("bind"); return -1; } - if (listen(listen_socket, 1024) < 0) { + if(listen(listen_socket, 1024) < 0) { close(listen_socket); perror("listen"); return -1; } hlog("socket"); - log_("wating for client on \"%s\"...\n", listen_address.sun_path); + log_("waiting for client on \"%s\"...\n", listen_address.sun_path); int client_socket = accept(listen_socket, NULL, NULL); - if (client_socket < 0) { + if(client_socket < 0) { close(listen_socket); perror("accept"); return -1; @@ -71,100 +102,107 @@ static int setup_socket(const char* listen_path) { return client_socket; } -int main(int argc, char* argv[]) { - if (argc != 2) { +int main(int argc, char *argv[]) +{ + libusb_context *context = NULL; + struct fxlink_device *fdev = NULL; + struct fxlink_pollfds fxlink_polled_fds = { 0 }; + int ret = 1; + + if(argc != 2) { elog("Usage : %s [listen path]\n", argv[0]); - return -1; + goto end; } - libusb_context* context = NULL; int err = libusb_init(&context); - if (err != 0) { + if(err != 0) { elog_libusb(err, "libusb_init"); - return -1; - } - struct fxlink_device* dev = setup_calc(context); - if (dev == NULL) { - return -1; - } - int client_socket = setup_socket(argv[1]); - if (client_socket < 0) { - return -1; + goto end; } + bool nostart = true; + fdev = setup_calc(context, nostart); + if(!fdev) + goto end; - struct pollfd client_socket_pollfd = {.fd = client_socket, .events = POLLIN}; - struct fxlink_pollfds fxlink_polled_fds; + int client_socket = setup_socket(argv[1]); + if(client_socket < 0) + goto end; + + /* Track libusb fds as an indirect way to watch the calculator itself */ + struct pollfd client_socket_pollfd = { + .fd = client_socket, .events = POLLIN + }; fxlink_pollfds_track(&fxlink_polled_fds, context); - if (!fxlink_device_start_bulk_IN(dev)) { - elog("unable to start bulk IN trasfer\n"); - return -1; - } - - // TODO : find a way to properly close socket or USB interface when the other side is disconnected - int ret = 0; - while (1) { - int err = fxlink_multipoll(-1, fxlink_polled_fds.fds, fxlink_polled_fds.count, - &client_socket_pollfd, 1, - NULL); + while(true) { + int err = fxlink_multipoll(-1, + fxlink_polled_fds.fds, fxlink_polled_fds.count, + &client_socket_pollfd, 1, + NULL); if (err < 0) { perror("poll"); - ret = -1; - break; + goto end; } struct timeval zero = {0}; libusb_handle_events_timeout(context, &zero); - struct fxlink_message* msg; - while ((msg = fxlink_device_finish_bulk_IN(dev)) != NULL) { - if (!fxlink_message_is_apptype(msg, "gdb", "remote")) { - elog("unknown fxlink message type\n"); - ret = -1; - break; + + struct fxlink_message *msg; + while((msg = fxlink_device_finish_bulk_IN(fdev)) != NULL) { + if(!fxlink_message_is_apptype(msg, "gdb", "remote")) { + wlog("dropped a message of type %.16s:%.16s\n", + msg->application, msg->type); + fxlink_device_start_bulk_IN(fdev); + continue; } + printf("CAL> %.*s\n", msg->size, (char *)msg->data); ssize_t send_ret = send(client_socket, msg->data, msg->size, 0); - if (send_ret != msg->size) { + if(send_ret != msg->size) { perror("send"); - ret = -1; - break; + goto end; } fxlink_message_free(msg, true); - fxlink_device_start_bulk_IN(dev); + fxlink_device_start_bulk_IN(fdev); } - if (ret != 0) { - break; - } + /* Don't start an OUT transfer if there's one in progress */ + if(fdev->comm->ftransfer_OUT) + continue; - // We don't want to start a new OUT transfer if another one is still in progress - if (!dev->comm->ftransfer_OUT) { - int bytes_socket; - if (ioctl(client_socket, FIONREAD, &bytes_socket) < 0) { - perror("ioctl"); - ret = -1; - break; + int bytes_socket; + if(ioctl(client_socket, FIONREAD, &bytes_socket) < 0) { + perror("ioctl"); + goto end; + } + if(bytes_socket > 0) { + char buf[1024]; + ssize_t recv_ret = recv(client_socket, buf, sizeof(buf), 0); + if(recv_ret < 0) { + perror("recv"); + goto end; } - if (bytes_socket > 0) { - char buf[1024]; - ssize_t recv_ret = recv(client_socket, buf, sizeof(buf), 0); - if (recv_ret < 0) { - perror("recv"); - ret = -1; - break; - } - if (!fxlink_device_start_bulk_OUT(dev, "gdb", "remote", buf, recv_ret, false)) { - elog("unable to start bulk OUT trasfer\n"); - ret = -1; - break; - } + printf("GDB> %.*s\n", (int)recv_ret, buf); + if(!fxlink_device_start_bulk_OUT(fdev, "gdb", "remote", buf, recv_ret, false)) { + elog("unable to start bulk OUT transfer\n"); + goto end; } } } - fxlink_pollfds_stop(&fxlink_polled_fds); - fxlink_device_cleanup(dev); - free(dev); - libusb_exit(context); + ret = 0; + +end: + /* TODO: Close socket at end, including after ^C */ + + if(fxlink_polled_fds.ctx) + fxlink_pollfds_stop(&fxlink_polled_fds); + if(fdev) { + fxlink_device_interrupt_transfers(fdev); + fxlink_device_cleanup(fdev); + free(fdev); + } + if(context) + libusb_exit(context); return ret; }