mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-09-28 15:06:33 +03:00
bip: report a location in PROVIDE LOCAL INFORMATION
TS 102 223 6.8.7: TERMINAL RESPONSE shall contain the data object the command qualifier (6.6.15) asked for. The card always asks for location information, so at least answer 00, with the GERAN form of TS 131.111 8.19.1, PLMN 262-01. Do not answer "terminal currently unable to process - no service"... Change-Id: I53547da2ea9f0a4ea7a4dd032985a546f2d4277f
This commit is contained in:
+25
-2
@@ -39,10 +39,16 @@ from pySim.sms import SMS_DELIVER, SMS_SUBMIT, AddressField
|
|||||||
from pySim.cat import (ProactiveCommand, SendShortMessage, SMS_TPDU, SMSPPDownload,
|
from pySim.cat import (ProactiveCommand, SendShortMessage, SMS_TPDU, SMSPPDownload,
|
||||||
BearerDescription, DeviceIdentities, Address, OtherAddress,
|
BearerDescription, DeviceIdentities, Address, OtherAddress,
|
||||||
UiccTransportLevel, BufferSize, ChannelStatus, ChannelData,
|
UiccTransportLevel, BufferSize, ChannelStatus, ChannelData,
|
||||||
ChannelDataLength, EventList, EventDownload, Result)
|
ChannelDataLength, EventList, EventDownload, Result,
|
||||||
|
CommandDetails, LocationInformation)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# PROVIDE LOCAL INFORMATION location, GERAN TS 31.111 8.19.1
|
||||||
|
# - 3 byte PLMN of TS 24.008 10.5.1.3 -> 262-01
|
||||||
|
# - 2 byte LAC and a 2 byte cid.
|
||||||
|
DEFAULT_LOCATION = h2b('62f21000010001')
|
||||||
|
|
||||||
|
|
||||||
def terminal_profile(num_channels: int = 7) -> bytes:
|
def terminal_profile(num_channels: int = 7) -> bytes:
|
||||||
"""TERMINAL PROFILE for what we implement, TS 102 223 5.2 and annex T.
|
"""TERMINAL PROFILE for what we implement, TS 102 223 5.2 and annex T.
|
||||||
@@ -247,12 +253,29 @@ class Proact(ProactiveHandler):
|
|||||||
sms_sink: callback(pdu), called with the SMPP deliver_sm of a SEND SHORT MESSAGE
|
sms_sink: callback(pdu), called with the SMPP deliver_sm of a SEND SHORT MESSAGE
|
||||||
the card issued; pySim-smpp2sim.py hands it to its SMPP server.
|
the card issued; pySim-smpp2sim.py hands it to its SMPP server.
|
||||||
None: the SMS is logged and dropped.
|
None: the SMS is logged and dropped.
|
||||||
|
location: Location information returned in PROVIDE LOCAL INFORMATION (location).
|
||||||
"""
|
"""
|
||||||
def __init__(self, data_available_sink=None, sms_sink=None):
|
def __init__(self, data_available_sink=None, sms_sink=None, location: bytes = DEFAULT_LOCATION):
|
||||||
self.data_available_sink = data_available_sink
|
self.data_available_sink = data_available_sink
|
||||||
self.sms_sink = sms_sink
|
self.sms_sink = sms_sink
|
||||||
|
self.location = location
|
||||||
self.channels = ProactChannels(on_data_available=self._on_channel_data_available)
|
self.channels = ProactChannels(on_data_available=self._on_channel_data_available)
|
||||||
|
|
||||||
|
def handle_ProvideLocalInformation(self, pcmd: ProactiveCommand):
|
||||||
|
"""only location
|
||||||
|
|
||||||
|
TS 102 223 6.8.7 says TERMINAL RESPONSE to PROVIDE LOCAL INFORMATION "shall"
|
||||||
|
contain the data object the command qualifier (6.6.15) asked for. At least answer '00',
|
||||||
|
location information, usually requested.
|
||||||
|
|
||||||
|
answering "terminal currently unable to process - no service", which is a handset
|
||||||
|
out of coverage makes SJA5 believe it and postpones the entire session!
|
||||||
|
it registers a location status event, starts a ten minute timer and waits for coverage."""
|
||||||
|
cmd_det_ie = Proact._find_first_element_of_type(pcmd.children, CommandDetails)
|
||||||
|
if cmd_det_ie is not None and cmd_det_ie.decoded['command_qualifier'] == 0x00:
|
||||||
|
return self.prepare_response(pcmd) + [LocationInformation(decoded=self.location)]
|
||||||
|
return self.prepare_response(pcmd)
|
||||||
|
|
||||||
def receive_fetch(self, pcmd: ProactiveCommand):
|
def receive_fetch(self, pcmd: ProactiveCommand):
|
||||||
"""Answer anything this handler has no specific handler for.
|
"""Answer anything this handler has no specific handler for.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -318,7 +318,9 @@ class FileList(COMPR_TLV_IE, tag=0x92):
|
|||||||
|
|
||||||
# TS 102 223 Section 8.19
|
# TS 102 223 Section 8.19
|
||||||
class LocationInformation(COMPR_TLV_IE, tag=0x93):
|
class LocationInformation(COMPR_TLV_IE, tag=0x93):
|
||||||
pass
|
# 8.19: coding is per access technology, and the lengths differ (TS 131.111 8.19.1-.4: GERAN 7,
|
||||||
|
# UTRAN/E-UTRAN 9, NG-RAN 11) with nothing in the IE to say which -> keep the value opaque.
|
||||||
|
_construct = GreedyBytes
|
||||||
|
|
||||||
class MobileIdentityAdapter(Adapter):
|
class MobileIdentityAdapter(Adapter):
|
||||||
"""TS 124.008 section 10.5.1.4 figure 10.5.4 + table 10.5.4
|
"""TS 124.008 section 10.5.1.4 figure 10.5.4 + table 10.5.4
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from pySim.sms import SMS_SUBMIT, AddressField
|
|||||||
from pySim.cat import (ProactiveCommand, CommandDetails, DeviceIdentities,
|
from pySim.cat import (ProactiveCommand, CommandDetails, DeviceIdentities,
|
||||||
BearerDescription, BufferSize, UiccTransportLevel,
|
BearerDescription, BufferSize, UiccTransportLevel,
|
||||||
OtherAddress, ChannelData, ChannelDataLength, ChannelStatus,
|
OtherAddress, ChannelData, ChannelDataLength, ChannelStatus,
|
||||||
Result)
|
Result, LocationInformation)
|
||||||
|
|
||||||
from pySim.bip import Proact, ProactChannels, terminal_profile
|
from pySim.bip import Proact, ProactChannels, terminal_profile
|
||||||
|
|
||||||
@@ -329,6 +329,34 @@ class OpenChannelRefusalTest(unittest.TestCase):
|
|||||||
self.assertEqual(self.proact.channels.channels, {}) # channel given back
|
self.assertEqual(self.proact.channels.channels, {}) # channel given back
|
||||||
|
|
||||||
|
|
||||||
|
class ProvideLocalInformationTest(unittest.TestCase):
|
||||||
|
"""TS 102 223 6.8.7: only 00 gets a data object; the rest keeps the empty result."""
|
||||||
|
|
||||||
|
def _cmd(self, qualifier):
|
||||||
|
return _pcmd([
|
||||||
|
CommandDetails(decoded={'command_number': 1, 'type_of_command': 'provide_local_info',
|
||||||
|
'command_qualifier': qualifier}).to_tlv(),
|
||||||
|
DeviceIdentities(decoded={'source_dev_id': 'uicc', 'dest_dev_id': 'terminal'}).to_tlv()])
|
||||||
|
|
||||||
|
def test_location(self):
|
||||||
|
til = Proact().handle_ProvideLocalInformation(self._cmd(0x00))
|
||||||
|
b''.join(x.to_tlv() for x in til)
|
||||||
|
self.assertEqual(_first(til, Result).decoded['general_result'], 'performed_successfully')
|
||||||
|
self.assertEqual(b2h(_first(til, LocationInformation).to_tlv()), '930762f21000010001')
|
||||||
|
self.assertEqual(b2h(_first(til, DeviceIdentities).to_tlv()), '82028281') # 6.8.2
|
||||||
|
|
||||||
|
def test_other_qualifiers_get_no_data_object(self):
|
||||||
|
for qualifier in (0x01, 0x03, 0x04, 0x1a):
|
||||||
|
with self.subTest(command_qualifier=qualifier):
|
||||||
|
til = Proact().handle_ProvideLocalInformation(self._cmd(qualifier))
|
||||||
|
b''.join(x.to_tlv() for x in til)
|
||||||
|
self.assertIsNone(_first(til, LocationInformation))
|
||||||
|
|
||||||
|
def test_location_is_configurable(self):
|
||||||
|
til = Proact(location=h2b('26f8100539')).handle_ProvideLocalInformation(self._cmd(0x00))
|
||||||
|
self.assertEqual(b2h(_first(til, LocationInformation).to_tlv()), '930526f8100539')
|
||||||
|
|
||||||
|
|
||||||
class TerminalProfileTest(unittest.TestCase):
|
class TerminalProfileTest(unittest.TestCase):
|
||||||
"""TS 102 223 5.2, one bit per CAT facility"""
|
"""TS 102 223 5.2, one bit per CAT facility"""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user