blob: 22b88fe615204e0a12d1b823331a4d55c771f2cf [file] [log] [blame]
Harald Welte2a33ad22021-10-20 10:14:18 +02001# -*- coding: utf-8 -*-
2
3# without this, pylint will fail when inner classes are used
4# within the 'nested' kwarg of our TlvMeta metaclass on python 3.7 :(
5# pylint: disable=undefined-variable
6
7"""
8The File (and its derived classes) uses the classes of pySim.filesystem in
9order to describe the files specified in UIC Reference P38 T 9001 5.0 "FFFIS for GSM-R SIM Cards"
10"""
11
12#
13# Copyright (C) 2021 Harald Welte <laforge@osmocom.org>
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 2 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27#
28
29
30from pySim.utils import *
31#from pySim.tlv import *
32from struct import pack, unpack
33from construct import *
34from construct import Optional as COptional
35from pySim.construct import *
36import enum
37
38from pySim.filesystem import *
39import pySim.ts_102_221
40import pySim.ts_51_011
41
42######################################################################
43# DF.EIRENE (FFFIS for GSM-R SIM Cards)
44######################################################################
45
46class FuncNTypeAdapter(Adapter):
47 def _decode(self, obj, context, path):
48 bcd = swap_nibbles(b2h(obj))
49 last_digit = bcd[-1]
50 return {'functional_number': bcd[:-1],
51 'presentation_of_only_this_fn': last_digit & 4,
52 'permanent_fn': last_digit & 8 }
53 def _encode(self, obj, context, path):
54 return 'FIXME'
55
56class EF_FN(LinFixedEF):
57 """Section 7.2"""
58 def __init__(self):
59 super().__init__(fid='6ff1', sfid=None, name='EF.EN', desc='Functional numbers', rec_len={9,9})
60 self._construct = Struct('functional_number_and_type'/FuncNTypeAdapter(Bytes(8)),
61 'list_number'/Int8ub)
62
63
64class PlConfAdapter(Adapter):
65 """Section 7.4.3"""
66 def _decode(self, obj, context, path):
67 num = int(obj) & 0x7
68 if num == 0:
69 return 'None'
70 elif num == 1:
71 return 4
72 elif num == 2:
73 return 3
74 elif num == 3:
75 return 2
76 elif num == 4:
77 return 1
78 elif num == 5:
79 return 0
80 def _encode(self, obj, context, path):
81 if obj == 'None':
82 return 0
83 obj = int(obj)
84 if obj == 4:
85 return 1
86 elif obj == 3:
87 return 2
88 elif obj == 2:
89 return 3
90 elif obj == 1:
91 return 4
92 elif obj == 0:
93 return 5
94
95class PlCallAdapter(Adapter):
96 """Section 7.4.12"""
97 def _decode(self, obj, context, path):
98 num = int(obj) & 0x7
99 if num == 0:
100 return 'None'
101 elif num == 1:
102 return 4
103 elif num == 2:
104 return 3
105 elif num == 3:
106 return 2
107 elif num == 4:
108 return 1
109 elif num == 5:
110 return 0
111 elif num == 6:
112 return 'B'
113 elif num == 7:
114 return 'A'
115 def _encode(self, obj, context, path):
116 if obj == 'None':
117 return 0
118 if obj == 4:
119 return 1
120 elif obj == 3:
121 return 2
122 elif obj == 2:
123 return 3
124 elif obj == 1:
125 return 4
126 elif obj == 0:
127 return 5
128 elif obj == 'B':
129 return 6
130 elif obj == 'A':
131 return 7
132
133NextTableType = Enum(Byte, decision=0xf0, predefined=0xf1, num_dial_digits=0xf2, ic=0xf3, empty=0xff)
134
135class EF_CallconfC(TransparentEF):
136 """Section 7.3"""
137 def __init__(self):
138 super().__init__(fid='6ff2', sfid=None, name='EF.CallconfC', size={24,24},
139 desc='Call Configuration of emergency calls Configuration')
140 self._construct = Struct('pl_conf'/PlConfAdapter(Int8ub),
141 'conf_nr'/BcdAdapter(Bytes(8)),
142 'max_rand'/Int8ub,
143 'n_ack_max'/Int16ub,
144 'pl_ack'/PlCallAdapter(Int8ub),
145 'n_nested_max'/Int8ub,
146 'train_emergency_gid'/Int8ub,
147 'shunting_emergency_gid'/Int8ub,
148 'imei'/BcdAdapter(Bytes(8)))
149
150class EF_CallconfI(LinFixedEF):
151 """Section 7.5"""
152 def __init__(self):
153 super().__init__(fid='6ff3', sfid=None, name='EF.CallconfI', rec_len={21,21},
154 desc='Call Configuration of emergency calls Information')
155 self._construct = Struct('t_dur'/Int24ub,
156 't_relcalc'/Int32ub,
157 'pl_call'/PlCallAdapter(Int8ub),
158 'cause'/FlagsEnum(Int8ub, powered_off=1, radio_link_error=2, user_command=5),
159 'gcr'/BcdAdapter(Bytes(4)),
160 'fnr'/BcdAdapter(Bytes(8)))
161
162class EF_Shunting(TransparentEF):
163 """Section 7.6"""
164 def __init__(self):
165 super().__init__(fid='6ff4', sfid=None, name='EF.Shunting', desc='Shunting', size={8,8})
166 self._construct = Struct('common_gid'/Int8ub,
167 'shunting_gid'/Bytes(7))
168
169class EF_GsmrPLMN(LinFixedEF):
170 """Section 7.7"""
171 def __init__(self):
172 super().__init__(fid='6ff5', sfid=None, name='EF.GsmrPLMN', desc='GSM-R network selection', rec_len={9,9})
173 self._construct = Struct('plmn'/BcdAdapter(Bytes(3)),
174 'class_of_network'/BitStruct('supported'/FlagsEnum(BitsInteger(5), vbs=1, vgcs=2, emlpp=4, fn=8, eirene=16),
175 'preference'/BitsInteger(3)),
176 'ic_incoming_ref_tbl'/HexAdapter(Bytes(2)),
177 'outgoing_ref_tbl'/HexAdapter(Bytes(2)),
178 'ic_table_ref'/HexAdapter(Bytes(1)))
179
180class EF_IC(LinFixedEF):
181 """Section 7.8"""
182 def __init__(self):
183 super().__init__(fid='6f8d', sfid=None, name='EF.IC', desc='International Code', rec_len={7,7})
184 self._construct = Struct('next_table_type'/NextTableType,
185 'id_of_next_table'/HexAdapter(Bytes(2)),
186 'ic_decision_value'/BcdAdapter(Bytes(2)),
187 'network_string_table_index'/Int8ub)
188
189class EF_NW(LinFixedEF):
190 """Section 7.9"""
191 def __init__(self):
192 super().__init__(fid='6f80', sfid=None, name='EF.NW', desc='Network Name', rec_len={8,8})
193 self._construct = GsmString(8)
194
195class EF_Switching(LinFixedEF):
196 """Section 8.4"""
197 def __init__(self, fid, name, desc):
198 super().__init__(fid=fid, sfid=None, name=name, desc=desc, rec_len={6,6})
199 self._construct = Struct('next_table_type'/NextTableType,
200 'id_of_next_table'/HexAdapter(Bytes(2)),
201 'decision_value'/BcdAdapter(Bytes(2)),
202 'string_table_index'/Int8ub)
203
204class EF_Predefined(LinFixedEF):
205 """Section 8.5"""
206 def __init__(self, fid, name, desc):
207 super().__init__(fid=fid, sfid=None, name=name, desc=desc, rec_len={3,3})
208 # header and other records have different structure. WTF !?!
209 self._construct = Struct('next_table_type'/NextTableType,
210 'id_of_next_table'/HexAdapter(Bytes(2)),
211 'predefined_value1'/HexAdapter(Bytes(2)),
212 'string_table_index1'/Int8ub)
213 # TODO: predefined value n, ...
214
215class EF_DialledVals(TransparentEF):
216 """Section 8.6"""
217 def __init__(self, fid, name, desc):
218 super().__init__(fid=fid, sfid=None, name=name, desc=desc, size={4,4})
219 self._construct = Struct('next_table_type'/NextTableType,
220 'id_of_next_table'/HexAdapter(Bytes(2)),
221 'dialed_digits'/BcdAdapter(Bytes(1)))
222
223
224class DF_EIRENE(CardDF):
225 def __init__(self, fid='7fe0', name='DF.EIRENE', desc='GSM-R EIRENE'):
226 super().__init__(fid=fid, name=name, desc=desc)
227 files = [
228 # Section 7.1.6 / Table 10 EIRENE GSM EFs
229 EF_FN(),
230 EF_CallconfC(),
231 EF_CallconfI(),
232 EF_Shunting(),
233 EF_GsmrPLMN(),
234 EF_IC(),
235 EF_NW(),
236
237 # support of the numbering plan
238 EF_Switching(fid='6f8e', name='EF.CT', desc='Call Type'),
239 EF_Switching(fid='6f8f', name='EF.SC', desc='Short Code'),
240 EF_Predefined(fid='6f88', name='EF.FC', desc='Function Code'),
241 EF_Predefined(fid='6f89', name='EF.Service', desc='VGCS/VBS Service Code'),
242 EF_Predefined(fid='6f8a', name='EF.Call', desc='First digit of the group ID'),
243 EF_Predefined(fid='6f8b', name='EF.FctTeam', desc='Call Type 6 Team Type + Team member function'),
244 EF_Predefined(fid='6f92', name='EF.Controller', desc='Call Type 7 Controller function code'),
245 EF_Predefined(fid='6f8c', name='EF.Gateway', desc='Access to external networks'),
246 EF_DialledVals(fid='6f81', name='EF.5to8digits', desc='Call Type 2 User Identity Number length'),
247 EF_DialledVals(fid='6f82', name='EF.2digits', desc='2 digits input'),
248 EF_DialledVals(fid='6f83', name='EF.8digits', desc='8 digits input'),
249 EF_DialledVals(fid='6f84', name='EF.9digits', desc='9 digits input'),
250 EF_DialledVals(fid='6f85', name='EF.SSSSS', desc='Group call area input'),
251 EF_DialledVals(fid='6f86', name='EF.LLLLL', desc='Location number Call Type 6'),
252 EF_DialledVals(fid='6f91', name='EF.Location', desc='Location number Call Type 7'),
253 EF_DialledVals(fid='6f87', name='EF.FreeNumber', desc='Free Number Call Type 0 and 8'),
254 ]
255 self.add_files(files)