2017-07-04 21:12:41 +00:00
|
|
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
|
#/**
|
|
|
|
|
# * Software Name : pycrate
|
2019-02-25 10:26:10 +00:00
|
|
|
|
# * Version : 0.4
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# *
|
2017-11-12 13:43:59 +00:00
|
|
|
|
# * Copyright 2017. Benoit Michau. ANSSI.
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# *
|
2018-04-15 19:47:21 +00:00
|
|
|
|
# * This library is free software; you can redistribute it and/or
|
|
|
|
|
# * modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
# * License as published by the Free Software Foundation; either
|
|
|
|
|
# * version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
# *
|
|
|
|
|
# * This library is distributed in the hope that it will be useful,
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2018-04-15 19:47:21 +00:00
|
|
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
# * Lesser General Public License for more details.
|
|
|
|
|
# *
|
|
|
|
|
# * You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
# * License along with this library; if not, write to the Free Software
|
|
|
|
|
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
|
# * MA 02110-1301 USA
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# *
|
|
|
|
|
# *--------------------------------------------------------
|
|
|
|
|
# * File Name : pycrate_mobile/TS24008_IE.py
|
|
|
|
|
# * Created : 2017-06-12
|
|
|
|
|
# * Authors : Benoit Michau
|
|
|
|
|
# *--------------------------------------------------------
|
|
|
|
|
#*/
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# 3GPP TS 24.008: Mobile radio interface layer 3 specification
|
|
|
|
|
# release 13 (d90)
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
from binascii import unhexlify
|
2019-11-08 15:11:02 +00:00
|
|
|
|
from time import struct_time
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
from pycrate_core.utils import *
|
2019-12-02 17:39:42 +00:00
|
|
|
|
from pycrate_core.elt import (
|
|
|
|
|
Envelope, Array, Sequence, Alt,
|
|
|
|
|
REPR_RAW, REPR_HEX, REPR_BIN, REPR_HD, REPR_HUM
|
|
|
|
|
)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
from pycrate_core.base import *
|
|
|
|
|
from pycrate_core.repr import *
|
|
|
|
|
from pycrate_core.charpy import Charpy
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
from .MCC_MNC import MNC_dict
|
2018-01-14 10:03:52 +00:00
|
|
|
|
from .PPP import LCP, LCPDataConf, NCP, NCPDataConf, PAP, CHAP
|
2017-11-12 14:18:50 +00:00
|
|
|
|
from .TS23038 import *
|
2018-02-09 20:58:36 +00:00
|
|
|
|
from .TS24007 import ProtDisc_dict
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# TS 24.008 IE specified with CSN.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
2018-07-31 21:16:12 +00:00
|
|
|
|
from pycrate_csn1dir.classmark_3_value_part import classmark_3_value_part
|
|
|
|
|
from pycrate_csn1dir.ms_network_capability_value_part import ms_network_capability_value_part
|
|
|
|
|
from pycrate_csn1dir.ms_ra_capability_value_part import ms_ra_capability_value_part
|
|
|
|
|
from pycrate_csn1dir.receive_npdu_number_list_value import receive_npdu_number_list_value
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
2017-10-13 19:28:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# str shortcuts
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_str_reserved = 'reserved'
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# std encoding / decoding routines
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
def encode_bcd(dig):
|
|
|
|
|
if len(dig) % 2:
|
|
|
|
|
dig += 'F'
|
|
|
|
|
dig = list(dig)
|
|
|
|
|
dig[1::2], dig[::2] = dig[::2], dig[1::2]
|
|
|
|
|
return unhexlify(''.join(dig))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def decode_bcd(buf):
|
|
|
|
|
if python_version < 3:
|
|
|
|
|
buf = [ord(c) for c in buf]
|
|
|
|
|
ret = []
|
|
|
|
|
for o in buf:
|
|
|
|
|
msb, lsb = o>>4, o&0xf
|
|
|
|
|
if lsb > 9:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
ret.append( str(lsb) )
|
|
|
|
|
if msb > 9:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
ret.append( str(msb) )
|
|
|
|
|
return ''.join(ret)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# TS 24.008 IE common objects
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
# BCD string is a string of digits, each digit being coded on a nibble (4 bits)
|
|
|
|
|
# Here, BufBCD is a subclass of pycrate_core.base.Buf
|
|
|
|
|
# with additionnal methods: encode(), decode()
|
|
|
|
|
|
|
|
|
|
class BufBCD(Buf):
|
2017-12-15 20:24:07 +00:00
|
|
|
|
"""Subclass of pycrate_core.base.Buf object
|
2017-07-04 21:12:41 +00:00
|
|
|
|
with additional encode() and decode() capabilities in order to handle
|
|
|
|
|
BCD encoding
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
_rep = REPR_HUM
|
2019-07-02 09:27:40 +00:00
|
|
|
|
_dic = None # dict lookup not supported for repr()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
# characters accepted in a BCD number
|
2019-07-02 09:27:40 +00:00
|
|
|
|
_chars = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'a', 'b', 'c')
|
|
|
|
|
# filler character for odd length number encoding
|
|
|
|
|
_filler = 0xF
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
# element name in kw, or first args
|
|
|
|
|
if len(args):
|
|
|
|
|
self._name = str(args[0])
|
|
|
|
|
elif 'name' in kw:
|
|
|
|
|
self._name = str(kw['name'])
|
|
|
|
|
# if not provided, it's the class name
|
|
|
|
|
else:
|
|
|
|
|
self._name = self.__class__.__name__
|
|
|
|
|
# element description customization
|
|
|
|
|
if 'desc' in kw:
|
|
|
|
|
self._desc = str(kw['desc'])
|
|
|
|
|
# element representation customization
|
|
|
|
|
if 'rep' in kw and kw['rep'] in self.REPR_TYPES:
|
|
|
|
|
self._rep = kw['rep']
|
|
|
|
|
# element hierarchy
|
|
|
|
|
if 'hier' in kw:
|
|
|
|
|
self._hier = kw['hier']
|
|
|
|
|
# element bit length
|
|
|
|
|
if 'bl' in kw:
|
|
|
|
|
self._bl = kw['bl']
|
|
|
|
|
# element value
|
|
|
|
|
if 'val' in kw:
|
2017-09-01 19:46:10 +00:00
|
|
|
|
self.set_val(kw['val'])
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# element transparency
|
|
|
|
|
if 'trans' in kw:
|
|
|
|
|
self._trans = kw['trans']
|
|
|
|
|
if self._SAFE_STAT:
|
|
|
|
|
self._chk_hier()
|
|
|
|
|
self._chk_bl()
|
|
|
|
|
self._chk_val()
|
|
|
|
|
self._chk_trans()
|
|
|
|
|
|
2017-09-01 19:46:10 +00:00
|
|
|
|
def set_val(self, val):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
if isinstance(val, Buf.TYPES + (NoneType, )):
|
2017-09-01 19:46:10 +00:00
|
|
|
|
Buf.set_val(self, val)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
elif isinstance(val, str_types):
|
|
|
|
|
self.encode(val)
|
2017-09-01 19:46:10 +00:00
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
def decode(self):
|
|
|
|
|
"""returns the encoded string of digits
|
|
|
|
|
"""
|
|
|
|
|
if python_version < 3:
|
|
|
|
|
num = [ord(c) for c in self.get_val()]
|
|
|
|
|
else:
|
|
|
|
|
num = self.get_val()
|
|
|
|
|
ret = []
|
|
|
|
|
for o in num:
|
|
|
|
|
msb, lsb = o>>4, o&0xf
|
|
|
|
|
if lsb == 0xF:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
ret.append( self._chars[lsb] )
|
|
|
|
|
if msb == 0xF:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
ret.append( self._chars[msb] )
|
|
|
|
|
return ''.join(ret)
|
|
|
|
|
|
|
|
|
|
def encode(self, bcd='12345678'):
|
|
|
|
|
"""encode the given BCD string and store the resulting buffer in
|
|
|
|
|
self._val
|
|
|
|
|
"""
|
|
|
|
|
# encode the chars
|
|
|
|
|
try:
|
2019-07-02 09:27:40 +00:00
|
|
|
|
ret = [self._chars.index(c) for c in bcd]
|
|
|
|
|
except Exception:
|
|
|
|
|
raise(PycrateErr('{0}: invalid character in BCD string to encode, {1!r}'\
|
2017-07-04 21:12:41 +00:00
|
|
|
|
.format(self._name, bcd)))
|
|
|
|
|
if len(ret) % 2:
|
2019-07-02 09:27:40 +00:00
|
|
|
|
ret.append( self._filler )
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#
|
|
|
|
|
if python_version < 3:
|
|
|
|
|
self._val = ''.join([chr(c) for c in map(lambda x,y:x+(y<<4), ret[::2], ret[1::2])])
|
|
|
|
|
else:
|
|
|
|
|
self._val = bytes(map(lambda x,y:x+(y<<4), ret[::2], ret[1::2]))
|
|
|
|
|
|
|
|
|
|
def repr(self):
|
|
|
|
|
# special hexdump representation
|
|
|
|
|
if self._rep == REPR_HD:
|
|
|
|
|
return '\n'.join(self._repr_hd())
|
|
|
|
|
# additional description
|
|
|
|
|
if self._desc:
|
|
|
|
|
desc = ' [%s]' % self._desc
|
|
|
|
|
else:
|
|
|
|
|
desc = ''
|
|
|
|
|
# element transparency
|
|
|
|
|
if self.get_trans():
|
|
|
|
|
trans = ' [transparent]'
|
|
|
|
|
else:
|
|
|
|
|
trans = ''
|
|
|
|
|
# type of representation to be used
|
|
|
|
|
if self._rep == REPR_HUM:
|
|
|
|
|
val_repr = self.decode()
|
|
|
|
|
elif self._rep == REPR_RAW:
|
|
|
|
|
val_repr = repr(self.get_val())
|
|
|
|
|
elif self._rep == REPR_BIN:
|
|
|
|
|
val_repr = '0b' + self.bin()
|
|
|
|
|
elif self._rep == REPR_HEX:
|
|
|
|
|
val_repr = '0x' + self.hex()
|
|
|
|
|
if self.REPR_MAXLEN > 0 and len(val_repr) > self.REPR_MAXLEN:
|
|
|
|
|
val_repr = val_repr[:self.REPR_MAXLEN] + '...'
|
|
|
|
|
return '<%s%s%s : %s>' % (self._name, desc, trans, val_repr)
|
|
|
|
|
|
|
|
|
|
__repr__ = repr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# PLMN is a string of digits, each digit being coded on a nibble (4 bits)
|
|
|
|
|
# Here, PLMN is a subclass of pycrate_core.base.Buf
|
|
|
|
|
# with additionnal methods: encode(), decode()
|
|
|
|
|
|
|
|
|
|
class PLMN(Buf):
|
|
|
|
|
"""Child of pycrate_core.base.Buf object
|
|
|
|
|
with additional encode() and decode() capabilities in order to handle
|
2017-09-01 19:46:10 +00:00
|
|
|
|
PLMN encoding
|
2017-07-04 21:12:41 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
_bl = 24 # 3 bytes
|
|
|
|
|
_rep = REPR_HUM
|
|
|
|
|
_dic = MNC_dict
|
|
|
|
|
|
2020-12-01 09:39:20 +00:00
|
|
|
|
# default to PLMN 001.01
|
|
|
|
|
DEFAULT_VAL = b'\x00\xf1\x10'
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
# element name in kw, or first args
|
|
|
|
|
if len(args):
|
|
|
|
|
self._name = str(args[0])
|
|
|
|
|
elif 'name' in kw:
|
|
|
|
|
self._name = str(kw['name'])
|
|
|
|
|
# if not provided, it's the class name
|
|
|
|
|
else:
|
|
|
|
|
self._name = self.__class__.__name__
|
|
|
|
|
# element description customization
|
|
|
|
|
if 'desc' in kw:
|
|
|
|
|
self._desc = str(kw['desc'])
|
|
|
|
|
# element representation customization
|
|
|
|
|
if 'rep' in kw and kw['rep'] in self.REPR_TYPES:
|
|
|
|
|
self._rep = kw['rep']
|
|
|
|
|
# element hierarchy
|
|
|
|
|
if 'hier' in kw:
|
|
|
|
|
self._hier = kw['hier']
|
2017-09-01 19:46:10 +00:00
|
|
|
|
# element bit length
|
|
|
|
|
if 'bl' in kw:
|
|
|
|
|
self._bl = kw['bl']
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# element value
|
|
|
|
|
if 'val' in kw:
|
2017-09-01 19:46:10 +00:00
|
|
|
|
self.set_val( kw['val'] )
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# element transparency
|
|
|
|
|
if 'trans' in kw:
|
|
|
|
|
self._trans = kw['trans']
|
|
|
|
|
if self._SAFE_STAT:
|
|
|
|
|
self._chk_hier()
|
|
|
|
|
self._chk_bl()
|
|
|
|
|
self._chk_val()
|
|
|
|
|
self._chk_trans()
|
|
|
|
|
|
2017-09-01 19:46:10 +00:00
|
|
|
|
def set_val(self, val):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
if isinstance(val, Buf.TYPES + (NoneType, )):
|
2017-09-01 19:46:10 +00:00
|
|
|
|
Buf.set_val(self, val)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
elif isinstance(val, str_types):
|
|
|
|
|
self.encode(val)
|
2017-09-01 19:46:10 +00:00
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
def decode(self):
|
|
|
|
|
"""returns the encoded string of digits
|
|
|
|
|
"""
|
|
|
|
|
plmn = []
|
2019-07-10 16:45:16 +00:00
|
|
|
|
if python_version < 3:
|
|
|
|
|
for c in self.get_val():
|
|
|
|
|
b = ord(c)
|
|
|
|
|
plmn.append(b>>4)
|
|
|
|
|
plmn.append(b&0xf)
|
|
|
|
|
if plmn[2] == 0xf:
|
|
|
|
|
return u'%i%i%i%i%i' % (plmn[1], plmn[0], plmn[3], plmn[5], plmn[4])
|
|
|
|
|
else:
|
|
|
|
|
return u'%i%i%i%i%i%i' % (plmn[1], plmn[0], plmn[3], plmn[5], plmn[4], plmn[2])
|
2017-07-04 21:12:41 +00:00
|
|
|
|
else:
|
2019-07-10 16:45:16 +00:00
|
|
|
|
for b in self.get_val():
|
|
|
|
|
plmn.append(b>>4)
|
|
|
|
|
plmn.append(b&0xf)
|
|
|
|
|
if plmn[2] == 0xf:
|
|
|
|
|
return '%i%i%i%i%i' % (plmn[1], plmn[0], plmn[3], plmn[5], plmn[4])
|
|
|
|
|
else:
|
|
|
|
|
return '%i%i%i%i%i%i' % (plmn[1], plmn[0], plmn[3], plmn[5], plmn[4], plmn[2])
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
2018-02-23 21:27:24 +00:00
|
|
|
|
def encode(self, plmn=u'00101'):
|
2017-07-04 21:12:41 +00:00
|
|
|
|
"""encode the given PLMN string and store the resulting buffer in
|
|
|
|
|
self._val
|
|
|
|
|
"""
|
|
|
|
|
if not plmn.isdigit():
|
|
|
|
|
raise(PycrateErr('{0}: invalid PLMN string to encode, {1!r}'\
|
2017-10-22 12:03:18 +00:00
|
|
|
|
.format(self._name, plmn)))
|
2017-07-04 21:12:41 +00:00
|
|
|
|
if len(plmn) == 5:
|
|
|
|
|
plmn += 'F'
|
|
|
|
|
elif len(plmn) != 6:
|
|
|
|
|
raise(PycrateErr('{0}: invalid PLMN string to encode, {1!r}'\
|
2017-10-22 12:03:18 +00:00
|
|
|
|
.format(self._name, plmn)))
|
2019-07-10 16:45:16 +00:00
|
|
|
|
# no need to distinguish Python version as join() and unhexlify() seems to
|
|
|
|
|
# do a good job here in both cases
|
|
|
|
|
self._val = unhexlify(''.join((plmn[1], plmn[0], plmn[5], plmn[2], plmn[4], plmn[3])))
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def repr(self):
|
|
|
|
|
# special hexdump representation
|
|
|
|
|
if self._rep == REPR_HD:
|
|
|
|
|
return '\n'.join(self._repr_hd())
|
|
|
|
|
# additional description
|
|
|
|
|
if self._desc:
|
|
|
|
|
desc = ' [%s]' % self._desc
|
|
|
|
|
else:
|
|
|
|
|
desc = ''
|
|
|
|
|
# element transparency
|
|
|
|
|
if self.get_trans():
|
|
|
|
|
trans = ' [transparent]'
|
|
|
|
|
else:
|
|
|
|
|
trans = ''
|
|
|
|
|
# type of representation to be used
|
|
|
|
|
if self._rep == REPR_HUM:
|
|
|
|
|
val_repr = self.decode()
|
|
|
|
|
if self._dic and val_repr in self._dic:
|
|
|
|
|
mccmnc = self._dic[val_repr]
|
2017-09-01 19:46:10 +00:00
|
|
|
|
val_repr += ' (%s.%s)' % (mccmnc[2], mccmnc[3])
|
2017-07-04 21:12:41 +00:00
|
|
|
|
elif self._rep == REPR_RAW:
|
|
|
|
|
val_repr = repr(self.get_val())
|
|
|
|
|
elif self._rep == REPR_BIN:
|
|
|
|
|
val_repr = '0b' + self.bin()
|
|
|
|
|
elif self._rep == REPR_HEX:
|
|
|
|
|
val_repr = '0x' + self.hex()
|
|
|
|
|
if self.REPR_MAXLEN > 0 and len(val_repr) > self.REPR_MAXLEN:
|
|
|
|
|
val_repr = val_repr[:self.REPR_MAXLEN] + '...'
|
|
|
|
|
return '<%s%s%s : %s>' % (self._name, desc, trans, val_repr)
|
|
|
|
|
|
|
|
|
|
__repr__ = repr
|
|
|
|
|
|
|
|
|
|
|
2018-11-21 08:20:40 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Cell Identity
|
|
|
|
|
# TS 24.008, 10.5.1.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class CellId(Uint16):
|
|
|
|
|
_rep = REPR_HEX
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# CKSN
|
|
|
|
|
# TS 24.008, 10.5.1.2
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
CKSN_dict = {
|
|
|
|
|
7:'No key is available (from MS) / reserved (from network)'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Local Area Identifier
|
|
|
|
|
# TS 24.008, 10.5.1.3
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class LAI(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
PLMN(),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint16('LAC', rep=REPR_HEX)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
encode = Envelope.set_val
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def decode(self):
|
2017-09-16 16:11:34 +00:00
|
|
|
|
return (self[0].decode(), self[1].get_val())
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Mobile Identity
|
|
|
|
|
# TS 24.008, 10.5.1.4
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
IDType_dict = {
|
|
|
|
|
0 : 'No Identity',
|
|
|
|
|
1 : 'IMSI',
|
|
|
|
|
2 : 'IMEI',
|
|
|
|
|
3 : 'IMEISV',
|
|
|
|
|
4 : 'TMSI',
|
|
|
|
|
5 : 'TMGI',
|
|
|
|
|
6 : 'ffu'
|
|
|
|
|
}
|
|
|
|
|
IDTYPE_NONE = 0
|
|
|
|
|
IDTYPE_IMSI = 1
|
|
|
|
|
IDTYPE_IMEI = 2
|
|
|
|
|
IDTYPE_IMEISV = 3
|
|
|
|
|
IDTYPE_TMSI = 4
|
|
|
|
|
IDTYPE_TMGI = 5
|
|
|
|
|
|
|
|
|
|
class IDNone(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=5, rep=REPR_HEX),
|
|
|
|
|
Uint('Type', bl=3, dic=IDType_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class IDTemp(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Digit1', val=0xF, bl=4, rep=REPR_HEX),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Odd', bl=1),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint('Type', val=IDTYPE_TMSI, bl=3, dic=IDType_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint32('TMSI', rep=REPR_HEX)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class IDDigit(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Digit1', val=0xF, bl=4, rep=REPR_HEX),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Odd', bl=1),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint('Type', val=IDTYPE_IMSI, bl=3, dic=IDType_dict),
|
|
|
|
|
Buf('Digits', val=b'', rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class IDGroup(Envelope):
|
2017-10-22 12:03:18 +00:00
|
|
|
|
ENV_SEL_TRANS = False
|
2017-07-04 21:12:41 +00:00
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('MBMSSessInd', bl=1),
|
|
|
|
|
Uint('MCCMNCInd', bl=1),
|
|
|
|
|
Uint('Odd', bl=1),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint('Type', val=IDTYPE_TMGI, dic=IDType_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint24('MBMSServID', rep=REPR_HEX),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
PLMN(),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('MBMSSessID')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
Envelope.__init__(self, *args, **kw)
|
|
|
|
|
self[6].set_transauto(lambda: False if self[2].get_val() else True)
|
|
|
|
|
self[7].set_transauto(lambda: False if self[1].get_val() else True)
|
|
|
|
|
|
|
|
|
|
class ID(Envelope):
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# during encode() / _from_char() processing
|
2017-10-22 12:03:18 +00:00
|
|
|
|
# specific attributes are created:
|
|
|
|
|
# self._IDNone = IDNone()
|
|
|
|
|
# self._IDTemp = IDTemp()
|
|
|
|
|
# self._IDDigit = IDDigit()
|
|
|
|
|
# self._IDGroup = IDGroup()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
2017-08-31 21:26:40 +00:00
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
if isinstance(vals, dict) and 'type' in vals and 'ident' in vals:
|
|
|
|
|
self.encode(vals['type'], vals['ident'])
|
2017-07-04 21:12:41 +00:00
|
|
|
|
else:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Envelope.set_val(self, vals)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def decode(self):
|
|
|
|
|
"""returns the mobile identity type and value
|
|
|
|
|
"""
|
|
|
|
|
type = self['Type'].get_val()
|
|
|
|
|
if type == IDTYPE_NONE:
|
|
|
|
|
return (type, None)
|
|
|
|
|
#
|
|
|
|
|
elif type == IDTYPE_TMSI:
|
|
|
|
|
return (type, self[3].get_val())
|
|
|
|
|
#
|
|
|
|
|
elif type in (IDTYPE_IMSI, IDTYPE_IMEI, IDTYPE_IMEISV):
|
|
|
|
|
return (type, str(self[0].get_val()) + decode_bcd(self[3].get_val()))
|
|
|
|
|
#
|
|
|
|
|
elif type == IDTYPE_TMGI:
|
|
|
|
|
if self[1].get_val():
|
|
|
|
|
# MBMSSessID
|
|
|
|
|
mid = self[7].get_val()
|
|
|
|
|
else:
|
|
|
|
|
mid = None
|
|
|
|
|
if self[2].get_val():
|
|
|
|
|
# MCCMNC
|
|
|
|
|
plmn = self[6].decode()
|
|
|
|
|
else:
|
|
|
|
|
plmn = None
|
|
|
|
|
return (type, (self[5].get_val(), plmn, mid))
|
|
|
|
|
|
|
|
|
|
def encode(self, type=IDTYPE_NONE, ident=None):
|
|
|
|
|
"""sets the mobile identity with given type
|
|
|
|
|
|
|
|
|
|
if type is IDTYPE_TMSI: ident must be an uint32
|
|
|
|
|
if type is IDTYPE_IMSI, IDTYPE_IMEI or IDTYPE_IMEISV: ident must be a
|
|
|
|
|
string of digits
|
|
|
|
|
if type is IDTYPE_TMGI: ident must be a 3-tuple (MBMSServID -uint24-,
|
|
|
|
|
PLMN -string of digits- or None, MBMSSessID -uint8- or None)
|
|
|
|
|
"""
|
|
|
|
|
if type == IDTYPE_NONE:
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDNone'):
|
|
|
|
|
self._IDNone = IDNone()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDNone._content
|
|
|
|
|
self._by_id = self._IDNone._by_id
|
|
|
|
|
self._by_name = self._IDNone._by_name
|
|
|
|
|
#
|
|
|
|
|
elif type == IDTYPE_TMSI:
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDTemp'):
|
|
|
|
|
self._IDTemp = IDTemp()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDTemp._content
|
|
|
|
|
self._by_id = self._IDTemp._by_id
|
|
|
|
|
self._by_name = self._IDTemp._by_name
|
|
|
|
|
self[3].set_val(ident)
|
|
|
|
|
#
|
|
|
|
|
elif type in (IDTYPE_IMSI, IDTYPE_IMEI, IDTYPE_IMEISV):
|
|
|
|
|
if not ident.isdigit():
|
|
|
|
|
raise(PycrateErr('{0}: invalid identity to encode, {1!r}'\
|
|
|
|
|
.format(self._name, ident)))
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDDigit'):
|
|
|
|
|
self._IDDigit = IDDigit()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDDigit._content
|
|
|
|
|
self._by_id = self._IDDigit._by_id
|
|
|
|
|
self._by_name = self._IDDigit._by_name
|
|
|
|
|
self[2]._val = type
|
|
|
|
|
if len(ident) % 2:
|
|
|
|
|
self[1]._val = 1
|
|
|
|
|
# encode digits the BCD way
|
|
|
|
|
self[0]._val = int(ident[0])
|
|
|
|
|
self[3]._val = encode_bcd(ident[1:])
|
|
|
|
|
#
|
|
|
|
|
elif type == IDTYPE_TMGI:
|
|
|
|
|
if not isinstance(ident, (tuple, list)) or len(ident) != 3:
|
|
|
|
|
raise(PycrateErr('{0}: invalid identity to encode, {1!r}'\
|
|
|
|
|
.format(self._name, ident)))
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDGroup'):
|
|
|
|
|
self._IDGroup = IDGroup()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDGroup._content
|
|
|
|
|
self._by_id = self._IDGroup._by_id
|
|
|
|
|
self._by_name = self._IDGroup._by_name
|
|
|
|
|
self[5].set_val( ident[0] )
|
|
|
|
|
if ident[1] is not None:
|
|
|
|
|
# MCCMNC
|
|
|
|
|
self[2]._val = 1
|
|
|
|
|
self[6].encode( ident[1] )
|
|
|
|
|
if ident[2] is not None:
|
|
|
|
|
# MBMSSessID
|
|
|
|
|
self[1]._val = 1
|
|
|
|
|
self[7].set_val( ident[2] )
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
if not self.get_trans():
|
|
|
|
|
try:
|
|
|
|
|
spare = char.get_uint(5)
|
|
|
|
|
type = char.get_uint(3)
|
|
|
|
|
except CharpyErr as err:
|
|
|
|
|
raise(CharpyErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
|
|
|
|
except Exception as err:
|
|
|
|
|
raise(EltErr('{0} [_from_char]: {1}'.format(self._name, err)))
|
|
|
|
|
#
|
|
|
|
|
if type == IDTYPE_TMSI:
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDTemp'):
|
|
|
|
|
self._IDTemp = IDTemp()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDTemp._content
|
|
|
|
|
self._by_id = self._IDTemp._by_id
|
|
|
|
|
self._by_name = self._IDTemp._by_name
|
|
|
|
|
self[0]._val = spare >> 1
|
|
|
|
|
self[1]._val = spare & 1
|
|
|
|
|
self[3]._from_char(char)
|
|
|
|
|
#
|
|
|
|
|
elif type in (IDTYPE_IMSI, IDTYPE_IMEI, IDTYPE_IMEISV):
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDDigit'):
|
|
|
|
|
self._IDDigit = IDDigit()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDDigit._content
|
|
|
|
|
self._by_id = self._IDDigit._by_id
|
|
|
|
|
self._by_name = self._IDDigit._by_name
|
|
|
|
|
self[0]._val = spare >> 1
|
|
|
|
|
self[1]._val = spare & 1
|
|
|
|
|
self[2]._val = type
|
|
|
|
|
self[3]._from_char(char)
|
|
|
|
|
#
|
|
|
|
|
elif type == IDTYPE_TMGI:
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDGroup'):
|
|
|
|
|
self._IDGroup = IDGroup()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDGroup._content
|
|
|
|
|
self._by_id = self._IDGroup._by_id
|
|
|
|
|
self._by_name = self._IDGroup._by_name
|
|
|
|
|
self[0]._val = spare >> 3
|
|
|
|
|
self[1]._val = (spare >> 2) & 1
|
|
|
|
|
self[2]._val = (spare >> 1) & 1
|
|
|
|
|
self[3]._val = spare & 1
|
|
|
|
|
self[5]._from_char(char)
|
|
|
|
|
if self[2]._val:
|
|
|
|
|
self[6]._from_char(char)
|
|
|
|
|
if self[1]._val:
|
|
|
|
|
self[7]._from_char(char)
|
|
|
|
|
#
|
2018-11-27 15:11:08 +00:00
|
|
|
|
elif type == IDTYPE_NONE:
|
|
|
|
|
if not hasattr(self, '_IDNone'):
|
|
|
|
|
self._IDNone = IDNone()
|
|
|
|
|
self._content = self._IDNone._content
|
|
|
|
|
self._by_id = self._IDNone._by_id
|
|
|
|
|
self._by_name = self._IDNone._by_name
|
|
|
|
|
#
|
2017-07-04 21:12:41 +00:00
|
|
|
|
else:
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if not hasattr(self, '_IDNone'):
|
|
|
|
|
self._IDNone = IDNone()
|
2018-01-02 13:51:01 +00:00
|
|
|
|
log('WNG: ID, type unhandled, %i' % type)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self._content = self._IDNone._content
|
|
|
|
|
self._by_id = self._IDNone._by_id
|
|
|
|
|
self._by_name = self._IDNone._by_name
|
|
|
|
|
|
|
|
|
|
def repr(self):
|
|
|
|
|
if not self._content:
|
|
|
|
|
return Envelope.repr(self)
|
|
|
|
|
# additional description
|
|
|
|
|
if self._desc:
|
|
|
|
|
desc = ' [%s]' % self._desc
|
|
|
|
|
else:
|
|
|
|
|
desc = ''
|
|
|
|
|
# element transparency
|
|
|
|
|
if self.get_trans():
|
|
|
|
|
trans = ' [transparent]'
|
|
|
|
|
else:
|
|
|
|
|
trans = ''
|
|
|
|
|
#
|
|
|
|
|
type = self['Type'].get_val()
|
|
|
|
|
#
|
|
|
|
|
if type == IDTYPE_TMSI:
|
|
|
|
|
if self[3]._rep in (REPR_RAW, REPR_HUM):
|
|
|
|
|
t_repr = repr(self[3].get_val())
|
|
|
|
|
elif self[3]._rep == REPR_HEX:
|
|
|
|
|
t_repr = '0x' + self[3].hex()
|
|
|
|
|
elif self[3].rep == REPR_BIN:
|
|
|
|
|
t_repr = '0b' + self[3].bin()
|
|
|
|
|
else:
|
|
|
|
|
t_repr = ''
|
|
|
|
|
return '<%s%s%s [TMSI] : %s>' % (self._name, desc, trans, t_repr)
|
|
|
|
|
elif type in (IDTYPE_IMSI, IDTYPE_IMEI, IDTYPE_IMEISV):
|
|
|
|
|
return '<%s%s%s [%s] : %s>' % (self._name, desc, trans, IDType_dict[type],
|
|
|
|
|
str(self[0].get_val()) + decode_bcd(self[3].get_val()))
|
|
|
|
|
else:
|
|
|
|
|
return Envelope.repr(self)
|
|
|
|
|
|
|
|
|
|
__repr__ = repr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Mobile Station Classmark 1
|
|
|
|
|
# TS 24.008, 10.5.1.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_RevLevel_dict = {
|
|
|
|
|
0:'Reserved for GSM phase 1',
|
|
|
|
|
1:'GSM phase 2 MS',
|
|
|
|
|
2:'MS supporting R99 or later',
|
|
|
|
|
3:'FFU'
|
|
|
|
|
}
|
|
|
|
|
_RFClass_dict = {
|
|
|
|
|
0:'class 1',
|
|
|
|
|
1:'class 2',
|
|
|
|
|
2:'class 3',
|
|
|
|
|
3:'class 4',
|
|
|
|
|
4:'class 5'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MSCm1(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint('RevLevel', val=2, bl=2, dic=_RevLevel_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('EarlyCmCap', bl=1),
|
|
|
|
|
Uint('NoA51', bl=1),
|
|
|
|
|
Uint('RFClass', bl=3, dic=_RFClass_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Mobile Station Classmark 2
|
|
|
|
|
# TS 24.008, 10.5.1.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
# SS screening indicator (TS 24.080, section 3.7.1)
|
|
|
|
|
_SSScreen_dict = {
|
|
|
|
|
0:'default value of phase 1',
|
|
|
|
|
1:'capability of handling of ellipsis notation and phase 2 error handling',
|
|
|
|
|
2:'ffu',
|
|
|
|
|
3:'ffu'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MSCm2(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint('RevLevel', val=2, bl=2, dic=_RevLevel_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('EarlyCmCap', bl=1),
|
|
|
|
|
Uint('NoA51', bl=1),
|
|
|
|
|
Uint('RFClass', bl=3, dic=_RFClass_dict),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('PSCap', bl=1),
|
|
|
|
|
Uint('SSScreeningCap', bl=2, dic=_SSScreen_dict),
|
|
|
|
|
Uint('MTSMSCap', bl=1),
|
|
|
|
|
Uint('VBSNotifCap', bl=1),
|
|
|
|
|
Uint('VGCSNotifCap', bl=1),
|
|
|
|
|
Uint('FCFreqCap', bl=1),
|
|
|
|
|
Uint('MSCm3Cap', bl=1),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('LCSVACap', bl=1),
|
|
|
|
|
Uint('UCS2', bl=1),
|
|
|
|
|
Uint('SoLSACap', bl=1),
|
|
|
|
|
Uint('CMServPrompt', bl=1),
|
|
|
|
|
Uint('A53', bl=1),
|
|
|
|
|
Uint('A52', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2018-11-21 08:20:40 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Descriptive group or broadcast call reference
|
|
|
|
|
# TS 24.008, 10.5.1.9
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
PriorityLevel_dict = {
|
|
|
|
|
0 : 'no priority applied',
|
|
|
|
|
1 : 'call priority level 4',
|
|
|
|
|
2 : 'call priority level 3',
|
|
|
|
|
3 : 'call priority level 2',
|
|
|
|
|
4 : 'call priority level 1',
|
|
|
|
|
5 : 'call priority level 0',
|
|
|
|
|
6 : 'call priority level B',
|
|
|
|
|
7 : 'call priority level A'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class BroadcastCallRef(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Value', bl=27, rep=REPR_HEX),
|
|
|
|
|
Uint('SF', bl=1, dic={0:'VBS, broadcast call', 1:'VGCS, group call'}),
|
|
|
|
|
Uint('AF', bl=1, dic={0:'ACK not required', 1:'ACK required'}),
|
|
|
|
|
Uint('CallPriority', bl=3, dic=PriorityLevel_dict),
|
|
|
|
|
Uint('CipheringInfo', bl=4, dic={0:'no ciphering'}),
|
|
|
|
|
Uint('spare', bl=4)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# PD and SAPI $(CCBS)$
|
|
|
|
|
# TS 24.008, 10.5.1.10a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class PD_SAPI(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('SAPI', bl=2),
|
|
|
|
|
Uint('PD', val=5, bl=4, dic=ProtDisc_dict)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Priority Level
|
|
|
|
|
# TS 24.008, 10.5.1.11
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class PriorityLevel(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('CallPriority', bl=3, dic=PriorityLevel_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# PLMN list
|
|
|
|
|
# TS 24.008, 10.5.1.13
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class PLMNList(Array):
|
|
|
|
|
_GEN = PLMN()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# MS network feature support
|
|
|
|
|
# TS 24.008, 10.5.1.15
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class MSNetFeatSupp(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('ExtPeriodTimers', bl=1)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Authentication Parameter AUTN (UMTS and EPS authentication challenge)
|
|
|
|
|
# TS 24.008, 10.5.3.1.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class AUTN(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Buf('SQNxAK', bl=48, rep=REPR_HEX),
|
|
|
|
|
Buf('AMF', bl=16, rep=REPR_HEX),
|
|
|
|
|
Buf('MAC', bl=64, rep=REPR_HEX)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# CM Service type
|
|
|
|
|
# TS 24.008, 10.5.3.3
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
CMService_dict = {
|
|
|
|
|
1:'Mobile originating call / packet mode connection',
|
|
|
|
|
2:'Emergency call',
|
|
|
|
|
4:'SMS',
|
|
|
|
|
8:'Supplementary service',
|
|
|
|
|
9:'Voice group call',
|
|
|
|
|
10:'Voice broadcast call',
|
|
|
|
|
11:'Location service'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Location Updating type
|
|
|
|
|
# TS 24.008, 10.5.3.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_LocUpdType_dict = {
|
|
|
|
|
0 : 'Normal location updating',
|
|
|
|
|
1 : 'Periodic updating',
|
|
|
|
|
2 : 'IMSI attach',
|
2017-10-13 19:28:18 +00:00
|
|
|
|
3 : _str_reserved
|
2017-07-04 21:12:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class LocUpdateType(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('FollowOnReq', bl=1),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Type', bl=2, dic=_LocUpdType_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Network Name
|
|
|
|
|
# section 10.5.3.5a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CodingScheme_dict = {
|
|
|
|
|
0 : 'GSM 7 bit default alphabet',
|
|
|
|
|
1 : 'UCS2 (16 bit)'
|
|
|
|
|
}
|
|
|
|
|
CODTYPE_7B = 0
|
|
|
|
|
CODTYPE_UCS2 = 1
|
|
|
|
|
|
|
|
|
|
class NetworkName(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('Coding', val=CODTYPE_7B, bl=3, dic=_CodingScheme_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('AddCountryInitials', bl=1),
|
|
|
|
|
Uint('SpareBits', bl=3),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Buf('Name', val=b'', rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
Name = None
|
|
|
|
|
if isinstance(vals, dict) and 'Name' in vals:
|
2018-12-13 09:38:13 +00:00
|
|
|
|
Name = dict(vals['Name'])
|
2017-11-12 14:18:50 +00:00
|
|
|
|
del vals['Name']
|
2018-12-13 09:38:13 +00:00
|
|
|
|
elif isinstance(vals, (tuple, list)) and len(vals) == 5:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
vals = list(vals)
|
|
|
|
|
Name = vals[-1]
|
|
|
|
|
vals[-1] = None
|
|
|
|
|
Envelope.set_val(self, vals)
|
|
|
|
|
if Name is not None:
|
|
|
|
|
if isinstance(Name, Buf.TYPES + (NoneType,)):
|
|
|
|
|
self[4].set_val(Name)
|
|
|
|
|
elif isinstance(Name, str_types):
|
|
|
|
|
# encode it according to the Coding value
|
|
|
|
|
Coding = self[1]()
|
|
|
|
|
if Coding == CODTYPE_7B:
|
2017-11-26 10:55:18 +00:00
|
|
|
|
enc, c = encode_7b(Name)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[4]._val = enc
|
2017-11-26 10:55:18 +00:00
|
|
|
|
self[3]._val = (8-((7*c)%8))%8
|
2017-11-12 14:18:50 +00:00
|
|
|
|
elif Coding == CODTYPE_UCS2:
|
2017-11-26 10:55:18 +00:00
|
|
|
|
self[4]._val = Name.encode('utf-16-be')
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[3]._val = 0
|
|
|
|
|
|
|
|
|
|
encode = set_val
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def decode(self):
|
|
|
|
|
"""returns the textual network name
|
|
|
|
|
"""
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Coding = self[1].get_val()
|
|
|
|
|
if Coding == CODTYPE_7B:
|
|
|
|
|
dec = decode_7b(self[4].get_val())
|
|
|
|
|
if self[3]() == 7:
|
|
|
|
|
dec = dec[:-1]
|
|
|
|
|
return dec
|
|
|
|
|
elif Coding == CODTYPE_UCS2:
|
2017-07-04 21:12:41 +00:00
|
|
|
|
# WNG: this will certainly fail in Python2
|
2017-11-26 10:55:18 +00:00
|
|
|
|
return self[4].get_val().decode('utf-16-be')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Reject Cause
|
|
|
|
|
# TS 24.008, section 10.5.3.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
_RejectCause_dict = {
|
2017-07-04 21:12:41 +00:00
|
|
|
|
2:'IMSI unknown in HLR',
|
|
|
|
|
3:'Illegal MS',
|
|
|
|
|
4:'IMSI unknown in VLR',
|
|
|
|
|
5:'IMEI not accepted',
|
|
|
|
|
6:'Illegal ME',
|
|
|
|
|
11:'PLMN not allowed',
|
|
|
|
|
12:'Location Area not allowed',
|
|
|
|
|
13:'Roaming not allowed in this location area',
|
|
|
|
|
15:'No Suitable Cells In Location Area',
|
|
|
|
|
17:'Network failure',
|
|
|
|
|
20:'MAC failure',
|
|
|
|
|
21:'Synch failure',
|
|
|
|
|
22:'Congestion',
|
|
|
|
|
23:'GSM authentication unacceptable',
|
|
|
|
|
25:'Not authorized for this CSG',
|
|
|
|
|
32:'Service option not supported',
|
|
|
|
|
33:'Requested service option not subscribed',
|
|
|
|
|
34:'Service option temporarily out of order',
|
|
|
|
|
38:'Call cannot be identified',
|
|
|
|
|
48:'retry upon entry into a new cell',
|
|
|
|
|
95:'Semantically incorrect message',
|
|
|
|
|
96:'Invalid mandatory information',
|
|
|
|
|
97:'Message type non-existent or not implemented',
|
|
|
|
|
98:'Message type not compatible with the protocol state',
|
|
|
|
|
99:'Information element non-existent or not implemented',
|
|
|
|
|
100:'Conditional IE error',
|
|
|
|
|
101:'Message not compatible with the protocol state',
|
|
|
|
|
111:'Protocol error, unspecified'
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
class RejectCause(Uint8):
|
|
|
|
|
_dic = _RejectCause_dict
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Time Zone
|
|
|
|
|
# TS 24.008, section 10.5.3.8
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# identical to TS23040_SMS._TP_SCTS_TZ structure
|
|
|
|
|
|
|
|
|
|
class TimeZone(Envelope):
|
|
|
|
|
_Sign_dict = {0: '+', 1: '-'}
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('TZ1', bl=4),
|
|
|
|
|
Uint('TZS', bl=1, dic=_Sign_dict),
|
|
|
|
|
Uint('TZ0', bl=3)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
if isinstance(vals, float):
|
|
|
|
|
self.encode(vals)
|
|
|
|
|
else:
|
|
|
|
|
Envelope.set_val(self, vals)
|
|
|
|
|
|
|
|
|
|
def encode(self, val):
|
|
|
|
|
if val < 0:
|
|
|
|
|
self[1].set_val(1)
|
|
|
|
|
val = -val
|
|
|
|
|
else:
|
|
|
|
|
self[1].set_val(0)
|
|
|
|
|
if val != 0:
|
|
|
|
|
quart = ceil((val*4) % 128)
|
|
|
|
|
self[0].set_val( quart%16 )
|
|
|
|
|
self[2].set_val( quart>>4 )
|
|
|
|
|
else:
|
|
|
|
|
self[0].set_val(0)
|
|
|
|
|
self[2].set_val(0)
|
|
|
|
|
|
|
|
|
|
def decode(self):
|
|
|
|
|
if self[1]() == 1:
|
|
|
|
|
return -0.25 * ((self[2]()<<4) + self[0]())
|
|
|
|
|
else:
|
|
|
|
|
return 0.25 * ((self[2]()<<4) + self[0]())
|
|
|
|
|
|
|
|
|
|
def repr(self):
|
|
|
|
|
return '<TimeZone: %s%.2f>' % (self._Sign_dict[self[1]()], 0.25 * (self[0]() + (self[2]()<<4)))
|
|
|
|
|
|
|
|
|
|
__repr__ = repr
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Time Zone and Time
|
|
|
|
|
# TS 24.008, section 10.5.3.9
|
|
|
|
|
#------------------------------------------------------------------------------#
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# identical to TS23040_SMS.TP_SCTS structure
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _TP_SCTS_Comp(Envelope):
|
|
|
|
|
|
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
if isinstance(vals, integer_types):
|
|
|
|
|
self.encode(vals)
|
|
|
|
|
else:
|
|
|
|
|
Envelope.set_val(self, vals)
|
|
|
|
|
|
|
|
|
|
def encode(self, val):
|
|
|
|
|
self.set_val( (val%10, val//10) )
|
|
|
|
|
|
|
|
|
|
def decode(self):
|
|
|
|
|
return self[0]()+10*self[1]()
|
|
|
|
|
|
|
|
|
|
def repr(self):
|
|
|
|
|
return '<%s : %i%i>' % (self._name, self[1](), self[0]())
|
|
|
|
|
|
|
|
|
|
__repr__ = repr
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
class TimeZoneTime(Envelope):
|
2019-11-08 15:11:02 +00:00
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
YEAR_BASE = 2000
|
2019-11-08 15:11:02 +00:00
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
_GEN = (
|
|
|
|
|
_TP_SCTS_Comp('Year', GEN=(Uint('Y1', bl=4), Uint('Y0', bl=4))),
|
|
|
|
|
_TP_SCTS_Comp('Mon', GEN=(Uint('M1', bl=4), Uint('M0', bl=4))),
|
|
|
|
|
_TP_SCTS_Comp('Day', GEN=(Uint('D1', bl=4), Uint('D0', bl=4))),
|
|
|
|
|
_TP_SCTS_Comp('Hour', GEN=(Uint('H1', bl=4), Uint('H0', bl=4))),
|
|
|
|
|
_TP_SCTS_Comp('Min', GEN=(Uint('M1', bl=4), Uint('M0', bl=4))),
|
|
|
|
|
_TP_SCTS_Comp('Sec', GEN=(Uint('S1', bl=4), Uint('S0', bl=4))),
|
|
|
|
|
TimeZone('TimeZone')
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def set_val(self, val):
|
|
|
|
|
if isinstance(val, (tuple, list)) and len(val) == 2:
|
|
|
|
|
self.encode(*val)
|
|
|
|
|
else:
|
|
|
|
|
Envelope.set_val(self, val)
|
|
|
|
|
|
|
|
|
|
def encode(self, ts, tz=0.0):
|
|
|
|
|
"""encode a Python struct_time and potential timezone shift as the value of
|
|
|
|
|
the TimeZoneTime
|
|
|
|
|
"""
|
|
|
|
|
self['Year'].encode( ts.tm_year-self.YEAR_BASE )
|
|
|
|
|
self['Mon'].encode( ts.tm_mon )
|
|
|
|
|
self['Day'].encode( ts.tm_mday )
|
|
|
|
|
self['Hour'].encode( ts.tm_hour )
|
|
|
|
|
self['Min'].encode( ts.tm_min )
|
|
|
|
|
self['Sec'].encode( ts.tm_sec )
|
|
|
|
|
self['TZ'].encode( tz )
|
|
|
|
|
|
|
|
|
|
def decode(self):
|
|
|
|
|
"""decode the value of the TimeZoneTime into a Python struct_time and
|
|
|
|
|
timezone shift
|
|
|
|
|
"""
|
2019-11-08 15:11:02 +00:00
|
|
|
|
ts = struct_time((
|
|
|
|
|
self.YEAR_BASE+self['Year'].decode(),
|
|
|
|
|
self['Mon'].decode(),
|
|
|
|
|
self['Day'].decode(),
|
|
|
|
|
self['Hour'].decode(),
|
|
|
|
|
self['Min'].decode(),
|
|
|
|
|
self['Sec'].decode(),
|
|
|
|
|
0, 0, 0))
|
2017-11-12 14:18:50 +00:00
|
|
|
|
return ts, self['TimeZone'].decode()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Daylight Saving Time
|
|
|
|
|
# TS 24.008, section 10.5.3.12
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_DLSavingTime = {
|
|
|
|
|
0 : 'No adjustment for Daylight Saving Time',
|
|
|
|
|
1 : '+1 hour adjustment for Daylight Saving Time',
|
|
|
|
|
2 : '+2 hours adjustment for Daylight Saving Time',
|
|
|
|
|
3 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DLSavingTime(Envelope):
|
2017-07-04 21:12:41 +00:00
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=6),
|
|
|
|
|
Uint('Value', bl=2, dic=_DLSavingTime)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Supported codec list
|
|
|
|
|
# TS 24.008, section 10.5.4.32
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class SuppCodec(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('SysID'),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
Uint8('BMLen'),
|
|
|
|
|
Buf('CodecBM', val=b'\0', rep=REPR_BIN),
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
Envelope.__init__(self, *args, **kw)
|
|
|
|
|
self[1].set_valauto( self[2].get_len )
|
|
|
|
|
self[2].set_blauto( lambda: 8*self[1]() )
|
|
|
|
|
|
|
|
|
|
class SuppCodecList(Array):
|
|
|
|
|
_GEN = SuppCodec()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Emergency Service Category
|
|
|
|
|
# TS 24.008, section 10.5.4.33
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class EmergServiceCat(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Police', bl=1),
|
|
|
|
|
Uint('Ambulance', bl=1),
|
|
|
|
|
Uint('Fire', bl=1),
|
|
|
|
|
Uint('Marine', bl=1),
|
|
|
|
|
Uint('Mountain', bl=1),
|
|
|
|
|
Uint('manual eCall', bl=1),
|
|
|
|
|
Uint('auto eCall', bl=1),
|
|
|
|
|
Uint('spare', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Emergency Number List
|
|
|
|
|
# TS 24.008, section 10.5.3.13
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class EmergNum(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint8('Len'),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
2017-09-01 19:46:10 +00:00
|
|
|
|
EmergServiceCat('ServiceCat')[:5],
|
|
|
|
|
BufBCD('Num')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
Envelope.__init__(self, *args, **kw)
|
2017-09-16 16:11:34 +00:00
|
|
|
|
self[2]._name = 'ServiceCat' # otherwise, it says 'slice'
|
|
|
|
|
self._by_name[2] = 'ServiceCat' # otherwise, it says 'slice'
|
2017-07-04 21:12:41 +00:00
|
|
|
|
self[0].set_valauto( lambda: 1 + self[3].get_len() )
|
|
|
|
|
self[3].set_blauto( lambda: 8*(self[0]()-1) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EmergNumList(Array):
|
|
|
|
|
_GEN = EmergNum()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Additional Update Parameters
|
|
|
|
|
# TS 24.008, 10.5.3.14
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CSMO_dict = {
|
|
|
|
|
1 : 'CS fallback MO call'
|
|
|
|
|
}
|
|
|
|
|
_CSMT_dict = {
|
|
|
|
|
1 : 'CS fallback MT call'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AddUpdateParams(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('CSMO', bl=1, dic=_CSMO_dict),
|
|
|
|
|
Uint('CSMT', bl=1, dic=_CSMT_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# MM Timer
|
|
|
|
|
# TS 24.008, 10.5.3.16
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_MMTimerUnit_dict = {
|
|
|
|
|
0 : '2 sec',
|
|
|
|
|
1 : '1 min',
|
|
|
|
|
2 : '6 min',
|
|
|
|
|
7 : 'timer deactivated'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MMTimer(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Unit', bl=3, dic=_MMTimerUnit_dict),
|
|
|
|
|
Uint('Value', bl=5)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Auxiliary states
|
|
|
|
|
# TS 24.008, 10.5.4.4
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_AuxHold_dict = {
|
|
|
|
|
0 : 'idle',
|
|
|
|
|
1 : 'hold request',
|
|
|
|
|
2 : 'call held',
|
|
|
|
|
3 : 'retrieve request'
|
|
|
|
|
}
|
|
|
|
|
_AuxMPTY_dict = {
|
|
|
|
|
0 : 'idle',
|
|
|
|
|
1 : 'MPTY request',
|
|
|
|
|
2 : 'call in MPTY',
|
|
|
|
|
3 : 'split request'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AuxiliaryStates(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Hold', bl=2, dic=_AuxHold_dict),
|
|
|
|
|
Uint('MPTY', bl=2, dic=_AuxMPTY_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Backup bearer capability
|
|
|
|
|
# TS 24.008, 10.5.4.4a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_RadioChanReq_dict = {
|
|
|
|
|
0:'reserved',
|
|
|
|
|
1:'full rate support only MS',
|
|
|
|
|
2:'dual rate support MS/half rate preferred',
|
|
|
|
|
3:'dual rate support MS/full rate preferred'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_BCapCodingStd_dict = {
|
|
|
|
|
0 : 'GSM standardized coding',
|
|
|
|
|
1 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_TransferMode_dict = {
|
|
|
|
|
0:'circuit',
|
|
|
|
|
1:'packet'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_TransferCap_dict = {
|
|
|
|
|
0:'speech',
|
|
|
|
|
1:'unrestricted digital information',
|
|
|
|
|
2:'3.1 kHz audio, ex PLMN',
|
|
|
|
|
3:'facsimile group 3',
|
|
|
|
|
5:'Other ITC (See Octet 5a)',
|
|
|
|
|
7:'reserved, to be used in the network'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _BearerCapOct4(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Compress', bl=1),
|
|
|
|
|
Uint('Structure', bl=2),
|
|
|
|
|
Uint('DuplexMode', bl=1),
|
|
|
|
|
Uint('Config', bl=1),
|
|
|
|
|
Uint('NIRR', bl=1),
|
|
|
|
|
Uint('Estab', bl=1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt5a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('OtherITC', bl=2),
|
|
|
|
|
Uint('OtherRateAdapt', bl=2),
|
|
|
|
|
Uint('spare', bl=3)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BUBearerCapOct5(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('AccessId', bl=2),
|
|
|
|
|
Uint('RateAdapt', bl=2),
|
|
|
|
|
Uint('SignalAccessProt', bl=3),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BearerCapExt5a('Ext5a')
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[4].set_transauto(lambda: self[0]() == 1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class _BearerCapExt6a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('NumStopBits', bl=1),
|
|
|
|
|
Uint('Negotation', bl=1),
|
|
|
|
|
Uint('NumDataBits', bl=1),
|
|
|
|
|
Uint('UserRate', bl=4)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6b(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('IntermedRate', bl=2),
|
|
|
|
|
Uint('NICOnTx', bl=1),
|
|
|
|
|
Uint('NICOnRx', bl=1),
|
|
|
|
|
Uint('Parity', bl=3)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6c(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('ConnectElt', bl=2),
|
|
|
|
|
Uint('ModemType', bl=5)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6d(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('OtherModemType', bl=2),
|
|
|
|
|
Uint('FixedNetUserRate', bl=5)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6e(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('AcceptableChanCodings', bl=4),
|
|
|
|
|
Uint('MaxNumOfTrafficChan', bl=3)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6f(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('UIMI', bl=3),
|
|
|
|
|
Uint('WantedAirIFUserRate', bl=4)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt6g(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('AcceptableChanCodingsExt', bl=3),
|
|
|
|
|
Uint('AssymetryInd', bl=2),
|
|
|
|
|
Uint('spare', bl=2)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapOct6(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('Layer1Id', val=1, bl=2),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('UserInfoLayer1Prot', bl=4),
|
|
|
|
|
Uint('Sync', bl=1),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BearerCapExt6a('Ext6a'),
|
|
|
|
|
_BearerCapExt6b('Ext6b'),
|
|
|
|
|
_BearerCapExt6c('Ext6c'),
|
|
|
|
|
_BearerCapExt6d('Ext6d'),
|
|
|
|
|
_BearerCapExt6e('Ext6e'),
|
|
|
|
|
_BearerCapExt6f('Ext6f'),
|
|
|
|
|
_BearerCapExt6g('Ext6g')
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[4].set_transauto(lambda: self[0]() == 1)
|
|
|
|
|
self[5].set_transauto(lambda: self[4].get_trans() or self[4][0]() == 1)
|
|
|
|
|
self[6].set_transauto(lambda: self[5].get_trans() or self[5][0]() == 1)
|
|
|
|
|
self[7].set_transauto(lambda: self[6].get_trans() or self[6][0]() == 1)
|
|
|
|
|
self[8].set_transauto(lambda: self[7].get_trans() or self[7][0]() == 1)
|
|
|
|
|
self[9].set_transauto(lambda: self[8].get_trans() or self[8][0]() == 1)
|
|
|
|
|
self[10].set_transauto(lambda: self[9].get_trans() or self[9][0]() == 1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class _BearerCapOct7(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('Layer2Id', val=2, bl=2),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('UserInfoLayer2Prot', bl=5)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class BackupBearerCap(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('RadioChanReq', val=1, bl=2, dic=_RadioChanReq_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=1, dic=_BCapCodingStd_dict),
|
|
|
|
|
Uint('TransferMode', bl=1, dic=_TransferMode_dict),
|
|
|
|
|
Uint('InfoTransferCap', bl=3, dic=_TransferCap_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BearerCapOct4('Oct4', trans=True),
|
|
|
|
|
_BUBearerCapOct5('Oct5', trans=True),
|
|
|
|
|
_BearerCapOct6('Oct6', trans=True),
|
|
|
|
|
_BearerCapOct7('Oct7', trans=True)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct4
|
|
|
|
|
self[5].set_trans(False)
|
|
|
|
|
self[5]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct5
|
|
|
|
|
self[6].set_trans(False)
|
|
|
|
|
self[6]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct6
|
|
|
|
|
self[7].set_trans(False)
|
|
|
|
|
self[7]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct7
|
|
|
|
|
self[8].set_trans(False)
|
|
|
|
|
self[8]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Bearer capability
|
|
|
|
|
# TS 24.008, 10.5.4.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CTMSupp_dict = {
|
|
|
|
|
0 : 'CTM text telephony is not supported',
|
|
|
|
|
1 : 'CTM text telephony is supported'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_CodingExt3_dict = {
|
|
|
|
|
0 : 'octet used for extension of information transfer capability',
|
|
|
|
|
1 : 'octet used for other extension of octet 3'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_SpeechVersInd_dict = {
|
|
|
|
|
0 : 'GSM FR v1 (GSM FR)',
|
|
|
|
|
2 : 'GSM FR v2 (GSM EFR)',
|
|
|
|
|
4 : 'GSM FR v3 (FR AMR)',
|
|
|
|
|
6 : 'GSM FR v4',
|
|
|
|
|
8 : 'GSM FR v5',
|
|
|
|
|
1 : 'GSM HR v1 (GSM HR)',
|
|
|
|
|
5 : 'GSM HR v3 (HR AMR)',
|
|
|
|
|
7 : 'GSM HR v4',
|
|
|
|
|
11 : 'GSM HR v6',
|
|
|
|
|
15 : 'no speech version supported for GERAN'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt3a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Coding', bl=1, dic=_CodingExt3_dict),
|
|
|
|
|
Uint('CTM', bl=1, dic=_CTMSupp_dict),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('SpeechVersionInd', bl=4, dic=_SpeechVersInd_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt3bRec(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Coding', bl=1, dic=_CodingExt3_dict),
|
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('SpeechVersionInd', bl=4, dic=_SpeechVersInd_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt3b(Sequence):
|
|
|
|
|
_GEN = _BearerCapExt3bRec()
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
# while Ext bit is 1, stack another sequenced element
|
|
|
|
|
if self.get_trans():
|
|
|
|
|
return
|
|
|
|
|
# 1) determine the number of iteration of the template within the sequence
|
|
|
|
|
num = None
|
|
|
|
|
# 2) init content
|
|
|
|
|
self._content = []
|
|
|
|
|
# 3) consume char and fill in self._content
|
|
|
|
|
# there is no predefined limit in the number of repeated content
|
|
|
|
|
# consume the charpy instance until Ext == 1
|
|
|
|
|
while True:
|
|
|
|
|
# remember charpy cursor position, to restore it when it raises
|
|
|
|
|
cur = char._cur
|
|
|
|
|
clone = self._tmpl.clone()
|
|
|
|
|
try:
|
|
|
|
|
clone._from_char(char)
|
|
|
|
|
except CharpyErr as err:
|
|
|
|
|
char._cur = cur
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
self._content.append(clone)
|
|
|
|
|
clone._env = self
|
|
|
|
|
if clone[0]() == 1:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
class _BearerCapExt5b(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Hdr', bl=1),
|
|
|
|
|
Uint('Multiframe', bl=1),
|
|
|
|
|
Uint('Mode', bl=1),
|
|
|
|
|
Uint('LLI', bl=1),
|
|
|
|
|
Uint('Assignor', bl=1),
|
|
|
|
|
Uint('InbNeg', bl=1),
|
|
|
|
|
Uint('spare', bl=1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _BearerCapOct5(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('AccessId', bl=2),
|
|
|
|
|
Uint('RateAdapt', bl=2),
|
|
|
|
|
Uint('SignalAccessProt', bl=3),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BearerCapExt5a('Ext5a'),
|
|
|
|
|
_BearerCapExt5b('Ext5b')
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[4].set_transauto(lambda: self[0]() == 1)
|
|
|
|
|
self[5].set_transauto(lambda: self[4].get_trans() or self[4][0]() == 1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class BearerCap(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('RadioChanReq', val=1, bl=2, dic=_RadioChanReq_dict),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=1, dic=_BCapCodingStd_dict),
|
|
|
|
|
Uint('TransferMode', bl=1, dic=_TransferMode_dict),
|
|
|
|
|
Uint('InfoTransferCap', bl=3, dic=_TransferCap_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BearerCapExt3a('Ext3a'),
|
|
|
|
|
_BearerCapExt3b('Ext3b'),
|
|
|
|
|
_BearerCapOct4('Oct4', trans=True),
|
|
|
|
|
_BearerCapOct5('Oct5', trans=True),
|
|
|
|
|
_BearerCapOct6('Oct6', trans=True),
|
|
|
|
|
_BearerCapOct7('Oct7', trans=True)
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[5].set_transauto(lambda: self[0]() == 1)
|
|
|
|
|
self[6].set_transauto(lambda: self[5].get_trans() or self[5][0]() == 1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct4
|
|
|
|
|
self[7].set_trans(False)
|
|
|
|
|
self[7]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct5
|
|
|
|
|
self[8].set_trans(False)
|
|
|
|
|
self[8]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct6
|
|
|
|
|
self[9].set_trans(False)
|
|
|
|
|
self[9]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if char.len_byte():
|
2017-11-12 14:18:50 +00:00
|
|
|
|
# Oct7
|
|
|
|
|
self[10].set_trans(False)
|
|
|
|
|
self[10]._from_char(char)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Call Control Capabilities
|
|
|
|
|
# TS 24.008, 10.5.4.5a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class CCCap(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('MaxNumSupportedBearers', bl=4),
|
|
|
|
|
Uint('MultimediaCAT', bl=1),
|
|
|
|
|
Uint('ENICM', bl=1),
|
|
|
|
|
Uint('PCP', bl=1),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint('DTMF', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('MaxNumSpeechBearers', bl=4)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Call state
|
|
|
|
|
# TS 24.008, 10.5.4.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CodingStd_dict = {
|
|
|
|
|
0 : 'Standardized coding, as described in ITU-T Q.931',
|
|
|
|
|
1 : 'Reserved for other international standards',
|
|
|
|
|
2 : 'National standard',
|
|
|
|
|
3 : 'Standard defined for the GSM PLMNs'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_CallState_dict = {
|
|
|
|
|
0 : 'null',
|
|
|
|
|
2 : 'MM connection pending',
|
|
|
|
|
34 : 'CC prompt present',
|
|
|
|
|
35 : 'Wait for network information',
|
|
|
|
|
36 : 'CC-Establishment present',
|
|
|
|
|
37 : 'CC-Establishment confirmed',
|
|
|
|
|
38 : 'Recall present',
|
|
|
|
|
1 : 'call initiated',
|
|
|
|
|
3 : 'mobile originating call proceeding',
|
|
|
|
|
4 : 'call delivered',
|
|
|
|
|
6 : 'call present',
|
|
|
|
|
7 : 'call received',
|
|
|
|
|
8 : 'connect request',
|
|
|
|
|
9 : 'mobile terminating call confirmed',
|
|
|
|
|
10 : 'active',
|
|
|
|
|
11 : 'disconnect request',
|
|
|
|
|
12 : 'disconnect indication',
|
|
|
|
|
19 : 'release request',
|
|
|
|
|
26 : 'mobile originating modify',
|
|
|
|
|
27 : 'mobile terminating modify',
|
|
|
|
|
28 : 'connect indication'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class CallState(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=2, dic=_CodingStd_dict),
|
|
|
|
|
Uint('Value', bl=6, dic=_CallState_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Called party BCD number
|
|
|
|
|
# TS 24.008, 10.5.4.7
|
|
|
|
|
#------------------------------------------------------------------------------#
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
# generic BCD number
|
2017-12-15 20:24:07 +00:00
|
|
|
|
# BCDType and NumPlan are extended with values from TS 23.040, section 9.1.2.15
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
_BCDType_dict = {
|
|
|
|
|
0 : 'unknown',
|
|
|
|
|
1 : 'international number',
|
|
|
|
|
2 : 'national number',
|
|
|
|
|
3 : 'network specific number',
|
|
|
|
|
4 : 'dedicated access, short code',
|
2019-07-02 15:01:22 +00:00
|
|
|
|
5 : 'alphanumeric', # only for SMS
|
|
|
|
|
6 : 'abbreviated number', # only for SMS
|
2017-11-12 14:18:50 +00:00
|
|
|
|
7 : _str_reserved
|
2017-07-04 21:12:41 +00:00
|
|
|
|
}
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
_NumPlan_dict = {
|
|
|
|
|
0 : 'unknown',
|
|
|
|
|
1 : 'ISDN / telephony numbering plan (E.164 / E.163)',
|
2017-12-15 20:24:07 +00:00
|
|
|
|
2 : 'generic numbering plan',
|
2017-07-04 21:12:41 +00:00
|
|
|
|
3 : 'data numbering plan (X.121)',
|
|
|
|
|
4 : 'telex numbering plan (F.69)',
|
2019-07-02 15:01:22 +00:00
|
|
|
|
5 : 'service center specific', # only for SMS
|
|
|
|
|
6 : 'service center specific', # only for SMS
|
2017-07-04 21:12:41 +00:00
|
|
|
|
8 : 'national numbering plan',
|
|
|
|
|
9 : 'private numbering plan',
|
2019-07-02 15:01:22 +00:00
|
|
|
|
10: 'ERMES numbering plan', # only for SMS
|
2017-07-04 21:12:41 +00:00
|
|
|
|
11: 'reserved for CTS',
|
2017-11-12 14:18:50 +00:00
|
|
|
|
15: _str_reserved
|
2017-07-04 21:12:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_PresInd_dict = {
|
|
|
|
|
0 : 'presentation allowed',
|
|
|
|
|
1 : 'presentation restricted',
|
|
|
|
|
2 : 'number not available due to interworking',
|
|
|
|
|
3 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_ScreenInd_dict = {
|
|
|
|
|
0 : 'user-provided, not screened',
|
|
|
|
|
1 : 'user-provided, verified and passed',
|
|
|
|
|
2 : 'user-provided, verified and failed',
|
|
|
|
|
3 : 'network provided'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _BCDNumberExt3a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('PresentationInd', bl=2, dic=_PresInd_dict),
|
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('ScreeningInd', bl=2, dic=_ScreenInd_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
class BCDNumber(Envelope):
|
2017-10-22 12:03:18 +00:00
|
|
|
|
ENV_SEL_TRANS = False
|
2017-07-04 21:12:41 +00:00
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
|
|
|
|
Uint('Type', val=1, bl=3, dic=_BCDType_dict),
|
|
|
|
|
Uint('NumberingPlan', val=1, bl=4, dic=_NumPlan_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_BCDNumberExt3a('Ext3a'),
|
2017-07-04 21:12:41 +00:00
|
|
|
|
BufBCD('Num')
|
|
|
|
|
)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[3].set_transauto(lambda: self[0]() == 1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class CalledPartyBCDNumber(BCDNumber):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Called party subaddress
|
|
|
|
|
# TS 24.008, 10.5.4.8
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
# generic sub-address
|
|
|
|
|
|
|
|
|
|
_SubaddrType_dict = {
|
|
|
|
|
0 : 'NSAP',
|
|
|
|
|
2 : 'user defined'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Subaddress(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Type', bl=3, dic=_SubaddrType_dict),
|
|
|
|
|
Uint('Odd', bl=1),
|
|
|
|
|
Uint('spare', bl=3),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Buf('Addr', val=b'', rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class CalledPartySubaddress(Subaddress):
|
|
|
|
|
pass
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Calling party BCD number
|
|
|
|
|
# TS 24.008, 10.5.4.9
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class CallingPartyBCDNumber(BCDNumber):
|
|
|
|
|
pass
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Calling party subaddress
|
|
|
|
|
# TS 24.008, 10.5.4.10
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class CallingPartySubaddress(Subaddress):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Cause
|
|
|
|
|
# TS 24.008, 10.5.4.11
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_Location_dict = {
|
|
|
|
|
0 : 'User',
|
|
|
|
|
1 : 'Private network serving the local user',
|
|
|
|
|
2 : 'Public network serving the local user',
|
|
|
|
|
4 : 'Public network serving the remote user',
|
|
|
|
|
5 : 'Private network serving the remote user',
|
|
|
|
|
10 : 'Network beyond interworking point'
|
2017-07-04 21:12:41 +00:00
|
|
|
|
}
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
_CauseClass_dict = {
|
|
|
|
|
0 : 'normal event',
|
|
|
|
|
1 : 'normal event',
|
|
|
|
|
2 : 'resource unavailable',
|
|
|
|
|
3 : 'service or option not available',
|
|
|
|
|
4 : 'service or option not implemented',
|
|
|
|
|
5 : 'invalid message (e.g. parameter out of range)',
|
|
|
|
|
6 : 'protocol error (e.g. unknown message)',
|
|
|
|
|
7 : 'interworking'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_CauseValue_dict = {
|
|
|
|
|
0 : {
|
|
|
|
|
1 : 'Unassigned (unallocated) number',
|
|
|
|
|
3 : 'No route to destination',
|
|
|
|
|
6 : 'Channel unacceptable',
|
|
|
|
|
8 : 'Operator determined barring'
|
|
|
|
|
},
|
|
|
|
|
1 : {
|
|
|
|
|
0 : 'Normal call clearing',
|
|
|
|
|
1 : 'User busy',
|
|
|
|
|
2 : 'No user responding',
|
|
|
|
|
3 : 'User alerting, no answer',
|
|
|
|
|
5 : 'Call rejected',
|
|
|
|
|
6 : 'Number changed',
|
|
|
|
|
8 : 'Call rejected due to feature at the destination',
|
|
|
|
|
9 : 'Pre-emption',
|
|
|
|
|
10 : 'Non selected user clearing',
|
|
|
|
|
11 : 'Destination out of order',
|
|
|
|
|
12 : 'Invalid number format (incomplete number)',
|
|
|
|
|
13 : 'Facility rejected',
|
|
|
|
|
14 : 'Response to STATUS ENQUIRY',
|
|
|
|
|
15 : 'Normal, unspecified'
|
|
|
|
|
},
|
|
|
|
|
2 : {
|
|
|
|
|
2 : 'No circuit/channel available',
|
|
|
|
|
6 : 'Network out of order',
|
|
|
|
|
9 : 'Temporary failure',
|
|
|
|
|
10 : 'Switching equipment congestion',
|
|
|
|
|
11 : 'Access information discarded',
|
|
|
|
|
12 : 'requested circuit/channel not available',
|
|
|
|
|
15 : 'Resources unavailable, unspecified'
|
|
|
|
|
},
|
|
|
|
|
3 : {
|
|
|
|
|
1 : 'Quality of service unavailable',
|
|
|
|
|
2 : 'Requested facility not subscribed',
|
|
|
|
|
7 : 'Incoming calls barred within the CUG',
|
|
|
|
|
9 : 'Bearer capability not authorized',
|
|
|
|
|
10 : 'Bearer capability not presently available',
|
|
|
|
|
15 : 'Service or option not available, unspecified'
|
|
|
|
|
},
|
|
|
|
|
4 : {
|
|
|
|
|
1 : 'Bearer service not implemented',
|
|
|
|
|
4 : 'ACM equal to or greater than ACMmax',
|
|
|
|
|
5 : 'Requested facility not implemented',
|
|
|
|
|
6 : 'Only restricted digital information bearer capability is available',
|
|
|
|
|
15 : 'Service or option not implemented, unspecified'
|
|
|
|
|
},
|
|
|
|
|
5 : {
|
|
|
|
|
1 : 'Invalid transaction identifier value',
|
|
|
|
|
7 : 'User not member of CUG',
|
|
|
|
|
8 : 'Incompatible destination',
|
|
|
|
|
11 : 'Invalid transit network selection',
|
|
|
|
|
15 : 'Semantically incorrect message'
|
|
|
|
|
},
|
|
|
|
|
6 : {
|
|
|
|
|
0 : 'Invalid mandatory information',
|
|
|
|
|
1 : 'Message type non-existent or not implemented',
|
|
|
|
|
2 : 'Message type not compatible with protocol state',
|
|
|
|
|
3 : 'Information element non-existent or not implemented',
|
|
|
|
|
4 : 'Conditional IE error',
|
|
|
|
|
5 : 'Message not compatible with protocol state',
|
|
|
|
|
6 : 'Recovery on timer expiry',
|
|
|
|
|
15 : 'Protocol error, unspecified'
|
|
|
|
|
},
|
|
|
|
|
7 : {
|
|
|
|
|
15 : 'Interworking, unspecified'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _CauseExt3a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Recommendation', bl=7)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class Cause(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=2, dic=_CodingStd_dict),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Location', bl=4, dic=_Location_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_CauseExt3a('Ext3a'),
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Class', bl=3, dic=_CauseClass_dict),
|
|
|
|
|
Uint('Value', bl=4),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Buf('Diagnostic', val=b'')
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[4].set_transauto(lambda: self[0]() == 1)
|
|
|
|
|
self[7].set_dicauto(lambda: _CauseValue_dict[self[6]()])
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Congestion level
|
|
|
|
|
# TS 24.008, 10.5.4.12
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
CongestionLevel_dict = {
|
|
|
|
|
0 : 'receiver ready',
|
|
|
|
|
15 : 'receiver not ready'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Connected number
|
|
|
|
|
# TS 24.008, 10.5.4.13
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class ConnectedNumber(BCDNumber):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Connected subaddress
|
|
|
|
|
# TS 24.008, 10.5.4.14
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class ConnectedSubaddress(Subaddress):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# High layer compatibility
|
|
|
|
|
# TS 24.008, 10.5.4.16
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class _HighLayerCompOct3(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=2, dic=_CodingStd_dict),
|
|
|
|
|
Uint('Interpretation', bl=3),
|
|
|
|
|
Uint('PresentationMethProtProfile', bl=2)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _HighLayerCompExt4a(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('HighLayerCharIdentExt', bl=7)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class _HighLayerCompOct4(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Ext', bl=1),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint('HighLayerCharIdent', bl=7),
|
|
|
|
|
_HighLayerCompExt4a('Ext4a')
|
|
|
|
|
)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[2].set_transauto(lambda: self[0]() == 1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class HighLayerComp(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
_HighLayerCompOct3('Oct3', trans=True),
|
|
|
|
|
_HighLayerCompOct4('Oct4', trans=True)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
l = char.len_byte()
|
|
|
|
|
if l > 1:
|
|
|
|
|
self[0].set_trans(False)
|
|
|
|
|
self[1].set_trans(False)
|
|
|
|
|
elif l == 1:
|
|
|
|
|
self[0].set_trans(False)
|
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Notification indicator
|
|
|
|
|
# TS 24.008, 10.5.4.20
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_Notification_dict = {
|
|
|
|
|
0 : 'User suspended',
|
|
|
|
|
1 : 'User resumed',
|
|
|
|
|
2 : 'Bearer change'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NotificationInd(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Notification', bl=7, dic=_Notification_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Progress indicator
|
|
|
|
|
# TS 24.008, 10.5.4.21
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_Progress_dict = {
|
|
|
|
|
1 : 'Call is not end-to-end PLMN/ISDN, further call progress information may be available in-band',
|
|
|
|
|
2 : 'Destination address in non-PLMN/ISDN',
|
|
|
|
|
3 : 'Origination address in non-PLMN/ISDN',
|
|
|
|
|
4 : 'Call has returned to the PLMN/ISDN',
|
|
|
|
|
8 : 'In-band information or appropriate pattern now available',
|
|
|
|
|
9 : 'In-band multimedia CAT available',
|
|
|
|
|
32: 'Call is end-to-end PLMN/ISDN',
|
|
|
|
|
64: 'Queueing'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProgressInd(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CodingStd', bl=2, dic=_CodingStd_dict),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Location', bl=4, dic=_Location_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Progress', bl=7, dic=_Progress_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Recall type $(CCBS)$
|
|
|
|
|
# TS 24.008, 10.5.4.21a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_RecallType_dict = {
|
|
|
|
|
0 : 'CCBS',
|
|
|
|
|
7 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RecallType(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=5),
|
|
|
|
|
Uint('Value', bl=3, dic=_RecallType_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Redirecting party BCD number
|
|
|
|
|
# TS 24.008, 10.5.4.21b
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class RedirectingPartyBCDNumber(BCDNumber):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Redirecting party subaddress
|
|
|
|
|
# TS 24.008, 10.5.4.21c
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class RedirectingPartySubaddress(Subaddress):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Repeat indicator
|
|
|
|
|
# TS 24.008, 10.5.4.22
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
RepeatInd_dict = {
|
|
|
|
|
1 : 'Circular for successive selection, mode 1 alternate mode 2',
|
|
|
|
|
2 : 'Support of fallback, mode 1 preferred, mode 2 selected if setup of mode 1 fails',
|
|
|
|
|
3 : _str_reserved,
|
|
|
|
|
4 : 'Service change and fallback, mode 1 alternate mode 2, mode 1 preferred'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Signal
|
|
|
|
|
# TS 24.008, 10.5.4.23
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_Signal_dict = {
|
|
|
|
|
0 : 'dial tone on',
|
|
|
|
|
1 : 'ring back tone on',
|
|
|
|
|
2 : 'intercept tone on',
|
|
|
|
|
3 : 'network congestion tone on',
|
|
|
|
|
4 : 'busy tone on',
|
|
|
|
|
5 : 'confirm tone on',
|
|
|
|
|
6 : 'answer tone on',
|
|
|
|
|
7 : 'call waiting tone on',
|
|
|
|
|
8 : 'off-hook warning tone on',
|
|
|
|
|
63 : 'tones off',
|
|
|
|
|
79 : 'alerting off'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Signal(Uint8):
|
|
|
|
|
_dic = _Signal_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# User-user
|
|
|
|
|
# TS 24.008, 10.5.4.25
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_UUType_dict = {
|
|
|
|
|
0 : 'User specific protocol',
|
|
|
|
|
1 : 'OSI high layer protocols',
|
|
|
|
|
2 : 'X.244',
|
|
|
|
|
3 : 'Reserved for system management convergence function',
|
|
|
|
|
4 : 'IA5 characters',
|
|
|
|
|
7 : 'rate adaption according to ITU-T V.120',
|
|
|
|
|
8 : 'user-network call control messages according to ITU-T Q.931',
|
|
|
|
|
79: '3GPP capability exchange protocol'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class UserUser(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint8('Type', val=4, dic=_UUType_dict),
|
|
|
|
|
Buf('Data', val=b'') # should be 32 or 128 bytes
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Alerting Pattern $(NIA)$
|
|
|
|
|
# TS 24.008, 10.5.4.26
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class AlertingPattern(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('Value', bl=4)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Allowed actions $(CCBS)$
|
|
|
|
|
# TS 24.008, 10.5.4.27
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CCBSAct_dict = {
|
|
|
|
|
0 : 'Activation of CCBS not possible',
|
|
|
|
|
1 : 'Activation of CCBS possible'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class CCBSAllowedActions(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('CCBSAct', bl=1, dic=_CCBSAct_dict),
|
|
|
|
|
Uint('spare', bl=7)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Stream Identifier
|
|
|
|
|
# TS 24.008, 10.5.4.28
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class StreamIdent(Uint8):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Network Call Control Capabilities
|
|
|
|
|
# TS 24.008, 10.5.4.29
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class NetCCCap(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=7),
|
|
|
|
|
Uint('MultiCallSupport', bl=1)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Cause of No CLI
|
|
|
|
|
# TS 24.008, 10.5.4.30
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CauseNoCLI_dict = {
|
|
|
|
|
0 : 'Unavailable',
|
|
|
|
|
1 : 'Reject by user',
|
|
|
|
|
2 : 'Interaction with other service',
|
|
|
|
|
3 : 'Coin line/payphone'
|
2017-07-04 21:12:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class CauseNoCLI(Uint8):
|
|
|
|
|
_dic = _CauseNoCLI_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Supported codec list
|
|
|
|
|
# TS 24.008, 10.5.4.32
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_CodecSysID_dict = {
|
|
|
|
|
0:'GSM',
|
|
|
|
|
4:'UMTS'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _CodecBitmap(Envelope):
|
2017-07-04 21:12:41 +00:00
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('TDMA_EFR', bl=1),
|
|
|
|
|
Uint('UMTS_AMR2', bl=1),
|
|
|
|
|
Uint('UMTS_AMR', bl=1),
|
|
|
|
|
Uint('HR_AMR', bl=1),
|
|
|
|
|
Uint('FR_AMR', bl=1),
|
|
|
|
|
Uint('GSM_EFR', bl=1),
|
|
|
|
|
Uint('GSM_HR', bl=1),
|
|
|
|
|
Uint('GSM_FR', bl=1),
|
|
|
|
|
Uint('reserved', bl=1),
|
|
|
|
|
Uint('reserved', bl=1),
|
|
|
|
|
Uint('OHR_AMR-WB', bl=1),
|
|
|
|
|
Uint('OFR_AMR-WB', bl=1),
|
|
|
|
|
Uint('OHR_AMR', bl=1),
|
|
|
|
|
Uint('UMTS_AMR-WB', bl=1),
|
|
|
|
|
Uint('FR_AMR-WB', bl=1),
|
|
|
|
|
Uint('PDC_EFR', bl=1),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Buf('spare', val=b'')
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class CodecSysID(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('SysID', dic=_CodecSysID_dict),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint8('BMLen'),
|
|
|
|
|
_CodecBitmap('CodecBM')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
|
|
|
|
self[1].set_valauto(lambda: self[2].get_len())
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
self[0]._from_char(char)
|
|
|
|
|
self[1]._from_char(char)
|
|
|
|
|
l = self[1]()
|
|
|
|
|
clen = char._len_bit
|
|
|
|
|
char._len_bit = char._cur + 8*l
|
2019-12-12 14:00:16 +00:00
|
|
|
|
if char._len_bit > clen:
|
|
|
|
|
raise(EltErr('{0} [_from_char]: bit length overflow'.format(self._name)))
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if l == 1:
|
|
|
|
|
for b in self[8:16]:
|
|
|
|
|
b.set_trans(True)
|
|
|
|
|
self[2]._from_char(char)
|
|
|
|
|
char._len_bit = clen
|
|
|
|
|
|
|
|
|
|
class SupportedCodecs(Sequence):
|
|
|
|
|
_GEN = CodecSysID()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Attach result
|
|
|
|
|
# TS 24.008, 10.5.5.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_AttachResult_dict = {
|
|
|
|
|
1 : 'GPRS-only attached',
|
|
|
|
|
3 : 'Combined GPRS/IMSI attached'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AttachResult(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('FollowOnProc', bl=1),
|
|
|
|
|
Uint('Result', bl=3, dic=_AttachResult_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Attach type
|
|
|
|
|
# TS 24.008, 10.5.5.2
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_AttachType_dict = {
|
|
|
|
|
1 : 'GPRS attach',
|
|
|
|
|
2 : 'Not used (earlier versions)',
|
|
|
|
|
3 : 'Combined GPRS/IMSI attach',
|
|
|
|
|
4 : 'Emergency attach'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AttachType(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('FollowOnReq', bl=1),
|
|
|
|
|
Uint('Type', bl=3, dic=_AttachType_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Ciphering algorithm
|
|
|
|
|
# TS 24.008, 10.5.5.3
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
CiphAlgo_dict = {
|
|
|
|
|
0 : 'ciphering not used',
|
|
|
|
|
1 : 'GEA/1',
|
|
|
|
|
2 : 'GEA/2',
|
|
|
|
|
3 : 'GEA/3',
|
|
|
|
|
4 : 'GEA/4',
|
|
|
|
|
5 : 'GEA/5',
|
|
|
|
|
6 : 'GEA/6',
|
|
|
|
|
7 : 'GEA/7'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Integrity algorithm
|
|
|
|
|
# TS 24.008, 10.5.5.3a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
IntegAlgo_dict = {
|
|
|
|
|
0 : 'GIA/4',
|
|
|
|
|
1 : 'GIA/5',
|
|
|
|
|
2 : 'GIA/6',
|
|
|
|
|
3 : 'GIA/7'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# TMSI Status
|
|
|
|
|
# TS 24.008, 10.5.5.4
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_TMSIStatus_dict = {
|
|
|
|
|
0 : 'no valid TMSI available',
|
|
|
|
|
1 : 'valid TMSI available'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TMSIStatus(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Flag', bl=1, dic=_TMSIStatus_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Detach type
|
|
|
|
|
# TS 24.008, 10.5.5.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_DetachTypeMO_dict = {
|
|
|
|
|
1 : 'GPRS detach',
|
|
|
|
|
2 : 'IMSI detach',
|
|
|
|
|
3 : 'Combined GPRS/IMSI detach'
|
|
|
|
|
}
|
|
|
|
|
_DetachTypeMT_dict = {
|
|
|
|
|
1 : 're-attach required',
|
|
|
|
|
2 : 're-attach not required',
|
|
|
|
|
3 : 'IMSI detach (after VLR failure)'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DetachTypeMO(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('PowerOff', bl=1),
|
|
|
|
|
Uint('Type', bl=3, dic=_DetachTypeMO_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class DetachTypeMT(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Type', bl=3, dic=_DetachTypeMT_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# DRX Parameter
|
|
|
|
|
# TS 24.008, 10.5.5.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_SplitPGCycleC_dict = {
|
|
|
|
|
0 : '704 (no DRX)',
|
|
|
|
|
65 : '71',
|
|
|
|
|
66 : '72',
|
|
|
|
|
67 : '74',
|
|
|
|
|
68 : '75',
|
|
|
|
|
69 : '77',
|
|
|
|
|
70 : '79',
|
|
|
|
|
71 : '80',
|
|
|
|
|
72 : '83',
|
|
|
|
|
73 : '86',
|
|
|
|
|
74 : '88',
|
|
|
|
|
75 : '90',
|
|
|
|
|
76 : '92',
|
|
|
|
|
77 : '96',
|
|
|
|
|
78 : '101',
|
|
|
|
|
79 : '103',
|
|
|
|
|
80 : '107',
|
|
|
|
|
81 : '112',
|
|
|
|
|
82 : '116',
|
|
|
|
|
83 : '118',
|
|
|
|
|
84 : '128',
|
|
|
|
|
85 : '141',
|
|
|
|
|
86 : '144',
|
|
|
|
|
87 : '150',
|
|
|
|
|
88 : '160',
|
|
|
|
|
89 : '171',
|
|
|
|
|
90 : '176',
|
|
|
|
|
91 : '192',
|
|
|
|
|
92 : '214',
|
|
|
|
|
93 : '224',
|
|
|
|
|
94 : '235',
|
|
|
|
|
95 : '256',
|
|
|
|
|
96 : '288',
|
|
|
|
|
97 : '320',
|
|
|
|
|
98 : '352'
|
|
|
|
|
}
|
|
|
|
|
_DRXCycleLen_dict = {
|
|
|
|
|
0 : 'DRX not specified by the MS',
|
|
|
|
|
6 : 'Iu coeff 6 and S1 T = 32',
|
|
|
|
|
7 : 'Iu coeff 7 and S1 T = 64',
|
|
|
|
|
8 : 'Iu coeff 8 and S1 T = 128',
|
|
|
|
|
9 : 'Iu coeff 9 and S1 T = 256'
|
|
|
|
|
}
|
|
|
|
|
_NonDRXTimer_dict = {
|
|
|
|
|
0 : 'no non-DRX mode after transfer state',
|
|
|
|
|
1 : 'max 1 sec non-DRX mode after transfer state',
|
|
|
|
|
2 : 'max 2 sec non-DRX mode after transfer state',
|
|
|
|
|
3 : 'max 4 sec non-DRX mode after transfer state',
|
|
|
|
|
4 : 'max 8 sec non-DRX mode after transfer state',
|
|
|
|
|
5 : 'max 16 sec non-DRX mode after transfer state',
|
|
|
|
|
6 : 'max 32 sec non-DRX mode after transfer state',
|
|
|
|
|
7 : 'max 64 sec non-DRX mode after transfer state'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DRXParam(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('SPLIT_PG_CYCLE_CODE', dic=_SplitPGCycleC_dict),
|
|
|
|
|
Uint('DRXCycleLen', bl=4, dic=_DRXCycleLen_dict),
|
|
|
|
|
Uint('SPLITonCCCH', bl=1),
|
|
|
|
|
Uint('NonDRXTimer', bl=3, dic=_NonDRXTimer_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Force to standby
|
|
|
|
|
# TS 24.008, 10.5.5.7
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
ForceStdby_dict = {
|
2017-07-04 21:12:41 +00:00
|
|
|
|
0 : 'Force to standby not indicated',
|
|
|
|
|
1 : 'Force to standby indicated'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ForceStdby(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
2018-02-09 20:58:36 +00:00
|
|
|
|
Uint('Value', bl=3, dic=ForceStdby_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2019-11-27 16:12:08 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# IMEISV request
|
|
|
|
|
# TS 24.008, 10.5.5.10
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class IMEISVReq(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Value', bl=3, dic={0:'IMEISV not requested', 1:'IMEISV requested'})
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# GMM Cause
|
|
|
|
|
# TS 24.008, 10.5.5.14
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
GMMCause_dict = {
|
|
|
|
|
0 : 'Protocol error, unspecified',
|
|
|
|
|
2 : 'IMSI unknown in HLR',
|
|
|
|
|
3 : 'Illegal MS',
|
|
|
|
|
5 : 'IMEI not accepted',
|
|
|
|
|
6 : 'Illegal ME',
|
|
|
|
|
7 : 'GPRS services not allowed',
|
|
|
|
|
8 : 'GPRS services and non-GPRS services not allowed',
|
|
|
|
|
9 : 'MS identity cannot be derived by the network',
|
|
|
|
|
10 : 'implicitly detached',
|
|
|
|
|
11 : 'PLMN not allowed',
|
|
|
|
|
12 : 'Location Area not allowed',
|
|
|
|
|
13 : 'Roaming not allowed in this location area',
|
|
|
|
|
14 : 'GPRS services not allowed in this PLMN',
|
|
|
|
|
15 : 'No Suitable Cells In Location Area',
|
|
|
|
|
16 : 'MSC temporarily not reachable',
|
|
|
|
|
17 : 'Network failure',
|
|
|
|
|
20 : 'MAC failure',
|
|
|
|
|
21 : 'Synch failure',
|
|
|
|
|
22 : 'Congestion',
|
|
|
|
|
23 : 'GSM authentication unacceptable',
|
|
|
|
|
25 : 'Not authorized for this CSG',
|
|
|
|
|
40 : 'No PDP context activated',
|
|
|
|
|
48 : 'retry upon entry into a new cell',
|
|
|
|
|
95 : 'Semantically incorrect message',
|
|
|
|
|
96 : 'Invalid mandatory information',
|
|
|
|
|
97 : 'Message type non-existent or not implemented',
|
|
|
|
|
98 : 'Message type not compatible with the protocol state',
|
|
|
|
|
99 : 'Information element non-existent or not implemented',
|
|
|
|
|
100: 'Conditional IE error',
|
|
|
|
|
101: 'Message not compatible with the protocol state',
|
|
|
|
|
111: 'Protocol error, unspecified'
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
class GMMCause(Uint8):
|
|
|
|
|
_dic = GMMCause_dict
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Routing Area Identifier
|
|
|
|
|
# TS 24.008, 10.5.5.15
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class RAI(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
PLMN(),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint16('LAC', rep=REPR_HEX),
|
|
|
|
|
Uint8('RAC', rep=REPR_HEX)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
encode = Envelope.set_val
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
def decode(self):
|
2017-09-16 16:11:34 +00:00
|
|
|
|
return (self[0].decode(), self[1].get_val(), self[2].get_val())
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Update result
|
|
|
|
|
# TS 24.008, 10.5.5.17
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_UpdateResult_dict = {
|
|
|
|
|
0 : 'RA updated',
|
|
|
|
|
1 : 'combined RA/LA updated',
|
|
|
|
|
4 : 'RA updated and ISR activated',
|
|
|
|
|
5 : 'combined RA/LA updated and ISR activated',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class UpdateResult(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('FollowOnProc', bl=1),
|
|
|
|
|
Uint('Value', bl=3, dic=_UpdateResult_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Update type
|
|
|
|
|
# TS 24.008, 10.5.5.18
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_UpdType_dict = {
|
|
|
|
|
0 : 'RA updating',
|
|
|
|
|
1 : 'combined RA/LA updating',
|
|
|
|
|
2 : 'combined RA/LA updating with IMSI attach',
|
|
|
|
|
3 : 'Periodic updating'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class UpdateType(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('FollowOnReq', bl=1),
|
|
|
|
|
Uint('Value', bl=3, dic=_UpdType_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Service type
|
|
|
|
|
# TS 24.008, 10.5.5.20
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
ServiceType_dict = {
|
|
|
|
|
0 : 'Signalling',
|
|
|
|
|
1 : 'Data',
|
|
|
|
|
2 : 'Paging Response',
|
|
|
|
|
3 : 'MBMS Multicast Service Reception',
|
|
|
|
|
4 : 'MBMS Broadcast Service Reception',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# PS LCS Capability
|
|
|
|
|
# TS 24.008, 10.5.5.22
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class PSLCSCap(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('APC', bl=1),
|
|
|
|
|
Uint('OTD_A', bl=1),
|
|
|
|
|
Uint('OTD_B', bl=1),
|
|
|
|
|
Uint('GPS_A', bl=1),
|
|
|
|
|
Uint('GPS_B', bl=1),
|
|
|
|
|
Uint('GPS_C', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Network feature support
|
|
|
|
|
# TS 24.008, 10.5.5.23
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class NetFeatSupp(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('LCS_MOLR', bl=1),
|
|
|
|
|
Uint('MBMS', bl=1),
|
|
|
|
|
Uint('IMS_VoPS', bl=1),
|
|
|
|
|
Uint('EMC_BS', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Additional network feature support
|
|
|
|
|
# TS 24.008, 10.5.5.23A
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class AddNetFeatSupp(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=7),
|
|
|
|
|
Uint('GPRS_SMS', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Voice Domain Preference
|
|
|
|
|
# TS 24.008, 10.5.5.24
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_UEUsage_dict = {
|
|
|
|
|
0 : 'Voice centric',
|
|
|
|
|
1 : 'Data centric'
|
|
|
|
|
}
|
|
|
|
|
_VoiceDomPref_dict = {
|
|
|
|
|
0 : 'CS Voice only',
|
|
|
|
|
1 : 'IMS PS Voice only',
|
|
|
|
|
2 : 'CS voice preferred, IMS PS Voice as secondary',
|
|
|
|
|
3 : 'IMS PS voice preferred, CS Voice as secondary'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class VoiceDomPref(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=5),
|
|
|
|
|
Uint('UEUsage', bl=1, dic=_UEUsage_dict),
|
|
|
|
|
Uint('VoiceDomPref', bl=2, dic=_VoiceDomPref_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Requested MS information
|
|
|
|
|
# TS 24.008, 10.5.5.25
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReqMSInfo(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('I_RAT', bl=1),
|
|
|
|
|
Uint('I_RAT2', bl=1),
|
|
|
|
|
Uint('spare', bl=2)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# P-TMSI Type
|
|
|
|
|
# TS 24.008, 10.5.5.29
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_PTMSIType_dict = {
|
|
|
|
|
0 : 'Native P-TMSI',
|
|
|
|
|
1 : 'Mapped P-TMSI'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PTMSIType(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Value', bl=1, dic=_PTMSIType_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Network Resource Identifier
|
|
|
|
|
# TS 24.008, 10.5.5.31
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class NRICont(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Value', bl=10, rep=REPR_HEX),
|
|
|
|
|
Uint('spare', bl=6)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Extended DRX parameters
|
|
|
|
|
# TS 24.008, 10.5.5.32
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class ExtDRXParam(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('PTX', bl=4),
|
|
|
|
|
Uint('eDRX', bl=4)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# User-Plane integrity indicator
|
|
|
|
|
# TS 24.008, 10.5.5.34
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class UPIntegrityInd(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Value', bl=1)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2019-11-08 15:11:02 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# DCN-ID
|
|
|
|
|
# TS 24.008, 10.5.5.35
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Dedicated Core Network ID
|
|
|
|
|
|
|
|
|
|
class DCNID(Uint16):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Non-3GPP NW provided policies
|
|
|
|
|
# TS 24.008, 10.5.5.37
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_Non3GPPNWProvPol_dict = {
|
|
|
|
|
0 : 'use of non-3GPP emergency numbers not permitted',
|
|
|
|
|
1 : 'use of non-3GPP emergency numbers permitted'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Non3GPPNWProvPol(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Value', bl=1, dic=_Non3GPPNWProvPol_dict)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Access point name
|
|
|
|
|
# TS 24.008, 10.5.6.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# referring TS 23.003
|
|
|
|
|
|
|
|
|
|
class _APNItem(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint8('Len'),
|
|
|
|
|
Buf('Value')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
|
|
|
|
self[0].set_valauto(self[1].get_len)
|
|
|
|
|
self[1].set_blauto(lambda: 8*self[0].get_val())
|
|
|
|
|
|
2019-11-26 17:34:57 +00:00
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
class APN(Sequence):
|
|
|
|
|
_GEN = _APNItem('APNItem')
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
|
|
|
2017-10-13 19:28:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Network service access point identifier
|
|
|
|
|
# TS 24.008, 10.5.6.2
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_NSAPI_dict = {
|
|
|
|
|
0 : _str_reserved,
|
|
|
|
|
1 : _str_reserved,
|
|
|
|
|
2 : _str_reserved,
|
|
|
|
|
3 : _str_reserved,
|
|
|
|
|
4 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NSAPI(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
2017-10-13 19:28:18 +00:00
|
|
|
|
Uint('Value', val=5, bl=4, dic=_NSAPI_dict)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Protocol configuration options
|
|
|
|
|
# TS 24.008, 10.5.6.3
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_ProtConfig_dict = {
|
|
|
|
|
# 3GPP additional parameters
|
|
|
|
|
0x0001 : 'P-CSCF IPv6 Address Request',
|
|
|
|
|
0x0002 : 'IM CN Subsystem Signaling Flag',
|
|
|
|
|
0x0003 : 'DNS Server IPv6 Address Request',
|
|
|
|
|
0x0004 : 'Policy Control rejection code',
|
|
|
|
|
0x0005 : 'Selected Bearer Control Mode',
|
|
|
|
|
0x0006 : 'Reserved',
|
|
|
|
|
0x0007 : 'DSMIPv6 Home Agent Address',
|
|
|
|
|
0x0008 : 'DSMIPv6 Home Network Prefix',
|
|
|
|
|
0x0009 : 'DSMIPv6 IPv4 Home Agent Address',
|
|
|
|
|
0x000A : 'IP address allocation via NAS signalling',
|
|
|
|
|
0x000B : 'Reserved',
|
|
|
|
|
0x000C : 'P-CSCF IPv4 Address',
|
|
|
|
|
0x000D : 'DNS server IPv4 address request',
|
|
|
|
|
0x000E : 'MSISDN Request',
|
|
|
|
|
0x000F : 'IFOM-Support-Request',
|
|
|
|
|
0x0010 : 'IPv4 Link MTU Request',
|
|
|
|
|
0x0011 : 'Support of Local address in TFT indicator',
|
|
|
|
|
0x0012 : 'P-CSCF Re-selection support',
|
|
|
|
|
0x0013 : 'NBIFOM request indicator',
|
|
|
|
|
0x0014 : 'NBIFOM mode',
|
|
|
|
|
0x0015 : 'Non-IP Link MTU Request',
|
|
|
|
|
0x0016 : 'APN rate control support indicator',
|
|
|
|
|
|
|
|
|
|
# ETSI / IETF protocol identifiers
|
|
|
|
|
0x8021 : 'IPCP',
|
|
|
|
|
0xC021 : 'LCP',
|
|
|
|
|
0xC023 : 'PAP',
|
|
|
|
|
0xC223 : 'CHAP'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProtConfigElt(Envelope):
|
2018-01-14 10:03:52 +00:00
|
|
|
|
# when set to True, will decode the content into NCP / LCP / PAP / CHAP
|
2017-11-12 14:18:50 +00:00
|
|
|
|
DECODE_INNER = True
|
|
|
|
|
_ContLUT = {
|
|
|
|
|
0x8021 : NCP,
|
2018-01-14 10:03:52 +00:00
|
|
|
|
0xC021 : LCP,
|
|
|
|
|
0xC023 : PAP,
|
|
|
|
|
0xC223 : CHAP
|
2017-11-12 14:18:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_GEN = (
|
|
|
|
|
Uint16('ID', val=0x8021, dic=_ProtConfig_dict),
|
|
|
|
|
Uint8('Len'),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Buf('Cont', val=b'', rep=REPR_HEX)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_valauto(lambda: self[2].get_len())
|
|
|
|
|
self[2].set_blauto(lambda: 8*self[1].get_val())
|
|
|
|
|
|
2018-01-14 10:03:52 +00:00
|
|
|
|
def set_val(self, val):
|
|
|
|
|
if isinstance(val, (list, tuple)) and not isinstance(val[2], bytes_types):
|
|
|
|
|
# eventually replace Cont by a NCP / LCP / PAP / CHAP Envelope
|
|
|
|
|
if val[0] in self._ContLUT:
|
|
|
|
|
self.replace(self[2], self._ContLUT[val[0]]('Cont'))
|
|
|
|
|
elif isinstance(val, dict) and 'ID' in val and 'Cont' in val \
|
|
|
|
|
and not isinstance(val['Cont'], bytes_types):
|
|
|
|
|
# eventually replace Cont by a NCP / LCP / PAP / CHAP Envelope
|
|
|
|
|
if val['ID'] in self._ContLUT:
|
|
|
|
|
self.replace(self[2], self._ContLUT[val['ID']]('Cont'))
|
|
|
|
|
Envelope.set_val(self, val)
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
self[0]._from_char(char)
|
|
|
|
|
self[1]._from_char(char)
|
|
|
|
|
ident, cont = self[0].get_val(), None
|
|
|
|
|
if self.DECODE_INNER and ident in self._ContLUT:
|
2018-01-14 10:03:52 +00:00
|
|
|
|
cont = self._ContLUT[ident]('Cont')
|
2017-11-12 14:18:50 +00:00
|
|
|
|
ccur, clen = char._cur, char._len_bit
|
|
|
|
|
char._len_bit = ccur + 8*self[1].get_val()
|
2019-12-12 14:00:16 +00:00
|
|
|
|
if char._len_bit > clen:
|
|
|
|
|
raise(EltErr('{0} [_from_char]: bit length overflow'.format(self._name)))
|
2017-11-12 14:18:50 +00:00
|
|
|
|
try:
|
|
|
|
|
cont._from_char(char)
|
2019-07-02 09:27:40 +00:00
|
|
|
|
except Exception:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
char._cur, char._len_bit = ccur, clen
|
|
|
|
|
else:
|
|
|
|
|
if char._cur < char._len_bit:
|
|
|
|
|
char._cur, char._len_bit = ccur, clen
|
|
|
|
|
else:
|
|
|
|
|
self.replace(self[2], cont)
|
|
|
|
|
char._len_bit = clen
|
|
|
|
|
if cont is None:
|
|
|
|
|
self[2]._from_char(char)
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class ProtConfig(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('Ext', val=1, bl=1),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('Prot', bl=3, dic={0:'PPP with IP PDP'}),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Sequence('Config', GEN=ProtConfigElt())
|
|
|
|
|
)
|
|
|
|
|
|
2017-10-13 19:28:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Packet data protocol address
|
|
|
|
|
# TS 24.008, 10.5.6.4
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_PDPTypeOrg_dict = {
|
|
|
|
|
0 : 'ETSI allocated',
|
|
|
|
|
1 : 'IETF allocated',
|
|
|
|
|
15 : 'Empty PDP type',
|
|
|
|
|
}
|
|
|
|
|
_PDPTypeNum0_dict = {
|
|
|
|
|
0 : 'reserved',
|
|
|
|
|
1 : 'PPP',
|
|
|
|
|
}
|
|
|
|
|
_PDPTypeNum1_dict = {
|
|
|
|
|
33 : 'IPv4',
|
|
|
|
|
87 : 'IPv6',
|
|
|
|
|
141 : 'IPv4v6',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PDPAddr(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('TypeOrg', val=1, bl=4, dic=_PDPTypeOrg_dict),
|
|
|
|
|
Uint8('Type', val=33),
|
2017-10-13 19:28:18 +00:00
|
|
|
|
Buf('Addr', val=b'', rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[2].set_dicauto(self._set_pdpt_dic)
|
2018-02-09 20:58:36 +00:00
|
|
|
|
# Addr can be empty, when PDPAddr is used within a request
|
|
|
|
|
#self[3].set_blauto(self._set_addr_len)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_pdpt_dic(self):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
to = self[1]()
|
|
|
|
|
if to == 0:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
return _PDPTypeNum0_dict
|
2017-11-12 14:18:50 +00:00
|
|
|
|
elif to == 1:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
return _PDPTypeNum1_dict
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
#def _set_addr_len(self):
|
|
|
|
|
# to, t = self[1](), self[2]()
|
|
|
|
|
# if to == 1:
|
|
|
|
|
# if t == 33:
|
|
|
|
|
# return 32
|
|
|
|
|
# elif t == 87:
|
|
|
|
|
# return 128
|
|
|
|
|
# elif t == 141:
|
|
|
|
|
# return 160
|
|
|
|
|
# return None
|
|
|
|
|
|
2017-10-13 19:28:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Quality of service
|
|
|
|
|
# TS 24.008, 10.5.6.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_ReliabClass_dict = {
|
|
|
|
|
0 : 'subscribed reliability class',
|
|
|
|
|
1 : 'unused; interpreted as unack GTP, ack LLC and RLC, protected data',
|
|
|
|
|
2 : 'unack GTP, ack LLC and RLC, protected data',
|
|
|
|
|
3 : 'unack GTP and LLC, ack RLC, protected data',
|
|
|
|
|
4 : 'unack GTP, LLC and RLC, protected data',
|
|
|
|
|
5 : 'unack GTP, LLC and RLC, unprotected data',
|
|
|
|
|
6 : 'unack GTP and RLC, ack LLC, protected data',
|
|
|
|
|
7 : _str_reserved,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_DelayClass_dict = {
|
|
|
|
|
0 : 'subscribed delay class',
|
|
|
|
|
1 : 'delay class 1',
|
|
|
|
|
2 : 'delay class 2',
|
|
|
|
|
3 : 'delay class 3',
|
|
|
|
|
4 : 'delay class 4 (best effort)',
|
|
|
|
|
7 : _str_reserved,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_PrecedClass_dict = {
|
|
|
|
|
0 : 'subscribed precedence',
|
|
|
|
|
1 : 'high priority',
|
|
|
|
|
2 : 'normal priority',
|
|
|
|
|
3 : 'low priority',
|
|
|
|
|
4 : 'normal priority',
|
|
|
|
|
7 : _str_reserved,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_PeakTP_dict = {
|
|
|
|
|
0 : 'subscribed peak throughput',
|
|
|
|
|
1 : 'Up to 1 000 octet/s',
|
|
|
|
|
2 : 'Up to 2 000 octet/s',
|
|
|
|
|
3 : 'Up to 4 000 octet/s',
|
|
|
|
|
4 : 'Up to 8 000 octet/s',
|
|
|
|
|
5 : 'Up to 16 000 octet/s',
|
|
|
|
|
6 : 'Up to 32 000 octet/s',
|
|
|
|
|
7 : 'Up to 64 000 octet/s',
|
|
|
|
|
8 : 'Up to 128 000 octet/s',
|
|
|
|
|
9 : 'Up to 256 000 octet/s',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_MeanTP_dict = {
|
|
|
|
|
0 : 'subscribed mean throughput',
|
|
|
|
|
1 : '100 octet/h',
|
|
|
|
|
2 : '200 octet/h',
|
|
|
|
|
3 : '500 octet/h',
|
|
|
|
|
4 : '1 000 octet/h',
|
|
|
|
|
5 : '2 000 octet/h',
|
|
|
|
|
6 : '5 000 octet/h',
|
|
|
|
|
7 : '10 000 octet/h',
|
|
|
|
|
8 : '20 000 octet/h',
|
|
|
|
|
9 : '50 000 octet/h',
|
|
|
|
|
10: '100 000 octet/h',
|
|
|
|
|
11: '200 000 octet/h',
|
|
|
|
|
12: '500 000 octet/h',
|
|
|
|
|
13: '1 000 000 octet/h',
|
|
|
|
|
14: '2 000 000 octet/h',
|
|
|
|
|
15: '5 000 000 octet/h',
|
|
|
|
|
16: '10 000 000 octet/h',
|
|
|
|
|
17: '20 000 000 octet/h',
|
|
|
|
|
18: '50 000 000 octet/h',
|
|
|
|
|
30: _str_reserved,
|
|
|
|
|
31: 'Best effort'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_ErronSDU_dict = {
|
|
|
|
|
0 : 'Subscribed delivery of erroneous SDUs',
|
|
|
|
|
1 : 'No detect',
|
|
|
|
|
2 : 'Erroneous SDUs are delivered',
|
|
|
|
|
3 : 'Erroneous SDUs are not delivered',
|
|
|
|
|
7 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_DeliverOrd_dict = {
|
|
|
|
|
0 : 'Subscribed delivery order',
|
|
|
|
|
1 : 'With delivery order',
|
|
|
|
|
2 : 'Without delivery order',
|
|
|
|
|
3 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_TraffClass_dict = {
|
|
|
|
|
0 : 'Subscribed traffic class',
|
|
|
|
|
1 : 'Conversational class',
|
|
|
|
|
2 : 'Streaming class',
|
|
|
|
|
3 : 'Interactive class',
|
|
|
|
|
4 : 'Background class',
|
|
|
|
|
7 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_SignalInd_dict = {
|
|
|
|
|
0 : 'Not optimised for signalling',
|
|
|
|
|
1 : 'Optimised for signalling'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_SourceStats_dict = {
|
|
|
|
|
0 : 'unknown',
|
|
|
|
|
1 : 'speech'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# TODO: build dicts for DL / UL max / guaranteed throughput
|
|
|
|
|
|
|
|
|
|
class QoS(Envelope):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
ENV_SEL_TRANS = False
|
2017-10-13 19:28:18 +00:00
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('DelayClass', bl=3, dic=_DelayClass_dict),
|
|
|
|
|
Uint('ReliabilityClass', bl=3, dic=_ReliabClass_dict), # 1
|
|
|
|
|
Uint('PeakThroughput', bl=4, dic=_PeakTP_dict),
|
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('PrecedenceClass', bl=3, dic=_PrecedClass_dict), # 2
|
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('MeanThroughput', bl=5, dic=_MeanTP_dict), # 3
|
|
|
|
|
Uint('TrafficClass', bl=3, dic=_TraffClass_dict),
|
|
|
|
|
Uint('DeliveryOrder', bl=2, dic=_DeliverOrd_dict),
|
|
|
|
|
Uint('ErroneousSDU', bl=3, dic=_ErronSDU_dict), # 4
|
|
|
|
|
Uint8('MaxSDUSize'),
|
|
|
|
|
Uint8('MaxULBitrate'),
|
|
|
|
|
Uint8('MaxDLBitrate'),
|
|
|
|
|
Uint('ResidualBER', bl=4),
|
|
|
|
|
Uint('SDUErrorRatio', bl=4), # 8
|
|
|
|
|
Uint('TransferDelay', bl=6),
|
|
|
|
|
Uint('TrafficHandlingPriority', bl=2), # 9
|
|
|
|
|
Uint8('GuaranteedULBitrate'),
|
|
|
|
|
Uint8('GuaranteedDLBitrate'),
|
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('SignallingInd', bl=1, dic=_SignalInd_dict),
|
|
|
|
|
Uint('SourceStatsDesc', bl=4, dic=_SourceStats_dict), # 12
|
|
|
|
|
Uint8('MaxDLBitrateExt', trans=True),
|
|
|
|
|
Uint8('GuaranteedDLBitrateExt', trans=True),
|
|
|
|
|
Uint8('MaxULBitrateExt', trans=True),
|
|
|
|
|
Uint8('GuaranteedULBitrateExt', trans=True),
|
|
|
|
|
Uint8('MaxDLBitrateExt2', trans=True),
|
|
|
|
|
Uint8('GuaranteedDLBitrateExt2', trans=True),
|
|
|
|
|
Uint8('MaxULBitrateExt2', trans=True),
|
|
|
|
|
Uint8('GuaranteedULBitrateExt2', trans=True),
|
2017-10-13 19:28:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
# in case extended values are set, make them non-transparent
|
|
|
|
|
if vals is None:
|
|
|
|
|
self._set_trans_dlbrext(True)
|
|
|
|
|
self._set_trans_ulbrext(True)
|
|
|
|
|
self._set_trans_dlbrext2(True)
|
|
|
|
|
self._set_trans_ulbrext2(True)
|
|
|
|
|
elif isinstance(vals, (tuple, list)):
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if len(vals) > 29:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
|
|
|
|
self._set_trans_ulbrext2(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif len(vals) > 27:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif len(vals) > 25:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif len(vals) > 23:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
elif isinstance(vals, dict):
|
|
|
|
|
if 'MaxULBitrateExt2' in vals or 'GuaranteedULBitrateExt2' in vals:
|
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
|
|
|
|
self._set_trans_ulbrext2(False)
|
|
|
|
|
elif 'MaxDLBitrateExt2' in vals or 'GuaranteedDLBitrateExt2' in vals:
|
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
|
|
|
|
elif 'MaxULBitrateExt' in vals or 'GuaranteedULBitrateExt' in vals:
|
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
elif 'MaxDLBitrateExt' in vals or 'GuaranteedDLBitrateExt' in vals:
|
|
|
|
|
self._set_trans_dlbrext(False)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Envelope.set_val(self, vals)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_trans_dlbrext(self, trans):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[23].set_trans(trans)
|
|
|
|
|
self[24].set_trans(trans)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_trans_ulbrext(self, trans):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[25].set_trans(trans)
|
|
|
|
|
self[26].set_trans(trans)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_trans_dlbrext2(self, trans):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[27].set_trans(trans)
|
|
|
|
|
self[28].set_trans(trans)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_trans_ulbrext2(self, trans):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[29].set_trans(trans)
|
|
|
|
|
self[30].set_trans(trans)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
# in case long-enough buffer is available, make extended fields non-transparent
|
|
|
|
|
l = char.len_byte()
|
2017-10-22 12:03:18 +00:00
|
|
|
|
if l > 18:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
|
|
|
|
self._set_trans_ulbrext2(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif l > 16:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
|
|
|
|
self._set_trans_dlbrext2(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif l > 14:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
self._set_trans_ulbrext(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif l > 12:
|
2017-10-13 19:28:18 +00:00
|
|
|
|
self._set_trans_dlbrext(False)
|
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Re-attempt indicator
|
|
|
|
|
# TS 24.008, 10.5.6.5a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_EPLMNC_dict = {
|
|
|
|
|
0 : 'MS is allowed to re-attempt the procedure in an equivalent PLMN',
|
|
|
|
|
1 : 'MS is not allowed to re-attempt the procedure in an equivalent PLMN'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_RATC_dict = {
|
|
|
|
|
0 : 'MS is allowed to re-attempt the procedure in S1 mode',
|
|
|
|
|
1 : 'MS is not allowed to re-attempt the procedure in S1 mode'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ReattemptInd(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=6),
|
|
|
|
|
Uint('EPLMNC', bl=1, dic=_EPLMNC_dict),
|
|
|
|
|
Uint('RATC', bl=1, dic=_RATC_dict)
|
2017-10-13 19:28:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# SM Cause
|
|
|
|
|
# TS 24.008, 10.5.6.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
SMCause_dict = {
|
|
|
|
|
8 : 'Operator Determined Barring',
|
|
|
|
|
24 : 'MBMS bearer capabilities insufficient for the service',
|
|
|
|
|
25 : 'LLC or SNDCP failure(A/Gb mode only)',
|
|
|
|
|
26 : 'Insufficient resources',
|
|
|
|
|
27 : 'Missing or unknown APN',
|
|
|
|
|
28 : 'Unknown PDP address or PDP type',
|
|
|
|
|
29 : 'User authentication failed',
|
|
|
|
|
30 : 'Activation rejected by GGSN, Serving GW or PDN GW',
|
|
|
|
|
31 : 'Activation rejected, unspecified',
|
|
|
|
|
32 : 'Service option not supported',
|
|
|
|
|
33 : 'Requested service option not subscribed',
|
|
|
|
|
34 : 'Service option temporarily out of order',
|
|
|
|
|
35 : 'NSAPI already used (not sent)',
|
|
|
|
|
36 : 'Regular deactivation',
|
|
|
|
|
37 : 'QoS not accepted',
|
|
|
|
|
38 : 'Network failure',
|
|
|
|
|
39 : 'Reactivation requested',
|
|
|
|
|
40 : 'Feature not supported',
|
|
|
|
|
41 : 'Semantic error in the TFT operation',
|
|
|
|
|
42 : 'Syntactical error in the TFT operation',
|
|
|
|
|
43 : 'Unknown PDP context',
|
|
|
|
|
44 : 'Semantic errors in packet filter(s)',
|
|
|
|
|
45 : 'Syntactical errors in packet filter(s)',
|
|
|
|
|
46 : 'PDP context without TFT already activated',
|
|
|
|
|
47 : 'Multicast group membership time-out',
|
|
|
|
|
48 : 'Request rejected, BCM violation',
|
|
|
|
|
50 : 'PDP type IPv4 only allowed',
|
|
|
|
|
51 : 'PDP type IPv6 only allowed',
|
|
|
|
|
52 : 'Single address bearers only allowed',
|
|
|
|
|
56 : 'Collision with network initiated request',
|
|
|
|
|
60 : 'Bearer handling not supported',
|
|
|
|
|
65 : 'Maximum number of PDP contexts reached',
|
|
|
|
|
66 : 'Requested APN not supported in current RAT and PLMN combination',
|
|
|
|
|
81 : 'Invalid transaction identifier value',
|
|
|
|
|
95 : 'Semantically incorrect message',
|
|
|
|
|
96 : 'Invalid mandatory information',
|
|
|
|
|
97 : 'Message type non-existent or not implemented',
|
|
|
|
|
98 : 'Message type not compatible with the protocol state',
|
|
|
|
|
99 : 'Information element non-existent or not implemented',
|
|
|
|
|
100 : 'Conditional IE error',
|
|
|
|
|
101 : 'Message not compatible with the protocol state',
|
|
|
|
|
111 : 'Protocol error, unspecified',
|
|
|
|
|
112 : 'APN restriction value incompatible with active PDP context',
|
|
|
|
|
113 : 'Multiple accesses to a PDN connection not allowed'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SMCause(Uint8):
|
2018-02-09 20:58:36 +00:00
|
|
|
|
_dic = SMCause_dict
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Linked TI
|
|
|
|
|
# TS 24.008, 10.5.6.7
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# see transaction identifier in TS 24.007, section 11.2.3.1.3
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
class TransId(Envelope):
|
2017-10-22 12:03:18 +00:00
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Flag', bl=1, dic={0: 'initiator', 1: 'responder'}),
|
|
|
|
|
Uint('TIO', bl=3),
|
|
|
|
|
Uint('spare', bl=4),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint('Ext', val=1, bl=1, trans=True),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('TIE', bl=7, trans=True),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint8('TI', trans=True) # virtual field to get the TI value easily
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[5].set_valauto(self._set_ti)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
def _set_ti(self):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
tio = self[1]()
|
|
|
|
|
if tio == 7 and not self[4].get_trans():
|
|
|
|
|
return self[4]()
|
2017-10-22 12:03:18 +00:00
|
|
|
|
else:
|
|
|
|
|
return tio
|
|
|
|
|
|
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
if isinstance(vals, dict) and 'TI' in vals:
|
|
|
|
|
ti = vals['TI']
|
|
|
|
|
del vals['TI']
|
|
|
|
|
if 0 <= ti < 7:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_val(ti)
|
|
|
|
|
self[3].set_trans(True)
|
|
|
|
|
self[4].set_trans(True)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif ti < 128:
|
|
|
|
|
# extended
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_val(7)
|
|
|
|
|
self[3].set_trans(False)
|
|
|
|
|
self[4].set_trans(False)
|
|
|
|
|
self[4].set_val(ti)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Envelope.set_val(self, vals)
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
if char.len_byte() > 1:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[3].set_trans(False)
|
|
|
|
|
self[4].set_trans(False)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
|
|
|
|
|
|
2017-11-12 14:18:50 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# LLC service access point identifier
|
|
|
|
|
# TS 24.008, 10.5.6.9
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_LLC_SAPI_dict = {
|
|
|
|
|
0 : 'not assigned',
|
|
|
|
|
1 : _str_reserved,
|
|
|
|
|
2 : _str_reserved,
|
|
|
|
|
4 : _str_reserved,
|
|
|
|
|
6 : _str_reserved,
|
|
|
|
|
7 : _str_reserved,
|
|
|
|
|
8 : _str_reserved,
|
|
|
|
|
10: _str_reserved,
|
|
|
|
|
11: _str_reserved,
|
|
|
|
|
12: _str_reserved,
|
|
|
|
|
13: _str_reserved,
|
|
|
|
|
14: _str_reserved,
|
|
|
|
|
15: _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class LLC_SAPI(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('Value', bl=4, dic=_LLC_SAPI_dict)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Tear Down Indicator
|
|
|
|
|
# TS 24.008, 10.5.6.10
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class TearDownInd(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('Value', bl=1, dic={0:'teardown not requested', 1:'teardown requested'}),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Packet Flow Identifier
|
|
|
|
|
# TS 24.008, 10.5.6.11
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_PktFlowId_dict = {
|
|
|
|
|
0: 'Best Effort',
|
|
|
|
|
1: 'Signaling',
|
|
|
|
|
2: 'SMS',
|
|
|
|
|
3: 'TOM8'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PacketFlowId(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
|
|
|
|
Uint('Value', bl=7, dic=_PktFlowId_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Traffic Flow Template
|
|
|
|
|
# TS 24.008, 10.5.6.12
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_TFTOpcode_dict = {
|
|
|
|
|
0 : 'Ignore this IE',
|
|
|
|
|
1 : 'Create new TFT',
|
|
|
|
|
2 : 'Delete existing TFT',
|
|
|
|
|
3 : 'Add packet filters to existing TFT',
|
|
|
|
|
4 : 'Replace packet filters in existing TFT',
|
|
|
|
|
5 : 'Delete packet filters from existing TFT',
|
|
|
|
|
6 : 'No TFT operation',
|
|
|
|
|
7 : _str_reserved
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_PktFilterDir_dict = {
|
|
|
|
|
0 : 'pre Rel-7 TFT filter',
|
|
|
|
|
1 : 'downlink only',
|
|
|
|
|
2 : 'uplink only',
|
|
|
|
|
3 : 'bidirectional'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_PktFilterCompType_dict = {
|
|
|
|
|
16 : 'IPv4 remote address type',
|
|
|
|
|
17 : 'IPv4 local address type ',
|
|
|
|
|
32 : 'IPv6 remote address type',
|
|
|
|
|
33 : 'IPv6 remote address/prefix length type',
|
|
|
|
|
35 : 'IPv6 local address/prefix length type',
|
|
|
|
|
48 : 'Protocol identifier/Next header type',
|
|
|
|
|
64 : 'Single local port type',
|
|
|
|
|
65 : 'Local port range type',
|
|
|
|
|
80 : 'Single remote port type',
|
|
|
|
|
81 : 'Remote port range type',
|
|
|
|
|
96 : 'Security parameter index type',
|
|
|
|
|
112 : 'Type of service/Traffic class type',
|
|
|
|
|
128 : 'Flow label type'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# if TFT opcode == 0, E == 0 and no pkt filters must be there
|
|
|
|
|
# if TFT opcode == 5, only pkt filters' id are provided in the pkt filters list
|
|
|
|
|
# TFTPktFilter content if made of a sequence of components
|
|
|
|
|
|
|
|
|
|
class TFTPktFilterId(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=4),
|
|
|
|
|
Uint('Id', bl=4)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class _CompIPv4(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Buf('Address', bl=32, rep=REPR_HEX),
|
|
|
|
|
Buf('Netmask', bl=32, rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class _CompIPv6(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Buf('Address', bl=128, rep=REPR_HEX),
|
|
|
|
|
Buf('Netmask', bl=128, rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class _CompIPv6Pref(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Buf('Address', bl=128, rep=REPR_HEX),
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('PrefixLen')
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class _CompPortRange(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint16('PortLo'),
|
|
|
|
|
Uint16('PortHi')
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class _CompTrafficClass(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('Class'),
|
|
|
|
|
Uint8('Mask')
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
|
|
|
|
class TFTPktFilterComp(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint8('Type', dic=_PktFilterCompType_dict),
|
|
|
|
|
Alt('Value', GEN={
|
|
|
|
|
16 : _CompIPv4('IPv4'),
|
|
|
|
|
17 : _CompIPv4('IPv4'),
|
|
|
|
|
32 : _CompIPv6('IPv6'),
|
|
|
|
|
33 : _CompIPv6Pref('IPv6Pref'),
|
|
|
|
|
35 : _CompIPv6Pref('IPv6Pref'),
|
|
|
|
|
48 : Uint8('ProtId'),
|
|
|
|
|
64 : Uint16('Port'),
|
|
|
|
|
65 : _CompPortRange('PortRange'),
|
|
|
|
|
80 : Uint16('Port'),
|
|
|
|
|
81 : _CompPortRange('PortRange'),
|
|
|
|
|
96 : Uint32('SPI'),
|
|
|
|
|
112 : _CompTrafficClass('TrafficClass'),
|
|
|
|
|
128 : Uint24('FlowLabel')
|
|
|
|
|
},
|
|
|
|
|
DEFAULT=Buf('unk', val=b'', rep=REPR_HEX),
|
|
|
|
|
sel=lambda self: self.get_env()['Type'].get_val())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TFTPktFilter(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('Dir', bl=2, dic=_PktFilterDir_dict),
|
|
|
|
|
Uint('Id', bl=4),
|
|
|
|
|
Uint8('Precedence'),
|
|
|
|
|
Uint8('Len'),
|
|
|
|
|
Sequence('Cont', GEN=TFTPktFilterComp())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
|
|
|
|
self['Len'].set_valauto(lambda: self['Cont'].get_len())
|
2019-12-12 14:00:16 +00:00
|
|
|
|
self['Cont'].set_blauto(lambda: self['Len'].get_val()<<3)
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
|
|
|
|
class TFTParameter(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('Id'),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint8('Len'),
|
2019-12-02 17:39:42 +00:00
|
|
|
|
Buf('Cont', val=b'', rep=REPR_HEX)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_valauto(self[2].get_len)
|
|
|
|
|
self[2].set_blauto(lambda: 8*self[1]())
|
2017-10-22 12:03:18 +00:00
|
|
|
|
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
class TFT(Envelope):
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Opcode', bl=3, dic=_TFTOpcode_dict),
|
|
|
|
|
Uint('E', bl=1, dic={0: 'no parameters list', 1: 'parameters list included'}),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Uint('NumPktFilters', bl=4),
|
|
|
|
|
Sequence('PktFilterIds', GEN=TFTPktFilterId()),
|
|
|
|
|
Sequence('PktFilters', GEN=TFTPktFilter()),
|
|
|
|
|
Sequence('Parameters', GEN=TFTParameter())
|
|
|
|
|
)
|
2019-12-02 17:39:42 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[2].set_valauto(lambda: self[3].get_num() if \
|
|
|
|
|
self[0]() == 5 else self[4].get_num())
|
|
|
|
|
self[3].set_transauto(lambda: self[0]() != 5)
|
|
|
|
|
self[3].set_numauto(lambda: self[2]())
|
|
|
|
|
self[4].set_transauto(lambda: self[0]() == 5)
|
|
|
|
|
self[4].set_numauto(lambda: self[2]())
|
|
|
|
|
self[5].set_transauto(lambda: self[1]() == 0)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
# there is no num automation of the Parameters
|
|
|
|
|
# hence, all remaining buffer will be consumed when calling _from_char()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Temporary mobile group identity (TMGI)
|
|
|
|
|
# TS 24.008, 10.5.6.13
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class TMGI(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint24('MBMSServID', rep=REPR_HEX),
|
2017-10-22 12:03:18 +00:00
|
|
|
|
PLMN()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def set_val(self, vals):
|
|
|
|
|
if isinstance(vals, (tuple, list)) and len(vals) == 1:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_trans(True)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
elif isinstance(vals, dict) and 'PLMN' not in vals:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_trans(True)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Envelope.set_val(self, vals)
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
if char.len_bit() < 48:
|
2017-11-12 14:18:50 +00:00
|
|
|
|
self[1].set_trans(True)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
Envelope._from_char(self, char)
|
2019-11-08 15:11:02 +00:00
|
|
|
|
|
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# MBMS bearer capabilities
|
|
|
|
|
# TS 24.008, 10.5.6.14
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class MBMSBearerCap(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint8('MaxDLBitrate'),
|
|
|
|
|
Uint8('MaxDLBitrateExt')
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Enhanced network service access point identifier
|
|
|
|
|
# TS 24.008, 10.5.6.16
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_ENSAPI_dict = {0xff: _str_reserved}
|
|
|
|
|
for i in range(0, 0x7f):
|
|
|
|
|
_ENSAPI_dict[i] = _str_reserved
|
|
|
|
|
for i in range(0x80, 0xfe):
|
|
|
|
|
_ENSAPI_dict[i] = 'NSAPI_%i_MBMS' % i
|
|
|
|
|
|
|
|
|
|
class ENSAPI(Uint8):
|
|
|
|
|
_dic = _ENSAPI_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Request type
|
|
|
|
|
# TS 24.008, 10.5.6.17
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
RequestType_dict = {
|
|
|
|
|
1 : 'Initial request',
|
|
|
|
|
2 : 'Handover',
|
|
|
|
|
3 : 'Unused. Interpreted as initial request',
|
|
|
|
|
4 : 'Emergency',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Notification indicator
|
|
|
|
|
# TS 24.008, 10.5.6.18
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class NotificationInd(Uint8):
|
|
|
|
|
_dic = {0:'SRVCC handover cancelled, IMS session re-establishment required'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Connectivity type
|
|
|
|
|
# TS 24.008, 10.5.6.19
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
ConnectivityType_dict = {
|
|
|
|
|
0 : 'The PDN connection type is not indicated',
|
|
|
|
|
1 : 'The PDN connection is considered a LIPA PDN connection'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# WLAN offload acceptability
|
|
|
|
|
# TS 24.008, 10.5.6.20
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_UTRANOffAcc_dict = {
|
|
|
|
|
0 : 'Offloading the traffic of the PDN connection via a WLAN when in Iu mode is not acceptable',
|
|
|
|
|
1 : 'Offloading the traffic of the PDN connection via a WLAN when in Iu mode is acceptable'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_EUTRANOffAcc_dict = {
|
|
|
|
|
0 : 'Offloading the traffic of the PDN connection via a WLAN when in S1 mode is not acceptable',
|
|
|
|
|
1 : 'Offloading the traffic of the PDN connection via a WLAN when in S1 mode is acceptable'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class WLANOffloadAccept(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=2),
|
|
|
|
|
Uint('UTRANOffloadAccept', bl=1, dic=_UTRANOffAcc_dict),
|
|
|
|
|
Uint('EUTRANOffloadAccept', bl=1, dic=_EUTRANOffAcc_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2019-11-08 15:11:02 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# NBIFOM container
|
|
|
|
|
# TS 24.008, 10.5.6.21
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_NBIFOMParamID_dict = {
|
|
|
|
|
0 : 'Not assigned',
|
|
|
|
|
1 : 'NBIFOM mode',
|
|
|
|
|
2 : 'NBIFOM default access',
|
|
|
|
|
3 : 'NBIFOM status',
|
|
|
|
|
4 : 'NBIFOM routing rules',
|
|
|
|
|
5 : 'NBIFOM IP flow mapping',
|
|
|
|
|
6 : 'NBIFOM RAN rules handling',
|
|
|
|
|
7 : 'NBIFOM Access stratum status',
|
|
|
|
|
8 : 'NBIFOM access usability indication',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NBIFOMParameter(Envelope):
|
|
|
|
|
_GEN = (
|
|
|
|
|
Uint8('ParamID', dic=_NBIFOMParamID_dict),
|
|
|
|
|
Uint8('ParamLen'),
|
|
|
|
|
Buf('Param', rep=REPR_HEX)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
Envelope.__init__(self, *args, **kwargs)
|
|
|
|
|
self[1].set_valauto(lambda: self[2].get_len())
|
|
|
|
|
self[2].set_blauto(lambda: self[1].get_val()<<3)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NBIFOMContainer(Sequence):
|
|
|
|
|
_GEN = NBIFOMParameter()
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# PDP Context Status
|
|
|
|
|
# TS 24.008, 10.5.7.1
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_PDPCtxtStat_dict = {
|
|
|
|
|
0 : 'PDP-INACTIVE',
|
|
|
|
|
1 : 'PDP-ACTIVE'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PDPCtxtStat(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('NSAPI_7', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_6', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_5', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_4', bl=1),
|
|
|
|
|
Uint('NSAPI_3', bl=1),
|
|
|
|
|
Uint('NSAPI_2', bl=1),
|
|
|
|
|
Uint('NSAPI_1', bl=1),
|
|
|
|
|
Uint('NSAPI_0', bl=1),
|
|
|
|
|
Uint('NSAPI_15', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_14', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_13', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_12', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_11', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_10', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_9', bl=1, dic=_PDPCtxtStat_dict),
|
|
|
|
|
Uint('NSAPI_8', bl=1, dic=_PDPCtxtStat_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-10-13 19:28:18 +00:00
|
|
|
|
|
2017-10-22 12:03:18 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Radio Priority
|
|
|
|
|
# TS 24.008, 10.5.7.2 and 10.5.7.5
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
2018-02-09 20:58:36 +00:00
|
|
|
|
RadioPrio_dict = {
|
2017-10-22 12:03:18 +00:00
|
|
|
|
1 : 'priority level 1 (highest)',
|
|
|
|
|
2 : 'priority level 2',
|
|
|
|
|
3 : 'priority level 3',
|
|
|
|
|
4 : 'priority level 4 (lowest)'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RadioPriority(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=1),
|
2018-02-09 20:58:36 +00:00
|
|
|
|
Uint('Value', bl=3, dic=RadioPrio_dict)
|
2017-10-22 12:03:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# GPRS Timer
|
|
|
|
|
# TS 24.008, 10.5.7.3
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_GPRSTimerUnit_dict = _MMTimerUnit_dict
|
|
|
|
|
|
|
|
|
|
class GPRSTimer(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Unit', bl=3, dic=_GPRSTimerUnit_dict),
|
|
|
|
|
Uint('Value', bl=5)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# GPRS Timer 3
|
|
|
|
|
# TS 24.008, 10.5.7.4a
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_GPRSTimer3Unit_dict = {
|
|
|
|
|
0 : '10 min',
|
|
|
|
|
1 : '1 hour',
|
|
|
|
|
2 : '10 hours',
|
|
|
|
|
3 : '2 sec',
|
|
|
|
|
4 : '30 sec',
|
|
|
|
|
5 : '1 min',
|
|
|
|
|
6 : '320 hours',
|
|
|
|
|
7 : 'timer deactivated'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class GPRSTimer3(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('Unit', bl=3, dic=_GPRSTimer3Unit_dict),
|
|
|
|
|
Uint('Value', bl=5)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# MBMS context status
|
|
|
|
|
# TS 24.008, 10.5.7.6
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class MBMSCtxtStat(Envelope):
|
|
|
|
|
|
|
|
|
|
ENV_SEL_TRANS = False
|
|
|
|
|
|
|
|
|
|
#_GEN = () # built at __init__()
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kw):
|
|
|
|
|
GEN = []
|
|
|
|
|
for i in range(16):
|
|
|
|
|
for j in range(7, -1, -1):
|
2017-11-12 14:18:50 +00:00
|
|
|
|
GEN.append( Uint('NSAPI_%i' % (128+8*i+j), bl=1, dic=_PDPCtxtStat_dict) )
|
2017-07-04 21:12:41 +00:00
|
|
|
|
kw['GEN'] = tuple(GEN)
|
|
|
|
|
Envelope.__init__(self, *args, **kw)
|
|
|
|
|
|
|
|
|
|
def _from_char(self, char):
|
|
|
|
|
l = char.len_bit()
|
|
|
|
|
self.enable_upto(l-1)
|
|
|
|
|
self.disable_from(l-1)
|
|
|
|
|
Envelope._from_char(self, char)
|
|
|
|
|
|
|
|
|
|
def disable_from(self, ind):
|
|
|
|
|
"""disables all elements from index `ind' excluded (integer -bit offset-
|
|
|
|
|
or element name)
|
|
|
|
|
"""
|
|
|
|
|
if isinstance(ind, str_types) and ind in self._by_name:
|
|
|
|
|
ind = self._by_name.index(ind)
|
|
|
|
|
[e.set_trans(True) for e in self._content[ind:]]
|
|
|
|
|
|
|
|
|
|
def enable_upto(self, ind):
|
|
|
|
|
"""enables all elements up to index `ind' included (integer -bit offset-
|
|
|
|
|
or element name)
|
|
|
|
|
"""
|
|
|
|
|
if isinstance(ind, str_types) and ind in self._by_name:
|
|
|
|
|
ind = 1 + self._by_name.index(ind)
|
|
|
|
|
[e.set_trans(False) for e in self._content[:ind]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Uplinlk data status
|
|
|
|
|
# TS 24.008, 10.5.7.7
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
_ULDataStat_dict = {
|
|
|
|
|
1 : 'UL data pending'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ULDataStat(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('NSAPI_7', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_6', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_5', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('spare', bl=5),
|
|
|
|
|
Uint('NSAPI_15', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_14', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_13', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_12', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_11', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_10', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_9', bl=1, dic=_ULDataStat_dict),
|
|
|
|
|
Uint('NSAPI_8', bl=1, dic=_ULDataStat_dict)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
# Device Properties
|
|
|
|
|
# TS 24.008, 10.5.7.8
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
|
|
|
|
|
class DeviceProp(Envelope):
|
|
|
|
|
_GEN = (
|
2017-11-12 14:18:50 +00:00
|
|
|
|
Uint('spare', bl=3),
|
|
|
|
|
Uint('LowPriority', bl=1)
|
2017-07-04 21:12:41 +00:00
|
|
|
|
)
|