From bb5ceb78c333129a44c0144f2cf49b17ede898f1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 26 Jan 2017 16:54:40 +0900 Subject: [PATCH] scd: Add INTERRUPT endp support to CCID driver. * scd/app.c (scd_update_reader_status_file): Fix releas of APP. * scd/ccid-driver.c (struct ccid_driver_s): Add INTR_BUF. (intr_cb, ccid_setup_intr): New. (ccid_open_usb_reader): Call ccid_setup_intr. (ccid_slot_status): Return CCID_DRIVER_ERR_NO_READER when removed. Signed-off-by: NIIBE Yutaka --- scd/app.c | 1 + scd/ccid-driver.c | 73 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/scd/app.c b/scd/app.c index b10a452d6..88a38010d 100644 --- a/scd/app.c +++ b/scd/app.c @@ -1049,6 +1049,7 @@ scd_update_reader_status_file (void) { log_debug ("Removal of a card: %d\n", a->slot); apdu_close_reader (a->slot); + release_application_internal (a); deallocate_app (a); } else diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b7f97edb0..ce5539385 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -272,6 +272,8 @@ struct ccid_driver_s ccid_set_progress_cb. */ void (*progress_cb)(void *, const char *, int, int, int); void *progress_cb_arg; + + unsigned char intr_buf[64]; }; @@ -1753,6 +1755,64 @@ ccid_compare_BAI (ccid_driver_t handle, unsigned int bai) return handle->bai == bai; } + +static void +intr_cb (struct libusb_transfer *transfer) +{ + ccid_driver_t handle = transfer->user_data; + + DEBUGOUT ("CCID: interrupt callback\n"); + + if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) + { + device_removed: + DEBUGOUT ("CCID: device removed\n"); + handle->powered_off = 1; + libusb_free_transfer (transfer); + } + else if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + { + if (transfer->actual_length == 2 + && transfer->buffer[0] == 0x50 + && (transfer->buffer[1] & 1) == 0) + { + DEBUGOUT ("CCID: card removed\n"); + handle->powered_off = 1; + libusb_free_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", err); + } + } + else + { + ; + } +} + +static void +ccid_setup_intr (ccid_driver_t handle) +{ + struct libusb_transfer *transfer; + int err; + + transfer = libusb_alloc_transfer (0); + libusb_fill_interrupt_transfer (transfer, handle->idev, handle->ep_intr, + handle->intr_buf, sizeof (handle->intr_buf), + intr_cb, handle, 0); + err = libusb_submit_transfer (transfer); + DEBUGOUT_2 ("CCID submit transfer (%x): %d", handle->ep_intr, err); +} + + static int ccid_open_usb_reader (const char *spec_reader_name, int idx, struct ccid_dev_table *ccid_table, @@ -1847,6 +1907,9 @@ ccid_open_usb_reader (const char *spec_reader_name, } } + if ((*handle)->ep_intr) + ccid_setup_intr (*handle); + rc = ccid_vendor_specific_init (*handle); leave: @@ -1871,8 +1934,8 @@ ccid_open_usb_reader (const char *spec_reader_name, /* Open the reader with the internal number READERNO and return a pointer to be used as handle in HANDLE. Returns 0 on success. */ int -ccid_open_reader (const char *spec_reader_name, - int idx, struct ccid_dev_table *ccid_table, +ccid_open_reader (const char *spec_reader_name, int idx, + struct ccid_dev_table *ccid_table, ccid_driver_t *handle, char **rdrname_p) { int n; @@ -2516,6 +2579,9 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) unsigned char seqno; int retries = 0; + if (handle->powered_off) + return CCID_DRIVER_ERR_NO_READER; + retry: msg[0] = PC_to_RDR_GetSlotStatus; msg[5] = 0; /* slot */ @@ -2546,8 +2612,7 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) retries++; goto retry; } - if (rc && rc != CCID_DRIVER_ERR_NO_CARD - && rc != CCID_DRIVER_ERR_CARD_INACTIVE) + if (rc && rc != CCID_DRIVER_ERR_NO_CARD && rc != CCID_DRIVER_ERR_CARD_INACTIVE) return rc; *statusbits = (msg[7] & 3);