CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyscard

Smartcard library for Python providing PC/SC interface for smart card communication

Pending
Overview
Eval results
Files

card-connections.mddocs/

Card Connections

Framework for waiting for card insertion, establishing connections, and managing card communication with fine-grained control over protocols, connection modes, and card services.

Capabilities

Card Request

The CardRequest class provides functionality for waiting for card insertion and obtaining card services when cards become available.

class CardRequest:
    def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1):
        """
        Create a card request for waiting for card insertion.
        
        Args:
            newcardonly (bool): If True, only newly inserted cards trigger the request
            readers (list[Reader], optional): List of readers to monitor. If None, monitors all readers
            cardType (CardType, optional): Specific card type to wait for. If None, accepts any card
            cardServiceClass (class, optional): Card service class to instantiate. Defaults to PassThruCardService
            timeout (int): Timeout in seconds for waitforcard() calls
        """
    
    def waitforcard(self):
        """
        Wait for a card matching the request criteria.
        
        Returns:
            CardService: Card service instance for the inserted card
            
        Raises:
            CardRequestTimeoutException: If timeout expires without card insertion
            CardRequestException: If card request fails
        """
    
    def waitforcardevent(self):
        """
        Wait for any card insertion or removal event.
        
        Returns:
            tuple: (inserted_cards, removed_cards) where each is a list of Card objects
        """
    
    def getReaders(self):
        """
        Get the list of readers being monitored by this request.
        
        Returns:
            list[Reader]: List of Reader objects
        """
    
    def __enter__(self):
        """Context manager entry."""
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""

Card Connection

CardConnection provides the core interface for communicating with smart cards, with protocol management and connection control.

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.

class CardConnection:
    # Protocol constants
    T0_protocol = 0x00000001
    T1_protocol = 0x00000002
    RAW_protocol = 0x00010000
    T15_protocol = 0x00000008
    
    def connect(self, protocol=None, mode=None, disposition=None):
        """
        Connect to the smart card.
        
        Args:
            protocol (int, optional): Communication protocol (T0_protocol, T1_protocol, etc.)
            mode (int, optional): Connection mode
            disposition (int, optional): What to do with card when disconnecting
        
        Raises:
            CardConnectionException: If connection fails
        """
    
    def reconnect(self, protocol=None, mode=None, disposition=None):
        """
        Reconnect to the smart card.
        
        Args:
            protocol (int, optional): Communication protocol  
            mode (int, optional): Connection mode
            disposition (int, optional): Disposition for reconnection
        """
    
    def disconnect(self):
        """
        Disconnect from the smart card.
        """
    
    def release(self):
        """
        Release the connection and associated resources.
        """
    
    def transmit(self, command, protocol=None):
        """
        Transmit an APDU command to the card.
        
        Args:
            command (list[int]): APDU command bytes
            protocol (int, optional): Protocol to use for transmission
            
        Returns:
            tuple[list[int], int, int]: (response, sw1, sw2)
        """
    
    def control(self, controlCode, command=None):
        """
        Send a control command to the reader.
        
        Args:
            controlCode (int): Reader-specific control code
            command (list[int], optional): Command data
            
        Returns:
            list[int]: Control command response
        """
    
    def getATR(self):
        """
        Get the Answer To Reset of the connected card.
        
        Returns:
            list[int]: ATR bytes
        """
    
    def getProtocol(self):
        """
        Get the active communication protocol.
        
        Returns:
            int: Protocol constant (T0_protocol, T1_protocol, etc.)
        """
    
    def getReader(self):
        """
        Get the reader associated with this connection.
        
        Returns:
            Reader: Reader object
        """
    
    def setProtocol(self, protocol):
        """
        Set the communication protocol.
        
        Args:
            protocol (int): Protocol constant
        """
    
    def setErrorCheckingChain(self, errorcheckingchain):
        """
        Set the error checking chain for status word processing.
        
        Args:
            errorcheckingchain (ErrorCheckingChain): Chain of error checkers
        """
    
    def addSWExceptionToFilter(self, exClass):
        """
        Add a status word exception class to the filter.
        
        Args:
            exClass (class): Exception class to filter
        """
    
    def addObserver(self, observer):
        """
        Add an observer for connection events.
        
        Args:
            observer (CardConnectionObserver): Observer to add
        """
    
    def deleteObserver(self, observer):
        """
        Remove an observer.
        
        Args:
            observer (CardConnectionObserver): Observer to remove
        """
    
    def __enter__(self):
        """Context manager entry."""
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit - automatically disconnects."""

Card Service

CardService provides an abstraction layer over card connections for implementing card-specific functionality.

class CardService:
    def __init__(self, connection, cardname=None):
        """
        Initialize card service with a connection.
        
        Args:
            connection (CardConnection): Connection to the card
            cardname (str, optional): Name identifier for the card
        """
    
    @staticmethod
    def supports(cardname):
        """
        Check if this service supports a given card.
        
        Args:
            cardname (str): Card name to check
            
        Returns:
            bool: True if card is supported
        """
    
    def __enter__(self):
        """Context manager entry."""
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""

class PassThruCardService(CardService):
    """Pass-through card service that supports all cards."""
    
    @staticmethod
    def supports(cardname):
        """Always returns True - supports all cards."""
        return True

Card and Reader Objects

class Card:
    def __init__(self, reader, atr):
        """
        Create a card object.
        
        Args:
            reader (Reader): Reader containing the card
            atr (list[int]): Answer To Reset bytes
        """
    
    def createConnection(self):
        """
        Create a connection to this card.
        
        Returns:
            CardConnection: Connection object for this card
        """
    
    def __eq__(self, other):
        """Check card equality based on ATR and reader."""
    
    def __hash__(self):
        """Hash based on ATR and reader."""
    
    def __repr__(self):
        """String representation of the card."""

class Reader:
    def __init__(self, readername):
        """
        Create a reader object.
        
        Args:
            readername (str): Name of the reader
        """
    
    def createConnection(self):
        """
        Create a connection through this reader.
        
        Returns:
            CardConnection: New connection object
        """
    
    def addtoreadergroup(self, groupname):
        """Add this reader to a reader group."""
    
    def removefromreadergroup(self, groupname):
        """Remove this reader from a reader group."""

Usage Examples

Basic Card Request

from smartcard.CardRequest import CardRequest
from smartcard.CardType import AnyCardType

# Wait for any card insertion
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=10, cardType=cardtype)

try:
    cardservice = cardrequest.waitforcard()
    print("Card inserted!")
    
    # Use the card service
    with cardservice:
        connection = cardservice.connection
        atr = connection.getATR()
        print(f"ATR: {' '.join(f'{b:02X}' for b in atr)}")
        
        # Send APDU
        response, sw1, sw2 = connection.transmit([0x00, 0xA4, 0x04, 0x00])
        print(f"Response: {response}, SW: {sw1:02X} {sw2:02X}")
        
except Exception as e:
    print(f"Card request failed: {e}")

Specific Card Type Request

from smartcard.CardRequest import CardRequest
from smartcard.CardType import ATRCardType

# Wait for card with specific ATR pattern
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]
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]

cardtype = ATRCardType(atr_pattern, atr_mask)
cardrequest = CardRequest(timeout=30, cardType=cardtype)

cardservice = cardrequest.waitforcard()
print("Matching card inserted!")

Connection Management

from smartcard.System import readers
from smartcard.CardRequest import CardRequest

# Get first reader and create connection
reader_list = readers()
if reader_list:
    reader = reader_list[0]
    connection = reader.createConnection()
    
    try:
        # Connect with specific protocol
        connection.connect(connection.T1_protocol)
        print(f"Connected using T=1 protocol")
        
        # Check active protocol
        protocol = connection.getProtocol()
        print(f"Active protocol: {protocol}")
        
        # Transmit command
        GET_CHALLENGE = [0x00, 0x84, 0x00, 0x00, 0x08]
        response, sw1, sw2 = connection.transmit(GET_CHALLENGE)
        
        if sw1 == 0x90 and sw2 == 0x00:
            print(f"Challenge: {' '.join(f'{b:02X}' for b in response)}")
        
    except Exception as e:
        print(f"Connection error: {e}")
    finally:
        connection.disconnect()

Context Manager Usage

from smartcard.CardRequest import CardRequest
from smartcard.CardType import AnyCardType

cardrequest = CardRequest(timeout=10, cardType=AnyCardType())

try:
    with cardrequest.waitforcard() as cardservice:
        with cardservice.connection as connection:
            # Connection automatically managed
            atr = connection.getATR()
            response, sw1, sw2 = connection.transmit([0x00, 0xCA, 0x9F, 0x7F, 0x00])
            
            print(f"ATR: {atr}")
            print(f"Response: {response}, Status: {sw1:02X} {sw2:02X}")
            
        # Connection automatically disconnected
    # Service automatically cleaned up
    
except Exception as e:
    print(f"Error: {e}")

Related Types

# Exception types
class CardConnectionException(SmartcardException):
    """Raised when card connection operations fail."""

class CardRequestException(SmartcardException):
    """Raised when card request operations fail."""

class CardRequestTimeoutException(CardRequestException):
    """Raised when card request times out."""

class CardServiceException(SmartcardException):
    """Raised when card service operations fail."""

class NoCardException(SmartcardException):
    """Raised when no card is present in reader."""

class InvalidReaderException(SmartcardException):
    """Raised when trying to access an invalid smartcard reader."""

class NoReadersException(SmartcardException):
    """Raised when the system has no smartcard reader."""

class InvalidATRMaskLengthException(SmartcardException):  
    """Raised when an ATR mask does not match an ATR length."""

# Connection event types
class CardConnectionEvent:
    def __init__(self, event_type, args=None):
        """
        Card connection event.
        
        Args:
            event_type (str): 'connect', 'reconnect', 'disconnect', 'command', 'response'
            args: Event-specific arguments
        """

class CardConnectionObserver:
    def update(self, cardconnection, ccevent):
        """
        Called when card connection events occur.
        
        Args:
            cardconnection (CardConnection): The connection that generated the event
            ccevent (CardConnectionEvent): Event details
        """

Install with Tessl CLI

npx tessl i tessl/pypi-pyscard

docs

atr-card-types.md

card-connections.md

gui-components.md

index.md

monitoring.md

pcsc-interface.md

reader-management.md

session-api.md

status-word-handling.md

utilities.md

tile.json