Skip to content

Commit 678dd75

Browse files
committed
Implement PC/SC compatibility helpers for non-PCSCLite builds
Linux and MacOS are both supported by pcsc-lite, but unfortunately there is no pcsc-lite package for MSYS2 and Windows does not provide the reader.h header.
1 parent ab3e72f commit 678dd75

File tree

2 files changed

+103
-20
lines changed

2 files changed

+103
-20
lines changed

src/pcsc.c

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@
2222
#include "pcsc.h"
2323

2424
#include <winscard.h>
25+
#ifdef USE_PCSCLITE
26+
// Only PCSCLite provides reader.h
2527
#include <reader.h>
28+
#endif
29+
// Compatibility helpers must not conflict with winscard.h or reader.h
30+
#include "pcsc_compat.h"
2631

2732
#include <stdbool.h>
2833
#include <stdint.h>
@@ -37,16 +42,6 @@
3742
#include <winsock.h>
3843
#endif
3944

40-
#ifndef USE_PCSCLITE
41-
// Only PCSCLite provides pcsc_stringify_error()
42-
static const char* pcsc_stringify_error(unsigned int result)
43-
{
44-
static char str[16];
45-
snprintf(str, sizeof(str), "0x%08X", result);
46-
return str;
47-
}
48-
#endif
49-
5045
struct pcsc_t {
5146
SCARDCONTEXT context;
5247

@@ -60,23 +55,19 @@ struct pcsc_t {
6055

6156
struct pcsc_reader_features_t {
6257
// Populated by SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)
63-
uint8_t buf[MAX_BUFFER_SIZE];
58+
uint8_t buf[PCSC_MAX_BUFFER_SIZE];
6459
DWORD buf_len;
6560

6661
// Populated by SCardControl(IFD_PIN_PROPERTIES)
6762
PIN_PROPERTIES_STRUCTURE pin_properties;
6863
DWORD pin_properties_len;
6964

7065
// Populated by SCardControl(IFD_DISPLAY_PROPERTIES)
71-
struct {
72-
uint16_t wLcdMaxCharacters;
73-
uint16_t wLcdMaxLines;
74-
} __attribute__((packed))
75-
display_properties;
66+
DISPLAY_PROPERTIES_STRUCTURE display_properties;
7667
DWORD display_properties_len;
7768

7869
// Populated by SCardControl(GET_TLV_PROPERTIES)
79-
uint8_t properties[MAX_BUFFER_SIZE];
70+
uint8_t properties[PCSC_MAX_BUFFER_SIZE];
8071
DWORD properties_len;
8172
};
8273

@@ -248,7 +239,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader)
248239
++pcsc_tlv;
249240
}
250241

251-
r = pcsc_reader_get_feature(reader, FEATURE_IFD_PIN_PROPERTIES, &control_code);
242+
r = pcsc_reader_get_feature(reader, PCSC_FEATURE_IFD_PIN_PROPERTIES, &control_code);
252243
if (r < 0) {
253244
r = -6;
254245
goto exit;
@@ -277,7 +268,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader)
277268
}
278269
}
279270

280-
r = pcsc_reader_get_feature(reader, FEATURE_IFD_DISPLAY_PROPERTIES, &control_code);
271+
r = pcsc_reader_get_feature(reader, PCSC_FEATURE_IFD_DISPLAY_PROPERTIES, &control_code);
281272
if (r < 0) {
282273
r = -9;
283274
goto exit;
@@ -306,7 +297,7 @@ static int pcsc_reader_populate_features(struct pcsc_reader_t* reader)
306297
}
307298
}
308299

309-
r = pcsc_reader_get_feature(reader, FEATURE_GET_TLV_PROPERTIES, &control_code);
300+
r = pcsc_reader_get_feature(reader, PCSC_FEATURE_GET_TLV_PROPERTIES, &control_code);
310301
if (r < 0) {
311302
r = -12;
312303
goto exit;

src/pcsc_compat.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @file pcsc_compat.h
3+
* @brief PC/SC compatibility helpers
4+
*
5+
* Copyright (c) 2024 Leon Lynch
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library. If not, see
19+
* <https://www.gnu.org/licenses/>.
20+
*/
21+
22+
#ifndef PCSC_COMPAT_H
23+
#define PCSC_COMPAT_H
24+
25+
#include <sys/cdefs.h>
26+
#include <stdint.h>
27+
#include <stdio.h>
28+
29+
__BEGIN_DECLS
30+
31+
#if !defined(SCARD_CTL_CODE) && defined(CTL_CODE)
32+
// Not all implementations define SCARD_CTL_CODE but it can be derived
33+
// from CTL_CODE when available
34+
#define SCARD_CTL_CODE(code) CTL_CODE(FILE_DEVICE_SMARTCARD, (code), METHOD_BUFFERED, FILE_ANY_ACCESS)
35+
#endif
36+
37+
// See PC/SC Part 10 Rev 2.02.09, 2.2
38+
#ifndef CM_IOCTL_GET_FEATURE_REQUEST
39+
#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
40+
#endif
41+
42+
// See PC/SC Part 10 Rev 2.02.09, 2.3
43+
#define PCSC_FEATURE_IFD_PIN_PROPERTIES (0x0A) ///< Interface Device (IFD) PIN handling properties
44+
#define PCSC_FEATURE_IFD_DISPLAY_PROPERTIES (0x11) ///< Interface Device (IFD) display properties
45+
#define PCSC_FEATURE_GET_TLV_PROPERTIES (0x12) ///< Interface Device (IFD) properties in Tag-Length-Value (TLV) form
46+
47+
#ifdef USE_PCSCLITE
48+
49+
#define PCSC_MAX_BUFFER_SIZE (MAX_BUFFER_SIZE)
50+
51+
#else // !USE_PCSCLITE
52+
53+
#define PCSC_MAX_BUFFER_SIZE (264)
54+
55+
// See PC/SC Part 10 Rev 2.02.09, 2.2
56+
typedef struct
57+
{
58+
uint8_t tag;
59+
uint8_t length;
60+
uint32_t value;
61+
} __attribute__((packed))
62+
PCSC_TLV_STRUCTURE;
63+
64+
// See PC/SC Part 10 Rev 2.02.09, 2.6.8
65+
typedef struct {
66+
uint16_t wLcdLayout;
67+
uint8_t bEntryValidationCondition;
68+
uint8_t bTimeOut2;
69+
} __attribute__((packed))
70+
PIN_PROPERTIES_STRUCTURE;
71+
72+
// Only PCSCLite provides pcsc_stringify_error()
73+
static const char* pcsc_stringify_error(unsigned int result)
74+
{
75+
static char str[16];
76+
snprintf(str, sizeof(str), "0x%08X", result);
77+
return str;
78+
}
79+
80+
#endif // USE_PCSCLITE
81+
82+
// PCSCLite does not provide DISPLAY_PROPERTIES_STRUCTURE
83+
// See PC/SC Part 10 Rev 2.02.09, 2.6.9
84+
typedef struct {
85+
uint16_t wLcdMaxCharacters;
86+
uint16_t wLcdMaxLines;
87+
} __attribute__((packed))
88+
DISPLAY_PROPERTIES_STRUCTURE;
89+
90+
__END_DECLS
91+
92+
#endif

0 commit comments

Comments
 (0)