ftdi: don't wait forever if we fail 19/3419/6
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sun, 14 Aug 2016 13:15:27 +0000 (15:15 +0200)
committerSpencer Oliver <spen@spen-soft.co.uk>
Tue, 4 Oct 2016 10:51:31 +0000 (11:51 +0100)
Currently if ftdi device is removed, OpenOCD will stall forever.
Only kill -9 will help in this case.
This patch makes use of libusb timeout functions and
trying to break out of while loop if some error is detected.

[andreas.fritiofson@gmail.com]: Add missing retval check

Change-Id: I97506190e376026705f14ef9fe37dc811b99b3ac
Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/3419
Reviewed-by: Andreas Färber <afaerber@suse.de>
Tested-by: jenkins
src/jtag/drivers/mpsse.c

index 0ef88ba..3c1c97c 100644 (file)
@@ -872,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx)
        libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer,
                ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout);
        retval = libusb_submit_transfer(write_transfer);
+       if (retval != LIBUSB_SUCCESS)
+               goto error_check;
 
        if (ctx->read_count) {
                read_transfer = libusb_alloc_transfer(0);
@@ -879,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx)
                        ctx->read_chunk_size, read_cb, &read_result,
                        ctx->usb_read_timeout);
                retval = libusb_submit_transfer(read_transfer);
+               if (retval != LIBUSB_SUCCESS)
+                       goto error_check;
        }
 
        /* Polling loop, more or less taken from libftdi */
        while (!write_result.done || !read_result.done) {
-               retval = libusb_handle_events(ctx->usb_ctx);
+               struct timeval timeout_usb;
+
+               timeout_usb.tv_sec = 1;
+               timeout_usb.tv_usec = 0;
+
+               retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL);
                keep_alive();
-               if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) {
+               if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED)
+                       break;
+
+               if (retval != LIBUSB_SUCCESS) {
                        libusb_cancel_transfer(write_transfer);
                        if (read_transfer)
                                libusb_cancel_transfer(read_transfer);
-                       while (!write_result.done || !read_result.done)
-                               if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS)
+                       while (!write_result.done || !read_result.done) {
+                               retval = libusb_handle_events_timeout_completed(ctx->usb_ctx,
+                                                               &timeout_usb, NULL);
+                               if (retval != LIBUSB_SUCCESS)
                                        break;
+                       }
                }
        }
 
+error_check:
        if (retval != LIBUSB_SUCCESS) {
                LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval));
                retval = ERROR_FAIL;