gdb: style, messages, add option to wait for gdb:start

This commit is contained in:
Lephenixnoir 2024-03-30 09:34:52 +01:00
parent 87a2feff15
commit 056ce41c9e
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495

View file

@ -12,32 +12,62 @@
#include <fxlink/filter.h> #include <fxlink/filter.h>
#include <fxlink/logging.h> #include <fxlink/logging.h>
static struct fxlink_device* setup_calc(libusb_context* context) { /* Establish a connection to the calculator. If nostart is set, assume the
struct fxlink_filter filter = { calculator is ready immediately; otherwise, wait for a message of type
.intf_fxlink = true, gdb:start. The latter can be useful is the calculator is using USB prior to
}; starting a debugging session. */
delay_t delay = delay_infinite(); 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); fxlink_filter_clean_libusb(&filter);
hlog("calculators"); hlog("calculators");
log_("wating for fxlink capable device...\n"); log_("waiting for calculator to connect...\n");
struct fxlink_device* dev = fxlink_device_find_wait(context, &filter, &delay); delay_t delay = delay_infinite();
if (!dev) { struct fxlink_device *fdev =
elog("unable to open fxlink_device\n"); 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; return NULL;
} }
if (!fxlink_device_claim_fxlink(dev)) { fxlink_device_start_bulk_IN(fdev);
elog("unable to claim fxlink\n");
return NULL; 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); int listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (listen_socket < 0) { if(listen_socket < 0) {
perror("socket"); perror("socket");
return -1; return -1;
} }
@ -46,23 +76,24 @@ static int setup_socket(const char* listen_path) {
.sun_family = AF_UNIX, .sun_family = AF_UNIX,
.sun_path = {0}, .sun_path = {0},
}; };
strncpy(listen_address.sun_path, listen_path, sizeof(listen_address.sun_path) - 1); strncpy(listen_address.sun_path, listen_path,
if (bind(listen_socket, (struct sockaddr*)&listen_address, sizeof(listen_address)) < 0) { sizeof(listen_address.sun_path) - 1);
if(bind(listen_socket, (struct sockaddr *)&listen_address, sizeof(listen_address)) < 0) {
close(listen_socket); close(listen_socket);
perror("bind"); perror("bind");
return -1; return -1;
} }
if (listen(listen_socket, 1024) < 0) { if(listen(listen_socket, 1024) < 0) {
close(listen_socket); close(listen_socket);
perror("listen"); perror("listen");
return -1; return -1;
} }
hlog("socket"); 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); int client_socket = accept(listen_socket, NULL, NULL);
if (client_socket < 0) { if(client_socket < 0) {
close(listen_socket); close(listen_socket);
perror("accept"); perror("accept");
return -1; return -1;
@ -71,100 +102,107 @@ static int setup_socket(const char* listen_path) {
return client_socket; return client_socket;
} }
int main(int argc, char* argv[]) { int main(int argc, char *argv[])
if (argc != 2) { {
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]); elog("Usage : %s [listen path]\n", argv[0]);
return -1; goto end;
} }
libusb_context* context = NULL;
int err = libusb_init(&context); int err = libusb_init(&context);
if (err != 0) { if(err != 0) {
elog_libusb(err, "libusb_init"); elog_libusb(err, "libusb_init");
return -1; goto end;
}
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;
} }
bool nostart = true;
fdev = setup_calc(context, nostart);
if(!fdev)
goto end;
struct pollfd client_socket_pollfd = {.fd = client_socket, .events = POLLIN}; int client_socket = setup_socket(argv[1]);
struct fxlink_pollfds fxlink_polled_fds; 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); fxlink_pollfds_track(&fxlink_polled_fds, context);
if (!fxlink_device_start_bulk_IN(dev)) { while(true) {
elog("unable to start bulk IN trasfer\n"); int err = fxlink_multipoll(-1,
return -1; fxlink_polled_fds.fds, fxlink_polled_fds.count,
} &client_socket_pollfd, 1,
NULL);
// 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);
if (err < 0) { if (err < 0) {
perror("poll"); perror("poll");
ret = -1; goto end;
break;
} }
struct timeval zero = {0}; struct timeval zero = {0};
libusb_handle_events_timeout(context, &zero); libusb_handle_events_timeout(context, &zero);
struct fxlink_message* msg;
while ((msg = fxlink_device_finish_bulk_IN(dev)) != NULL) { struct fxlink_message *msg;
if (!fxlink_message_is_apptype(msg, "gdb", "remote")) { while((msg = fxlink_device_finish_bulk_IN(fdev)) != NULL) {
elog("unknown fxlink message type\n"); if(!fxlink_message_is_apptype(msg, "gdb", "remote")) {
ret = -1; wlog("dropped a message of type %.16s:%.16s\n",
break; 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); ssize_t send_ret = send(client_socket, msg->data, msg->size, 0);
if (send_ret != msg->size) { if(send_ret != msg->size) {
perror("send"); perror("send");
ret = -1; goto end;
break;
} }
fxlink_message_free(msg, true); fxlink_message_free(msg, true);
fxlink_device_start_bulk_IN(dev); fxlink_device_start_bulk_IN(fdev);
} }
if (ret != 0) { /* Don't start an OUT transfer if there's one in progress */
break; if(fdev->comm->ftransfer_OUT)
} continue;
// We don't want to start a new OUT transfer if another one is still in progress int bytes_socket;
if (!dev->comm->ftransfer_OUT) { if(ioctl(client_socket, FIONREAD, &bytes_socket) < 0) {
int bytes_socket; perror("ioctl");
if (ioctl(client_socket, FIONREAD, &bytes_socket) < 0) { goto end;
perror("ioctl"); }
ret = -1; if(bytes_socket > 0) {
break; 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) { printf("GDB> %.*s\n", (int)recv_ret, buf);
char buf[1024]; if(!fxlink_device_start_bulk_OUT(fdev, "gdb", "remote", buf, recv_ret, false)) {
ssize_t recv_ret = recv(client_socket, buf, sizeof(buf), 0); elog("unable to start bulk OUT transfer\n");
if (recv_ret < 0) { goto end;
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;
}
} }
} }
} }
fxlink_pollfds_stop(&fxlink_polled_fds); ret = 0;
fxlink_device_cleanup(dev);
free(dev); end:
libusb_exit(context); /* 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; return ret;
} }