pySim-shell: add method to match card profile to card

UICC and old SIM cards can be difficult to tell apart without prior
knowledge of the card. The ATR won't tell if the card is UICC or not.
The only remaining option is to try out if the card is able to handle
UICC APDUs. The same is true for 2G SIM cards. It is not guranteed that
every UICC card will have 2G functionality.

Lets add functionality to match a profile to the currently plugged card
by actively probing it.

Lets also add another profile to distinguish between UICC-only cards and
UICC cards that include SIM functionality.

Change-Id: If090d32551145f75c644657b90085a3ef5bfa691
Related: OS#5274
diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py
index 61e236e..53cd118 100644
--- a/pySim/ts_102_221.py
+++ b/pySim/ts_102_221.py
@@ -23,6 +23,13 @@
 from pySim.utils import *
 from pySim.filesystem import *
 from bidict import bidict
+from pySim.profile import CardProfile
+from pySim.profile import match_uicc
+from pySim.profile import match_sim
+
+# A UICC will usually also support 2G functionality. If this is the case, we
+# need to add DF_GSM and DF_TELECOM along with the UICC related files
+from pySim.ts_51_011 import DF_GSM, DF_TELECOM
 
 ts_102_22x_cmdset = CardCommandSet('TS 102 22x', [
     # TS 102 221 Section 10.1.2 Table 10.5 "Coding of Instruction Byte"
@@ -603,9 +610,11 @@
         addl_info = FlagsEnum(Byte, req_inc_idle_current=1, support_uicc_suspend=2)
         self._construct = Struct('max_current_mA'/Int8ub, 't_op_s'/Int8ub, 'addl_info'/addl_info)
 
-
 class CardProfileUICC(CardProfile):
-    def __init__(self):
+
+    ORDER = 1
+
+    def __init__(self, name = 'UICC'):
         files = [
             EF_DIR(),
             EF_ICCID(),
@@ -683,7 +692,27 @@
             },
           }
 
-        super().__init__('UICC', desc='ETSI TS 102 221', cla="00", sel_ctrl="0004", files_in_mf=files, sw=sw)
+        super().__init__(name, desc='ETSI TS 102 221', cla="00", sel_ctrl="0004", files_in_mf=files, sw=sw)
 
     def decode_select_response(self, data_hex:str) -> Any:
         return decode_select_response(data_hex)
+
+    @staticmethod
+    def match_with_card(scc:SimCardCommands) -> bool:
+        return match_uicc(scc)
+
+class CardProfileUICCSIM(CardProfileUICC):
+    """Same as above, but including 2G SIM support"""
+
+    ORDER = 0
+
+    def __init__(self):
+        super().__init__('UICC-SIM')
+
+        # Add GSM specific files
+        self.files_in_mf.append(DF_TELECOM())
+        self.files_in_mf.append(DF_GSM())
+
+    @staticmethod
+    def match_with_card(scc:SimCardCommands) -> bool:
+        return match_uicc(scc) and match_sim(scc)