laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/38175?usp=email )
Change subject: pySim.profile: Further refactor card <-> profile matching ......................................................................
pySim.profile: Further refactor card <-> profile matching
The new architecture avoids sim/ruim/uicc specific methods in pySim.profile and instead moves the profile-specific code into the profile; it also solves everything within the class hierarchy, no need for global methods.
Change-Id: I3b6c44d2f5cce2513c3ec8a3ce939a242f3e4901 --- M pySim/cdma_ruim.py M pySim/profile.py M pySim/ts_102_221.py M pySim/ts_51_011.py 4 files changed, 55 insertions(+), 56 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/75/38175/1
diff --git a/pySim/cdma_ruim.py b/pySim/cdma_ruim.py index 747a0d2..f5382c9 100644 --- a/pySim/cdma_ruim.py +++ b/pySim/cdma_ruim.py @@ -24,7 +24,6 @@ from osmocom.construct import *
from pySim.filesystem import * -from pySim.profile import match_ruim from pySim.profile import CardProfile, CardProfileAddon from pySim.ts_51_011 import CardProfileSIM from pySim.ts_51_011 import DF_TELECOM, DF_GSM @@ -191,8 +190,11 @@ return CardProfileSIM.decode_select_response(data_hex)
@classmethod - def match_with_card(cls, scc: SimCardCommands) -> bool: - return match_ruim(scc) + def _try_match_card(cls, scc: SimCardCommands) -> None: + """ Try to access MF/DF.CDMA via 2G APDUs (3GPP TS 11.11), if this works, + the card is considered an R-UIM card for CDMA.""" + cls._mf_select_test(scc, "a0", "0000", ["3f00", "7f25"]) +
class AddonRUIM(CardProfileAddon): """An Addon that can be found on on a combined SIM + RUIM or UICC + RUIM to support CDMA.""" diff --git a/pySim/profile.py b/pySim/profile.py index ae9e19f..e1fd11f 100644 --- a/pySim/profile.py +++ b/pySim/profile.py @@ -25,54 +25,11 @@ import operator from typing import List
+from pySim.exceptions import SwMatchError from pySim.commands import SimCardCommands from pySim.filesystem import CardApplication, interpret_sw from pySim.utils import all_subclasses
-def _mf_select_test(scc: SimCardCommands, - cla_byte: str, sel_ctrl: str, - fids: List[str]) -> bool: - cla_byte_bak = scc.cla_byte - sel_ctrl_bak = scc.sel_ctrl - scc.reset_card() - - scc.cla_byte = cla_byte - scc.sel_ctrl = sel_ctrl - rc = True - try: - for fid in fids: - scc.select_file(fid) - except: - rc = False - - scc.reset_card() - scc.cla_byte = cla_byte_bak - scc.sel_ctrl = sel_ctrl_bak - return rc - - -def match_uicc(scc: SimCardCommands) -> bool: - """ Try to access MF via UICC APDUs (3GPP TS 102.221), if this works, the - card is considered a UICC card. - """ - return _mf_select_test(scc, "00", "0004", ["3f00"]) - - -def match_sim(scc: SimCardCommands) -> bool: - """ Try to access MF via 2G APDUs (3GPP TS 11.11), if this works, the card - is also a simcard. This will be the case for most UICC cards, but there may - also be plain UICC cards without 2G support as well. - """ - return _mf_select_test(scc, "a0", "0000", ["3f00"]) - - -def match_ruim(scc: SimCardCommands) -> bool: - """ Try to access MF/DF.CDMA via 2G APDUs (3GPP TS 11.11), if this works, - the card is considered an R-UIM card for CDMA. - """ - return _mf_select_test(scc, "a0", "0000", ["3f00", "7f25"]) - - class CardProfile: """A Card Profile describes a card, it's filesystem hierarchy, an [initial] list of applications as well as profile-specific SW and shell commands. Every card has @@ -137,14 +94,54 @@ """ return data_hex
+ @staticmethod + def _mf_select_test(scc: SimCardCommands, + cla_byte: str, sel_ctrl: str, + fids: List[str]) -> bool: + """Helper function used by some derived _try_match_card() methods.""" + scc.reset_card() + + scc.cla_byte = cla_byte + scc.sel_ctrl = sel_ctrl + for fid in fids: + scc.select_file(fid) + + @staticmethod + def _match_helper(scc, fn) -> bool: + sel_backup = scc.sel_ctrl + cla_backup = scc.cla_byte + try: + fn(scc) + return True + except SwMatchError: + return False + finally: + scc.sel_ctrl = sel_backup + scc.cla_byte = cla_backup + scc.reset_card() + @classmethod @abc.abstractmethod - def match_with_card(cls, scc: SimCardCommands) -> bool: - """Check if the specific profile matches the card. This method is a + def _try_match_card(cls, scc: SimCardCommands) -> None: + """Try to see if the specific profile matches the card. This method is a placeholder that is overloaded by specific dirived classes. The method actively probes the card to make sure the profile class matches the physical card. This usually also means that the card is reset during the process, so this method must not be called at random times. It may + only be called on startup. If there is no exception raised, we assume + the card matches the profile. + + Args: + scc: SimCardCommands class + """ + pass + + @classmethod + def match_with_card(cls, scc: SimCardCommands) -> bool: + """Check if the specific profile matches the card. The method + actively probes the card to make sure the profile class matches the + physical card. This usually also means that the card is reset during + the process, so this method must not be called at random times. It may only be called on startup.
Args: @@ -152,7 +149,7 @@ Returns: match = True, no match = False """ - return False + return cls._match_helper(scc, cls._try_match_card)
@staticmethod def pick(scc: SimCardCommands): diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py index c1c1388..9fed6af 100644 --- a/pySim/ts_102_221.py +++ b/pySim/ts_102_221.py @@ -27,7 +27,6 @@ from pySim.utils import * from pySim.filesystem import * from pySim.profile import CardProfile -from pySim.profile import match_uicc from pySim import iso7816_4
# A UICC will usually also support 2G functionality. If this is the case, we @@ -885,8 +884,10 @@ return flatten_dict_lists(d['fcp_template'])
@classmethod - def match_with_card(cls, scc: SimCardCommands) -> bool: - return match_uicc(scc) + def _try_match_card(cls, scc: SimCardCommands) -> None: + """ Try to access MF via UICC APDUs (3GPP TS 102.221), if this works, the + card is considered a UICC card.""" + cls._mf_select_test(scc, "00", "0004", ["3f00"])
@with_default_category('TS 102 221 Specific Commands') class AddlShellCommands(CommandSet): diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 69c8c79..8cbca58 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -41,7 +41,6 @@
from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_plmn, enc_plmn, dec_xplmn_w_act from pySim.utils import dec_msisdn, enc_msisdn -from pySim.profile import match_sim from pySim.profile import CardProfile, CardProfileAddon from pySim.filesystem import * from pySim.ts_31_102_telecom import DF_PHONEBOOK, DF_MULTIMEDIA, DF_MCS, DF_V2X @@ -1193,8 +1192,8 @@ return ret
@classmethod - def match_with_card(cls, scc: SimCardCommands) -> bool: - return match_sim(scc) + def _try_match_card(cls, scc: SimCardCommands) -> None: + cls._mf_select_test(scc, "a0", "0000", ["3f00"])
class AddonSIM(CardProfileAddon):