diff --git a/src/pcsc.c b/src/pcsc.c index afb5f67..3c57162 100644 --- a/src/pcsc.c +++ b/src/pcsc.c @@ -22,7 +22,12 @@ #include "pcsc.h" #include +#ifdef USE_PCSCLITE +// Only PCSCLite provides reader.h #include +#endif +// Compatibility helpers must not conflict with winscard.h or reader.h +#include "pcsc_compat.h" #include #include @@ -37,16 +42,6 @@ #include #endif -#ifndef USE_PCSCLITE -// Only PCSCLite provides pcsc_stringify_error() -static const char* pcsc_stringify_error(unsigned int result) -{ - static char str[16]; - snprintf(str, sizeof(str), "0x%08X", result); - return str; -} -#endif - struct pcsc_t { SCARDCONTEXT context; @@ -60,7 +55,7 @@ struct pcsc_t { struct pcsc_reader_features_t { // Populated by SCardControl(CM_IOCTL_GET_FEATURE_REQUEST) - uint8_t buf[MAX_BUFFER_SIZE]; + uint8_t buf[PCSC_MAX_BUFFER_SIZE]; DWORD buf_len; // Populated by SCardControl(IFD_PIN_PROPERTIES) @@ -68,15 +63,11 @@ struct pcsc_reader_features_t { DWORD pin_properties_len; // Populated by SCardControl(IFD_DISPLAY_PROPERTIES) - struct { - uint16_t wLcdMaxCharacters; - uint16_t wLcdMaxLines; - } __attribute__((packed)) - display_properties; + DISPLAY_PROPERTIES_STRUCTURE display_properties; DWORD display_properties_len; // Populated by SCardControl(GET_TLV_PROPERTIES) - uint8_t properties[MAX_BUFFER_SIZE]; + uint8_t properties[PCSC_MAX_BUFFER_SIZE]; DWORD properties_len; }; @@ -248,7 +239,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader) ++pcsc_tlv; } - r = pcsc_reader_get_feature(reader, FEATURE_IFD_PIN_PROPERTIES, &control_code); + r = pcsc_reader_get_feature(reader, PCSC_FEATURE_IFD_PIN_PROPERTIES, &control_code); if (r < 0) { r = -6; goto exit; @@ -277,7 +268,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader) } } - r = pcsc_reader_get_feature(reader, FEATURE_IFD_DISPLAY_PROPERTIES, &control_code); + r = pcsc_reader_get_feature(reader, PCSC_FEATURE_IFD_DISPLAY_PROPERTIES, &control_code); if (r < 0) { r = -9; goto exit; @@ -306,7 +297,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader) } } - r = pcsc_reader_get_feature(reader, FEATURE_GET_TLV_PROPERTIES, &control_code); + r = pcsc_reader_get_feature(reader, PCSC_FEATURE_GET_TLV_PROPERTIES, &control_code); if (r < 0) { r = -12; goto exit; diff --git a/src/pcsc_compat.h b/src/pcsc_compat.h new file mode 100644 index 0000000..754d58b --- /dev/null +++ b/src/pcsc_compat.h @@ -0,0 +1,92 @@ +/** + * @file pcsc_compat.h + * @brief PC/SC compatibility helpers + * + * Copyright (c) 2024 Leon Lynch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef PCSC_COMPAT_H +#define PCSC_COMPAT_H + +#include +#include +#include + +__BEGIN_DECLS + +#if !defined(SCARD_CTL_CODE) && defined(CTL_CODE) +// Not all implementations define SCARD_CTL_CODE but it can be derived +// from CTL_CODE when available +#define SCARD_CTL_CODE(code) CTL_CODE(FILE_DEVICE_SMARTCARD, (code), METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + +// See PC/SC Part 10 Rev 2.02.09, 2.2 +#ifndef CM_IOCTL_GET_FEATURE_REQUEST +#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) +#endif + +// See PC/SC Part 10 Rev 2.02.09, 2.3 +#define PCSC_FEATURE_IFD_PIN_PROPERTIES (0x0A) ///< Interface Device (IFD) PIN handling properties +#define PCSC_FEATURE_IFD_DISPLAY_PROPERTIES (0x11) ///< Interface Device (IFD) display properties +#define PCSC_FEATURE_GET_TLV_PROPERTIES (0x12) ///< Interface Device (IFD) properties in Tag-Length-Value (TLV) form + +#ifdef USE_PCSCLITE + +#define PCSC_MAX_BUFFER_SIZE (MAX_BUFFER_SIZE) + +#else // !USE_PCSCLITE + +#define PCSC_MAX_BUFFER_SIZE (264) + +// See PC/SC Part 10 Rev 2.02.09, 2.2 +typedef struct +{ + uint8_t tag; + uint8_t length; + uint32_t value; +} __attribute__((packed)) +PCSC_TLV_STRUCTURE; + +// See PC/SC Part 10 Rev 2.02.09, 2.6.8 +typedef struct { + uint16_t wLcdLayout; + uint8_t bEntryValidationCondition; + uint8_t bTimeOut2; +} __attribute__((packed)) +PIN_PROPERTIES_STRUCTURE; + +// Only PCSCLite provides pcsc_stringify_error() +static const char* pcsc_stringify_error(unsigned int result) +{ + static char str[16]; + snprintf(str, sizeof(str), "0x%08X", result); + return str; +} + +#endif // USE_PCSCLITE + +// PCSCLite does not provide DISPLAY_PROPERTIES_STRUCTURE +// See PC/SC Part 10 Rev 2.02.09, 2.6.9 +typedef struct { + uint16_t wLcdMaxCharacters; + uint16_t wLcdMaxLines; +} __attribute__((packed)) +DISPLAY_PROPERTIES_STRUCTURE; + +__END_DECLS + +#endif