aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/jenkins.sh1
-rwxr-xr-xpySim-prog.py183
-rw-r--r--pySim/card_handler.py108
3 files changed, 214 insertions, 78 deletions
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index fdcd0cb..a70f139 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -12,6 +12,7 @@ fi
virtualenv -p python2 venv --system-site-packages
. venv/bin/activate
pip install pytlv
+pip install pyyaml
cd pysim-testdata
../tests/pysim-test.sh
diff --git a/pySim-prog.py b/pySim-prog.py
index 13e8bb5..55634a5 100755
--- a/pySim-prog.py
+++ b/pySim-prog.py
@@ -30,6 +30,7 @@ import os
import random
import re
import sys
+import traceback
try:
import json
@@ -41,6 +42,7 @@ from pySim.commands import SimCardCommands
from pySim.cards import _cards_classes
from pySim.utils import h2b, swap_nibbles, rpad, derive_milenage_opc, calculate_luhn, dec_iccid
from pySim.ts_51_011 import EF
+from pySim.card_handler import *
def parse_options():
@@ -163,6 +165,9 @@ def parse_options():
help="Perform a 'dry run', don't actually program the card",
default=False, action="store_true")
+ parser.add_option("--card_handler", dest="card_handler", metavar="FILE",
+ help="Use automatic card handling machine")
+
(options, args) = parser.parse_args()
if options.type == 'list':
@@ -610,6 +615,74 @@ def card_detect(opts, scc):
return card
+def process_card(opts, first, card_handler):
+
+ if opts.dry_run is False:
+ # Connect transport
+ card_handler.get(first)
+
+ if opts.dry_run is False:
+ # Get card
+ card = card_detect(opts, scc)
+ if card is None:
+ print "No card detected!"
+ return -1
+
+ # Probe only
+ if opts.probe:
+ return 0
+
+ # Erase if requested
+ if opts.erase:
+ print "Formatting ..."
+ card.erase()
+ card.reset()
+
+ # Generate parameters
+ if opts.source == 'cmdline':
+ cp = gen_parameters(opts)
+ elif opts.source == 'csv':
+ imsi = None
+ iccid = None
+ if opts.read_iccid:
+ if opts.dry_run:
+ # Connect transport
+ card_handler.get(false)
+ (res,_) = scc.read_binary(['3f00', '2fe2'], length=10)
+ iccid = dec_iccid(res)
+ elif opts.read_imsi:
+ if opts.dry_run:
+ # Connect transport
+ card_handler.get(false)
+ (res,_) = scc.read_binary(EF['IMSI'])
+ imsi = swap_nibbles(res)[3:]
+ else:
+ imsi = opts.imsi
+ cp = read_params_csv(opts, imsi=imsi, iccid=iccid)
+ if cp is None:
+ print "Error reading parameters\n"
+ return 2
+ print_parameters(cp)
+
+ if opts.dry_run is False:
+ # Program the card
+ print "Programming ..."
+ card.program(cp)
+ else:
+ print "Dry Run: NOT PROGRAMMING!"
+
+ # Write parameters permanently
+ write_parameters(opts, cp)
+
+ # Batch mode state update and save
+ if opts.num is not None:
+ opts.num += 1
+ save_batch(opts)
+
+ card_handler.done()
+ return 0
+
+
if __name__ == '__main__':
# Parse options
@@ -638,88 +711,42 @@ if __name__ == '__main__':
# Batch mode init
init_batch(opts)
+ if opts.card_handler:
+ card_handler = card_handler_auto(sl, opts.card_handler)
+ else:
+ card_handler = card_handler(sl)
+
# Iterate
- done = False
first = True
card = None
- while not done:
-
- if opts.dry_run is False:
- # Connect transport
- print "Insert card now (or CTRL-C to cancel)"
- sl.wait_for_card(newcardonly=not first)
+ while 1:
+ try:
+ rc = process_card(opts, first, card_handler)
+ except (KeyboardInterrupt):
+ print ""
+ print "Terminated by user!"
+ sys.exit(0)
+ except (SystemExit):
+ raise
+ except:
+ print ""
+ print "Card programming failed with an execption:"
+ print "---------------------8<---------------------"
+ traceback.print_exc()
+ print "---------------------8<---------------------"
+ print ""
+ rc = -1
+
+ # Something did not work as well as expected, however, lets
+ # make sure the card is pulled from the reader.
+ if rc != 0:
+ card_handler.error()
+
+ # If we are not in batch mode we are done in any case, so lets
+ # exit here.
+ if not opts.batch_mode:
+ sys.exit(rc)
- # Not the first anymore !
first = False
- if opts.dry_run is False:
- # Get card
- card = card_detect(opts, scc)
- if card is None:
- if opts.batch_mode:
- first = False
- continue
- else:
- sys.exit(-1)
-
- # Probe only
- if opts.probe:
- break;
-
- # Erase if requested
- if opts.erase:
- print "Formatting ..."
- card.erase()
- card.reset()
-
- # Generate parameters
- if opts.source == 'cmdline':
- cp = gen_parameters(opts)
- elif opts.source == 'csv':
- imsi = None
- iccid = None
- if opts.read_iccid:
- if opts.dry_run:
- # Connect transport
- print "Insert card now (or CTRL-C to cancel)"
- sl.wait_for_card(newcardonly=not first)
- (res,_) = scc.read_binary(['3f00', '2fe2'], length=10)
- iccid = dec_iccid(res)
- print iccid
- elif opts.read_imsi:
- if opts.dry_run:
- # Connect transport
- print "Insert card now (or CTRL-C to cancel)"
- sl.wait_for_card(newcardonly=not first)
- (res,_) = scc.read_binary(EF['IMSI'])
- imsi = swap_nibbles(res)[3:]
- else:
- imsi = opts.imsi
- cp = read_params_csv(opts, imsi=imsi, iccid=iccid)
- if cp is None:
- print "Error reading parameters\n"
- sys.exit(2)
- print_parameters(cp)
-
- if opts.dry_run is False:
- # Program the card
- print "Programming ..."
- if opts.dry_run is not True:
- card.program(cp)
- else:
- print "Dry Run: NOT PROGRAMMING!"
-
- # Write parameters permanently
- write_parameters(opts, cp)
-
- # Batch mode state update and save
- if opts.num is not None:
- opts.num += 1
- save_batch(opts)
-
- # Done for this card and maybe for everything ?
- print "Done !\n"
-
- if not opts.batch_mode:
- done = True
diff --git a/pySim/card_handler.py b/pySim/card_handler.py
new file mode 100644
index 0000000..46ec93e
--- /dev/null
+++ b/pySim/card_handler.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+""" pySim: card handler utilities
+"""
+
+#
+# (C) 2019 by Sysmocom s.f.m.c. GmbH
+# All Rights Reserved
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import subprocess
+import sys
+import yaml
+
+# Manual card handler: User is prompted to insert/remove card from the reader.
+class card_handler:
+
+ sl = None
+
+ def __init__(self, sl):
+ self.sl = sl
+
+ def get(self, first = False):
+ print "Ready for Programming: Insert card now (or CTRL-C to cancel)"
+ self.sl.wait_for_card(newcardonly=not first)
+
+ def error(self):
+ print "Programming failed: Remove card from reader"
+ print ""
+
+ def done(self):
+ print "Programming successful: Remove card from reader"
+ print ""
+
+# Automatic card handler: A machine is used to handle the cards.
+class card_handler_auto:
+
+ sl = None
+ cmds = None
+ verbose = True
+
+ def __init__(self, sl, config_file):
+ print "Card handler Config-file: " + str(config_file)
+ self.sl = sl
+ with open(config_file) as cfg:
+ self.cmds = yaml.load(cfg, Loader=yaml.FullLoader)
+
+ self.verbose = (self.cmds.get('verbose') == True)
+
+ def __print_outout(self,out):
+ print ""
+ print "Card handler output:"
+ print "---------------------8<---------------------"
+ stdout = out[0].strip()
+ if len(stdout) > 0:
+ print "stdout:"
+ print stdout
+ stderr = out[1].strip()
+ if len(stderr) > 0:
+ print "stderr:"
+ print stderr
+ print "---------------------8<---------------------"
+ print ""
+
+ def __exec_cmd(self, command):
+ print "Card handler Commandline: " + str(command)
+
+ proc = subprocess.Popen([command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ out = proc.communicate()
+ rc = proc.returncode
+
+ if rc != 0 or self.verbose:
+ self.__print_outout(out)
+
+ if rc != 0:
+ print ""
+ print "Error: Card handler failure! (rc=" + str(rc) + ")"
+ sys.exit(rc)
+
+ def get(self, first = False):
+ print "Ready for Programming: Transporting card into the reader-bay..."
+ self.__exec_cmd(self.cmds['get'])
+ self.sl.connect()
+
+ def error(self):
+ print "Programming failed: Transporting card to the error-bin..."
+ self.__exec_cmd(self.cmds['error'])
+ print ""
+
+ def done(self):
+ print "Programming successful: Transporting card into the collector bin..."
+ self.__exec_cmd(self.cmds['done'])
+ print ""