# -*- coding: utf-8 -*-

""" pySim: Transport Link for serial (RS232) based readers included with simcard
"""

#
# Copyright (C) 2009-2010  Sylvain Munaut <tnt@246tNt.com>
#
# 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/>.
#

from __future__ import absolute_import

import serial
import time
import os.path

from pySim.exceptions import NoCardError, ProtocolError
from pySim.transport import LinkBase
from pySim.utils import h2b, b2h


class SerialSimLink(LinkBase):

	def __init__(self, device='/dev/ttyUSB0', baudrate=9600, rst='-rts', debug=False):
		if not os.path.exists(device):
			raise ValueError("device file %s does not exist -- abort" % device)
		self._sl = serial.Serial(
				port = device,
				parity = serial.PARITY_EVEN,
				bytesize = serial.EIGHTBITS,
				stopbits = serial.STOPBITS_TWO,
				timeout = 1,
				xonxoff = 0,
				rtscts = 0,
				baudrate = baudrate,
			)
		self._rst_pin = rst
		self._debug = debug
		self._atr = None

	def __del__(self):
		if (hasattr(self, "_sl")):
			self._sl.close()

	def wait_for_card(self, timeout=None, newcardonly=False):
		# Direct try
		existing = False

		try:
			self.reset_card()
			if not newcardonly:
				return
			else:
				existing = True
		except NoCardError:
			pass

		# Poll ...
		mt = time.time() + timeout if timeout is not None else None
		pe = 0

		while (mt is None) or (time.time() < mt):
			try:
				time.sleep(0.5)
				self.reset_card()
				if not existing:
					return
			except NoCardError:
				existing = False
			except ProtocolError:
				if existing:
					existing = False
				else:
					# Tolerate a couple of protocol error ... can happen if
					# we try when the card is 'half' inserted
					pe += 1
					if (pe > 2):
						raise

		# Timed out ...
		raise NoCardError()

	def connect(self):
		self.reset_card()

	def get_atr(self):
		return self._atr

	def disconnect(self):
		pass # Nothing to do really ...

	def reset_card(self):
		rv = self._reset_card()
		if rv == 0:
			raise NoCardError()
		elif rv < 0:
			raise ProtocolError()

	def _reset_card(self):
		self._atr = None
		rst_meth_map = {
			'rts': self._sl.setRTS,
			'dtr': self._sl.setDTR,
		}
		rst_val_map = { '+':0, '-':1 }

		try:
			rst_meth = rst_meth_map[self._rst_pin[1:]]
			rst_val  = rst_val_map[self._rst_pin[0]]
		except:
			raise ValueError('Invalid reset pin %s' % self._rst_pin)

		rst_meth(rst_val)
		time.sleep(0.1)  # 100 ms
		self._sl.flushInput()
		rst_meth(rst_val ^ 1)

		b = self._rx_byte()
		if not b:
			return 0
		if ord(b) != 0x3b:
			return -1
		self._dbg_print("TS: 0x%x Direct convention" % ord(b))

		while ord(b) == 0x3b:
			b = self._rx_byte()

		if not b:
			return -1
		t0 = ord(b)
		self._dbg_print("T0: 0x%x" % t0)
		self._atr = [0x3b, ord(b)]

		for i in range(4):
			if t0 & (0x10 << i):
				b = self._rx_byte()
				self._atr.append(ord(b))
				self._dbg_print("T%si = %x" % (chr(ord('A')+i), ord(b)))

		for i in range(0, t0 & 0xf):
			b = self._rx_byte()
			self._atr.append(ord(b))
			self._dbg_print("Historical = %x" % ord(b))

		while True:
			x = self._rx_byte()
			if not x:
				break
			self._atr.append(ord(x))
			self._dbg_print("Extra: %x" % ord(x))

		return 1

	def _dbg_print(self, s):
		if self._debug:
			print(s)

	def _tx_byte(self, b):
		self._sl.write(b)
		r = self._sl.read()
		if r != b:	# TX and RX are tied, so we must clear the echo
			raise ProtocolError("Bad echo value. Expected %02x, got %s)" % (ord(b), '%02x'%ord(r) if r else '(nil)'))

	def _tx_string(self, s):
		"""This is only safe if it's guaranteed the card won't send any data
		during the time of tx of the string !!!"""
		self._sl.write(s)
		r = self._sl.read(len(s))
		if r != s:	# TX and RX are tied, so we must clear the echo
			raise ProtocolError("Bad echo value (Expected: %s, got %s)" % (b2h(s), b2h(r)))

	def _rx_byte(self):
		return self._sl.read()

	def send_apdu_raw(self, pdu):
		"""see LinkBase.send_apdu_raw"""

		pdu = h2b(pdu)
		data_len = ord(pdu[4])	# P3

		# Send first CLASS,INS,P1,P2,P3
		self._tx_string(pdu[0:5])

		# Wait ack which can be
		#  - INS: Command acked -> go ahead
		#  - 0x60: NULL, just wait some more
		#  - SW1: The card can apparently proceed ...
		while True:
			b = self._rx_byte()
			if b == pdu[1]:
				break
			elif b != '\x60':
				# Ok, it 'could' be SW1
				sw1 = b
				sw2 = self._rx_byte()
				nil = self._rx_byte()
				if (sw2 and not nil):
					return '', b2h(sw1+sw2)

				raise ProtocolError()

		# Send data (if any)
		if len(pdu) > 5:
			self._tx_string(pdu[5:])

		# Receive data (including SW !)
		#  length = [P3 - tx_data (=len(pdu)-len(hdr)) + 2 (SW1//2) ]
		to_recv = data_len - len(pdu) + 5 + 2

		data = ''
		while (len(data) < to_recv):
			b = self._rx_byte()
			if (to_recv == 2) and (b == '\x60'): # Ignore NIL if we have no RX data (hack ?)
				continue
			if not b:
				break
			data += b

		# Split datafield from SW
		if len(data) < 2:
			return None, None
		sw = data[-2:]
		data = data[0:-2]

		# Return value
		return b2h(data), b2h(sw)
