[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