Update pcsc pinpad code to latest pcsc-lite code, limit to pcsc-lite only.
Verify works fine, modify needs some debugging-testing. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2668 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
1f58981bcb
commit
89cfac8735
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#ifdef HAVE_READER_H
|
#ifdef HAVE_READER_H
|
||||||
#include <reader.h>
|
#include <reader.h>
|
||||||
|
#ifdef HOST_TO_CCID_32
|
||||||
|
#define PINPAD_ENABLED
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default timeout value for SCardGetStatusChange
|
/* Default timeout value for SCardGetStatusChange
|
||||||
|
@ -436,10 +439,11 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
int r;
|
int r;
|
||||||
#ifdef CM_IOCTL_GET_FEATURE_REQUEST
|
#ifdef PINPAD_ENABLED
|
||||||
int i;
|
int i;
|
||||||
u8 feature_buf[256];
|
u8 feature_buf[256];
|
||||||
DWORD feature_len;
|
DWORD feature_len;
|
||||||
|
PCSC_TLV_STRUCTURE *pcsc_tlv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
r = refresh_slot_attributes(reader, slot);
|
r = refresh_slot_attributes(reader, slot);
|
||||||
|
@ -465,28 +469,33 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
pslot->pcsc_card = card_handle;
|
pslot->pcsc_card = card_handle;
|
||||||
|
|
||||||
/* check for pinpad support */
|
/* check for pinpad support */
|
||||||
#ifdef CM_IOCTL_GET_FEATURE_REQUEST
|
#ifdef PINPAD_ENABLED
|
||||||
sc_debug(reader->ctx, "Requesting reader features ... ");
|
sc_debug(reader->ctx, "Requesting reader features ... ");
|
||||||
|
|
||||||
rv = SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL,
|
rv = SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL,
|
||||||
0, feature_buf, sizeof(feature_buf), &feature_len);
|
0, feature_buf, sizeof(feature_buf), &feature_len);
|
||||||
if (rv == SCARD_S_SUCCESS) {
|
if (rv == SCARD_S_SUCCESS) {
|
||||||
if (!(feature_len % 6)) {
|
|
||||||
for (i = 0; i < feature_len; i += 6) {
|
if (!(feature_len % sizeof(PCSC_TLV_STRUCTURE))) {
|
||||||
if (feature_buf[i] == FEATURE_VERIFY_PIN_DIRECT) {
|
/* get the number of elements instead of the complete size */
|
||||||
|
feature_len /= sizeof(PCSC_TLV_STRUCTURE);
|
||||||
|
|
||||||
|
pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf;
|
||||||
|
for (i = 0; i < feature_len; i++) {
|
||||||
|
if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT) {
|
||||||
sc_debug(reader->ctx, "Reader supports pinpad PIN verification");
|
sc_debug(reader->ctx, "Reader supports pinpad PIN verification");
|
||||||
pslot->verify_ioctl = dw2i_be(feature_buf, i + 2);
|
pslot->verify_ioctl = pcsc_tlv[i].value;
|
||||||
if (priv->gpriv->enable_pinpad) {
|
if (priv->gpriv->enable_pinpad) {
|
||||||
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||||
}
|
}
|
||||||
} else if (feature_buf[i] == FEATURE_MODIFY_PIN_DIRECT) {
|
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT) {
|
||||||
sc_debug(reader->ctx, "Reader supports pinpad PIN modification");
|
sc_debug(reader->ctx, "Reader supports pinpad PIN modification");
|
||||||
pslot->modify_ioctl = dw2i_be(feature_buf, i + 2);
|
pslot->modify_ioctl = pcsc_tlv[i].value;
|
||||||
if (priv->gpriv->enable_pinpad) {
|
if (priv->gpriv->enable_pinpad) {
|
||||||
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc_debug(reader->ctx, "Reader pinpad feature: %02x not recognized", feature_buf[i]);
|
sc_debug(reader->ctx, "Reader pinpad feature: %02x not recognized", pcsc_tlv[i].tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -494,7 +503,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
} else {
|
} else {
|
||||||
PCSC_ERROR(reader->ctx, "SCardControl failed", rv)
|
PCSC_ERROR(reader->ctx, "SCardControl failed", rv)
|
||||||
}
|
}
|
||||||
#endif /* CM_IOCTL_GET_FEATURE_REQUEST */
|
#endif /* PINPAD_ENABLED */
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,6 +738,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
|
||||||
* Similar to CCID in spirit.
|
* Similar to CCID in spirit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PINPAD_ENABLED
|
||||||
/* Local definitions */
|
/* Local definitions */
|
||||||
#define SC_CCID_PIN_TIMEOUT 30
|
#define SC_CCID_PIN_TIMEOUT 30
|
||||||
|
|
||||||
|
@ -742,22 +752,23 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
|
||||||
/* Build a pin verification block + APDU */
|
/* Build a pin verification block + APDU */
|
||||||
static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
|
static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
|
||||||
{
|
{
|
||||||
size_t buflen, count = 0;
|
int offset = 0, count = 0;
|
||||||
sc_apdu_t *apdu = data->apdu;
|
sc_apdu_t *apdu = data->apdu;
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
buflen = sizeof(buf);
|
uint16_t tmp16;
|
||||||
|
PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
|
||||||
|
|
||||||
/* PIN verification control message */
|
/* PIN verification control message */
|
||||||
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut */
|
pin_verify->bTimerOut = SC_CCID_PIN_TIMEOUT;
|
||||||
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */
|
pin_verify->bTimerOut2 = SC_CCID_PIN_TIMEOUT;
|
||||||
|
|
||||||
/* bmFormatString */
|
/* bmFormatString */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
if (data->pin1.encoding == SC_PIN_ENCODING_ASCII) {
|
if (data->pin1.encoding == SC_PIN_ENCODING_ASCII) {
|
||||||
tmp |= SC_CCID_PIN_ENCODING_ASCII;
|
tmp |= SC_CCID_PIN_ENCODING_ASCII;
|
||||||
|
|
||||||
/* if the effective pin length offset is specified, use it */
|
/* if the effective pin length offset is specified, use it */
|
||||||
if (data->pin1.length_offset > 3) {
|
if (data->pin1.length_offset > 4) {
|
||||||
tmp |= SC_CCID_PIN_UNITS_BYTES;
|
tmp |= SC_CCID_PIN_UNITS_BYTES;
|
||||||
tmp |= (data->pin1.length_offset - 5) << 3;
|
tmp |= (data->pin1.length_offset - 5) << 3;
|
||||||
}
|
}
|
||||||
|
@ -771,7 +782,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
} else
|
} else
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
||||||
buf[count++] = tmp; /* bmFormatString */
|
pin_verify->bmFormatString = tmp;
|
||||||
|
|
||||||
/* bmPINBlockString */
|
/* bmPINBlockString */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
|
@ -779,7 +790,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
|
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
|
||||||
tmp |= 0x40 | 0x08;
|
tmp |= 0x40 | 0x08;
|
||||||
}
|
}
|
||||||
buf[count++] = tmp; /* bmPINBlockString */
|
pin_verify->bmPINBlockString = tmp;
|
||||||
|
|
||||||
/* bmPINLengthFormat */
|
/* bmPINLengthFormat */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
|
@ -787,43 +798,39 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
/* GLP pins expect the effective pin length from bit 4 */
|
/* GLP pins expect the effective pin length from bit 4 */
|
||||||
tmp |= 0x04;
|
tmp |= 0x04;
|
||||||
}
|
}
|
||||||
buf[count++] = tmp; /* bmPINLengthFormat */
|
pin_verify->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
|
||||||
|
|
||||||
if (!data->pin1.min_length || !data->pin1.max_length)
|
if (!data->pin1.min_length || !data->pin1.max_length)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
buf[count++] = data->pin1.max_length; /* wPINMaxExtraDigit: max */
|
|
||||||
buf[count++] = data->pin1.min_length; /* wPINMaxExtraDigit: min */
|
|
||||||
|
|
||||||
buf[count++] = 0x02; /* bEntryValidationCondition, keypress only */
|
|
||||||
|
|
||||||
|
tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
|
||||||
|
pin_verify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
|
||||||
|
|
||||||
|
pin_verify->bEntryValidationCondition = 0x02; /* Keypress only */
|
||||||
|
|
||||||
/* Ignore language and T=1 parameters. */
|
/* Ignore language and T=1 parameters. */
|
||||||
buf[count++] = 0x00; /* bNumberMessage */
|
pin_verify->bNumberMessage = 0x00;
|
||||||
buf[count++] = 0x00; /* wLangId */
|
pin_verify->wLangId = HOST_TO_CCID_16(0x0000);
|
||||||
buf[count++] = 0x00; /* " */
|
pin_verify->bMsgIndex = 0x00;
|
||||||
buf[count++] = 0x00; /* bMsgIndex */
|
pin_verify->bTeoPrologue[0] = 0x00;
|
||||||
buf[count++] = 0x00; /* bTeoPrologue */
|
pin_verify->bTeoPrologue[1] = 0x00;
|
||||||
buf[count++] = 0x00; /* " */
|
pin_verify->bTeoPrologue[2] = 0x00;
|
||||||
buf[count++] = 0x00; /* " */
|
|
||||||
|
|
||||||
/* ulDataLength */
|
|
||||||
if (data->pin1.length_offset != 4)
|
|
||||||
tmp = apdu->datalen + 4;
|
|
||||||
else
|
|
||||||
tmp = 4;
|
|
||||||
buf[count++] = tmp; /* ulDataLength */
|
|
||||||
|
|
||||||
/* APDU itself */
|
/* APDU itself */
|
||||||
buf[count++] = apdu->cla;
|
pin_verify->abData[offset++] = apdu->cla;
|
||||||
buf[count++] = apdu->ins;
|
pin_verify->abData[offset++] = apdu->ins;
|
||||||
buf[count++] = apdu->p1;
|
pin_verify->abData[offset++] = apdu->p1;
|
||||||
buf[count++] = apdu->p2;
|
pin_verify->abData[offset++] = apdu->p2;
|
||||||
|
|
||||||
/* Copy data if not Case 1 */
|
/* Copy data if not Case 1 */
|
||||||
if (data->pin1.length_offset != 4) {
|
if (data->pin1.length_offset != 4) {
|
||||||
memcpy(&buf[count], apdu->data, apdu->datalen);
|
memcpy(&pin_verify->abData[offset], apdu->data, apdu->datalen);
|
||||||
count += apdu->datalen;
|
offset += apdu->datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pin_verify->ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
|
||||||
|
|
||||||
|
count = sizeof(PIN_VERIFY_STRUCTURE) + offset -1;
|
||||||
*size = count;
|
*size = count;
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -833,14 +840,15 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
/* Build a pin modification block + APDU */
|
/* Build a pin modification block + APDU */
|
||||||
static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
|
static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
|
||||||
{
|
{
|
||||||
size_t buflen, count = 0;
|
int offset = 0, count = 0;
|
||||||
sc_apdu_t *apdu = data->apdu;
|
sc_apdu_t *apdu = data->apdu;
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
buflen = sizeof(buf);
|
uint16_t tmp16;
|
||||||
|
PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf;
|
||||||
|
|
||||||
/* PIN verification control message */
|
/* PIN verification control message */
|
||||||
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut */
|
pin_modify->bTimerOut = SC_CCID_PIN_TIMEOUT; /* bTimeOut */
|
||||||
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */
|
pin_modify->bTimerOut2 = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */
|
||||||
|
|
||||||
/* bmFormatString */
|
/* bmFormatString */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
|
@ -848,7 +856,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
tmp |= SC_CCID_PIN_ENCODING_ASCII;
|
tmp |= SC_CCID_PIN_ENCODING_ASCII;
|
||||||
|
|
||||||
/* if the effective pin length offset is specified, use it */
|
/* if the effective pin length offset is specified, use it */
|
||||||
if (data->pin1.length_offset > 3) {
|
if (data->pin1.length_offset > 4) {
|
||||||
tmp |= SC_CCID_PIN_UNITS_BYTES;
|
tmp |= SC_CCID_PIN_UNITS_BYTES;
|
||||||
tmp |= (data->pin1.length_offset - 5) << 3;
|
tmp |= (data->pin1.length_offset - 5) << 3;
|
||||||
}
|
}
|
||||||
|
@ -862,7 +870,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
} else
|
} else
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
||||||
buf[count++] = tmp; /* bmFormatString */
|
pin_modify->bmFormatString = tmp; /* bmFormatString */
|
||||||
|
|
||||||
/* bmPINBlockString */
|
/* bmPINBlockString */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
|
@ -870,7 +878,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
|
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
|
||||||
tmp |= 0x40 | 0x08;
|
tmp |= 0x40 | 0x08;
|
||||||
}
|
}
|
||||||
buf[count++] = tmp; /* bmPINBlockString */
|
pin_modify->bmPINBlockString = tmp; /* bmPINBlockString */
|
||||||
|
|
||||||
/* bmPINLengthFormat */
|
/* bmPINLengthFormat */
|
||||||
tmp = 0x00;
|
tmp = 0x00;
|
||||||
|
@ -878,59 +886,56 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
||||||
/* GLP pins expect the effective pin length from bit 4 */
|
/* GLP pins expect the effective pin length from bit 4 */
|
||||||
tmp |= 0x04;
|
tmp |= 0x04;
|
||||||
}
|
}
|
||||||
buf[count++] = tmp; /* bmPINLengthFormat */
|
pin_modify->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
|
||||||
|
|
||||||
buf[count++] = 0x00; /* bOffsetOld */
|
pin_modify->bInsertionOffsetOld = 0x00; /* bOffsetOld */
|
||||||
buf[count++] = 0x00; /* bOffsetNew */
|
pin_modify->bInsertionOffsetNew = 0x00; /* bOffsetNew */
|
||||||
|
|
||||||
if (!data->pin1.min_length || !data->pin1.max_length)
|
if (!data->pin1.min_length || !data->pin1.max_length)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
buf[count++] = data->pin1.max_length; /* wPINMaxExtraDigit: max */
|
|
||||||
buf[count++] = data->pin1.min_length; /* wPINMaxExtraDigit: min */
|
tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
|
||||||
|
pin_modify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
|
||||||
|
|
||||||
buf[count++] = 0x03; /* bConfirmPIN, all */
|
pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */
|
||||||
buf[count++] = 0x02; /* bEntryValidationCondition, keypress only */
|
pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */
|
||||||
|
|
||||||
/* Ignore language and T=1 parameters. */
|
/* Ignore language and T=1 parameters. */
|
||||||
buf[count++] = 0x00; /* bNumberMessage */
|
pin_modify->bNumberMessage = 0x00;
|
||||||
buf[count++] = 0x00; /* wLangId */
|
pin_modify->wLangId = HOST_TO_CCID_16(0x0000);
|
||||||
buf[count++] = 0x00; /* " */
|
pin_modify->bMsgIndex1 = 0x00;
|
||||||
/* Only as many as bNumberMessage messages, currently none */
|
pin_modify->bMsgIndex2 = 0x00;
|
||||||
/* buf[count++] = 0x00; */ /* bMsgIndex1 */
|
pin_modify->bMsgIndex3 = 0x00;
|
||||||
/* buf[count++] = 0x00; */ /* bMsgIndex2 */
|
pin_modify->bTeoPrologue[0] = 0x00;
|
||||||
/* buf[count++] = 0x00; */ /* bMsgIndex3 */
|
pin_modify->bTeoPrologue[1] = 0x00;
|
||||||
buf[count++] = 0x00; /* bTeoPrologue */
|
pin_modify->bTeoPrologue[2] = 0x00;
|
||||||
buf[count++] = 0x00; /* " */
|
|
||||||
buf[count++] = 0x00; /* " */
|
|
||||||
|
|
||||||
/* ulDataLength */
|
|
||||||
if (data->pin1.length_offset != 4)
|
|
||||||
tmp = apdu->datalen + 4;
|
|
||||||
else
|
|
||||||
tmp = 4;
|
|
||||||
buf[count++] = tmp; /* ulDataLength */
|
|
||||||
|
|
||||||
/* APDU itself */
|
/* APDU itself */
|
||||||
buf[count++] = apdu->cla;
|
pin_modify->abData[offset++] = apdu->cla;
|
||||||
buf[count++] = apdu->ins;
|
pin_modify->abData[offset++] = apdu->ins;
|
||||||
buf[count++] = apdu->p1;
|
pin_modify->abData[offset++] = apdu->p1;
|
||||||
buf[count++] = apdu->p2;
|
pin_modify->abData[offset++] = apdu->p2;
|
||||||
|
|
||||||
/* Copy full APDU if not Case 1 */
|
/* Copy data if not Case 1 */
|
||||||
if (data->pin1.length_offset != 4) {
|
if (data->pin1.length_offset != 4) {
|
||||||
memcpy(&buf[count], apdu->data, apdu->datalen);
|
memcpy(&pin_modify->abData[offset], apdu->data, apdu->datalen);
|
||||||
count += apdu->datalen;
|
offset += apdu->datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pin_modify->ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
|
||||||
|
|
||||||
|
count = sizeof(PIN_MODIFY_STRUCTURE) + offset -1;
|
||||||
*size = count;
|
*size = count;
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
/* Do the PIN command */
|
/* Do the PIN command */
|
||||||
static int
|
static int
|
||||||
part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
struct sc_pin_cmd_data *data)
|
struct sc_pin_cmd_data *data)
|
||||||
{
|
{
|
||||||
|
#ifdef PINPAD_ENABLED
|
||||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3];
|
char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3];
|
||||||
size_t rcount = sizeof(rbuf), scount = 0;
|
size_t rcount = sizeof(rbuf), scount = 0;
|
||||||
|
@ -1014,6 +1019,9 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
|
|
||||||
/* PIN command completed, all is good */
|
/* PIN command completed, all is good */
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
|
#else
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
#endif /* PINPAD_ENABLED */
|
||||||
}
|
}
|
||||||
#endif /* HAVE_PCSC */
|
#endif /* HAVE_PCSC */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue