aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/ccid-driver.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 1bb0fb267..cb4b4e69f 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -262,9 +262,9 @@ struct ccid_driver_s
unsigned int auto_param:1;
unsigned int auto_pps:1;
unsigned int auto_ifsd:1;
- unsigned int powered_off:1;
unsigned int has_pinpad:2;
unsigned int enodev_seen:1;
+ int powered_off;
time_t last_progress; /* Last time we sent progress line. */
@@ -1764,12 +1764,17 @@ intr_cb (struct libusb_transfer *transfer)
DEBUGOUT_1 ("CCID: interrupt callback %d\n", transfer->status);
- if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE
- || transfer->status == LIBUSB_TRANSFER_ERROR)
+ if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT)
{
- device_removed:
- DEBUGOUT ("CCID: device removed\n");
- handle->powered_off = 1;
+ int err;
+
+ submit_again:
+ /* Submit the URB again to keep watching the INTERRUPT transfer. */
+ err = libusb_submit_transfer (transfer);
+ if (err == LIBUSB_ERROR_NO_DEVICE)
+ goto device_removed;
+
+ DEBUGOUT_1 ("CCID submit transfer again %d\n", err);
}
else if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
{
@@ -1782,19 +1787,17 @@ intr_cb (struct libusb_transfer *transfer)
}
else
{
- int err;
-
- /* Submit the URB again to keep watching the INTERRUPT transfer. */
- err = libusb_submit_transfer (transfer);
- if (err == LIBUSB_ERROR_NO_DEVICE)
- goto device_removed;
-
- DEBUGOUT_1 ("CCID submit transfer again %d\n", err);
+ /* Event other than card removal. */
+ goto submit_again;
}
}
+ else if (transfer->status == LIBUSB_TRANSFER_CANCELLED)
+ handle->powered_off = 1;
else
{
- DEBUGOUT_1 ("CCID intr_cb: %d\n", transfer->status);
+ device_removed:
+ DEBUGOUT ("CCID: device removed\n");
+ handle->powered_off = 1;
}
}
@@ -2048,11 +2051,19 @@ do_close_reader (ccid_driver_t handle)
if (!rc)
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
seqno, 2000, 0);
- handle->powered_off = 1;
}
if (handle->idev)
{
- libusb_free_transfer (handle->transfer);
+ if (handle->transfer)
+ {
+ if (!handle->powered_off)
+ {
+ libusb_cancel_transfer (handle->transfer);
+ while (!handle->powered_off)
+ libusb_handle_events_completed (NULL, &handle->powered_off);
+ }
+ libusb_free_transfer (handle->transfer);
+ }
libusb_release_interface (handle->idev, handle->ifc_no);
libusb_close (handle->idev);
handle->idev = NULL;