forked from public/pysim
pySim-shell: Add suspend_uicc command
This is an optional command, and it is not supported by e.g. sysmoISIM-SJA2 Change-Id: Icc726ffd672744e56cc8dd3762891af507942c1e
This commit is contained in:
@@ -156,6 +156,20 @@ close_channel
|
|||||||
:func: Iso7816Commands.close_chan_parser
|
:func: Iso7816Commands.close_chan_parser
|
||||||
|
|
||||||
|
|
||||||
|
suspend_uicc
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
This command allows you to perform the SUSPEND UICC command on the card. This is a relatively
|
||||||
|
recent power-saving addition to the UICC specifications, allowing for suspend/resume while maintaining
|
||||||
|
state, as opposed to a full power-off (deactivate) and power-on (activate) of the card.
|
||||||
|
|
||||||
|
The pySim command just sends that SUSPEND UICC command and doesn't perform the full related sequence
|
||||||
|
including the electrical power down.
|
||||||
|
|
||||||
|
.. argparse::
|
||||||
|
:module: pySim-shell
|
||||||
|
:func: Iso7816Commands.suspend_uicc_parser
|
||||||
|
|
||||||
|
|
||||||
pySim commands
|
pySim commands
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|||||||
@@ -718,6 +718,20 @@ class Iso7816Commands(CommandSet):
|
|||||||
fcp_dec = self._cmd.rs.status()
|
fcp_dec = self._cmd.rs.status()
|
||||||
self._cmd.poutput_json(fcp_dec)
|
self._cmd.poutput_json(fcp_dec)
|
||||||
|
|
||||||
|
suspend_uicc_parser = argparse.ArgumentParser()
|
||||||
|
suspend_uicc_parser.add_argument('--min-duration-secs', type=int, default=60,
|
||||||
|
help='Proposed minimum duration of suspension')
|
||||||
|
suspend_uicc_parser.add_argument('--max-duration-secs', type=int, default=24*60*60,
|
||||||
|
help='Proposed maximum duration of suspension')
|
||||||
|
|
||||||
|
# not ISO7816-4 but TS 102 221
|
||||||
|
@cmd2.with_argparser(suspend_uicc_parser)
|
||||||
|
def do_suspend_uicc(self, opts):
|
||||||
|
"""Perform the SUSPEND UICC command. Only supported on some UICC."""
|
||||||
|
(duration, token, sw) = self._cmd.card._scc.suspend_uicc(min_len_secs=opts.min_duration_secs,
|
||||||
|
max_len_secs=opts.max_duration_secs)
|
||||||
|
self._cmd.poutput('Negotiated Duration: %u secs, Token: %s, SW: %s' % (duration, token, sw))
|
||||||
|
|
||||||
|
|
||||||
option_parser = argparse.ArgumentParser(prog='pySim-shell', description='interactive SIM card shell',
|
option_parser = argparse.ArgumentParser(prog='pySim-shell', description='interactive SIM card shell',
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
from construct import *
|
from construct import *
|
||||||
from pySim.construct import LV
|
from pySim.construct import LV
|
||||||
from pySim.utils import rpad, b2h, h2b, sw_match, bertlv_encode_len
|
from pySim.utils import rpad, b2h, h2b, sw_match, bertlv_encode_len, Hexstr, h2i
|
||||||
from pySim.exceptions import SwMatchError
|
from pySim.exceptions import SwMatchError
|
||||||
|
|
||||||
class SimCardCommands(object):
|
class SimCardCommands(object):
|
||||||
@@ -448,3 +448,39 @@ class SimCardCommands(object):
|
|||||||
data_length = len(payload) // 2
|
data_length = len(payload) // 2
|
||||||
data, sw = self._tp.send_apdu(('80100000%02x' % data_length) + payload)
|
data, sw = self._tp.send_apdu(('80100000%02x' % data_length) + payload)
|
||||||
return (data, sw)
|
return (data, sw)
|
||||||
|
|
||||||
|
# ETSI TS 102 221 11.1.22
|
||||||
|
def suspend_uicc(self, min_len_secs:int=60, max_len_secs:int=43200):
|
||||||
|
"""Send SUSPEND UICC to the card."""
|
||||||
|
def encode_duration(secs:int) -> Hexstr:
|
||||||
|
if secs >= 10*24*60*60:
|
||||||
|
return '04%02x' % (secs // (10*24*60*60))
|
||||||
|
elif secs >= 24*60*60:
|
||||||
|
return '03%02x' % (secs // (24*60*60))
|
||||||
|
elif secs >= 60*60:
|
||||||
|
return '02%02x' % (secs // (60*60))
|
||||||
|
elif secs >= 60:
|
||||||
|
return '01%02x' % (secs // 60)
|
||||||
|
else:
|
||||||
|
return '00%02x' % secs
|
||||||
|
def decode_duration(enc:Hexstr) -> int:
|
||||||
|
time_unit = enc[:2]
|
||||||
|
length = h2i(enc[2:4])
|
||||||
|
if time_unit == '04':
|
||||||
|
return length * 10*24*60*60
|
||||||
|
elif time_unit == '03':
|
||||||
|
return length * 24*60*60
|
||||||
|
elif time_unit == '02':
|
||||||
|
return length * 60*60
|
||||||
|
elif time_unit == '01':
|
||||||
|
return length * 60
|
||||||
|
elif time_unit == '00':
|
||||||
|
return length
|
||||||
|
else:
|
||||||
|
raise ValueError('Time unit must be 0x00..0x04')
|
||||||
|
min_dur_enc = encode_duration(min_len_secs)
|
||||||
|
max_dur_enc = encode_duration(max_len_secs)
|
||||||
|
data, sw = self._tp.send_apdu_checksw('8076000004' + min_dur_enc + max_dur_enc)
|
||||||
|
negotiated_duration_secs = decode_duration(data[:4])
|
||||||
|
resume_token = data[4:]
|
||||||
|
return (negotiated_duration_secs, resume_token, sw)
|
||||||
|
|||||||
Reference in New Issue
Block a user