smartcard 0.2.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,207 @@
1
+ /*
2
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3
+ *
4
+ * Copyright (C) 1999-2005
5
+ * David Corcoran <corcoran@linuxnet.com>
6
+ * Ludovic Rousseau <ludovic.rousseau@free.fr>
7
+ *
8
+ * $Id: reader.h.in 2572 2007-06-20 07:24:35Z rousseau $
9
+ */
10
+
11
+ /**
12
+ * @file
13
+ * @brief This keeps a list of defines shared between the driver and the application
14
+ */
15
+
16
+ #ifndef __reader_h__
17
+ #define __reader_h__
18
+
19
+ /*
20
+ * Tags for requesting card and reader attributes
21
+ */
22
+
23
+ #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
24
+
25
+ #define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */
26
+ #define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */
27
+ #define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */
28
+ #define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */
29
+ #define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */
30
+ #define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */
31
+ #define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */
32
+ #define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */
33
+ #define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */
34
+ #define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */
35
+
36
+ #define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100)
37
+ #define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101)
38
+ #define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102)
39
+ #define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103)
40
+ #define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110)
41
+ #define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120)
42
+ #define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121)
43
+ #define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122)
44
+ #define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123)
45
+ #define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124)
46
+ #define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125)
47
+ #define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126)
48
+ #define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131)
49
+ #define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140)
50
+ #define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142)
51
+ #define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150)
52
+
53
+ #define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201)
54
+ #define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202)
55
+ #define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203)
56
+ #define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204)
57
+ #define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205)
58
+ #define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206)
59
+ #define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207)
60
+ #define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208)
61
+ #define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209)
62
+ #define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a)
63
+ #define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b)
64
+ #define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c)
65
+
66
+ #define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300)
67
+ #define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301)
68
+ #define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302)
69
+ #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
70
+ #define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304)
71
+
72
+ #define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000)
73
+ #define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003)
74
+ #define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005)
75
+ #define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007)
76
+
77
+ #define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001)
78
+ #define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002)
79
+ #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
80
+ #define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004)
81
+ #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
82
+ #define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006)
83
+ #define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007)
84
+
85
+ #ifdef UNICODE
86
+ #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W
87
+ #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W
88
+ #else
89
+ #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A
90
+ #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A
91
+ #endif
92
+
93
+ /**
94
+ * Provide source compatibility on different platforms
95
+ */
96
+ #define SCARD_CTL_CODE(code) (0x42000000 + (code))
97
+
98
+ /**
99
+ * TeleTrust Class 2 reader tags
100
+ */
101
+ #define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
102
+
103
+ #define FEATURE_VERIFY_PIN_START 0x01 /**< OMNIKEY Proposal */
104
+ #define FEATURE_VERIFY_PIN_FINISH 0x02 /**< OMNIKEY Proposal */
105
+ #define FEATURE_MODIFY_PIN_START 0x03 /**< OMNIKEY Proposal */
106
+ #define FEATURE_MODIFY_PIN_FINISH 0x04 /**< OMNIKEY Proposal */
107
+ #define FEATURE_GET_KEY_PRESSED 0x05 /**< OMNIKEY Proposal */
108
+ #define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< USB CCID PIN Verify */
109
+ #define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< USB CCID PIN Modify */
110
+ #define FEATURE_MCT_READERDIRECT 0x08 /**< KOBIL Proposal */
111
+ #define FEATURE_MCT_UNIVERSAL 0x09 /**< KOBIL Proposal */
112
+ #define FEATURE_IFD_PIN_PROP 0x0A /**< Gemplus Proposal */
113
+ #define FEATURE_ABORT 0x0B /**< SCM Proposal */
114
+
115
+ /* structures used (but not defined) in PCSC Part 10 revision 2.01.02:
116
+ * "IFDs with Secure Pin Entry Capabilities" */
117
+
118
+ #include <inttypes.h>
119
+
120
+ /* Set structure elements aligment on bytes
121
+ * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
122
+ #if defined(__APPLE__) | defined(sun)
123
+ #pragma pack(1)
124
+ #else
125
+ #pragma pack(push, 1)
126
+ #endif
127
+
128
+ /** the structure must be 6-bytes long */
129
+ typedef struct
130
+ {
131
+ uint8_t tag;
132
+ uint8_t length;
133
+ uint32_t value; /**< This value is always in BIG ENDIAN format as documented in PCSC v2 part 10 ch 2.2 page 2. You can use ntohl() for example */
134
+ } PCSC_TLV_STRUCTURE;
135
+
136
+ /** the wLangId and wPINMaxExtraDigit are 16-bits long so are subject to byte
137
+ * ordering */
138
+ #define HOST_TO_CCID_16(x) @host_to_ccid_16@
139
+ #define HOST_TO_CCID_32(x) @host_to_ccid_32@
140
+
141
+ /** structure used with \ref FEATURE_VERIFY_PIN_DIRECT */
142
+ typedef struct
143
+ {
144
+ uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
145
+ uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
146
+ uint8_t bmFormatString; /**< formatting options */
147
+ uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
148
+ * bits 3-0 PIN block size in bytes after
149
+ * justification and formatting */
150
+ uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
151
+ * bit 4 set if system units are bytes, clear if
152
+ * system units are bits,
153
+ * bits 3-0 PIN length position in system units */
154
+ uint16_t wPINMaxExtraDigit; /**< 0xXXYY where XX is minimum PIN size in digits,
155
+ and YY is maximum PIN size in digits */
156
+ uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
157
+ * be considered complete */
158
+ uint8_t bNumberMessage; /**< Number of messages to display for PIN verification */
159
+ uint16_t wLangId; /**< Language for messages */
160
+ uint8_t bMsgIndex; /**< Message index (should be 00) */
161
+ uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
162
+ uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
163
+ uint8_t abData[1]; /**< Data to send to the ICC */
164
+ } PIN_VERIFY_STRUCTURE;
165
+
166
+ /** structure used with \ref FEATURE_MODIFY_PIN_DIRECT */
167
+ typedef struct
168
+ {
169
+ uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
170
+ uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
171
+ uint8_t bmFormatString; /**< formatting options */
172
+ uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
173
+ * bits 3-0 PIN block size in bytes after
174
+ * justification and formatting */
175
+ uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
176
+ * bit 4 set if system units are bytes, clear if
177
+ * system units are bits,
178
+ * bits 3-0 PIN length position in system units */
179
+ uint8_t bInsertionOffsetOld; /**< Insertion position offset in bytes for
180
+ the current PIN */
181
+ uint8_t bInsertionOffsetNew; /**< Insertion position offset in bytes for
182
+ the new PIN */
183
+ uint16_t wPINMaxExtraDigit;
184
+ /**< 0xXXYY where XX is minimum PIN size in digits,
185
+ and YY is maximum PIN size in digits */
186
+ uint8_t bConfirmPIN; /**< Flags governing need for confirmation of new PIN */
187
+ uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
188
+ * be considered complete */
189
+ uint8_t bNumberMessage; /**< Number of messages to display for PIN verification*/
190
+ uint16_t wLangId; /**< Language for messages */
191
+ uint8_t bMsgIndex1; /**< index of 1st prompting message */
192
+ uint8_t bMsgIndex2; /**< index of 2d prompting message */
193
+ uint8_t bMsgIndex3; /**< index of 3d prompting message */
194
+ uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
195
+ uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
196
+ uint8_t abData[1]; /**< Data to send to the ICC */
197
+ } PIN_MODIFY_STRUCTURE;
198
+
199
+ /* restore default structure elements alignment */
200
+ #if defined(__APPLE__) | defined(sun)
201
+ #pragma pack()
202
+ #else
203
+ #pragma pack(pop)
204
+ #endif
205
+
206
+ #endif
207
+
@@ -0,0 +1,63 @@
1
+ /*
2
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3
+ *
4
+ * Copyright (C) 1999
5
+ * David Corcoran <corcoran@linuxnet.com>
6
+ *
7
+ * $Id: wintypes.h 2537 2007-05-22 15:02:26Z rousseau $
8
+ */
9
+
10
+ /**
11
+ * @file
12
+ * @brief This keeps a list of Windows(R) types.
13
+ */
14
+
15
+ #ifndef __wintypes_h__
16
+ #define __wintypes_h__
17
+
18
+ #ifdef __cplusplus
19
+ extern "C"
20
+ {
21
+ #endif
22
+
23
+ #if !defined(WIN32)
24
+
25
+ #ifndef BYTE
26
+ typedef unsigned char BYTE;
27
+ #endif
28
+ typedef unsigned char UCHAR;
29
+ typedef unsigned char *PUCHAR;
30
+ typedef unsigned short USHORT;
31
+
32
+ #ifndef __COREFOUNDATION_CFPLUGINCOM__
33
+ typedef unsigned long ULONG;
34
+ typedef void *LPVOID;
35
+ typedef short BOOL;
36
+ #endif
37
+
38
+ typedef unsigned long *PULONG;
39
+ typedef const void *LPCVOID;
40
+ typedef uint32_t DWORD;
41
+ typedef uint32_t *PDWORD;
42
+ typedef uint16_t WORD;
43
+ typedef long LONG;
44
+ typedef const char *LPCSTR;
45
+ typedef const BYTE *LPCBYTE;
46
+ typedef BYTE *LPBYTE;
47
+ typedef DWORD *LPDWORD;
48
+ typedef unsigned char *LPSTR;
49
+
50
+ /* these types were deprecated but still used by old drivers and
51
+ * applications. So just declare and use them. */
52
+ typedef LPSTR LPTSTR;
53
+ typedef LPCSTR LPCTSTR;
54
+
55
+ #else
56
+ #include <windows.h>
57
+ #endif
58
+
59
+ #ifdef __cplusplus
60
+ }
61
+ #endif
62
+
63
+ #endif
data/lib/smartcard.rb ADDED
@@ -0,0 +1 @@
1
+ require 'smartcard/pcsc'
Binary file
data/smartcard.gemspec ADDED
@@ -0,0 +1,53 @@
1
+
2
+ # Gem::Specification for Smartcard-0.2.0
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{smartcard}
7
+ s.version = "0.2.0"
8
+ s.date = %q{2007-11-18}
9
+ s.summary = %q{Interface with ISO 7816 smart cards.}
10
+ s.require_paths = ["lib", "ext"]
11
+ s.email = %q{victor@costan.us}
12
+ s.homepage = %q{http://www.costan.us/smartcard}
13
+ s.rubyforge_project = %q{smartcard}
14
+ s.description = %q{Interface with ISO 7816 smart cards.}
15
+ s.has_rdoc = true
16
+ s.platform = %q{mswin32}
17
+ s.authors = ["Victor Costan"]
18
+ s.files = ["CHANGELOG", "ext/smartcard_pcsc/extconf.rb", "ext/smartcard_pcsc/pcsc.h", "ext/smartcard_pcsc/pcsc_card.c", "ext/smartcard_pcsc/pcsc_constants.c", "ext/smartcard_pcsc/pcsc_context.c", "ext/smartcard_pcsc/pcsc_io_request.c", "ext/smartcard_pcsc/pcsc_main.c", "ext/smartcard_pcsc/pcsc_multi_strings.c", "ext/smartcard_pcsc/pcsc_namespace.c", "ext/smartcard_pcsc/pcsc_reader_states.c", "ext/smartcard_pcsc/pcsc_surrogate_reader.h", "ext/smartcard_pcsc/pcsc_surrogate_wintypes.h", "lib/smartcard.rb", "LICENSE", "README", "test/test_all.rb", "tests/ts_pcsc_ext.rb", "Manifest", "smartcard.gemspec", "lib/smartcard/pcsc.so"]
19
+ s.test_files = ["test/test_all.rb"]
20
+ end
21
+
22
+
23
+ # # Original Rakefile source (requires the Echoe gem):
24
+ #
25
+ # # Needs the 'echoe' gem
26
+ # require 'echoe'
27
+ #
28
+ # Echoe.new('smartcard') do |p|
29
+ # p.project = 'smartcard' # rubyforge project
30
+ #
31
+ # p.author = 'Victor Costan'
32
+ # p.email = 'victor@costan.us'
33
+ # p.summary = 'Interface with ISO 7816 smart cards.'
34
+ # p.url = 'http://www.costan.us/smartcard'
35
+ #
36
+ # p.need_tar_gz = false
37
+ # p.clean_pattern += ['ext/**/*.manifest', 'ext/**/*_autogen.h']
38
+ #
39
+ # p.eval = proc do |p|
40
+ # case RUBY_PLATFORM
41
+ # when /mswin/
42
+ # p.files += ['lib/smartcard/pcsc.so']
43
+ # p.platform = Gem::Platform::WIN32
44
+ #
45
+ # # take out the extension info from the gemspec
46
+ # task :postcompile_hacks => [:compile] do
47
+ # p.extensions.clear
48
+ # end
49
+ #
50
+ # task :package => [ :clean, :compile, :postcompile_hacks ]
51
+ # end
52
+ # end
53
+ # end
data/test/test_all.rb ADDED
File without changes
@@ -0,0 +1,135 @@
1
+ require 'smartcard'
2
+ require 'pp'
3
+
4
+ def test_reader_states
5
+ reader_states = Smartcard::PCSC::ReaderStates.new(2)
6
+ reader_states.set_current_state_of!(1, Smartcard::PCSC::STATE_ATRMATCH)
7
+ reader_states.set_current_state_of!(0, Smartcard::PCSC::STATE_CHANGED)
8
+ reader_states.set_event_state_of!(0, Smartcard::PCSC::STATE_IGNORE)
9
+ reader_states.set_event_state_of!(1, Smartcard::PCSC::STATE_PRESENT)
10
+ reader_states.set_atr_of!(1, "Ruby\0rocks!")
11
+ reader_states.set_atr_of!(0, "grreat success")
12
+ reader_states.set_reader_name_of!(0, "PC/SC Reader 0")
13
+ reader_states.set_reader_name_of!(1, "CCID Reader 1")
14
+
15
+ test_state1, test_state0 = reader_states.current_state_of(1), reader_states.current_state_of(0)
16
+ if (test_state1 != Smartcard::PCSC::STATE_ATRMATCH) or (test_state0 != Smartcard::PCSC::STATE_CHANGED)
17
+ puts "FAILED: ReaderStates.set_current_state_of! / current_state_of returned #{test_state1},#{test_state0} instead of #{Smartcard::PCSC::STATE_ATRMATCH},#{Smartcard::PCSC::STATE_CHANGED}\n"
18
+ return false
19
+ end
20
+ test_state0, test_state1 = reader_states.event_state_of(0), reader_states.event_state_of(1)
21
+ if (test_state0 != Smartcard::PCSC::STATE_IGNORE) or (test_state1 != Smartcard::PCSC::STATE_PRESENT)
22
+ puts "FAILED: ReaderStates.set_event_state_of! / event_state_of returned #{test_state0},#{test_state1} instead of #{Smartcard::PCSC::STATE_IGNORE},#{Smartcard::PCSC::STATE_PRESENT}\n"
23
+ return false
24
+ end
25
+ test_atr1, test_atr0 = reader_states.atr_of(1), reader_states.atr_of(0)
26
+ if (test_atr1 != "Ruby\0rocks!") or (test_atr0 != "grreat success")
27
+ puts "FAILED: ReaderStates.set_atr_of! / atr_of returned '#{test_atr1}','#{test_atr0}' instead of 'Ruby\\0rocks!','grreat success'\n"
28
+ return false
29
+ end
30
+ test_reader0, test_reader1 = reader_states.reader_name_of(0), reader_states.reader_name_of(1)
31
+ if (test_reader0 != "PC/SC Reader 0") or (test_reader1 != "CCID Reader 1")
32
+ puts "FAILED: ReaderStates.set_reader_name_of! / reader_name_of returned '#{test_reader0}','#{test_reader1}' instead of 'PC/SC Reader 0','CCID Reader 1'\n"
33
+ return false
34
+ end
35
+
36
+ [5, 2, nil].each do |bad_index|
37
+ exception_thrown = false
38
+ begin
39
+ reader_states.current_state_of(bad_index)
40
+ rescue IndexError => e
41
+ puts "(expected) exception thrown: #{e}\n"
42
+ exception_thrown = e
43
+ rescue TypeError => e
44
+ puts "(expected) exception thrown: #{e}\n"
45
+ exception_thrown = e
46
+ end
47
+ unless exception_thrown
48
+ puts "FAILED: ReaderStates.current_state_of responded for bad index #{bad_index}\n"
49
+ return false
50
+ end
51
+ end
52
+
53
+ return true
54
+ end
55
+
56
+ def test_io_request
57
+ io_request = Smartcard::PCSC::IoRequest.new
58
+ [Smartcard::PCSC::PROTOCOL_T0, Smartcard::PCSC::PROTOCOL_T1, Smartcard::PCSC::PROTOCOL_RAW].each do |t_protocol|
59
+ io_request.protocol = t_protocol
60
+ r_protocol = io_request.protocol
61
+ if r_protocol != t_protocol
62
+ puts "FAILED: IoRequest.protocol= / protocol failed for protocol #{t_protocol} (got #{r_protocol} instead)\n"
63
+ return false
64
+ end
65
+ end
66
+ end
67
+
68
+ test_reader_states
69
+ test_io_request
70
+
71
+
72
+ context = Smartcard::PCSC::Context.new(Smartcard::PCSC::SCOPE_SYSTEM);
73
+
74
+ reader_groups = context.list_reader_groups
75
+ pp reader_groups
76
+ readers1 = context.list_readers reader_groups
77
+ pp readers1
78
+ readers2 = context.list_readers reader_groups.first
79
+ pp readers2
80
+ readers3 = context.list_readers nil
81
+ pp readers3
82
+
83
+ context.cancel
84
+
85
+ reader0 = readers3.first
86
+ puts "Waiting for card in reader: #{reader0}\n"
87
+ reader_states = Smartcard::PCSC::ReaderStates.new(1)
88
+ reader_states.set_reader_name_of!(0, reader0)
89
+ reader_states.set_current_state_of!(0, Smartcard::PCSC::STATE_UNKNOWN)
90
+ while (reader_states.event_state_of(0) & Smartcard::PCSC::STATE_PRESENT) == 0 do
91
+ context.get_status_change reader_states, Smartcard::PCSC::INFINITE_TIMEOUT
92
+ puts "Status change: now it's #{reader_states.event_state_of(0)} and we want #{Smartcard::PCSC::STATE_PRESENT}\n"
93
+ reader_states.acknowledge_events!
94
+ end
95
+
96
+ puts "Connecting to card\n"
97
+ card0 = Smartcard::PCSC::Card.new(context, reader0, Smartcard::PCSC::SHARE_SHARED, Smartcard::PCSC::PROTOCOL_ANY)
98
+
99
+ card0.begin_transaction
100
+ card0.end_transaction Smartcard::PCSC::DISPOSITION_LEAVE
101
+
102
+ card0.reconnect Smartcard::PCSC::SHARE_EXCLUSIVE, Smartcard::PCSC::PROTOCOL_ANY, Smartcard::PCSC::INITIALIZATION_RESET
103
+
104
+ card_status = card0.status
105
+ pp card_status
106
+ puts "ATR Length: #{card_status[:atr].length}\n"
107
+
108
+ begin
109
+ puts "IFD vendor: #{card0.get_attribute Smartcard::PCSC::ATTR_VENDOR_IFD_VERSION}\n"
110
+ rescue RuntimeError => e
111
+ puts "Card.get_attribute threw exception #{e}\n"
112
+ end
113
+
114
+ puts "Selecting applet\n"
115
+ aid = [0x19, 0x83, 0x12, 0x29, 0xba, 0xbe]
116
+ select_apdu = [0x00, 0xA4, 0x04, 0x00, aid.length, aid].flatten
117
+ send_ioreq = Smartcard::PCSC::IoRequest.new; send_ioreq.protocol = Smartcard::PCSC::PROTOCOL_T1;
118
+ recv_ioreq = Smartcard::PCSC::IoRequest.new
119
+ select_response = card0.transmit(select_apdu.map {|byte| byte.chr}.join(''), send_ioreq, recv_ioreq)
120
+ select_response_str = (0...select_response.length).map { |i| ' %02x' % select_response[i].to_i }.join('')
121
+ puts "Response:#{select_response_str}\n"
122
+
123
+ begin
124
+ # This only works with GemPlus readers... any other suggestions?
125
+ puts "Testing low-level control\n"
126
+ ctl_string = [0x82, 0x01, 0x07, 0x00].map {|byte| byte.chr}.join('')
127
+ ctl_response = card0.control 2049, ctl_string, 4
128
+ pp ctl_response
129
+ rescue RuntimeError => e
130
+ puts "Card.control threw exception #{e}\n"
131
+ end
132
+
133
+ puts "Disconnecting and cleaning up\n"
134
+ card0.disconnect Smartcard::PCSC::DISPOSITION_LEAVE
135
+ context.release