0
# Reader Management
1
2
Functions for discovering and managing smart card readers, including reader groups and system-level reader operations. This module provides the foundation for all smart card reader interactions.
3
4
## Capabilities
5
6
### System Reader Functions
7
8
Core functions for listing and managing smart card readers at the system level.
9
10
```python { .api }
11
def readers(groups=None):
12
"""
13
Get list of smart card readers as Reader objects.
14
15
Args:
16
groups (list[str], optional): Reader groups to search. If None, searches all groups.
17
18
Returns:
19
list[Reader]: List of available readers
20
21
Example groups: ['SCard$DefaultReaders', 'MyReaderGroup']
22
"""
23
24
def readergroups():
25
"""
26
Get list of all reader groups in the system.
27
28
Returns:
29
list[str]: List of reader group names
30
"""
31
```
32
33
### Reader Class
34
35
The Reader class represents individual smart card readers and provides methods for connection management.
36
37
```python { .api }
38
class Reader:
39
def __init__(self, readername):
40
"""
41
Create a reader object.
42
43
Args:
44
readername (str): Name of the smart card reader
45
"""
46
47
def createConnection(self):
48
"""
49
Create a connection to this reader for card communication.
50
51
Returns:
52
CardConnection: New connection object for this reader
53
54
Raises:
55
ReaderException: If connection creation fails
56
"""
57
58
def addtoreadergroup(self, groupname):
59
"""
60
Add this reader to a reader group.
61
62
Args:
63
groupname (str): Name of the reader group
64
"""
65
66
def removefromreadergroup(self, groupname):
67
"""
68
Remove this reader from a reader group.
69
70
Args:
71
groupname (str): Name of the reader group
72
"""
73
74
def __eq__(self, other):
75
"""
76
Check reader equality based on name.
77
78
Args:
79
other (Reader): Other reader to compare
80
81
Returns:
82
bool: True if readers have the same name
83
"""
84
85
def __hash__(self):
86
"""
87
Get hash value based on reader name.
88
89
Returns:
90
int: Hash value for use in sets and dictionaries
91
"""
92
93
def __repr__(self):
94
"""
95
Get detailed string representation.
96
97
Returns:
98
str: Detailed reader representation
99
"""
100
101
def __str__(self):
102
"""
103
Get reader name string.
104
105
Returns:
106
str: Reader name
107
"""
108
```
109
110
### Reader Factory
111
112
Factory functions for creating and managing reader instances.
113
114
```python { .api }
115
def createReader(clazz, readername):
116
"""
117
Create a reader instance from a class name.
118
119
Args:
120
clazz (str): Reader class name
121
readername (str): Name of the reader
122
123
Returns:
124
Reader: New reader instance
125
"""
126
```
127
128
## Usage Examples
129
130
### Basic Reader Discovery
131
132
```python
133
from smartcard.System import readers, readergroups
134
135
# List all available readers
136
reader_list = readers()
137
print(f"Found {len(reader_list)} readers:")
138
for i, reader in enumerate(reader_list):
139
print(f" {i}: {reader}")
140
141
# List reader groups
142
groups = readergroups()
143
print(f"\nReader groups: {groups}")
144
145
# Get readers from specific groups
146
if groups:
147
group_readers = readers([groups[0]])
148
print(f"\nReaders in '{groups[0]}': {len(group_readers)}")
149
```
150
151
### Reader Information and Management
152
153
```python
154
from smartcard.System import readers
155
156
reader_list = readers()
157
if reader_list:
158
reader = reader_list[0]
159
160
print(f"Reader name: {reader}")
161
print(f"Reader repr: {repr(reader)}")
162
print(f"Reader type: {type(reader)}")
163
164
# Reader comparison
165
same_reader = readers()[0]
166
print(f"Same reader: {reader == same_reader}") # True
167
168
# Use reader in a set (requires __hash__)
169
reader_set = {reader}
170
print(f"Reader in set: {reader in reader_set}") # True
171
```
172
173
### Connection Creation and Management
174
175
```python
176
from smartcard.System import readers
177
from smartcard.Exceptions import CardConnectionException
178
179
def test_reader_connection(reader):
180
"""Test connection capabilities of a reader."""
181
try:
182
print(f"Testing reader: {reader}")
183
184
# Create connection
185
connection = reader.createConnection()
186
print("✓ Connection created successfully")
187
188
# Test connection properties
189
print(f"Connection type: {type(connection)}")
190
print(f"Reader from connection: {connection.getReader()}")
191
192
# Try to connect (may fail if no card present)
193
try:
194
connection.connect()
195
print("✓ Connected to card")
196
197
# Get card information
198
atr = connection.getATR()
199
protocol = connection.getProtocol()
200
201
print(f"ATR: {' '.join(f'{b:02X}' for b in atr)}")
202
print(f"Protocol: {protocol}")
203
204
connection.disconnect()
205
print("✓ Disconnected successfully")
206
207
except CardConnectionException as e:
208
print(f"ⓘ No card present or connection failed: {e}")
209
210
except Exception as e:
211
print(f"✗ Reader test failed: {e}")
212
213
print()
214
215
# Test all readers
216
reader_list = readers()
217
for reader in reader_list:
218
test_reader_connection(reader)
219
```
220
221
### Reader Group Management
222
223
```python
224
from smartcard.System import readers, readergroups
225
226
def manage_reader_groups():
227
"""Demonstrate reader group management."""
228
reader_list = readers()
229
if not reader_list:
230
print("No readers available")
231
return
232
233
reader = reader_list[0]
234
print(f"Working with reader: {reader}")
235
236
# Show current groups
237
current_groups = readergroups()
238
print(f"Current groups: {current_groups}")
239
240
# Add reader to a custom group (may require admin privileges)
241
custom_group = "MyApplicationGroup"
242
try:
243
reader.addtoreadergroup(custom_group)
244
print(f"✓ Added reader to '{custom_group}'")
245
246
# Check if group was created
247
updated_groups = readergroups()
248
if custom_group in updated_groups:
249
print(f"✓ Group '{custom_group}' is now available")
250
251
# Remove reader from group
252
reader.removefromreadergroup(custom_group)
253
print(f"✓ Removed reader from '{custom_group}'")
254
255
except Exception as e:
256
print(f"ⓘ Group management failed (may require admin privileges): {e}")
257
258
manage_reader_groups()
259
```
260
261
### Reader Monitoring with System Functions
262
263
```python
264
import time
265
from smartcard.System import readers
266
267
def monitor_reader_changes(duration=30):
268
"""Monitor for reader connection/disconnection events."""
269
print(f"Monitoring readers for {duration} seconds...")
270
print("Connect or disconnect readers to see changes")
271
272
last_readers = set(str(r) for r in readers())
273
print(f"Initial readers: {len(last_readers)}")
274
for reader in last_readers:
275
print(f" {reader}")
276
print()
277
278
start_time = time.time()
279
while time.time() - start_time < duration:
280
current_readers = set(str(r) for r in readers())
281
282
# Check for changes
283
added = current_readers - last_readers
284
removed = last_readers - current_readers
285
286
if added:
287
print(f"✓ Readers connected: {added}")
288
if removed:
289
print(f"✗ Readers disconnected: {removed}")
290
291
if added or removed:
292
print(f"Current reader count: {len(current_readers)}")
293
last_readers = current_readers
294
print()
295
296
time.sleep(1)
297
298
print("Monitoring completed")
299
300
# Run monitoring
301
monitor_reader_changes(10)
302
```
303
304
### Cross-Platform Reader Handling
305
306
```python
307
import platform
308
from smartcard.System import readers
309
310
def analyze_system_readers():
311
"""Analyze readers based on operating system."""
312
system = platform.system()
313
reader_list = readers()
314
315
print(f"Operating System: {system}")
316
print(f"Total readers: {len(reader_list)}")
317
print()
318
319
for i, reader in enumerate(reader_list):
320
reader_name = str(reader)
321
print(f"Reader {i+1}: {reader_name}")
322
323
# Identify reader types based on naming patterns
324
if system == "Windows":
325
if "CCID" in reader_name:
326
print(" Type: CCID (Generic)")
327
elif "PICC" in reader_name:
328
print(" Type: Contactless")
329
elif "Microsoft" in reader_name:
330
print(" Type: Windows built-in")
331
332
elif system == "Darwin": # macOS
333
if "CCID" in reader_name:
334
print(" Type: CCID")
335
elif "PICC" in reader_name:
336
print(" Type: Contactless")
337
338
elif system == "Linux":
339
if "CCID" in reader_name:
340
print(" Type: CCID")
341
elif "pc/sc" in reader_name.lower():
342
print(" Type: PC/SC")
343
344
# Test connection capability
345
try:
346
connection = reader.createConnection()
347
print(" Status: Connection OK")
348
except Exception as e:
349
print(f" Status: Connection failed - {e}")
350
351
print()
352
353
analyze_system_readers()
354
```
355
356
## Related Types
357
358
```python { .api }
359
# Type aliases
360
ReaderName = str
361
ReaderGroupName = str
362
ReaderList = list[Reader]
363
364
# Exception types for reader operations
365
class ReaderException(SmartcardException):
366
"""Base exception for reader operations."""
367
368
class ListReadersException(SmartcardException):
369
"""Raised when reader listing fails."""
370
371
class InvalidReaderException(SmartcardException):
372
"""Raised when specified reader is invalid."""
373
```