[Pcsclite-cvs-commit] r5028 - in /trunk/Drivers/ccid/src: ccid_usb.c ccid_usb.h ifdhandler.c
rousseau at users.alioth.debian.org
rousseau at users.alioth.debian.org
Tue Jun 22 09:27:02 UTC 2010
Author: rousseau
Date: Tue Jun 22 09:27:01 2010
New Revision: 5028
URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=5028
Log:
Add support of TAG_IFD_STOP_POLLING_THREAD and use of the asynchronous
libusb API to be able to stop a transfer.
We are now "polling" for card movements every 1 hour or once an event
is detected on the interrupt endpoint of the device.
Another gain is that the driver will terminate "instantly" after pcscd
request instead of after a maximum of 2 seconds (previous polling
timeout).
Modified:
trunk/Drivers/ccid/src/ccid_usb.c
trunk/Drivers/ccid/src/ccid_usb.h
trunk/Drivers/ccid/src/ifdhandler.c
Modified: trunk/Drivers/ccid/src/ccid_usb.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ccid_usb.c?rev=5028&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ccid_usb.c (original)
+++ trunk/Drivers/ccid/src/ccid_usb.c Tue Jun 22 09:27:01 2010
@@ -82,6 +82,9 @@
* CCID infos common to USB and serial
*/
_ccid_descriptor ccid;
+
+ /* libusb transfer for the polling (or NULL) */
+ struct libusb_transfer *polling_transfer;
} _usbDevice;
@@ -519,6 +522,7 @@
usbDevice[reader_index].interface = interface;
usbDevice[reader_index].real_nb_opened_slots = 1;
usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots;
+ usbDevice[reader_index].polling_transfer = NULL;
/* CCID common informations */
usbDevice[reader_index].ccid.real_bSeq = 0;
@@ -978,6 +982,18 @@
/*****************************************************************************
*
+ * Transfer is complete
+ *
+ ****************************************************************************/
+static void bulk_transfer_cb(struct libusb_transfer *transfer)
+{
+ int *completed = transfer->user_data;
+ *completed = 1;
+ /* caller interprets results and frees transfer */
+}
+
+/*****************************************************************************
+ *
* InterruptRead
*
****************************************************************************/
@@ -985,24 +1001,90 @@
{
int ret, actual_length;
unsigned char buffer[8];
+ struct libusb_transfer *transfer;
+ int completed = 0;
DEBUG_PERIODIC2("before (%d)", reader_index);
- ret = libusb_interrupt_transfer(usbDevice[reader_index].dev_handle,
+
+ transfer = libusb_alloc_transfer(0);
+ if (NULL == transfer)
+ return LIBUSB_ERROR_NO_MEM;
+
+ libusb_fill_bulk_transfer(transfer,
+ usbDevice[reader_index].dev_handle,
usbDevice[reader_index].interrupt, buffer, sizeof(buffer),
- &actual_length, timeout);
+ bulk_transfer_cb, &completed, timeout);
+ transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
+
+ ret = libusb_submit_transfer(transfer);
+ if (ret < 0) {
+ libusb_free_transfer(transfer);
+ return ret;
+ }
+
+ usbDevice[reader_index].polling_transfer = transfer;
+
+ while (!completed)
+ {
+ ret = libusb_handle_events(ctx);
+ if (ret < 0)
+ {
+ if (ret == LIBUSB_ERROR_INTERRUPTED)
+ continue;
+ libusb_cancel_transfer(transfer);
+ while (!completed)
+ if (libusb_handle_events(ctx) < 0)
+ break;
+ libusb_free_transfer(transfer);
+ return ret;
+ }
+ }
+
+ actual_length = transfer->actual_length;
+ ret = transfer->status;
+
+ usbDevice[reader_index].polling_transfer = NULL;
+ libusb_free_transfer(transfer);
+
DEBUG_PERIODIC3("after (%d) (%d)", reader_index, ret);
- if (ret < 0)
- {
- /* if libusb_interrupt_transfer() times out we get EILSEQ or EAGAIN */
- if ((errno != EILSEQ) && (errno != EAGAIN) && (errno != ENODEV) && (errno != 0))
- DEBUG_COMM4("libusb_interrupt_transfer(%d/%d): %s",
+ switch (ret)
+ {
+ case LIBUSB_TRANSFER_COMPLETED:
+ DEBUG_XXD("NotifySlotChange: ", buffer, actual_length);
+ break;
+
+ case LIBUSB_TRANSFER_TIMED_OUT:
+ break;
+
+ default:
+ /* if libusb_interrupt_transfer() times out we get EILSEQ or EAGAIN */
+ DEBUG_COMM4("InterruptRead (%d/%d): %s",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address, strerror(errno));
}
- else
- DEBUG_XXD("NotifySlotChange: ", (const unsigned char *)buffer, actual_length);
return ret;
} /* InterruptRead */
+
+/*****************************************************************************
+ *
+ * Stop the async loop
+ *
+ ****************************************************************************/
+void InterruptStop(int reader_index)
+{
+ struct libusb_transfer *transfer;
+
+ transfer = usbDevice[reader_index].polling_transfer;
+ if (transfer)
+ {
+ int ret;
+
+ ret = libusb_cancel_transfer(transfer);
+ if (ret < 0)
+ DEBUG_CRITICAL2("libusb_cancel_transfer failed: %d", ret);
+ }
+} /* InterruptStop */
+
Modified: trunk/Drivers/ccid/src/ccid_usb.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ccid_usb.h?rev=5028&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ccid_usb.h (original)
+++ trunk/Drivers/ccid/src/ccid_usb.h Tue Jun 22 09:27:01 2010
@@ -43,4 +43,5 @@
unsigned char *bytes, unsigned int size);
int InterruptRead(int reader_index, int timeout);
+void InterruptStop(int reader_index);
#endif
Modified: trunk/Drivers/ccid/src/ifdhandler.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ifdhandler.c?rev=5028&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ifdhandler.c (original)
+++ trunk/Drivers/ccid/src/ifdhandler.c Tue Jun 22 09:27:01 2010
@@ -333,7 +333,7 @@
if (LogLevel & DEBUG_LEVEL_PERIODIC)
DEBUG_INFO3("%s (lun: %X)", CcidSlots[reader_index].readerName, Lun);
- ret = InterruptRead(reader_index, 2*1000); /* 2 seconds */
+ ret = InterruptRead(reader_index, 60*60*1000); /* 1 hour */
if (ret > 0)
return IFD_SUCCESS;
if (0 == ret)
@@ -360,6 +360,19 @@
* and be killed before pcscd exits
*/
(void)sleep(600); /* 10 minutes */
+ return IFD_SUCCESS;
+}
+
+static RESPONSECODE IFDHStopPolling(DWORD Lun)
+{
+ int reader_index;
+
+ if (-1 == (reader_index = LunToReaderIndex(Lun)))
+ return IFD_COMMUNICATION_ERROR;
+
+ DEBUG_INFO3("%s (lun: %X)", CcidSlots[reader_index].readerName, Lun);
+
+ (void)InterruptStop(reader_index);
return IFD_SUCCESS;
}
#endif
@@ -569,6 +582,26 @@
}
}
break;
+
+ case TAG_IFD_STOP_POLLING_THREAD:
+ {
+ _ccid_descriptor *ccid_desc;
+
+ /* default value: not supported */
+ *Length = 0;
+
+ ccid_desc = get_ccid_descriptor(reader_index);
+ /* CCID and not ICCD */
+ if ((PROTOCOL_CCID == ccid_desc -> bInterfaceProtocol)
+ /* 3 end points */
+ && (3 == ccid_desc -> bNumEndpoints))
+ {
+ *Length = sizeof(void *);
+ if (Value)
+ *(void **)Value = IFDHStopPolling;
+ }
+ }
+ break;
#endif
case SCARD_ATTR_VENDOR_IFD_SERIAL_NO:
More information about the Pcsclite-cvs-commit
mailing list