blob: 43ef06d4cb50d60a6b5f3744e2f56e4133b2da2e [file] [log] [blame]
Harald Welte8fab4632023-11-03 01:03:28 +01001# (C) 2021-2023 by Harald Welte <laforge@osmocom.org>
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation, either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16
Harald Welte8fab4632023-11-03 01:03:28 +010017from typing import Tuple
18
19from pySim.transport import LinkBase
20from pySim.commands import SimCardCommands
21from pySim.filesystem import CardModel, CardApplication
22from pySim.cards import card_detect, SimCardBase, UiccCardBase
23from pySim.exceptions import NoCardError
24from pySim.runtime import RuntimeState
25from pySim.profile import CardProfile
26from pySim.cdma_ruim import CardProfileRUIM
27from pySim.ts_102_221 import CardProfileUICC
Harald Weltedffe7af2023-12-23 17:23:52 +010028from pySim.utils import all_subclasses
Harald Welte8fab4632023-11-03 01:03:28 +010029
30# we need to import this module so that the SysmocomSJA2 sub-class of
31# CardModel is created, which will add the ATR-based matching and
32# calling of SysmocomSJA2.add_files. See CardModel.apply_matching_models
33import pySim.sysmocom_sja2
34
35# we need to import these modules so that the various sub-classes of
36# CardProfile are created, which will be used in init_card() to iterate
37# over all known CardProfile sub-classes.
38import pySim.ts_31_102
39import pySim.ts_31_103
40import pySim.ts_31_104
41import pySim.ara_m
42import pySim.global_platform
43import pySim.euicc
44
45def init_card(sl: LinkBase) -> Tuple[RuntimeState, SimCardBase]:
46 """
47 Detect card in reader and setup card profile and runtime state. This
48 function must be called at least once on startup. The card and runtime
49 state object (rs) is required for all pySim-shell commands.
50 """
51
52 # Create command layer
53 scc = SimCardCommands(transport=sl)
54
55 # Wait up to three seconds for a card in reader and try to detect
56 # the card type.
57 print("Waiting for card...")
Philipp Maierf1e1e722023-11-23 11:33:55 +010058 sl.wait_for_card(3)
Harald Welte8fab4632023-11-03 01:03:28 +010059
60 generic_card = False
61 card = card_detect(scc)
62 if card is None:
63 print("Warning: Could not detect card type - assuming a generic card type...")
64 card = SimCardBase(scc)
65 generic_card = True
66
67 profile = CardProfile.pick(scc)
68 if profile is None:
Philipp Maierf1e1e722023-11-23 11:33:55 +010069 # It is not an unrecoverable error in case profile detection fails. It
70 # just means that pySim was unable to recognize the card profile. This
71 # may happen in particular with unprovisioned cards that do not have
72 # any files on them yet.
Harald Welte8fab4632023-11-03 01:03:28 +010073 print("Unsupported card type!")
74 return None, card
75
76 # ETSI TS 102 221, Table 9.3 specifies a default for the PIN key
77 # references, however card manufactures may still decide to pick an
78 # arbitrary key reference. In case we run on a generic card class that is
79 # detected as an UICC, we will pick the key reference that is officially
80 # specified.
81 if generic_card and isinstance(profile, CardProfileUICC):
82 card._adm_chv_num = 0x0A
83
84 print("Info: Card is of type: %s" % str(profile))
85
86 # FIXME: this shouldn't really be here but somewhere else/more generic.
87 # We cannot do it within pySim/profile.py as that would create circular
88 # dependencies between the individual profiles and profile.py.
89 if isinstance(profile, CardProfileUICC):
Harald Weltedffe7af2023-12-23 17:23:52 +010090 for app_cls in all_subclasses(CardApplication):
Harald Welte8fab4632023-11-03 01:03:28 +010091 # skip any intermediary sub-classes such as CardApplicationSD
Harald Weltedffe7af2023-12-23 17:23:52 +010092 if hasattr(app_cls, '_' + app_cls.__name__ + '__intermediate'):
Harald Welte8fab4632023-11-03 01:03:28 +010093 continue
94 profile.add_application(app_cls())
95 # We have chosen SimCard() above, but we now know it actually is an UICC
96 # so it's safe to assume it supports USIM application (which we're adding above).
97 # IF we don't do this, we will have a SimCard but try USIM specific commands like
98 # the update_ust method (see https://osmocom.org/issues/6055)
99 if generic_card:
100 card = UiccCardBase(scc)
101
102 # Create runtime state with card profile
103 rs = RuntimeState(card, profile)
104
105 CardModel.apply_matching_models(scc, rs)
106
107 # inform the transport that we can do context-specific SW interpretation
108 sl.set_sw_interpreter(rs)
109
110 return rs, card
111
112
113