JPM has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/38993?usp=email )
Change subject: Modem related fixes. ......................................................................
Modem related fixes.
Change-Id: I3e45603a13496fff41b9f859de486143252fb28d --- M pySim/app.py M pySim/cards.py M pySim/transport/modem_atcmd.py 3 files changed, 29 insertions(+), 8 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/93/38993/1
diff --git a/pySim/app.py b/pySim/app.py index 23a4c3c..3483cb2 100644 --- a/pySim/app.py +++ b/pySim/app.py @@ -17,6 +17,7 @@ from typing import Tuple
from pySim.transport import LinkBase +from pySim.transport.modem_atcmd import ModemATCommandLink from pySim.commands import SimCardCommands from pySim.filesystem import CardModel, CardApplication from pySim.cards import card_detect, SimCardBase, UiccCardBase, CardBase @@ -63,12 +64,19 @@ if skip_card_init: return None, CardBase(scc)
- generic_card = False + # Avoid using channel 0 with a Modem to avoid context conflicts. + if isinstance(sl,ModemATCommandLink) and scc.lchan_nr == 0: + scc.cla_byte = '00' + (chan,sw) = scc.manage_channel('open') + scc.lchan_nr = int(chan) + card = card_detect(scc) if card is None: print("Warning: Could not detect card type - assuming a generic card type...") card = SimCardBase(scc) generic_card = True + else: + generic_card = False
profile = CardProfile.pick(scc) if profile is None: diff --git a/pySim/cards.py b/pySim/cards.py index b7958f4..77a2949 100644 --- a/pySim/cards.py +++ b/pySim/cards.py @@ -40,7 +40,7 @@ rc = self._scc.reset_card() if rc == 1: return self._scc.get_atr() - return None + return [] #return empty ATR
def set_apdu_parameter(self, cla: Hexstr, sel_ctrl: Hexstr) -> None: """Set apdu parameters (class byte and selection control bytes)""" diff --git a/pySim/transport/modem_atcmd.py b/pySim/transport/modem_atcmd.py index 340ed92..efe9847 100644 --- a/pySim/transport/modem_atcmd.py +++ b/pySim/transport/modem_atcmd.py @@ -56,7 +56,8 @@ if hasattr(self, '_sl'): self._sl.close()
- def send_at_cmd(self, cmd, timeout=0.2, patience=0.002): + def send_at_cmd(self, cmd, timeout=1.5, patience=0.1): + _timeout = timeout # Convert from string to bytes, if needed bcmd = cmd if isinstance(cmd, bytes) else cmd.encode() bcmd += b'\r' @@ -76,6 +77,7 @@ its = 1 t_start = time.time() while True: + time.sleep(patience) rsp = rsp + self._sl.read(self._sl.in_waiting) lines = rsp.split(b'\r\n') if len(lines) >= 2: @@ -86,13 +88,14 @@ if res == b'ERROR' or res.startswith(b'+CME ERROR:'): log.error('Command failed with result: %s', res) break - if lines[-1].startswith(b'+CSIM:'): # Sequans Monarch GM02S Long APDU response is OK and then all multiple +CSIM - t_start = time.time() # Reset the timer on each additional +CSIM received + if res.startswith(b'+CSIM:'): # Sequans Monarch GM02S Long APDU response is OK and then followed by multiple +CSIM + if not res.startswith(b'+CSIM: 516'): # If max length, then high probability of one more incoming +CSIM + break + _timeout = timeout * (len(lines)-2)
- if time.time() - t_start >= timeout: - log.info('Command finished with timeout >= %ss', timeout) + if time.time() - t_start >= _timeout: + log.info('Command finished with timeout >= %ss', _timeout) break - time.sleep(patience) its += 1 log.debug('Command took %0.6fs (%d cycles a %fs)', time.time() - t_start, its, patience)
@@ -105,6 +108,9 @@ log.debug('Got response from modem: %s', rsp) return rsp
+ def get_atr(self) -> Hexstr: + return Hexstr('') + def _check_echo(self): """Verify the correct response to 'AT' command and detect if inputs are echoed by the device @@ -128,6 +134,13 @@ raise ReaderError('Interface '%s' does not respond to 'AT' command' % self._device)
def _reset_card(self): + # Rebooting the modem to force card reset + cfun = self.send_at_cmd('AT+CFUN?') # Reading current operation mode + if cfun[-1] != b'OK': + raise ReaderError('Failed to read modem operation mode') + if cfun[0].startswith(b'+CFUN:'): + self.send_at_cmd(f'AT+CFUN={cfun[0][-1]-0x30},1',timeout=3.5,patience=1) + # Reset the modem, just to be sure if self.send_at_cmd('ATZ') != [b'OK']: raise ReaderError('Failed to reset the modem')