pc-stlinkv2: Detect stlink detach.

As libusb has no real async callback, we need to call libusb_handle_events()
in different places. While waiting for the gdb connection, we set the
socket to non-blocking and check additional for usb events in that loop. That
way, detach is also detected while waiting for connection. With debugger
attached, SET_IDLE_STATE ist missused for checking for usb events.
This commit is contained in:
Uwe Bonnes 2019-08-31 15:27:16 +02:00
parent 6f1cae9203
commit 1d868bfffb
3 changed files with 72 additions and 4 deletions

View File

@ -37,7 +37,8 @@
#define PLATFORM_IDENT "StlinkV2/3"
#define SET_RUN_STATE(state)
#define SET_IDLE_STATE(state)
void stlink_check_detach(int state);
#define SET_IDLE_STATE(state) stlink_check_detach(state)
//#define SET_ERROR_STATE(state)
void platform_buffer_flush(void);

View File

@ -228,7 +228,7 @@ stlink Stlink;
static void exit_function(void)
{
libusb_exit(NULL);
DEBUG_STLINK("Cleanup\n");
DEBUG("\nCleanup\n");
}
/* SIGTERM handler. */
@ -256,7 +256,34 @@ static int LIBUSB_CALL hotplug_callback_attach(
(void)event;
(void)user_data;
has_attached = true;
return 0;
return 1; /* deregister Callback*/
}
int device_detached = 0;
static int LIBUSB_CALL hotplug_callback_detach(
libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event,
void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
device_detached = 1;
return 1; /* deregister Callback*/
}
void stlink_check_detach(int state)
{
if (state == 1) {
/* Check for hotplug events */
struct timeval tv = {0,0};
libusb_handle_events_timeout_completed(
Stlink.libusb_ctx, &tv, &device_detached);
if (device_detached) {
DEBUG("Dongle was detached\n");
exit(0);
}
}
}
static void LIBUSB_CALL on_trans_done(struct libusb_transfer * trans)
@ -332,6 +359,7 @@ static int send_recv(uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize)
{
int res = 0;
stlink_check_detach(1);
if( txsize) {
int txlen = txsize;
libusb_fill_bulk_transfer(Stlink.req_trans, Stlink.handle,
@ -725,6 +753,8 @@ void stlink_init(int argc, char **argv)
DEBUG("STLINKV1 not supported\n");
continue;
}
Stlink.vid = desc.idVendor;
Stlink.pid = desc.idProduct;
r = libusb_open(dev, &Stlink.handle);
if (r == LIBUSB_SUCCESS) {
uint8_t data[32];
@ -852,6 +882,16 @@ void stlink_init(int argc, char **argv)
DEBUG("libusb_claim_interface failed %s\n", libusb_strerror(r));
goto error_1;
}
if (hotplug) { /* Allow gracefully exit when stlink is unplugged*/
libusb_hotplug_callback_handle hp;
int rc = libusb_hotplug_register_callback
(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, Stlink.vid, Stlink.pid,
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback_detach, NULL, &hp);
if (LIBUSB_SUCCESS != rc) {
DEBUG("Error registering detach callback\n");
goto error;
}
}
Stlink.req_trans = libusb_alloc_transfer(0);
Stlink.rep_trans = libusb_alloc_transfer(0);
stlink_version();

View File

@ -32,6 +32,7 @@
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <sys/select.h>
# include <fcntl.h>
#endif
#include <stdio.h>
@ -100,7 +101,33 @@ unsigned char gdb_if_getchar(void)
while(i <= 0) {
if(gdb_if_conn <= 0) {
gdb_if_conn = accept(gdb_if_serv, NULL, NULL);
#if defined(_WIN32) || defined(__CYGWIN__)
unsigned long opt = 1;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
#else
int flags = fcntl(gdb_if_serv, F_GETFL);
fcntl(gdb_if_serv, F_SETFL, flags | O_NONBLOCK);
#endif
while(1) {
gdb_if_conn = accept(gdb_if_serv, NULL, NULL);
if (gdb_if_conn == -1) {
if (errno == EWOULDBLOCK) {
SET_IDLE_STATE(1);
platform_delay(100);
} else {
DEBUG("error when accepting connection");
exit(1);
}
} else {
#if defined(_WIN32) || defined(__CYGWIN__)
unsigned long opt = 0;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
#else
fcntl(gdb_if_serv, F_SETFL, flags);
#endif
break;
}
}
DEBUG("Got connection\n");
}
i = recv(gdb_if_conn, (void*)&ret, 1, 0);