blob: 57e0d32bf31c8a8a838cc962fc57ffc5eb288eb8 [file] [log] [blame]
Philipp Maierc5b422e2019-08-30 11:41:02 +02001# -*- coding: utf-8 -*-
2
Harald Welte913e6162021-10-11 10:55:00 +02003""" pySim: card handler utilities. A 'card handler' is some method
4by which cards can be inserted/removed into the card reader. For
5normal smart card readers, this has to be done manually. However,
6there are also automatic card feeders.
Philipp Maierc5b422e2019-08-30 11:41:02 +02007"""
8
9#
10# (C) 2019 by Sysmocom s.f.m.c. GmbH
11# All Rights Reserved
12#
13# This program is free software: you can redistribute it and/or modify
14# it under the terms of the GNU General Public License as published by
15# the Free Software Foundation, either version 2 of the License, or
16# (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program. If not, see <http://www.gnu.org/licenses/>.
25#
26
Harald Welte913e6162021-10-11 10:55:00 +020027from pySim.transport import LinkBase
Philipp Maierc5b422e2019-08-30 11:41:02 +020028
29import subprocess
30import sys
31import yaml
32
Harald Weltec91085e2022-02-10 18:05:45 +010033
Harald Welte913e6162021-10-11 10:55:00 +020034class CardHandlerBase:
Harald Weltec91085e2022-02-10 18:05:45 +010035 """Abstract base class representing a mechanism for card insertion/removal."""
Philipp Maierc5b422e2019-08-30 11:41:02 +020036
Harald Weltec91085e2022-02-10 18:05:45 +010037 def __init__(self, sl: LinkBase):
38 self.sl = sl
Philipp Maierc5b422e2019-08-30 11:41:02 +020039
Harald Weltec91085e2022-02-10 18:05:45 +010040 def get(self, first: bool = False):
41 """Method called when pySim needs a new card to be inserted.
Harald Welte913e6162021-10-11 10:55:00 +020042
Harald Weltec91085e2022-02-10 18:05:45 +010043 Args:
44 first : set to true when the get method is called the
45 first time. This is required to prevent blocking
46 when a card is already inserted into the reader.
47 The reader API would not recognize that card as
48 "new card" until it would be removed and re-inserted
49 again.
50 """
51 print("Ready for Programming: ", end='')
52 self._get(first)
Philipp Maierc5b422e2019-08-30 11:41:02 +020053
Harald Weltec91085e2022-02-10 18:05:45 +010054 def error(self):
55 """Method called when pySim failed to program a card. Move card to 'bad' batch."""
56 print("Programming failed: ", end='')
57 self._error()
Philipp Maierc5b422e2019-08-30 11:41:02 +020058
Harald Weltec91085e2022-02-10 18:05:45 +010059 def done(self):
60 """Method called when pySim failed to program a card. Move card to 'good' batch."""
61 print("Programming successful: ", end='')
62 self._done()
Harald Welte913e6162021-10-11 10:55:00 +020063
Harald Weltec91085e2022-02-10 18:05:45 +010064 def _get(self, first: bool = False):
65 pass
Harald Welte913e6162021-10-11 10:55:00 +020066
Harald Weltec91085e2022-02-10 18:05:45 +010067 def _error(self):
68 pass
Harald Welte913e6162021-10-11 10:55:00 +020069
Harald Weltec91085e2022-02-10 18:05:45 +010070 def _done(self):
71 pass
Harald Welte913e6162021-10-11 10:55:00 +020072
73
74class CardHandler(CardHandlerBase):
Harald Weltec91085e2022-02-10 18:05:45 +010075 """Manual card handler: User is prompted to insert/remove card from the reader."""
Harald Welte913e6162021-10-11 10:55:00 +020076
Harald Weltec91085e2022-02-10 18:05:45 +010077 def _get(self, first: bool = False):
78 print("Insert card now (or CTRL-C to cancel)")
79 self.sl.wait_for_card(newcardonly=not first)
Harald Welte913e6162021-10-11 10:55:00 +020080
Harald Weltec91085e2022-02-10 18:05:45 +010081 def _error(self):
82 print("Remove card from reader")
83 print("")
Philipp Maierc5b422e2019-08-30 11:41:02 +020084
Harald Weltec91085e2022-02-10 18:05:45 +010085 def _done(self):
86 print("Remove card from reader")
87 print("")
Philipp Maierc5b422e2019-08-30 11:41:02 +020088
Harald Welte913e6162021-10-11 10:55:00 +020089
90class CardHandlerAuto(CardHandlerBase):
Harald Weltec91085e2022-02-10 18:05:45 +010091 """Automatic card handler: A machine is used to handle the cards."""
Harald Welte913e6162021-10-11 10:55:00 +020092
Harald Weltec91085e2022-02-10 18:05:45 +010093 verbose = True
Philipp Maierc5b422e2019-08-30 11:41:02 +020094
Harald Weltec91085e2022-02-10 18:05:45 +010095 def __init__(self, sl: LinkBase, config_file: str):
96 super().__init__(sl)
97 print("Card handler Config-file: " + str(config_file))
98 with open(config_file) as cfg:
99 self.cmds = yaml.load(cfg, Loader=yaml.FullLoader)
100 self.verbose = (self.cmds.get('verbose') == True)
Philipp Maierc5b422e2019-08-30 11:41:02 +0200101
Harald Weltec91085e2022-02-10 18:05:45 +0100102 def __print_outout(self, out):
103 print("")
104 print("Card handler output:")
105 print("---------------------8<---------------------")
106 stdout = out[0].strip()
107 if len(stdout) > 0:
108 print("stdout:")
109 print(stdout)
110 stderr = out[1].strip()
111 if len(stderr) > 0:
112 print("stderr:")
113 print(stderr)
114 print("---------------------8<---------------------")
115 print("")
Philipp Maierc5b422e2019-08-30 11:41:02 +0200116
Harald Weltec91085e2022-02-10 18:05:45 +0100117 def __exec_cmd(self, command):
118 print("Card handler Commandline: " + str(command))
Philipp Maierc5b422e2019-08-30 11:41:02 +0200119
Harald Weltec91085e2022-02-10 18:05:45 +0100120 proc = subprocess.Popen(
121 [command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
122 out = proc.communicate()
123 rc = proc.returncode
Philipp Maierc5b422e2019-08-30 11:41:02 +0200124
Harald Weltec91085e2022-02-10 18:05:45 +0100125 if rc != 0 or self.verbose:
126 self.__print_outout(out)
Philipp Maierc5b422e2019-08-30 11:41:02 +0200127
Harald Weltec91085e2022-02-10 18:05:45 +0100128 if rc != 0:
129 print("")
130 print("Error: Card handler failure! (rc=" + str(rc) + ")")
131 sys.exit(rc)
Philipp Maierc5b422e2019-08-30 11:41:02 +0200132
Harald Weltec91085e2022-02-10 18:05:45 +0100133 def _get(self, first: bool = False):
134 print("Transporting card into the reader-bay...")
135 self.__exec_cmd(self.cmds['get'])
136 if self.sl:
137 self.sl.connect()
Philipp Maierc5b422e2019-08-30 11:41:02 +0200138
Harald Weltec91085e2022-02-10 18:05:45 +0100139 def _error(self):
140 print("Transporting card to the error-bin...")
141 self.__exec_cmd(self.cmds['error'])
142 print("")
Philipp Maierc5b422e2019-08-30 11:41:02 +0200143
Harald Weltec91085e2022-02-10 18:05:45 +0100144 def _done(self):
145 print("Transporting card into the collector bin...")
146 self.__exec_cmd(self.cmds['done'])
147 print("")