diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py index f6f6c00e..e2ab925b 100644 --- a/pySim/ts_31_102.py +++ b/pySim/ts_31_102.py @@ -165,6 +165,13 @@ EF_UST_map = { 135: 'Support for Trusted non-3GPP access networks by USIM' } +# Mapping between USIM Enbled Service Number and its description +EF_EST_map = { + 1: 'Fixed Dialling Numbers (FDN)', + 2: 'Barred Dialling Numbers (BDN)', + 3: 'APN Control List (ACL)' +} + LOCI_STATUS_map = { 0: 'updated', 1: 'not updated', @@ -282,6 +289,7 @@ EF_USIM_ADF_map = { import enum from struct import unpack, pack +from typing import Tuple from construct import * from construct import Optional as COptional from pySim.construct import * @@ -519,30 +527,49 @@ class EF_HPPLMN(TransparentEF): self._construct = Int8ub # TS 31.102 Section 4.2.8 -class EF_UST(TransparentEF): - def __init__(self, fid='6f38', sfid=0x04, name='EF.UST', desc='USIM Service Table', size={1,17}): +class EF_UServiceTable(TransparentEF): + def __init__(self, fid, sfid, name, desc, size, table): super().__init__(fid=fid, sfid=sfid, name=name, desc=desc, size=size) + self.table = table # add those commands to the general commands of a TransparentEF self.shell_commands += [self.AddlShellCommands()] + @staticmethod + def _bit_byte_offset_for_service(service:int) -> Tuple[int, int]: + i = service - 1 + byte_offset = i//8 + bit_offset = (i % 8) + return (byte_offset, bit_offset) def _decode_bin(self, in_bin): - ret = [] + ret = {} for i in range (0, len(in_bin)): byte = in_bin[i] for bitno in range(0,7): - if byte & (1 << bitno): - ret.append(i * 8 + bitno + 1) + service_nr = i * 8 + bitno + 1 + ret[service_nr] = { + 'activated': True if byte & (1 << bitno) else False + } + if service_nr in self.table: + ret[service_nr]['description'] = self.table[service_nr] return ret def _encode_bin(self, in_json): - # FIXME: size this to length of file - ret = bytearray(20) - for srv in in_json: - print("srv=%d"%srv) - srv = srv-1 - byte_nr = srv // 8 - # FIXME: detect if service out of range was selected - bit_nr = srv % 8 - ret[byte_nr] |= (1 << bit_nr) - return ret + # compute the required binary size + bin_len = 0 + for srv in in_json.keys(): + service_nr = int(srv) + (byte_offset, bit_offset) = EF_UServiceTable._bit_byte_offset_for_service(service_nr) + if byte_offset >= bin_len: + bin_len = byte_offset+1 + # encode the actual data + out = bytearray(b'\x00' * bin_len) + for srv in in_json.keys(): + service_nr = int(srv) + (byte_offset, bit_offset) = EF_UServiceTable._bit_byte_offset_for_service(service_nr) + if in_json[srv]['activated'] == True: + bit = 1 + else: + bit = 0 + out[byte_offset] |= (bit) << bit_offset + return out @with_default_category('File-Specific Commands') class AddlShellCommands(CommandSet): def __init__(self): @@ -991,7 +1018,7 @@ class ADF_USIM(CardADF): 'User controlled PLMN Selector with Access Technology'), EF_HPPLMN(), EF_ACMmax(), - EF_UST(), + EF_UServiceTable('6f38', 0x04, 'EF.UST', 'USIM Service Table', size={1,17}, table=EF_UST_map), CyclicEF('6f39', None, 'EF.ACM', 'Accumulated call meter', rec_len={3,3}), TransparentEF('6f3e', None, 'EF.GID1', 'Group Identifier Level 1'), TransparentEF('6f3f', None, 'EF.GID2', 'Group Identifier Level 2'), @@ -1027,7 +1054,7 @@ class ADF_USIM(CardADF): EF_ADN('6f4d', None, 'EF.BDN', 'Barred Dialling Numbers'), EF_EXT('6f55', None, 'EF.EXT4', 'Extension4 (BDN/SSC)'), EF_CMI(), - EF_UST('6f56', 0x05, 'EF.EST', 'Enabled Services Table', size={1,None}), + EF_UServiceTable('6f56', 0x05, 'EF.EST', 'Enabled Services Table', size={1,None}, table=EF_EST_map), EF_ACL(), EF_DCK(), EF_CNL(), diff --git a/pySim/ts_31_103.py b/pySim/ts_31_103.py index 9c7843fb..6b69990e 100644 --- a/pySim/ts_31_103.py +++ b/pySim/ts_31_103.py @@ -26,7 +26,7 @@ from pySim.filesystem import * from pySim.utils import * from pySim.tlv import * from pySim.ts_51_011 import EF_AD, EF_SMS, EF_SMSS, EF_SMSR, EF_SMSP -from pySim.ts_31_102 import ADF_USIM, EF_FromPreferred +from pySim.ts_31_102 import ADF_USIM, EF_FromPreferred, EF_UServiceTable import pySim.ts_102_221 from pySim.ts_102_221 import EF_ARR @@ -101,26 +101,6 @@ class EF_IMPU(LinFixedEF): super().__init__(fid=fid, sfid=sfid, name=name, desc=desc) self._tlv = EF_IMPU.impu -# TS 31.103 Section 4.2.7 -class EF_IST(TransparentEF): - def __init__(self, fid='6f07', sfid=0x07, name='EF.IST', desc='ISIM Service Table'): - super().__init__(fid=fid, sfid=sfid, name=name, desc=desc, size={1,4}) - # add those commands to the general commands of a TransparentEF - self.shell_commands += [self.AddlShellCommands()] - - @with_default_category('File-Specific Commands') - class AddlShellCommands(CommandSet): - def __init__(self): - super().__init__() - - def do_ist_service_activate(self, arg): - """Activate a service within EF.IST""" - self._cmd.card.update_ist(int(arg), 1) - - def do_ist_service_deactivate(self, arg): - """Deactivate a service within EF.IST""" - self._cmd.card.update_ist(int(arg), 0) - # TS 31.103 Section 4.2.8 class EF_PCSCF(LinFixedEF): def __init__(self, fid='6f09', sfid=None, name='EF.P-CSCF', desc='P-CSCF Address'): @@ -192,7 +172,7 @@ class ADF_ISIM(CardADF): EF_IMPU(), EF_AD(), EF_ARR('6f06', 0x06), - EF_IST(), + EF_UServiceTable('6f07', 0x07, 'EF.IST', 'ISIM Service Table', {1,None}, EF_IST_map), EF_PCSCF(), EF_GBABP(), EF_GBANL(),