fix encode/decode of xPLMNwAcT

There are some pretty intricate rules about how GSM and E-UTRAN are
encoded, let's make sure we fully  support both as per 3GPP TS 31.102
Release 17.  As part of this, switch to a sorted list of access technologies,
in order to have a defined order.  This makes comparing in unit tests
much easier.  However, it also means that we need to sort the set
when printing the list of AcT in pySim-read to generate deterministic
output.

Change-Id: I398ac2a2527bd11e9c652e49fa46d6ca8d334b88
This commit is contained in:
Harald Welte
2023-12-21 20:14:48 +01:00
parent e45168ef29
commit 542dbf6771
8 changed files with 42 additions and 38 deletions

View File

@@ -728,7 +728,7 @@ class EF_LOCIGPRS(TransparentEF):
# TS 51.011 Section 10.3.35..37
class EF_xPLMNwAcT(TransRecEF):
_test_de_encode = [
( '62F2104000', { "mcc": "262", "mnc": "01", "act": [ "E-UTRAN" ] } ),
( '62F2104000', { "mcc": "262", "mnc": "01", "act": [ "E-UTRAN NB-S1", "E-UTRAN WB-S1" ] } ),
( '62F2108000', { "mcc": "262", "mnc": "01", "act": [ "UTRAN" ] } ),
]
def __init__(self, fid='1234', sfid=None, name=None, desc=None, size=(40, None), rec_len=5, **kwargs):
@@ -763,18 +763,18 @@ class EF_xPLMNwAcT(TransRecEF):
if 'cdma2000 1xRTT' in in_list:
u16 |= 0x0010
# E-UTRAN
if 'E-UTRAN' in in_list:
if 'E-UTRAN WB-S1' in in_list and 'E-UTRAN NB-S1' in in_list:
u16 |= 0x4000
if 'E-UTRAN WB-S1' in in_list:
elif 'E-UTRAN WB-S1' in in_list:
u16 |= 0x6000
if 'E-UTRAN NB-S1' in in_list:
elif 'E-UTRAN NB-S1' in in_list:
u16 |= 0x5000
# GSM mess
if 'GSM' in in_list and 'EC-GSM-IoT' in in_list:
u16 |= 0x008C
elif 'GSM' in in_list:
u16 |= 0x0084
elif 'EC-GSM-IuT' in in_list:
elif 'EC-GSM-IoT' in in_list:
u16 |= 0x0088
return '%04X' % (u16)

View File

@@ -486,33 +486,37 @@ def dec_mnc_from_plmn_str(plmn: Hexstr) -> str:
def dec_act(twohexbytes: Hexstr) -> List[str]:
act_list = [
{'bit': 15, 'name': "UTRAN"},
{'bit': 14, 'name': "E-UTRAN"},
{'bit': 11, 'name': "NG-RAN"},
{'bit': 7, 'name': "GSM"},
{'bit': 6, 'name': "GSM COMPACT"},
{'bit': 5, 'name': "cdma2000 HRPD"},
{'bit': 4, 'name': "cdma2000 1xRTT"},
]
ia = h2i(twohexbytes)
u16t = (ia[0] << 8) | ia[1]
sel = []
sel = set()
# only the simple single-bit ones
for a in act_list:
if u16t & (1 << a['bit']):
if a['name'] == "E-UTRAN":
# The Access technology identifier of E-UTRAN
# allows a more detailed specification:
if u16t & (1 << 13) and u16t & (1 << 12):
sel.append("E-UTRAN WB-S1")
sel.append("E-UTRAN NB-S1")
elif u16t & (1 << 13):
sel.append("E-UTRAN WB-S1")
elif u16t & (1 << 12):
sel.append("E-UTRAN NB-S1")
else:
sel.append("E-UTRAN")
else:
sel.append(a['name'])
return sel
sel.add(a['name'])
# TS 31.102 Section 4.2.5 Table 4.2.5.1
eutran_bits = u16t & 0x7000
if eutran_bits == 0x4000 or eutran_bits == 0x7000:
sel.add("E-UTRAN WB-S1")
sel.add("E-UTRAN NB-S1")
elif eutran_bits == 0x5000:
sel.add("E-UTRAN NB-S1")
elif eutran_bits == 0x6000:
sel.add("E-UTRAN WB-S1")
# TS 31.102 Section 4.2.5 Table 4.2.5.2
gsm_bits = u16t & 0x008C
if gsm_bits == 0x0080 or gsm_bits == 0x008C:
sel.add("GSM")
sel.add("EC-GSM-IoT")
elif u16t & 0x008C == 0x0084:
sel.add("GSM")
elif u16t & 0x008C == 0x0086:
sel.add("EC-GSM-IoT")
return sorted(list(sel))
def dec_xplmn_w_act(fivehexbytes: Hexstr) -> Dict[str, Any]: