1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-05-24 16:43:28 +02:00

scd: Improve internal CCID driver.

* scd/ccid-driver.c (scan_or_find_usb_device): Don't scan for
configuration but use active configuration.  Support alt_setting.
(scan_or_find_devices): Support alt_setting.
(ccid_open_reader): Support alt_setting.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2016-12-29 11:31:25 +09:00
parent c48cf7e32f
commit cdc8d0bd93

View File

@ -1125,39 +1125,29 @@ scan_or_find_usb_device (int scan_mode,
libusb_device_handle **r_idev, libusb_device_handle **r_idev,
unsigned char **ifcdesc_extra, unsigned char **ifcdesc_extra,
size_t *ifcdesc_extra_len, size_t *ifcdesc_extra_len,
int *interface_number, int *interface_number, int *setting_number,
int *ep_bulk_out, int *ep_bulk_in, int *ep_intr) int *ep_bulk_out, int *ep_bulk_in, int *ep_intr)
{ {
int cfg_no;
int ifc_no; int ifc_no;
int set_no; int set_no;
const struct libusb_interface_descriptor *ifcdesc; const struct libusb_interface_descriptor *ifcdesc;
char *rid; char *rid;
libusb_device_handle *idev = NULL; libusb_device_handle *idev = NULL;
int err; int err;
struct libusb_config_descriptor *config;
err = libusb_get_device_descriptor (dev, desc); err = libusb_get_device_descriptor (dev, desc);
if (err < 0) if (err)
return 0; return 0;
*r_idev = NULL; *r_idev = NULL;
for (cfg_no=0; cfg_no < desc->bNumConfigurations; cfg_no++) err = libusb_get_active_config_descriptor (dev, &config);
{ if (err)
struct libusb_config_descriptor *config;
err = libusb_get_config_descriptor (dev, cfg_no, &config);
if (err < 0)
{
if (err == LIBUSB_ERROR_NO_MEM)
return 0; return 0;
continue;
}
for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++)
{ for (set_no=0; set_no < config->interface[ifc_no].num_altsetting; set_no++)
for (set_no=0; set_no < config->interface[ifc_no].num_altsetting;
set_no++)
{ {
ifcdesc = (config->interface[ifc_no].altsetting + set_no); ifcdesc = (config->interface[ifc_no].altsetting + set_no);
/* The second condition is for older SCM SPR 532 who did /* The second condition is for older SCM SPR 532 who did
@ -1177,15 +1167,13 @@ scan_or_find_usb_device (int scan_mode,
&& desc->idProduct == CHERRY_ST2000))) && desc->idProduct == CHERRY_ST2000)))
{ {
++*count; ++*count;
if (!scan_mode if (!scan_mode && ((readerno > 0 && readerno != *count - 1)))
&& ((readerno > 0 && readerno != *count - 1)))
continue; continue;
err = libusb_open (dev, &idev); err = libusb_open (dev, &idev);
if (err < 0) if (err)
{ {
DEBUGOUT_1 ("usb_open failed: %s\n", DEBUGOUT_1 ("usb_open failed: %s\n", libusb_error_name (err));
libusb_error_name (err));
continue; /* with next setting. */ continue; /* with next setting. */
} }
@ -1208,8 +1196,7 @@ scan_or_find_usb_device (int scan_mode,
/* We are collecting infos about all /* We are collecting infos about all
available CCID readers. Store them and available CCID readers. Store them and
continue. */ continue. */
DEBUGOUT_2 ("found CCID reader %d (ID=%s)\n", DEBUGOUT_2 ("found CCID reader %d (ID=%s)\n", *count, rid);
*count, rid );
p = malloc ((*rid_list? strlen (*rid_list):0) + 1 p = malloc ((*rid_list? strlen (*rid_list):0) + 1
+ strlen (rid) + 1); + strlen (rid) + 1);
if (p) if (p)
@ -1236,8 +1223,7 @@ scan_or_find_usb_device (int scan_mode,
/* We found the requested reader. */ /* We found the requested reader. */
if (ifcdesc_extra && ifcdesc_extra_len) if (ifcdesc_extra && ifcdesc_extra_len)
{ {
*ifcdesc_extra = malloc (ifcdesc *ifcdesc_extra = malloc (ifcdesc->extra_length);
->extra_length);
if (!*ifcdesc_extra) if (!*ifcdesc_extra)
{ {
libusb_close (idev); libusb_close (idev);
@ -1251,7 +1237,10 @@ scan_or_find_usb_device (int scan_mode,
} }
if (interface_number) if (interface_number)
*interface_number = (ifcdesc->bInterfaceNumber); *interface_number = ifc_no;
if (setting_number)
*setting_number = set_no;
if (ep_bulk_out) if (ep_bulk_out)
*ep_bulk_out = find_endpoint (ifcdesc, 0); *ep_bulk_out = find_endpoint (ifcdesc, 0);
@ -1278,10 +1267,8 @@ scan_or_find_usb_device (int scan_mode,
idev = NULL; idev = NULL;
} }
} }
}
libusb_free_config_descriptor (config); libusb_free_config_descriptor (config);
}
return 0; return 0;
} }
@ -1329,7 +1316,7 @@ scan_or_find_devices (int readerno, const char *readerid,
struct libusb_device_descriptor *r_desc, struct libusb_device_descriptor *r_desc,
unsigned char **ifcdesc_extra, unsigned char **ifcdesc_extra,
size_t *ifcdesc_extra_len, size_t *ifcdesc_extra_len,
int *interface_number, int *interface_number, int *setting_number,
int *ep_bulk_out, int *ep_bulk_in, int *ep_intr, int *ep_bulk_out, int *ep_bulk_in, int *ep_intr,
libusb_device_handle **r_idev, libusb_device_handle **r_idev,
int *r_fd) int *r_fd)
@ -1353,6 +1340,8 @@ scan_or_find_devices (int readerno, const char *readerid,
*ifcdesc_extra_len = 0; *ifcdesc_extra_len = 0;
if (interface_number) if (interface_number)
*interface_number = 0; *interface_number = 0;
if (setting_number)
*setting_number = 0;
if (r_idev) if (r_idev)
*r_idev = NULL; *r_idev = NULL;
if (r_fd) if (r_fd)
@ -1377,7 +1366,7 @@ scan_or_find_devices (int readerno, const char *readerid,
&idev, &idev,
ifcdesc_extra, ifcdesc_extra,
ifcdesc_extra_len, ifcdesc_extra_len,
interface_number, interface_number, setting_number,
ep_bulk_out, ep_bulk_in, ep_intr)) ep_bulk_out, ep_bulk_in, ep_intr))
{ {
libusb_free_device_list (dev_list, 1); libusb_free_device_list (dev_list, 1);
@ -1512,7 +1501,7 @@ ccid_get_reader_list (void)
} }
if (scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL, NULL, if (scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL)) NULL, NULL, NULL, NULL, NULL, NULL))
return NULL; /* Error. */ return NULL; /* Error. */
return reader_list; return reader_list;
} }
@ -1558,7 +1547,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid,
unsigned char *ifcdesc_extra = NULL; unsigned char *ifcdesc_extra = NULL;
size_t ifcdesc_extra_len; size_t ifcdesc_extra_len;
int readerno; int readerno;
int ifc_no, ep_bulk_out, ep_bulk_in, ep_intr; int ifc_no, set_no, ep_bulk_out, ep_bulk_in, ep_intr;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
*handle = NULL; *handle = NULL;
@ -1587,10 +1576,9 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid,
else else
readerno = 0; /* Default. */ readerno = 0; /* Default. */
if (scan_or_find_devices (readerno, readerid, &rid, &desc, if (scan_or_find_devices (readerno, readerid, &rid, &desc, &ifcdesc_extra,
&ifcdesc_extra, &ifcdesc_extra_len, &ifcdesc_extra_len, &ifc_no, &set_no, &ep_bulk_out,
&ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr, &ep_bulk_in, &ep_intr, &idev, &dev_fd))
&idev, &dev_fd) )
{ {
if (readerno == -1) if (readerno == -1)
DEBUGOUT_1 ("no CCID reader with ID %s\n", readerid ); DEBUGOUT_1 ("no CCID reader with ID %s\n", readerid );
@ -1646,12 +1634,23 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid,
} }
rc = libusb_claim_interface (idev, ifc_no); rc = libusb_claim_interface (idev, ifc_no);
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc);
rc = CCID_DRIVER_ERR_CARD_IO_ERROR; rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
goto leave; goto leave;
} }
if (set_no != 0)
{
rc = libusb_set_interface_alt_setting (idev, ifc_no, set_no);
if (rc)
{
DEBUGOUT_1 ("usb_set_interface_alt_setting failed: %d\n", rc);
rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
goto leave;
}
}
} }
rc = ccid_vendor_specific_init (*handle); rc = ccid_vendor_specific_init (*handle);
@ -1852,7 +1851,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
if (rc == 0 && transferred == msglen) if (rc == 0 && transferred == msglen)
return 0; return 0;
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_bulk_write error: %s\n", libusb_error_name (rc)); DEBUGOUT_1 ("usb_bulk_write error: %s\n", libusb_error_name (rc));
if (rc == LIBUSB_ERROR_NO_DEVICE) if (rc == LIBUSB_ERROR_NO_DEVICE)
@ -1899,7 +1898,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
{ {
rc = libusb_bulk_transfer (handle->idev, handle->ep_bulk_in, rc = libusb_bulk_transfer (handle->idev, handle->ep_bulk_in,
(char*)buffer, length, &msglen, timeout); (char*)buffer, length, &msglen, timeout);
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_bulk_read error: %s\n", libusb_error_name (rc)); DEBUGOUT_1 ("usb_bulk_read error: %s\n", libusb_error_name (rc));
if (rc == LIBUSB_ERROR_NO_DEVICE) if (rc == LIBUSB_ERROR_NO_DEVICE)
@ -2041,7 +2040,7 @@ abort_cmd (ccid_driver_t handle, int seqno)
handle->ifc_no, handle->ifc_no,
dummybuf, 0, dummybuf, 0,
1000 /* ms timeout */); 1000 /* ms timeout */);
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_control_msg error: %s\n", libusb_error_name (rc)); DEBUGOUT_1 ("usb_control_msg error: %s\n", libusb_error_name (rc));
return CCID_DRIVER_ERR_CARD_IO_ERROR; return CCID_DRIVER_ERR_CARD_IO_ERROR;
@ -2070,7 +2069,7 @@ abort_cmd (ccid_driver_t handle, int seqno)
5000 /* ms timeout */); 5000 /* ms timeout */);
if (rc == 0 && transferred == msglen) if (rc == 0 && transferred == msglen)
rc = 0; rc = 0;
else if (rc < 0) else if (rc)
DEBUGOUT_1 ("usb_bulk_write error in abort_cmd: %s\n", DEBUGOUT_1 ("usb_bulk_write error in abort_cmd: %s\n",
libusb_error_name (rc)); libusb_error_name (rc));
@ -2080,7 +2079,7 @@ abort_cmd (ccid_driver_t handle, int seqno)
rc = libusb_bulk_transfer (handle->idev, handle->ep_bulk_in, rc = libusb_bulk_transfer (handle->idev, handle->ep_bulk_in,
(char*)msg, sizeof msg, &msglen, (char*)msg, sizeof msg, &msglen,
5000 /*ms timeout*/); 5000 /*ms timeout*/);
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_bulk_read error in abort_cmd: %s\n", DEBUGOUT_1 ("usb_bulk_read error in abort_cmd: %s\n",
libusb_error_name (rc)); libusb_error_name (rc));
@ -2205,7 +2204,7 @@ ccid_poll (ccid_driver_t handle)
else else
return 0; return 0;
if (rc < 0) if (rc)
{ {
DEBUGOUT_1 ("usb_intr_read error: %s\n", libusb_error_name (rc)); DEBUGOUT_1 ("usb_intr_read error: %s\n", libusb_error_name (rc));
return CCID_DRIVER_ERR_CARD_IO_ERROR; return CCID_DRIVER_ERR_CARD_IO_ERROR;