0
# Card Connections
1
2
Framework for waiting for card insertion, establishing connections, and managing card communication with fine-grained control over protocols, connection modes, and card services.
3
4
## Capabilities
5
6
### Card Request
7
8
The CardRequest class provides functionality for waiting for card insertion and obtaining card services when cards become available.
9
10
```python { .api }
11
class CardRequest:
12
def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1):
13
"""
14
Create a card request for waiting for card insertion.
15
16
Args:
17
newcardonly (bool): If True, only newly inserted cards trigger the request
18
readers (list[Reader], optional): List of readers to monitor. If None, monitors all readers
19
cardType (CardType, optional): Specific card type to wait for. If None, accepts any card
20
cardServiceClass (class, optional): Card service class to instantiate. Defaults to PassThruCardService
21
timeout (int): Timeout in seconds for waitforcard() calls
22
"""
23
24
def waitforcard(self):
25
"""
26
Wait for a card matching the request criteria.
27
28
Returns:
29
CardService: Card service instance for the inserted card
30
31
Raises:
32
CardRequestTimeoutException: If timeout expires without card insertion
33
CardRequestException: If card request fails
34
"""
35
36
def waitforcardevent(self):
37
"""
38
Wait for any card insertion or removal event.
39
40
Returns:
41
tuple: (inserted_cards, removed_cards) where each is a list of Card objects
42
"""
43
44
def getReaders(self):
45
"""
46
Get the list of readers being monitored by this request.
47
48
Returns:
49
list[Reader]: List of Reader objects
50
"""
51
52
def __enter__(self):
53
"""Context manager entry."""
54
55
def __exit__(self, exc_type, exc_val, exc_tb):
56
"""Context manager exit."""
57
```
58
59
### Card Connection
60
61
CardConnection provides the core interface for communicating with smart cards, with protocol management and connection control.
62
63
**Note**: CardConnection is an abstract base class. Actual implementations are provided by concrete classes like `PCSCCardConnection` in the `smartcard.pcsc` module. The methods below define the interface that all implementations must provide.
64
65
```python { .api }
66
class CardConnection:
67
# Protocol constants
68
T0_protocol = 0x00000001
69
T1_protocol = 0x00000002
70
RAW_protocol = 0x00010000
71
T15_protocol = 0x00000008
72
73
def connect(self, protocol=None, mode=None, disposition=None):
74
"""
75
Connect to the smart card.
76
77
Args:
78
protocol (int, optional): Communication protocol (T0_protocol, T1_protocol, etc.)
79
mode (int, optional): Connection mode
80
disposition (int, optional): What to do with card when disconnecting
81
82
Raises:
83
CardConnectionException: If connection fails
84
"""
85
86
def reconnect(self, protocol=None, mode=None, disposition=None):
87
"""
88
Reconnect to the smart card.
89
90
Args:
91
protocol (int, optional): Communication protocol
92
mode (int, optional): Connection mode
93
disposition (int, optional): Disposition for reconnection
94
"""
95
96
def disconnect(self):
97
"""
98
Disconnect from the smart card.
99
"""
100
101
def release(self):
102
"""
103
Release the connection and associated resources.
104
"""
105
106
def transmit(self, command, protocol=None):
107
"""
108
Transmit an APDU command to the card.
109
110
Args:
111
command (list[int]): APDU command bytes
112
protocol (int, optional): Protocol to use for transmission
113
114
Returns:
115
tuple[list[int], int, int]: (response, sw1, sw2)
116
"""
117
118
def control(self, controlCode, command=None):
119
"""
120
Send a control command to the reader.
121
122
Args:
123
controlCode (int): Reader-specific control code
124
command (list[int], optional): Command data
125
126
Returns:
127
list[int]: Control command response
128
"""
129
130
def getATR(self):
131
"""
132
Get the Answer To Reset of the connected card.
133
134
Returns:
135
list[int]: ATR bytes
136
"""
137
138
def getProtocol(self):
139
"""
140
Get the active communication protocol.
141
142
Returns:
143
int: Protocol constant (T0_protocol, T1_protocol, etc.)
144
"""
145
146
def getReader(self):
147
"""
148
Get the reader associated with this connection.
149
150
Returns:
151
Reader: Reader object
152
"""
153
154
def setProtocol(self, protocol):
155
"""
156
Set the communication protocol.
157
158
Args:
159
protocol (int): Protocol constant
160
"""
161
162
def setErrorCheckingChain(self, errorcheckingchain):
163
"""
164
Set the error checking chain for status word processing.
165
166
Args:
167
errorcheckingchain (ErrorCheckingChain): Chain of error checkers
168
"""
169
170
def addSWExceptionToFilter(self, exClass):
171
"""
172
Add a status word exception class to the filter.
173
174
Args:
175
exClass (class): Exception class to filter
176
"""
177
178
def addObserver(self, observer):
179
"""
180
Add an observer for connection events.
181
182
Args:
183
observer (CardConnectionObserver): Observer to add
184
"""
185
186
def deleteObserver(self, observer):
187
"""
188
Remove an observer.
189
190
Args:
191
observer (CardConnectionObserver): Observer to remove
192
"""
193
194
def __enter__(self):
195
"""Context manager entry."""
196
197
def __exit__(self, exc_type, exc_val, exc_tb):
198
"""Context manager exit - automatically disconnects."""
199
```
200
201
### Card Service
202
203
CardService provides an abstraction layer over card connections for implementing card-specific functionality.
204
205
```python { .api }
206
class CardService:
207
def __init__(self, connection, cardname=None):
208
"""
209
Initialize card service with a connection.
210
211
Args:
212
connection (CardConnection): Connection to the card
213
cardname (str, optional): Name identifier for the card
214
"""
215
216
@staticmethod
217
def supports(cardname):
218
"""
219
Check if this service supports a given card.
220
221
Args:
222
cardname (str): Card name to check
223
224
Returns:
225
bool: True if card is supported
226
"""
227
228
def __enter__(self):
229
"""Context manager entry."""
230
231
def __exit__(self, exc_type, exc_val, exc_tb):
232
"""Context manager exit."""
233
234
class PassThruCardService(CardService):
235
"""Pass-through card service that supports all cards."""
236
237
@staticmethod
238
def supports(cardname):
239
"""Always returns True - supports all cards."""
240
return True
241
```
242
243
### Card and Reader Objects
244
245
```python { .api }
246
class Card:
247
def __init__(self, reader, atr):
248
"""
249
Create a card object.
250
251
Args:
252
reader (Reader): Reader containing the card
253
atr (list[int]): Answer To Reset bytes
254
"""
255
256
def createConnection(self):
257
"""
258
Create a connection to this card.
259
260
Returns:
261
CardConnection: Connection object for this card
262
"""
263
264
def __eq__(self, other):
265
"""Check card equality based on ATR and reader."""
266
267
def __hash__(self):
268
"""Hash based on ATR and reader."""
269
270
def __repr__(self):
271
"""String representation of the card."""
272
273
class Reader:
274
def __init__(self, readername):
275
"""
276
Create a reader object.
277
278
Args:
279
readername (str): Name of the reader
280
"""
281
282
def createConnection(self):
283
"""
284
Create a connection through this reader.
285
286
Returns:
287
CardConnection: New connection object
288
"""
289
290
def addtoreadergroup(self, groupname):
291
"""Add this reader to a reader group."""
292
293
def removefromreadergroup(self, groupname):
294
"""Remove this reader from a reader group."""
295
```
296
297
## Usage Examples
298
299
### Basic Card Request
300
301
```python
302
from smartcard.CardRequest import CardRequest
303
from smartcard.CardType import AnyCardType
304
305
# Wait for any card insertion
306
cardtype = AnyCardType()
307
cardrequest = CardRequest(timeout=10, cardType=cardtype)
308
309
try:
310
cardservice = cardrequest.waitforcard()
311
print("Card inserted!")
312
313
# Use the card service
314
with cardservice:
315
connection = cardservice.connection
316
atr = connection.getATR()
317
print(f"ATR: {' '.join(f'{b:02X}' for b in atr)}")
318
319
# Send APDU
320
response, sw1, sw2 = connection.transmit([0x00, 0xA4, 0x04, 0x00])
321
print(f"Response: {response}, SW: {sw1:02X} {sw2:02X}")
322
323
except Exception as e:
324
print(f"Card request failed: {e}")
325
```
326
327
### Specific Card Type Request
328
329
```python
330
from smartcard.CardRequest import CardRequest
331
from smartcard.CardType import ATRCardType
332
333
# Wait for card with specific ATR pattern
334
atr_pattern = [0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x84, 0x41, 0x82, 0x54, 0x43, 0x4F, 0x53, 0x70, 0x02, 0x47, 0x00, 0x44, 0x32, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
335
atr_mask = [0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
336
337
cardtype = ATRCardType(atr_pattern, atr_mask)
338
cardrequest = CardRequest(timeout=30, cardType=cardtype)
339
340
cardservice = cardrequest.waitforcard()
341
print("Matching card inserted!")
342
```
343
344
### Connection Management
345
346
```python
347
from smartcard.System import readers
348
from smartcard.CardRequest import CardRequest
349
350
# Get first reader and create connection
351
reader_list = readers()
352
if reader_list:
353
reader = reader_list[0]
354
connection = reader.createConnection()
355
356
try:
357
# Connect with specific protocol
358
connection.connect(connection.T1_protocol)
359
print(f"Connected using T=1 protocol")
360
361
# Check active protocol
362
protocol = connection.getProtocol()
363
print(f"Active protocol: {protocol}")
364
365
# Transmit command
366
GET_CHALLENGE = [0x00, 0x84, 0x00, 0x00, 0x08]
367
response, sw1, sw2 = connection.transmit(GET_CHALLENGE)
368
369
if sw1 == 0x90 and sw2 == 0x00:
370
print(f"Challenge: {' '.join(f'{b:02X}' for b in response)}")
371
372
except Exception as e:
373
print(f"Connection error: {e}")
374
finally:
375
connection.disconnect()
376
```
377
378
### Context Manager Usage
379
380
```python
381
from smartcard.CardRequest import CardRequest
382
from smartcard.CardType import AnyCardType
383
384
cardrequest = CardRequest(timeout=10, cardType=AnyCardType())
385
386
try:
387
with cardrequest.waitforcard() as cardservice:
388
with cardservice.connection as connection:
389
# Connection automatically managed
390
atr = connection.getATR()
391
response, sw1, sw2 = connection.transmit([0x00, 0xCA, 0x9F, 0x7F, 0x00])
392
393
print(f"ATR: {atr}")
394
print(f"Response: {response}, Status: {sw1:02X} {sw2:02X}")
395
396
# Connection automatically disconnected
397
# Service automatically cleaned up
398
399
except Exception as e:
400
print(f"Error: {e}")
401
```
402
403
## Related Types
404
405
```python { .api }
406
# Exception types
407
class CardConnectionException(SmartcardException):
408
"""Raised when card connection operations fail."""
409
410
class CardRequestException(SmartcardException):
411
"""Raised when card request operations fail."""
412
413
class CardRequestTimeoutException(CardRequestException):
414
"""Raised when card request times out."""
415
416
class CardServiceException(SmartcardException):
417
"""Raised when card service operations fail."""
418
419
class NoCardException(SmartcardException):
420
"""Raised when no card is present in reader."""
421
422
class InvalidReaderException(SmartcardException):
423
"""Raised when trying to access an invalid smartcard reader."""
424
425
class NoReadersException(SmartcardException):
426
"""Raised when the system has no smartcard reader."""
427
428
class InvalidATRMaskLengthException(SmartcardException):
429
"""Raised when an ATR mask does not match an ATR length."""
430
431
# Connection event types
432
class CardConnectionEvent:
433
def __init__(self, event_type, args=None):
434
"""
435
Card connection event.
436
437
Args:
438
event_type (str): 'connect', 'reconnect', 'disconnect', 'command', 'response'
439
args: Event-specific arguments
440
"""
441
442
class CardConnectionObserver:
443
def update(self, cardconnection, ccevent):
444
"""
445
Called when card connection events occur.
446
447
Args:
448
cardconnection (CardConnection): The connection that generated the event
449
ccevent (CardConnectionEvent): Event details
450
"""
451
```