cleanup
This commit is contained in:
parent
8e7a8e1b61
commit
6f793da1c1
1 changed files with 119 additions and 63 deletions
|
@ -109,35 +109,92 @@ pcsc_free_scardcontext(void)
|
|||
#define ICC_TYPE_14443A 5
|
||||
#define ICC_TYPE_14443B 6
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
DRIVER_DATA(pnd)->last_error = SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen);
|
||||
data->last_error = SCardGetAttrib(data->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen);
|
||||
return it;
|
||||
}
|
||||
|
||||
int pcsc_get_uid(struct nfc_device *pnd, uint8_t *puid, size_t szuid)
|
||||
int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len)
|
||||
{
|
||||
uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}, data[256 + 2];
|
||||
DWORD dwRxLen = sizeof data;
|
||||
const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
|
||||
uint8_t resp[256 + 2];
|
||||
size_t resp_len = sizeof resp;
|
||||
|
||||
LOG_HEX(NFC_LOG_GROUP_COM, "TX", get_data, sizeof get_data);
|
||||
DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), get_data, sizeof get_data, NULL, data, &dwRxLen);
|
||||
if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS)
|
||||
|| dwRxLen < 2) {
|
||||
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_EIO;
|
||||
pnd->last_error = NFC_EDEVNOTSUPP;
|
||||
return pnd->last_error;
|
||||
}
|
||||
LOG_HEX(NFC_LOG_GROUP_COM, "RX", data, dwRxLen);
|
||||
if (szuid < (size_t) dwRxLen - 2) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Malformed response code");
|
||||
pnd->last_error = NFC_EINVARG;
|
||||
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(puid, data, dwRxLen - 2);
|
||||
return dwRxLen - 2;
|
||||
|
||||
memcpy(uid, resp, resp_len - 2);
|
||||
return resp_len - 2;
|
||||
}
|
||||
|
||||
int pcsc_props_to_target(uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt)
|
||||
|
@ -530,84 +587,81 @@ int pcsc_initiator_init(struct nfc_device *pnd)
|
|||
|
||||
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 pbAtr[MAX_ATR_SIZE];
|
||||
uint8_t atr[MAX_ATR_SIZE];
|
||||
uint8_t uid[10];
|
||||
DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr;
|
||||
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;
|
||||
DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen);
|
||||
if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS
|
||||
&& DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD)
|
||||
|| !(dwState & SCARD_PRESENT)) {
|
||||
|
||||
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 it = pcsc_get_icc_type(pnd);
|
||||
int szuid = pcsc_get_uid(pnd, uid, sizeof uid);
|
||||
if (pcsc_props_to_target(it, pbAtr, dwAtrLen, uid, szuid, nm.nmt, pnt) != NFC_SUCCESS
|
||||
|| (DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol))) != SCARD_S_SUCCESS) {
|
||||
// We can not reconnect to this device.
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed");
|
||||
return NFC_EIO;
|
||||
|
||||
uint8_t icc_type = pcsc_get_icc_type(pnd);
|
||||
int uid_len = pcsc_get_uid(pnd, uid, sizeof uid);
|
||||
if (pcsc_props_to_target(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;
|
||||
}
|
||||
DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_SHARED;
|
||||
|
||||
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)
|
||||
{
|
||||
DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
|
||||
if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS
|
||||
&& DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) {
|
||||
// We can not reconnect to this device.
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed");
|
||||
return NFC_EIO;
|
||||
}
|
||||
DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT;
|
||||
return NFC_SUCCESS;
|
||||
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;
|
||||
|
||||
DWORD dwRxLen = szRx;
|
||||
|
||||
LOG_HEX(NFC_LOG_GROUP_COM, "TX", pbtTx, szTx);
|
||||
DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), pbtTx, szTx, NULL, pbtRx, &dwRxLen);
|
||||
if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed");
|
||||
pnd->last_error = NFC_EIO;
|
||||
pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len);
|
||||
if (pnd->last_error != NFC_SUCCESS)
|
||||
return pnd->last_error;
|
||||
}
|
||||
LOG_HEX(NFC_LOG_GROUP_COM, "RX", pbtRx, dwRxLen);
|
||||
|
||||
return dwRxLen;
|
||||
return resp_len;
|
||||
}
|
||||
|
||||
int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
|
||||
{
|
||||
uint8_t pbAtr[MAX_ATR_SIZE];
|
||||
DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr;
|
||||
uint8_t atr[MAX_ATR_SIZE];
|
||||
int target_present;
|
||||
size_t atr_len = sizeof atr;
|
||||
nfc_target nt;
|
||||
|
||||
DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen);
|
||||
if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS
|
||||
&& DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD)
|
||||
|| !(dwState & SCARD_PRESENT)) {
|
||||
pnd->last_error = NFC_EIO;
|
||||
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) {
|
||||
if (pcsc_props_to_target(ICC_TYPE_UNKNOWN, pbAtr, dwAtrLen, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS
|
||||
if (pcsc_props_to_target(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) {
|
||||
pnd->last_error = NFC_EINVARG;
|
||||
return pnd->last_error;
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements");
|
||||
return NFC_ENOTSUCHDEV;
|
||||
}
|
||||
}
|
||||
return NFC_SUCCESS;
|
||||
|
@ -636,7 +690,8 @@ int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property pro
|
|||
break;
|
||||
case NP_ACTIVATE_FIELD:
|
||||
if (bEnable == false) {
|
||||
SCardReconnect(DRIVER_DATA(pnd)->hCard, DRIVER_DATA(pnd)->dwShareMode, DRIVER_DATA(pnd)->ioCard.dwProtocol, SCARD_RESET_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
|
||||
struct pcsc_data *data = pnd->driver_data;
|
||||
pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD);
|
||||
}
|
||||
return NFC_SUCCESS;
|
||||
default:
|
||||
|
@ -667,6 +722,7 @@ int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode mode, co
|
|||
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;
|
||||
|
@ -678,10 +734,10 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf)
|
|||
return pnd->last_error;
|
||||
}
|
||||
|
||||
SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len);
|
||||
SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len);
|
||||
SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len);
|
||||
SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len);
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue