From 1b1bf7e481bc29ffac3b4c6a6da9eeff36beb1d0 Mon Sep 17 00:00:00 2001 From: Eugene Hutorny Date: Sat, 23 Jan 2016 06:41:30 +0200 Subject: [PATCH] Added ftdi_transfer_data_cancel for cancelation of a submitted transfer, avoided resubmittion of a cancelled transfer in the callbacks, replaced calls to libusb_handle_events with libusb_handle_events_timeout_completed (Eugene Hutorny, eugene@hutorny.in.ua) --- AUTHORS | 1 + ChangeLog | 9 ++++++++ src/ftdi.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/ftdi.h | 1 + 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/AUTHORS b/AUTHORS index ac74557..0200e22 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,6 +22,7 @@ see Changelog for full details: Davide Michelizza Denis Sirotkin Emil + Eugene Hutorny Evan Nemerson Evgeny Sinelnikov Flynn Marquardt diff --git a/ChangeLog b/ChangeLog index aaae78b..82c5a9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +New in 1.3 - 2016-04-xx +----------------------- +* Added ftdi_transfer_data_cancel for cancelation of a submitted transfer, + avoided resubmittion of a cancelled transfer in the callbacks, replaced calls + to libusb_handle_events with libusb_handle_events_timeout_completed + (Eugene Hutorny, eugene@hutorny.in.ua) + +Note: All other changes are not listed yet + New in 1.2 - 2014-11-21 ----------------------- * Support for FT230X devices (Uwe Bonnes) diff --git a/src/ftdi.c b/src/ftdi.c index aa4b4ec..573080a 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -1470,9 +1470,15 @@ static void LIBUSB_CALL ftdi_read_data_cb(struct libusb_transfer *transfer) } } } - ret = libusb_submit_transfer (transfer); - if (ret < 0) - tc->completed = 1; + + if (transfer->status == LIBUSB_TRANSFER_CANCELLED) + tc->completed = LIBUSB_TRANSFER_CANCELLED; + else + { + ret = libusb_submit_transfer (transfer); + if (ret < 0) + tc->completed = 1; + } } @@ -1497,9 +1503,15 @@ static void LIBUSB_CALL ftdi_write_data_cb(struct libusb_transfer *transfer) transfer->length = write_size; transfer->buffer = tc->buf + tc->offset; - ret = libusb_submit_transfer (transfer); - if (ret < 0) - tc->completed = 1; + + if (transfer->status == LIBUSB_TRANSFER_CANCELLED) + tc->completed = LIBUSB_TRANSFER_CANCELLED; + else + { + ret = libusb_submit_transfer (transfer); + if (ret < 0) + tc->completed = 1; + } } } @@ -1662,17 +1674,19 @@ struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, u int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) { int ret; - + struct timeval to = { 0, 0 }; while (!tc->completed) { - ret = libusb_handle_events(tc->ftdi->usb_ctx); + ret = libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, + &to, &tc->completed); if (ret < 0) { if (ret == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(tc->transfer); while (!tc->completed) - if (libusb_handle_events(tc->ftdi->usb_ctx) < 0) + if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, + &to, &tc->completed) < 0) break; libusb_free_transfer(tc->transfer); free (tc); @@ -1696,6 +1710,39 @@ int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) } /** + Cancel transfer and wait for completion. + + Use libusb 1.0 asynchronous API. + + \param tc pointer to ftdi_transfer_control + \param to pointer to timeout value or NULL for infinite +*/ + +void ftdi_transfer_data_cancel(struct ftdi_transfer_control *tc, + struct timeval * to) +{ + struct timeval tv = { 0, 0 }; + + if (!tc->completed && tc->transfer != NULL) + { + if (to == NULL) + to = &tv; + + libusb_cancel_transfer(tc->transfer); + while (!tc->completed) + { + if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, to, &tc->completed) < 0) + break; + } + } + + if (tc->transfer) + libusb_free_transfer(tc->transfer); + + free (tc); +} + +/** Configure write buffer chunk size. Default is 4096. diff --git a/src/ftdi.h b/src/ftdi.h index 9a6ec79..fa53b29 100644 --- a/src/ftdi.h +++ b/src/ftdi.h @@ -521,6 +521,7 @@ extern "C" struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, unsigned char *buf, int size); int ftdi_transfer_data_done(struct ftdi_transfer_control *tc); + void ftdi_transfer_data_cancel(struct ftdi_transfer_control *tc, struct timeval * to); int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode); int ftdi_disable_bitbang(struct ftdi_context *ftdi); -- 1.7.1