diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index bbd575a..3ee1763 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -59,19 +59,19 @@ #define LOG_CATEGORY "libnfc.driver.pcsc" static const char *supported_devices[] = { - "ACS ACR122", // ACR122U & Touchatag, last version - "ACS ACR 38U-CCID", // Touchatag, early version - "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX - "ACS AET65", // Touchatag using CCID driver version >= 1.4.6 - " CCID USB", // ?? - NULL + "ACS ACR122", // ACR122U & Touchatag, last version + "ACS ACR 38U-CCID", // Touchatag, early version + "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX + "ACS AET65", // Touchatag using CCID driver version >= 1.4.6 + " CCID USB", // ?? + NULL }; struct pcsc_data { - SCARDHANDLE hCard; - SCARD_IO_REQUEST ioCard; - DWORD dwShareMode; - DWORD last_error; + SCARDHANDLE hCard; + SCARD_IO_REQUEST ioCard; + DWORD dwShareMode; + DWORD last_error; }; #define DRIVER_DATA(pnd) ((struct pcsc_data*)(pnd->driver_data)) @@ -97,24 +97,24 @@ const nfc_modulation_type pcsc_supported_mts[] = {NMT_ISO14443A, NMT_ISO14443B, SCARDCONTEXT * pcsc_get_scardcontext(void) { - if (_iSCardContextRefCount == 0) { - if (SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS) - return NULL; - } - _iSCardContextRefCount++; - - return &_SCardContext; + if (_iSCardContextRefCount == 0) { + if (SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS) + return NULL; + } + _iSCardContextRefCount++; + + return &_SCardContext; } void pcsc_free_scardcontext(void) { - if (_iSCardContextRefCount) { - _iSCardContextRefCount--; - if (!_iSCardContextRefCount) { - SCardReleaseContext(_SCardContext); + if (_iSCardContextRefCount) { + _iSCardContextRefCount--; + if (!_iSCardContextRefCount) { + SCardReleaseContext(_SCardContext); + } } - } } #define ICC_TYPE_UNKNOWN 0 @@ -123,135 +123,274 @@ pcsc_free_scardcontext(void) int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len) { - struct pcsc_data *data = pnd->driver_data; - DWORD dw_rx_len = *rx_len; - - LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len); - - data->last_error = SCardTransmit(data->hCard, &data->ioCard, tx, tx_len, - NULL, rx, &dw_rx_len); - if (data->last_error != SCARD_S_SUCCESS) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed"); - return NFC_EIO; - } - *rx_len = dw_rx_len; - LOG_HEX(NFC_LOG_GROUP_COM, "RX", rx, *rx_len); - - return NFC_SUCCESS; + struct pcsc_data *data = pnd->driver_data; + DWORD dw_rx_len = *rx_len; + + LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len); + + data->last_error = SCardTransmit(data->hCard, &data->ioCard, tx, tx_len, + NULL, rx, &dw_rx_len); + if (data->last_error != SCARD_S_SUCCESS) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed"); + return NFC_EIO; + } + *rx_len = dw_rx_len; + + LOG_HEX(NFC_LOG_GROUP_COM, "RX", rx, *rx_len); + + return NFC_SUCCESS; } int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t *atr, size_t *atr_len) { - struct pcsc_data *data = pnd->driver_data; - DWORD dw_atr_len = *atr_len, reader_len, state, protocol; - - data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len); - if (data->last_error != SCARD_S_SUCCESS - && data->last_error != SCARD_W_RESET_CARD) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed"); - return NFC_EIO; - } - - *target_present = state & SCARD_PRESENT; - *atr_len = dw_atr_len; - - return NFC_SUCCESS; + struct pcsc_data *data = pnd->driver_data; + DWORD dw_atr_len = *atr_len, reader_len, state, protocol; + + data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len); + if (data->last_error != SCARD_S_SUCCESS + && data->last_error != SCARD_W_RESET_CARD) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed"); + return NFC_EIO; + } + + *target_present = state & SCARD_PRESENT; + *atr_len = dw_atr_len; + + return NFC_SUCCESS; } int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWORD disposition) { - struct pcsc_data *data = pnd->driver_data; - - data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol); - if (data->last_error != SCARD_S_SUCCESS - && data->last_error != SCARD_W_RESET_CARD) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed"); - return NFC_EIO; - } - - data->dwShareMode = share_mode; - - return NFC_SUCCESS; + struct pcsc_data *data = pnd->driver_data; + + data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol); + if (data->last_error != SCARD_S_SUCCESS + && data->last_error != SCARD_W_RESET_CARD) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed"); + return NFC_EIO; + } + + data->dwShareMode = share_mode; + + return NFC_SUCCESS; } uint8_t pcsc_get_icc_type(struct nfc_device *pnd) { - struct pcsc_data *data = pnd->driver_data; - uint8_t it = 0; - DWORD dwItLen = sizeof it; - data->last_error = SCardGetAttrib(data->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen); - return it; + struct pcsc_data *data = pnd->driver_data; + uint8_t it = 0; + DWORD dwItLen = sizeof it; + data->last_error = SCardGetAttrib(data->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen); + return it; +} + +char* pcsc_get_vendor_name(struct nfc_device *pnd){ + struct pcsc_data *data = pnd->driver_data; + LPBYTE vendor_name = NULL; + DWORD vendor_name_len = SCARD_AUTOALLOCATE; + + int res = SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&vendor_name, &vendor_name_len); + if (!res && vendor_name && vendor_name_len > 0 && vendor_name[0] != '\0') { + char *psVendorName = (char *)malloc(sizeof(char) * vendor_name_len); + memcpy(psVendorName, vendor_name, vendor_name_len); + return psVendorName; + } + return NULL; +} + +bool is_pcsc_reader_vendor(struct nfc_device *pnd, const char * target_vendor_name) +{ + bool isTarget = false; + char * sReaderVendorName = pcsc_get_vendor_name(pnd); + if (sReaderVendorName) + { + isTarget = (strstr(sReaderVendorName, target_vendor_name)) ? true:false; + free(sReaderVendorName); + sReaderVendorName = NULL; + } + + return isTarget; +} + +bool is_pcsc_reader_vendor_feitian(struct nfc_device *pnd) +{ + return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") ||is_pcsc_reader_vendor(pnd, "feitian"); +} + +//get atqa by send apdu +int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x03, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATQA"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (atqa_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATQA length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + memcpy(atqa, resp, resp_len - 2); + return resp_len - 2; +} + +//get ats by send apdu +int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x01, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (ats_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATS length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + //memcpy(ats, resp + 1, resp_len - 2 - 1); + memcpy(ats, resp + 1, resp[0] - 1); + return resp_len - 2 - 1; +} + +//get sak by send apdu +int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x02, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for SAK"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (sak_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SAK length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + memcpy(sak, resp, resp_len - 2); + return resp_len - 2; } int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) { - const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}; - uint8_t resp[256 + 2]; - size_t resp_len = sizeof resp; - - pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); - if (pnd->last_error != NFC_SUCCESS) - return pnd->last_error; - - if (resp_len < 2) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for UID"); - pnd->last_error = NFC_EDEVNOTSUPP; - return pnd->last_error; - } - if (uid_len < resp_len - 2) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "UID too big"); - pnd->last_error = NFC_ESOFT; - return pnd->last_error; - } - - memcpy(uid, resp, resp_len - 2); - return resp_len - 2; + const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for UID"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (uid_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "UID too big"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + memcpy(uid, resp, resp_len - 2); + return resp_len - 2; } +int pcsc_props_to_target(const struct nfc_device *pnd, uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) { - if (NULL != pnt) { - switch (nmt) { - case NMT_ISO14443A: - if ((it == ICC_TYPE_UNKNOWN || it == ICC_TYPE_14443A) - && (szuid <= 0 || szuid == 4 || szuid == 7 || szuid == 10) - && NULL != patr && szatr >= 5 - && patr[0] == 0x3B - && patr[1] == (0x80 | ((uint8_t)(szatr - 5))) - && patr[2] == 0x80 - && patr[3] == 0x01) { - memset(pnt, 0, sizeof * pnt); - pnt->nm.nmt = NMT_ISO14443A; - pnt->nm.nbr = pcsc_supported_brs[0]; - if (szuid > 0) { - memcpy(pnt->nti.nai.abtUid, puid, szuid); - pnt->nti.nai.szUidLen = szuid; - } - return NFC_SUCCESS; + if (NULL != pnt) { + switch (nmt) { + case NMT_ISO14443A: + if ((it == ICC_TYPE_UNKNOWN || it == ICC_TYPE_14443A) + && (szuid <= 0 || szuid == 4 || szuid == 7 || szuid == 10) + && NULL != patr && szatr >= 5 + && patr[0] == 0x3B + && patr[1] == (0x80 | ((uint8_t)(szatr - 5))) + && patr[2] == 0x80 + && patr[3] == 0x01) { + memset(pnt, 0, sizeof * pnt); + pnt->nm.nmt = NMT_ISO14443A; + pnt->nm.nbr = pcsc_supported_brs[0]; + if (szuid > 0) { + memcpy(pnt->nti.nai.abtUid, puid, szuid); + pnt->nti.nai.szUidLen = szuid; + } + if (is_pcsc_reader_vendor_feitian(pnd)) + { + uint8_t atqa[2]; + pcsc_get_atqa(pnd,atqa,sizeof(atqa)); + //memcpy(pnt->nti.nai.abtAtqa,atqa,2); + pnt->nti.nai.abtAtqa[0] = atqa[1]; + pnt->nti.nai.abtAtqa[1] = atqa[0]; + uint8_t sak[1]; + pcsc_get_sak(pnd,sak,sizeof(sak)); + pnt->nti.nai.btSak = sak[0]; + uint8_t ats[256]; + int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats)); + memcpy(pnt->nti.nai.abtAts, ats, ats_len); + //memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5)); + pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5; + } else { + /* SAK_ISO14443_4_COMPLIANT */ + pnt->nti.nai.btSak = 0x20; + /* Choose TL, TA, TB, TC according to Mifare DESFire */ + memcpy(pnt->nti.nai.abtAts, "\x75\x77\x81\x02", 4); + /* copy historical bytes */ + memcpy(pnt->nti.nai.abtAts + 4, patr + 4, (uint8_t)(szatr - 5)); + pnt->nti.nai.szAtsLen = 4 + (uint8_t)(szatr - 5); + } + + return NFC_SUCCESS; + } + break; + case NMT_ISO14443B: + if ((ICC_TYPE_UNKNOWN == 0 || ICC_TYPE_14443B == 6) + && (szuid <= 0 || szuid == 8) + && NULL != patr && szatr == 5 + 8 + && patr[0] == 0x3B + && patr[1] == (0x80 | 0x08) + && patr[2] == 0x80 + && patr[3] == 0x01) { + memset(pnt, 0, sizeof * pnt); + pnt->nm.nmt = NMT_ISO14443B; + pnt->nm.nbr = pcsc_supported_brs[0]; + memcpy(pnt->nti.nbi.abtApplicationData, patr + 4, 4); + memcpy(pnt->nti.nbi.abtProtocolInfo, patr + 8, 3); + /* PI_ISO14443_4_SUPPORTED */ + pnt->nti.nbi.abtProtocolInfo[1] = 0x01; + return NFC_SUCCESS; + } + break; + default: + break; } - break; - case NMT_ISO14443B: - if ((ICC_TYPE_UNKNOWN == 0 || ICC_TYPE_14443B == 6) - && (szuid <= 0 || szuid == 8) - && NULL != patr && szatr == 5 + 8 - && patr[0] == 0x3B - && patr[1] == (0x80 | 0x08) - && patr[2] == 0x80 - && patr[3] == 0x01) { - memset(pnt, 0, sizeof * pnt); - pnt->nm.nmt = NMT_ISO14443B; - pnt->nm.nbr = pcsc_supported_brs[0]; - memcpy(pnt->nti.nbi.abtApplicationData, patr + 4, 4); - memcpy(pnt->nti.nbi.abtProtocolInfo, patr + 8, 3); - /* PI_ISO14443_4_SUPPORTED */ - pnt->nti.nbi.abtProtocolInfo[1] = 0x01; - return NFC_SUCCESS; - } - break; - default: - break; } - } - return NFC_EINVARG; + return NFC_EINVARG; } #define PCSC_MAX_DEVICES 16 @@ -267,500 +406,589 @@ int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) static size_t pcsc_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) { - (void) context; - size_t szPos = 0; - char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES]; - size_t szDeviceNamesLen = sizeof(acDeviceNames); - SCARDCONTEXT *pscc; - int i; - - // Clear the reader list - memset(acDeviceNames, '\0', szDeviceNamesLen); - - // Test if context succeeded - if (!(pscc = pcsc_get_scardcontext())) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "PCSC context not found (make sure PCSC daemon is running)."); - return 0; - } - // Retrieve the string array of all available pcsc readers - DWORD dwDeviceNamesLen = szDeviceNamesLen; - if (SCardListReaders(*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS) - return 0; - - size_t device_found = 0; - while ((acDeviceNames[szPos] != '\0') && (device_found < connstrings_len)) { - bool bSupported = false; - for (i = 0; supported_devices[i] && !bSupported; i++) { - int l = strlen(supported_devices[i]); - bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l); + (void) context; + size_t szPos = 0; + char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES]; + size_t szDeviceNamesLen = sizeof(acDeviceNames); + SCARDCONTEXT *pscc; + int i; + + // Clear the reader list + memset(acDeviceNames, '\0', szDeviceNamesLen); + + // Test if context succeeded + if (!(pscc = pcsc_get_scardcontext())) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "PCSC context not found (make sure PCSC daemon is running)."); + return 0; } + // Retrieve the string array of all available pcsc readers + DWORD dwDeviceNamesLen = szDeviceNamesLen; + if (SCardListReaders(*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS) + return 0; + + size_t device_found = 0; + while ((acDeviceNames[szPos] != '\0') && (device_found < connstrings_len)) { + bool bSupported = false; + for (i = 0; supported_devices[i] && !bSupported; i++) { + int l = strlen(supported_devices[i]); + bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l); + } + + if (bSupported) { + // Supported non-ACR122 device found + snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s", PCSC_DRIVER_NAME, acDeviceNames + szPos); + device_found++; + } else { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Skipping PCSC device [%s] as it is supported by acr122_pcsc driver.", acDeviceNames + szPos); + } + + // Find next device name position + while (acDeviceNames[szPos++] != '\0'); } - - if (bSupported) { - // Supported non-ACR122 device found - snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s", PCSC_DRIVER_NAME, acDeviceNames + szPos); - device_found++; - } else { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Skipping PCSC device [%s] as it is supported by acr122_pcsc driver.", acDeviceNames + szPos); - } - - // Find next device name position - while (acDeviceNames[szPos++] != '\0'); - } - pcsc_free_scardcontext(); - - return device_found; + pcsc_free_scardcontext(); + + return device_found; } struct pcsc_descriptor { - char *pcsc_device_name; + char *pcsc_device_name; }; static nfc_device * pcsc_open(const nfc_context *context, const nfc_connstring connstring) { - struct pcsc_descriptor ndd; - int connstring_decode_level = connstring_decode(connstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); - - if (connstring_decode_level < 1) { - return NULL; - } - - nfc_connstring fullconnstring; - if (connstring_decode_level == 1) { - // Device was not specified, take the first one we can find - size_t szDeviceFound = pcsc_scan(context, &fullconnstring, 1); - if (szDeviceFound < 1) - return NULL; - connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); - if (connstring_decode_level < 2) { - return NULL; + struct pcsc_descriptor ndd; + int connstring_decode_level = connstring_decode(connstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + + if (connstring_decode_level < 1) { + return NULL; } - } else { - memcpy(fullconnstring, connstring, sizeof(nfc_connstring)); - } - if (strlen(ndd.pcsc_device_name) < 5) { // We can assume it's a reader ID as pcsc_name always ends with "NN NN" - // Device was not specified, only ID, retrieve it - size_t index; - if (sscanf(ndd.pcsc_device_name, "%4" SCNuPTR, &index) != 1) { - free(ndd.pcsc_device_name); - return NULL; + + nfc_connstring fullconnstring; + if (connstring_decode_level == 1) { + // Device was not specified, take the first one we can find + size_t szDeviceFound = pcsc_scan(context, &fullconnstring, 1); + if (szDeviceFound < 1) + return NULL; + connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + if (connstring_decode_level < 2) { + return NULL; + } + } else { + memcpy(fullconnstring, connstring, sizeof(nfc_connstring)); } - nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1)); - if (!ncs) { - perror("malloc"); - free(ndd.pcsc_device_name); - return NULL; + if (strlen(ndd.pcsc_device_name) < 5) { // We can assume it's a reader ID as pcsc_name always ends with "NN NN" + // Device was not specified, only ID, retrieve it + size_t index; + if (sscanf(ndd.pcsc_device_name, "%4" SCNuPTR, &index) != 1) { + free(ndd.pcsc_device_name); + return NULL; + } + nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1)); + if (!ncs) { + perror("malloc"); + free(ndd.pcsc_device_name); + return NULL; + } + size_t szDeviceFound = pcsc_scan(context, ncs, index + 1); + if (szDeviceFound < index + 1) { + free(ncs); + free(ndd.pcsc_device_name); + return NULL; + } + strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring)); + fullconnstring[sizeof(nfc_connstring) - 1] = '\0'; + free(ncs); + connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + + if (connstring_decode_level < 2) { + free(ndd.pcsc_device_name); + return NULL; + } } - size_t szDeviceFound = pcsc_scan(context, ncs, index + 1); - if (szDeviceFound < index + 1) { - free(ncs); - free(ndd.pcsc_device_name); - return NULL; + + nfc_device *pnd = nfc_device_new(context, fullconnstring); + if (!pnd) { + perror("malloc"); + goto error; } - strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring)); - fullconnstring[sizeof(nfc_connstring) - 1] = '\0'; - free(ncs); - connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); - - if (connstring_decode_level < 2) { - free(ndd.pcsc_device_name); - return NULL; + pnd->driver_data = malloc(sizeof(struct pcsc_data)); + if (!pnd->driver_data) { + perror("malloc"); + goto error; } - } - - nfc_device *pnd = nfc_device_new(context, fullconnstring); - if (!pnd) { - perror("malloc"); - goto error; - } - pnd->driver_data = malloc(sizeof(struct pcsc_data)); - if (!pnd->driver_data) { - perror("malloc"); - goto error; - } - - SCARDCONTEXT *pscc; - - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open %s", ndd.pcsc_device_name); - // Test if context succeeded - if (!(pscc = pcsc_get_scardcontext())) - goto error; - if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { - // We can not connect to this device. - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); - goto error; - } - // Configure I/O settings for card communication - DRIVER_DATA(pnd)->ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); - DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT; - - // Done, we found the reader we are looking for - snprintf(pnd->name, sizeof(pnd->name), "%s", ndd.pcsc_device_name); - - pnd->driver = &pcsc_driver; - - free(ndd.pcsc_device_name); - return pnd; - + + SCARDCONTEXT *pscc; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open %s", ndd.pcsc_device_name); + // Test if context succeeded + if (!(pscc = pcsc_get_scardcontext())) + goto error; + DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { + // We can not connect to this device. + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); + goto error; + } + // Configure I/O settings for card communication + DRIVER_DATA(pnd)->ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); + DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT; + + // Done, we found the reader we are looking for + snprintf(pnd->name, sizeof(pnd->name), "%s", ndd.pcsc_device_name); + + pnd->driver = &pcsc_driver; + + free(ndd.pcsc_device_name); + return pnd; + error: - free(ndd.pcsc_device_name); - nfc_device_free(pnd); - return NULL; + free(ndd.pcsc_device_name); + nfc_device_free(pnd); + return NULL; } static void pcsc_close(nfc_device *pnd) { - SCardDisconnect(DRIVER_DATA(pnd)->hCard, SCARD_LEAVE_CARD); - pcsc_free_scardcontext(); - - nfc_device_free(pnd); + SCardDisconnect(DRIVER_DATA(pnd)->hCard, SCARD_LEAVE_CARD); + pcsc_free_scardcontext(); + + nfc_device_free(pnd); } static const char *stringify_error(const LONG pcscError) { - static char strError[75]; - const char *msg = NULL; - - switch (pcscError) { - case SCARD_S_SUCCESS: - msg = "Command successful."; - break; - case SCARD_F_INTERNAL_ERROR: - msg = "Internal error."; - break; - case SCARD_E_CANCELLED: - msg = "Command cancelled."; - break; - case SCARD_E_INVALID_HANDLE: - msg = "Invalid handle."; - break; - case SCARD_E_INVALID_PARAMETER: - msg = "Invalid parameter given."; - break; - case SCARD_E_INVALID_TARGET: - msg = "Invalid target given."; - break; - case SCARD_E_NO_MEMORY: - msg = "Not enough memory."; - break; - case SCARD_F_WAITED_TOO_LONG: - msg = "Waited too long."; - break; - case SCARD_E_INSUFFICIENT_BUFFER: - msg = "Insufficient buffer."; - break; - case SCARD_E_UNKNOWN_READER: - msg = "Unknown reader specified."; - break; - case SCARD_E_TIMEOUT: - msg = "Command timeout."; - break; - case SCARD_E_SHARING_VIOLATION: - msg = "Sharing violation."; - break; - case SCARD_E_NO_SMARTCARD: - msg = "No smart card inserted."; - break; - case SCARD_E_UNKNOWN_CARD: - msg = "Unknown card."; - break; - case SCARD_E_CANT_DISPOSE: - msg = "Cannot dispose handle."; - break; - case SCARD_E_PROTO_MISMATCH: - msg = "Card protocol mismatch."; - break; - case SCARD_E_NOT_READY: - msg = "Subsystem not ready."; - break; - case SCARD_E_INVALID_VALUE: - msg = "Invalid value given."; - break; - case SCARD_E_SYSTEM_CANCELLED: - msg = "System cancelled."; - break; - case SCARD_F_COMM_ERROR: - msg = "RPC transport error."; - break; - case SCARD_F_UNKNOWN_ERROR: - msg = "Unknown error."; - break; - case SCARD_E_INVALID_ATR: - msg = "Invalid ATR."; - break; - case SCARD_E_NOT_TRANSACTED: - msg = "Transaction failed."; - break; - case SCARD_E_READER_UNAVAILABLE: - msg = "Reader is unavailable."; - break; - /* case SCARD_P_SHUTDOWN: */ - case SCARD_E_PCI_TOO_SMALL: - msg = "PCI struct too small."; - break; - case SCARD_E_READER_UNSUPPORTED: - msg = "Reader is unsupported."; - break; - case SCARD_E_DUPLICATE_READER: - msg = "Reader already exists."; - break; - case SCARD_E_CARD_UNSUPPORTED: - msg = "Card is unsupported."; - break; - case SCARD_E_NO_SERVICE: - msg = "Service not available."; - break; - case SCARD_E_SERVICE_STOPPED: - msg = "Service was stopped."; - break; - /* case SCARD_E_UNEXPECTED: */ - /* case SCARD_E_ICC_CREATEORDER: */ - /* case SCARD_E_UNSUPPORTED_FEATURE: */ - /* case SCARD_E_DIR_NOT_FOUND: */ - /* case SCARD_E_NO_DIR: */ - /* case SCARD_E_NO_FILE: */ - /* case SCARD_E_NO_ACCESS: */ - /* case SCARD_E_WRITE_TOO_MANY: */ - /* case SCARD_E_BAD_SEEK: */ - /* case SCARD_E_INVALID_CHV: */ - /* case SCARD_E_UNKNOWN_RES_MNG: */ - /* case SCARD_E_NO_SUCH_CERTIFICATE: */ - /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */ - case SCARD_E_NO_READERS_AVAILABLE: - msg = "Cannot find a smart card reader."; - break; - /* case SCARD_E_COMM_DATA_LOST: */ - /* case SCARD_E_NO_KEY_CONTAINER: */ - /* case SCARD_E_SERVER_TOO_BUSY: */ - case SCARD_W_UNSUPPORTED_CARD: - msg = "Card is not supported."; - break; - case SCARD_W_UNRESPONSIVE_CARD: - msg = "Card is unresponsive."; - break; - case SCARD_W_UNPOWERED_CARD: - msg = "Card is unpowered."; - break; - case SCARD_W_RESET_CARD: - msg = "Card was reset."; - break; - case SCARD_W_REMOVED_CARD: - msg = "Card was removed."; - break; - /* case SCARD_W_SECURITY_VIOLATION: */ - /* case SCARD_W_WRONG_CHV: */ - /* case SCARD_W_CHV_BLOCKED: */ - /* case SCARD_W_EOF: */ - /* case SCARD_W_CANCELLED_BY_USER: */ - /* case SCARD_W_CARD_NOT_AUTHENTICATED: */ - - case SCARD_E_UNSUPPORTED_FEATURE: - msg = "Feature not supported."; - break; - default: - (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", - pcscError); - }; - - if (msg) - (void)strncpy(strError, msg, sizeof(strError)); - else - (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", - pcscError); - - /* add a null byte */ - strError[sizeof(strError) - 1] = '\0'; - - return strError; + static char strError[75]; + const char *msg = NULL; + + switch (pcscError) { + case SCARD_S_SUCCESS: + msg = "Command successful."; + break; + case SCARD_F_INTERNAL_ERROR: + msg = "Internal error."; + break; + case SCARD_E_CANCELLED: + msg = "Command cancelled."; + break; + case SCARD_E_INVALID_HANDLE: + msg = "Invalid handle."; + break; + case SCARD_E_INVALID_PARAMETER: + msg = "Invalid parameter given."; + break; + case SCARD_E_INVALID_TARGET: + msg = "Invalid target given."; + break; + case SCARD_E_NO_MEMORY: + msg = "Not enough memory."; + break; + case SCARD_F_WAITED_TOO_LONG: + msg = "Waited too long."; + break; + case SCARD_E_INSUFFICIENT_BUFFER: + msg = "Insufficient buffer."; + break; + case SCARD_E_UNKNOWN_READER: + msg = "Unknown reader specified."; + break; + case SCARD_E_TIMEOUT: + msg = "Command timeout."; + break; + case SCARD_E_SHARING_VIOLATION: + msg = "Sharing violation."; + break; + case SCARD_E_NO_SMARTCARD: + msg = "No smart card inserted."; + break; + case SCARD_E_UNKNOWN_CARD: + msg = "Unknown card."; + break; + case SCARD_E_CANT_DISPOSE: + msg = "Cannot dispose handle."; + break; + case SCARD_E_PROTO_MISMATCH: + msg = "Card protocol mismatch."; + break; + case SCARD_E_NOT_READY: + msg = "Subsystem not ready."; + break; + case SCARD_E_INVALID_VALUE: + msg = "Invalid value given."; + break; + case SCARD_E_SYSTEM_CANCELLED: + msg = "System cancelled."; + break; + case SCARD_F_COMM_ERROR: + msg = "RPC transport error."; + break; + case SCARD_F_UNKNOWN_ERROR: + msg = "Unknown error."; + break; + case SCARD_E_INVALID_ATR: + msg = "Invalid ATR."; + break; + case SCARD_E_NOT_TRANSACTED: + msg = "Transaction failed."; + break; + case SCARD_E_READER_UNAVAILABLE: + msg = "Reader is unavailable."; + break; + /* case SCARD_P_SHUTDOWN: */ + case SCARD_E_PCI_TOO_SMALL: + msg = "PCI struct too small."; + break; + case SCARD_E_READER_UNSUPPORTED: + msg = "Reader is unsupported."; + break; + case SCARD_E_DUPLICATE_READER: + msg = "Reader already exists."; + break; + case SCARD_E_CARD_UNSUPPORTED: + msg = "Card is unsupported."; + break; + case SCARD_E_NO_SERVICE: + msg = "Service not available."; + break; + case SCARD_E_SERVICE_STOPPED: + msg = "Service was stopped."; + break; + /* case SCARD_E_UNEXPECTED: */ + /* case SCARD_E_ICC_CREATEORDER: */ + /* case SCARD_E_UNSUPPORTED_FEATURE: */ + /* case SCARD_E_DIR_NOT_FOUND: */ + /* case SCARD_E_NO_DIR: */ + /* case SCARD_E_NO_FILE: */ + /* case SCARD_E_NO_ACCESS: */ + /* case SCARD_E_WRITE_TOO_MANY: */ + /* case SCARD_E_BAD_SEEK: */ + /* case SCARD_E_INVALID_CHV: */ + /* case SCARD_E_UNKNOWN_RES_MNG: */ + /* case SCARD_E_NO_SUCH_CERTIFICATE: */ + /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */ + case SCARD_E_NO_READERS_AVAILABLE: + msg = "Cannot find a smart card reader."; + break; + /* case SCARD_E_COMM_DATA_LOST: */ + /* case SCARD_E_NO_KEY_CONTAINER: */ + /* case SCARD_E_SERVER_TOO_BUSY: */ + case SCARD_W_UNSUPPORTED_CARD: + msg = "Card is not supported."; + break; + case SCARD_W_UNRESPONSIVE_CARD: + msg = "Card is unresponsive."; + break; + case SCARD_W_UNPOWERED_CARD: + msg = "Card is unpowered."; + break; + case SCARD_W_RESET_CARD: + msg = "Card was reset."; + break; + case SCARD_W_REMOVED_CARD: + msg = "Card was removed."; + break; + /* case SCARD_W_SECURITY_VIOLATION: */ + /* case SCARD_W_WRONG_CHV: */ + /* case SCARD_W_CHV_BLOCKED: */ + /* case SCARD_W_EOF: */ + /* case SCARD_W_CANCELLED_BY_USER: */ + /* case SCARD_W_CARD_NOT_AUTHENTICATED: */ + + case SCARD_E_UNSUPPORTED_FEATURE: + msg = "Feature not supported."; + break; + default: + (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", + pcscError); + }; + + if (msg) + (void)strncpy(strError, msg, sizeof(strError)); + else + (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", + pcscError); + + /* add a null byte */ + strError[sizeof(strError) - 1] = '\0'; + + return strError; } const char * pcsc_strerror(const struct nfc_device *pnd) { - return stringify_error(DRIVER_DATA(pnd)->last_error); + return stringify_error(DRIVER_DATA(pnd)->last_error); } int pcsc_initiator_init(struct nfc_device *pnd) { - (void) pnd; - return NFC_SUCCESS; + (void) pnd; + return NFC_SUCCESS; } int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) { - uint8_t atr[MAX_ATR_SIZE]; - uint8_t uid[10]; - int target_present; - size_t atr_len = sizeof atr; - - (void) pbtInitData; - (void) szInitData; - - if (nm.nbr != pcsc_supported_brs[0] && nm.nbr != pcsc_supported_brs[1]) - return NFC_EINVARG; - - pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); - if (pnd->last_error != NFC_SUCCESS) - return pnd->last_error; - - if (!target_present) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); - return NFC_ENOTSUCHDEV; - } - - uint8_t icc_type = pcsc_get_icc_type(pnd); - int uid_len = pcsc_get_uid(pnd, uid, sizeof uid); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Type of target not supported"); - return NFC_EDEVNOTSUPP; - } - - pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD); - if (pnd->last_error != NFC_SUCCESS) - return pnd->last_error; - - return 1; + uint8_t atr[MAX_ATR_SIZE]; + uint8_t uid[10]; + int target_present; + size_t atr_len = sizeof atr; + + (void) pbtInitData; + (void) szInitData; + + if (nm.nbr != pcsc_supported_brs[0] && nm.nbr != pcsc_supported_brs[1]) + return NFC_EINVARG; + + pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (!target_present) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); + return NFC_ENOTSUCHDEV; + } + + uint8_t icc_type = pcsc_get_icc_type(pnd); + int uid_len = pcsc_get_uid(pnd, uid, sizeof uid); + if (pcsc_props_to_target(pnd, icc_type, atr, atr_len, uid, uid_len, nm.nmt, pnt) != NFC_SUCCESS) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Type of target not supported"); + return NFC_EDEVNOTSUPP; + } + + pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + return 1; } int pcsc_initiator_deselect_target(struct nfc_device *pnd) { - pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD); - return pnd->last_error; + pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD); + return pnd->last_error; } int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout) { - size_t resp_len = szRx; - - // FIXME: timeout is not handled - (void) timeout; - - if (pnd->last_error != NFC_SUCCESS) - return pnd->last_error; - - return resp_len; + size_t resp_len = szRx; + + // FIXME: timeout is not handled + (void) timeout; + + if (is_pcsc_reader_vendor_feitian(pnd)){ + LOG_HEX(NFC_LOG_GROUP_COM, "not feitian pcsc apdu send", pbtTx, szTx); + + uint8_t apdu_data[256]; + uint8_t resp[256 + 2]; + size_t send_size = 0; + if (pbtTx[0] == 0x30) {//read data + apdu_data[0] = 0xFF; + apdu_data[1] = 0xB0; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = 0x10; + send_size = 5; + } else if (pbtTx[0] == 0xA0 || pbtTx[0] == 0xA2) {//write data + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD6; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = szTx - 2; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A){//Auth command + apdu_data[0] = 0xFF; + apdu_data[1] = 0x86; + apdu_data[2] = 0x00; + apdu_data[3] = 0x00; + apdu_data[4] = 0x05; + apdu_data[5] = 0x01; + apdu_data[6] = 0x00; + apdu_data[7] = pbtTx[1];//block index + apdu_data[8] = pbtTx[0];//type a or type b + apdu_data[9] = 0x01; + send_size = 10; + } else if (pbtTx[0] == 0xB0 ){//TRANSFER cmd + ; + } else if (pbtTx[0] == 0xC0){//DECREMENT cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD7; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1];//block index + apdu_data[4] = 0x05; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0xC1){//INCREMENT cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD7; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1];//block index + apdu_data[4] = 0x05; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0xC2){//STORE cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD8; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = szTx - 2; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else {//other cmd + memcpy(apdu_data, pbtTx, szTx); + send_size = szTx; + } + LOG_HEX(NFC_LOG_GROUP_COM, "feitian pcsc apdu send:", apdu_data, send_size); + pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len); + LOG_HEX(NFC_LOG_GROUP_COM, "feitian pcsc apdu received:", resp, resp_len); + + memcpy(pbtRx, resp, resp_len); + // pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); + // LOG_HEX(NFC_LOG_GROUP_COM, "apdu return to client:", pbtRx, resp_len); + } else { + pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); + } + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + return resp_len; } int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { - uint8_t atr[MAX_ATR_SIZE]; - int target_present; - size_t atr_len = sizeof atr; - nfc_target nt; - - pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); - if (pnd->last_error != NFC_SUCCESS) - return pnd->last_error; - - if (!target_present) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); - return NFC_ENOTSUCHDEV; - } - - if (pnt) { - || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements"); - return NFC_ENOTSUCHDEV; + uint8_t atr[MAX_ATR_SIZE]; + int target_present; + size_t atr_len = sizeof atr; + nfc_target nt; + + pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (!target_present) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); + return NFC_ENOTSUCHDEV; } - } - return NFC_SUCCESS; + + if (pnt) { + if (pcsc_props_to_target(pnd, ICC_TYPE_UNKNOWN, atr, atr_len, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS + || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements"); + return NFC_ENOTSUCHDEV; + } + } + return NFC_SUCCESS; } int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable) { - (void) pnd; - switch (property) { - case NP_INFINITE_SELECT: - // ignore - return NFC_SUCCESS; - case NP_AUTO_ISO14443_4: - case NP_EASY_FRAMING: - case NP_FORCE_ISO14443_A: - case NP_HANDLE_CRC: - case NP_HANDLE_PARITY: - case NP_FORCE_SPEED_106: - if (bEnable == true) - return NFC_SUCCESS; - break; - case NP_ACCEPT_INVALID_FRAMES: - case NP_ACCEPT_MULTIPLE_FRAMES: - if (bEnable == false) - return NFC_SUCCESS; - break; - case NP_ACTIVATE_FIELD: - if (bEnable == false) { - struct pcsc_data *data = pnd->driver_data; - pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD); - } - return NFC_SUCCESS; - default: - break; - } - return NFC_EDEVNOTSUPP; + (void) pnd; + switch (property) { + case NP_INFINITE_SELECT: + // ignore + return NFC_SUCCESS; + case NP_AUTO_ISO14443_4: + { + if (is_pcsc_reader_vendor_feitian(pnd)) + { + //ignore + return NFC_SUCCESS; + } + } + case NP_EASY_FRAMING: + { + if (is_pcsc_reader_vendor_feitian(pnd)) + { + //ignore + return NFC_SUCCESS; + } + } + case NP_FORCE_ISO14443_A: + case NP_HANDLE_CRC: + case NP_HANDLE_PARITY: + case NP_FORCE_SPEED_106: + if (bEnable == true) + return NFC_SUCCESS; + break; + case NP_ACCEPT_INVALID_FRAMES: + case NP_ACCEPT_MULTIPLE_FRAMES: + if (bEnable == false) + return NFC_SUCCESS; + break; + case NP_ACTIVATE_FIELD: + if (bEnable == false) { + struct pcsc_data *data = pnd->driver_data; + pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD); + } + return NFC_SUCCESS; + default: + break; + } + return NFC_EDEVNOTSUPP; } int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) { - (void) pnd; - if (mode == N_TARGET || NULL == supported_mt) - return NFC_EINVARG; - *supported_mt = pcsc_supported_mts; - return NFC_SUCCESS; + (void) pnd; + if (mode == N_TARGET || NULL == supported_mt) + return NFC_EINVARG; + *supported_mt = pcsc_supported_mts; + return NFC_SUCCESS; } int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) { - (void) pnd; - (void) nmt; - if (mode == N_TARGET || NULL == supported_br) - return NFC_EINVARG; - *supported_br = pcsc_supported_brs; - return NFC_SUCCESS; + (void) pnd; + (void) nmt; + if (mode == N_TARGET || NULL == supported_br) + return NFC_EINVARG; + *supported_br = pcsc_supported_brs; + return NFC_SUCCESS; } int pcsc_get_information_about(nfc_device *pnd, char **pbuf) { - struct pcsc_data *data = pnd->driver_data; - LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; - DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, - type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; - int res = NFC_SUCCESS; - SCARDCONTEXT *pscc; - - if (!(pscc = pcsc_get_scardcontext())) { - pnd->last_error = NFC_ESOFT; - return pnd->last_error; - } - - SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len); - SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len); - SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len); - SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len); - - *pbuf = malloc(name_len + type_len + version_len + serial_len + 30); - if (! *pbuf) { - res = NFC_ESOFT; - goto error; - } - sprintf((char *) *pbuf, - "%s" // model - "%s%s" // version - " (%s)" // vendor - "%s%s\n" // serial - , - name && name_len > 0 && name[0] != '\0' - ? (char *)name : "unknown model", - version && version_len > 0 && version[0] != '\0' - ? " " : "", version_len > 0 ? (char *)version : "", - type && type_len > 0 && type[0] != '\0' - ? (char *)type : "unknown vendor", - serial && serial_len > 0 && serial[0] != '\0' - ? "\nserial: " : "", serial_len > 0 ? (char *)serial : ""); - + struct pcsc_data *data = pnd->driver_data; + LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; + DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, + type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; + int res = NFC_SUCCESS; + SCARDCONTEXT *pscc; + + if (!(pscc = pcsc_get_scardcontext())) { + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len); + + *pbuf = malloc(name_len + type_len + version_len + serial_len + 30); + if (! *pbuf) { + res = NFC_ESOFT; + goto error; + } + sprintf((char *) *pbuf, + "%s" // model + "%s%s" // version + " (%s)" // vendor + "%s%s\n" // serial + , + name && name_len > 0 && name[0] != '\0' + ? (char *)name : "unknown model", + version && version_len > 0 && version[0] != '\0' + ? " " : "", version_len > 0 ? (char *)version : "", + type && type_len > 0 && type[0] != '\0' + ? (char *)type : "unknown vendor", + serial && serial_len > 0 && serial[0] != '\0' + ? "\nserial: " : "", serial_len > 0 ? (char *)serial : ""); + error: -// SCardFreeMemory function not supported in macOS. + // SCardFreeMemory function not supported in macOS. #if defined(__APPLE__) if (name != NULL){ free(name); @@ -787,44 +1015,43 @@ error: SCardFreeMemory(*pscc, version); SCardFreeMemory(*pscc, version); SCardFreeMemory(*pscc, serial); SCardFreeMemory(*pscc, serial); #endif - - pnd->last_error = res; - return pnd->last_error; + + pnd->last_error = res; + return pnd->last_error; } const struct nfc_driver pcsc_driver = { - .name = PCSC_DRIVER_NAME, - .scan = pcsc_scan, - .open = pcsc_open, - .close = pcsc_close, - .strerror = pcsc_strerror, - - .initiator_init = pcsc_initiator_init, - .initiator_init_secure_element = NULL, // No secure-element support - .initiator_select_passive_target = pcsc_initiator_select_passive_target, - .initiator_poll_target = NULL, - .initiator_select_dep_target = NULL, - .initiator_deselect_target = NULL, - .initiator_transceive_bytes = pcsc_initiator_transceive_bytes, - .initiator_transceive_bits = NULL, - .initiator_transceive_bytes_timed = NULL, - .initiator_transceive_bits_timed = NULL, - .initiator_target_is_present = pcsc_initiator_target_is_present, - - .target_init = NULL, - .target_send_bytes = NULL, - .target_receive_bytes = NULL, - .target_send_bits = NULL, - .target_receive_bits = NULL, - - .device_set_property_bool = pcsc_device_set_property_bool, - .device_set_property_int = NULL, - .get_supported_modulation = pcsc_get_supported_modulation, - .get_supported_baud_rate = pcsc_get_supported_baud_rate, - .device_get_information_about = pcsc_get_information_about, - - .abort_command = NULL, // Abort is not supported in this driver - .idle = NULL, - .powerdown = NULL, + .name = PCSC_DRIVER_NAME, + .scan = pcsc_scan, + .open = pcsc_open, + .close = pcsc_close, + .strerror = pcsc_strerror, + + .initiator_init = pcsc_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support + .initiator_select_passive_target = pcsc_initiator_select_passive_target, + .initiator_poll_target = NULL, + .initiator_select_dep_target = NULL, + .initiator_deselect_target = NULL, + .initiator_transceive_bytes = pcsc_initiator_transceive_bytes, + .initiator_transceive_bits = NULL, + .initiator_transceive_bytes_timed = NULL, + .initiator_transceive_bits_timed = NULL, + .initiator_target_is_present = pcsc_initiator_target_is_present, + + .target_init = NULL, + .target_send_bytes = NULL, + .target_receive_bytes = NULL, + .target_send_bits = NULL, + .target_receive_bits = NULL, + + .device_set_property_bool = pcsc_device_set_property_bool, + .device_set_property_int = NULL, + .get_supported_modulation = pcsc_get_supported_modulation, + .get_supported_baud_rate = pcsc_get_supported_baud_rate, + .device_get_information_about = pcsc_get_information_about, + + .abort_command = NULL, // Abort is not supported in this driver + .idle = NULL, + .powerdown = NULL, }; -