diff --git a/scd/apdu.c b/scd/apdu.c index dfd9451de..83be7cb49 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -502,6 +502,13 @@ host_sw_string (long err) case SW_HOST_NO_PINPAD: return "no pinpad"; case SW_HOST_ALREADY_CONNECTED: return "already connected"; case SW_HOST_CANCELLED: return "cancelled"; + case SW_HOST_USB_OTHER: return "USB general error"; + case SW_HOST_USB_IO: return "USB I/O error"; + case SW_HOST_USB_ACCESS: return "USB permission denied"; + case SW_HOST_USB_NO_DEVICE:return "USB no device"; + case SW_HOST_USB_BUSY: return "USB busy"; + case SW_HOST_USB_TIMEOUT: return "USB timeout"; + case SW_HOST_USB_OVERFLOW: return "USB overflow"; default: return "unknown host status error"; } } diff --git a/scd/apdu.h b/scd/apdu.h index 1392aab71..1cd04c2ee 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -72,7 +72,15 @@ enum { SW_HOST_ABORTED = 0x1000d, SW_HOST_NO_PINPAD = 0x1000e, SW_HOST_ALREADY_CONNECTED = 0x1000f, - SW_HOST_CANCELLED = 0x10010 + SW_HOST_CANCELLED = 0x10010, + SW_HOST_DEVICE_ACCESS = 0x10011, + SW_HOST_USB_OTHER = 0x10020, + SW_HOST_USB_IO = 0x10021, + SW_HOST_USB_ACCESS = 0x10023, + SW_HOST_USB_NO_DEVICE = 0x10024, + SW_HOST_USB_BUSY = 0x10026, + SW_HOST_USB_TIMEOUT = 0x10027, + SW_HOST_USB_OVERFLOW = 0x10028 }; struct dev_list; diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index cff1a31d7..f6da154c0 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -285,6 +285,24 @@ static int send_escape_cmd (ccid_driver_t handle, const unsigned char *data, size_t datalen, unsigned char *result, size_t resultmax, size_t *resultlen); + +static int +map_libusb_error (int usberr) +{ + switch (usberr) + { + case 0: return 0; + case LIBUSB_ERROR_IO: return CCID_DRIVER_ERR_USB_IO; + case LIBUSB_ERROR_ACCESS: return CCID_DRIVER_ERR_USB_ACCESS; + case LIBUSB_ERROR_NO_DEVICE:return CCID_DRIVER_ERR_USB_NO_DEVICE; + case LIBUSB_ERROR_BUSY: return CCID_DRIVER_ERR_USB_BUSY; + case LIBUSB_ERROR_TIMEOUT: return CCID_DRIVER_ERR_USB_TIMEOUT; + case LIBUSB_ERROR_OVERFLOW: return CCID_DRIVER_ERR_USB_OVERFLOW; + } + return CCID_DRIVER_ERR_USB_OTHER; +} + + /* Convert a little endian stored 4 byte value into an unsigned integer. */ static unsigned int @@ -1575,7 +1593,7 @@ ccid_open_usb_reader (const char *spec_reader_name, DEBUGOUT_1 ("usb_open failed: %s\n", libusb_error_name (rc)); free (*handle); *handle = NULL; - return rc; + return map_libusb_error (rc); } if (ccid_usb_thread_is_alive++ == 0) @@ -1610,6 +1628,7 @@ ccid_open_usb_reader (const char *spec_reader_name, if (rc) { DEBUGOUT ("get_device_descripor failed\n"); + rc = map_libusb_error (rc); goto leave; } @@ -1649,7 +1668,7 @@ ccid_open_usb_reader (const char *spec_reader_name, if (rc) { DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + rc = map_libusb_error (rc); goto leave; } @@ -1658,7 +1677,7 @@ ccid_open_usb_reader (const char *spec_reader_name, if (rc) { DEBUGOUT_1 ("usb_set_interface_alt_setting failed: %d\n", rc); - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + rc = map_libusb_error (rc); goto leave; } @@ -1963,12 +1982,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, { DEBUGOUT_1 ("usb_bulk_read error: %s\n", libusb_error_name (rc)); if (rc == LIBUSB_ERROR_NO_DEVICE) - { - handle->enodev_seen = 1; - return CCID_DRIVER_ERR_NO_READER; - } + handle->enodev_seen = 1; - return CCID_DRIVER_ERR_CARD_IO_ERROR; + return map_libusb_error (rc); } if (msglen < 0) return CCID_DRIVER_ERR_INV_VALUE; /* Faulty libusb. */ @@ -2119,7 +2135,7 @@ abort_cmd (ccid_driver_t handle, int seqno) if (rc) { DEBUGOUT_1 ("usb_control_msg error: %s\n", libusb_error_name (rc)); - return CCID_DRIVER_ERR_CARD_IO_ERROR; + return map_libusb_error (rc); } /* Now send the abort command to the bulk out pipe using the same @@ -2156,7 +2172,7 @@ abort_cmd (ccid_driver_t handle, int seqno) libusb_error_name (rc)); if (rc) - return rc; + return map_libusb_error (rc); #ifdef USE_NPTH npth_unprotect (); @@ -2171,7 +2187,7 @@ abort_cmd (ccid_driver_t handle, int seqno) { DEBUGOUT_1 ("usb_bulk_read error in abort_cmd: %s\n", libusb_error_name (rc)); - return CCID_DRIVER_ERR_CARD_IO_ERROR; + return map_libusb_error (rc); } if (msglen < 10) diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 32b947566..8f66d2c67 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -108,6 +108,13 @@ enum { #define CCID_DRIVER_ERR_NO_READER 0x1000c #define CCID_DRIVER_ERR_ABORTED 0x1000d #define CCID_DRIVER_ERR_NO_PINPAD 0x1000e +#define CCID_DRIVER_ERR_USB_OTHER 0x10020 +#define CCID_DRIVER_ERR_USB_IO 0x10021 +#define CCID_DRIVER_ERR_USB_ACCESS 0x10023 +#define CCID_DRIVER_ERR_USB_NO_DEVICE 0x10024 +#define CCID_DRIVER_ERR_USB_BUSY 0x10026 +#define CCID_DRIVER_ERR_USB_TIMEOUT 0x10027 +#define CCID_DRIVER_ERR_USB_OVERFLOW 0x10028 struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; diff --git a/scd/iso7816.c b/scd/iso7816.c index 092a119a6..20706706c 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -97,6 +97,13 @@ map_sw (int sw) case SW_HOST_ABORTED: ec = GPG_ERR_INV_RESPONSE; break; case SW_HOST_NO_PINPAD: ec = GPG_ERR_NOT_SUPPORTED; break; case SW_HOST_CANCELLED: ec = GPG_ERR_CANCELED; break; + case SW_HOST_USB_OTHER: ec = GPG_ERR_EIO; break; + case SW_HOST_USB_IO: ec = GPG_ERR_EIO; break; + case SW_HOST_USB_ACCESS: ec = GPG_ERR_EACCES; break; + case SW_HOST_USB_NO_DEVICE: ec = GPG_ERR_ENODEV; break; + case SW_HOST_USB_BUSY: ec = GPG_ERR_EBUSY; break; + case SW_HOST_USB_TIMEOUT: ec = GPG_ERR_TIMEOUT; break; + case SW_HOST_USB_OVERFLOW: ec = GPG_ERR_EOVERFLOW; break; default: if ((sw & 0x010000))