laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/34960?usp=email )
Change subject: transport/pcsc: Allow opening PC/SC readers by a regex of their name ......................................................................
transport/pcsc: Allow opening PC/SC readers by a regex of their name
Opening PC/SC readers by index/number is very error-prone as the order is never deterministic in any system with multiple (hot-plugged, USB) readers. Instead, let's offer the alternative of specifying a regular expression to match the reader name (similar to remsim-bankd).
Change-Id: I983f19c6741904c1adf27749c9801b44a03a5d78 --- M pySim/transport/pcsc.py 1 file changed, 49 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/60/34960/1
diff --git a/pySim/transport/pcsc.py b/pySim/transport/pcsc.py index 762908c..4041728 100644 --- a/pySim/transport/pcsc.py +++ b/pySim/transport/pcsc.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*-
# Copyright (C) 2009-2010 Sylvain Munaut tnt@246tNt.com -# Copyright (C) 2010 Harald Welte laforge@gnumonks.org +# Copyright (C) 2010-2023 Harald Welte laforge@gnumonks.org # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@
import argparse import os +import re from typing import Optional
from smartcard.CardConnection import CardConnection @@ -31,21 +32,44 @@ from pySim.utils import h2i, i2h, Hexstr, ResTuple
+def is_a_number(arg: str) -> bool: + """Determine if the passed string can be converted into an integer.""" + try: + int(arg) + except: + return False + return True + class PcscSimLink(LinkBase): """ pySim: PCSC reader transport link."""
- def __init__(self, reader_number: int = 0, **kwargs): + def __init__(self, reader_number: int | str = 0, **kwargs): super().__init__(**kwargs) + self._reader = None + r = readers() + if is_a_number(reader_number): + # actual reader index number (integer) + reader_number = int(reader_number) + if reader_number >= len(r): + raise ReaderError('No reader found for number %d' % reader_number) + self._reader = r[reader_number] + else: + # reader regex string + cre = re.compile(reader_number) + for reader in r: + if cre.search(reader.name): + self._reader = reader + break + if not self._reader: + raise ReaderError('No matching reader found for regex %s' % reader_number) + + self._con = self._reader.createConnection() + if os.environ.get('PYSIM_INTEGRATION_TEST') == "1": print("Using PC/SC reader interface") else: - print("Using PC/SC reader number %u" % reader_number) - r = readers() - if reader_number >= len(r): - raise ReaderError('No reader found for number %d' % reader_number) - self._reader = r[reader_number] - self._con = self._reader.createConnection() - self._reader_number = reader_number + print("Using PC/SC reader %s" % self) +
def __del__(self): try: @@ -100,10 +124,10 @@ return i2h(data), i2h(sw)
def __str__(self) -> str: - return "PCSC:%u[%s]" % (self._reader_number, self._reader) + return "PCSC[%s]" % (self._reader)
@staticmethod def argparse_add_reader_args(arg_parser: argparse.ArgumentParser): pcsc_group = arg_parser.add_argument_group('PC/SC Reader') - pcsc_group.add_argument('-p', '--pcsc-device', type=int, dest='pcsc_dev', metavar='PCSC', default=None, + pcsc_group.add_argument('-p', '--pcsc-device', type=str, dest='pcsc_dev', metavar='PCSC', default=None, help='PC/SC reader number to use for SIM access')