diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 0fe2c40..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pyc
-build/
diff --git a/CHANGES b/CHANGES
deleted file mode 100644
index 3a9c935..0000000
--- a/CHANGES
+++ /dev/null
@@ -1,245 +0,0 @@
-v0.1:  2006-04-28
-First release.
-
-v0.1a: 2006-05-16
-Add 'Value' commands:
-	readvalueblock
-	writevalueblock
-	MIFAREvb (set variables from value block)
-
-v0.1b: 2006-05-29
-Make readblock non MIFARE specific
-Add readMIFAREblock command
-Add reset() call to all test programs (to switch off constant read)
-Add readlfx program to support ACG LFX reader
-
-v0.1c: 2006-05-30
-Add LFXTags hash (125 kHz tag types)
-Add lfxtype.py (command line tag identifier)
-
-v0.d: 2006-06-01
-Add access control block user data byte to MIFARE structure
-Add LFX tag type detection to cardselect.py 
-
-v0.e: 2006-09-29
-Add ICAO 9303 structures for Machine Readable Passports
-New test program: mrpkey.py for ICAO 9303
-Move reader config to RFIDIOtconfig.py
-Add EM4x05 ID decode
-
-v0.f: 2006-10-24
-Emergency release - 0.e lost in webserver disk crash
-Contains work in progress!!!
-Rename EM4x05 decode to more generic FDX-B
-Add EM4x02 'Unique' ID decode/encode
-Add passport file reads and image display
-
-v0.g: 2006-10-27
-Tidy up!
-Update all version numbers
-
-v.0.h:
-Add Hitag2 reading (readlfx)
-Add fdx-b cloning to Q5 / Hitag2 (fdxbnum)
-Add q5unfuck (does what it say on the tin!)
-mrpkey - display all data in GUI
-fdxbnum - add ability to write raw 16 digit HEX (to clone non-compliant tags)
-
-v0.i: 2006-12-10
-Fix login error for sector 0
-
-v0.j:
-Fix iso_7816_fail to allow non-passports to fail properly
-Add support for Frosch Hitag reader/writer
-Start to rationalise routines to always return True or False
-fdxbnum - add Frosch support for Hitag2
-fdxbnum - wait for blank tag in WRITE mode
-
-v0.k:
-was release j - forgot to update version number!
-
-v0.m:
-add facility to set Q5 native ID in 'q5reset.py'
-fix 'EM4x02' ID mode in 'unique.py' (was reversed)
-allow forcing of tag type in 'readlfx.py'
-add 'readtag.py' - read data blocks with no login
-add 'copytag.py' - copy data blocks to matching blank
-add 'isotype.py' - determine HF tag types
-add CHECK for Machine Readable Document  in 'mrpkey.py'
-fix bruteforce for non complete document numbers in 'mrpkey.py'
-fix bruteforce length of field in 'mrpkey.py'
-add offsets for usa & netherlands to 'mrpkey.py'
-add global overrides for line/speed etc. in RFIDIOtconfig.py [AL & Philippe Biondi]
-
-v0.n:
-add CLONE mode to 'unique.py'
-make 'mrpkey.py' more intelligent about reading passport contents:
-  read all data groups
-  extract image from CBEFF block in EF.DG2
-  extract public key certificate from EF.SOD (requires openssl installation)
-  add asn.1 field length encoding rules
-add 'sod.py' tool for brute force finding of certificates in EF_SOD.BIN (requires openssl installation)
-
-v0.p
-add PCSC support (http://pcsclite.alioth.debian.org/ and http://pyscard.sourceforge.net/) [hints/tips/inspiration Henryk Plötz]
-fix cardselect.py and multiselect.py to check for presence of card
-fix 'waitfor/do nothing' in RFIDIOt.py [Philippe Biondi]
-cleaner check digit calc in mrpkey.py [Philippe Biondi]
-change -r to -R (reader type) to allow -r to be used for PCSC compatibility
-add speed/framesize reporting to mrpkey.py
-increase MAX read chunk size to 118 in mrpkey.py (needs fixing to go up to device supported size ISO_FRAMESIZE)
-fix bit allignment issue in FDXBID encoding/decoding [Matsche]
-add global uid variable
-add locked block reporting to readmifare
-add readmifaresimple.py
-
-v0.q
-fix asn1 field length calculation in mrpkey.py
-add human readable config block for Q5 in readlfx.py
-add Manchester encoding to RFIDIOt.py and unique.py
-add serial port opening and baud rate checking for ACG / Frosch in RFIDIOt.py
-add Q5 emulation detection in lfxtype.py
-
-v0.r
-add SCM Microsystems reader support
-add -d (debug) option
-switch to T=1 protocol for PC/SC
-add auto-detect of PC/SC reader types
-fix minor reporting issues in readmifaresimple.py
-fix setting of tag type 'ALL' on ACG readers (different for LF or HF)
-added a bunch of PCSC ATR card types
-add reading of previously stored files to mrpkey.py
-fix CBEFF processing in mrpkey.py 
-fix bruteforcing of first character in mrpkey.py [Petter Bjorklund]
-add ID Card processing to mrpkey.py [vonJeek <mailto:vonjeek@thc.org>]
-
-v0.s
-fix -L issue in RFIDIOtconfig (readernum must be 0)
-add human readable dump to readmifaresimple.py (ReadablePrint() in RFIDIOt)
-fix logic in tag selection in unique.py (would not use hitag2)
-add hitag2 login (password mode) to RFIDIOt.py
-add hitag2bruteforce program hitag2brute.py
-start migrating definitions into smaller files to aid sharing with other apps (e.g. iso3166.py)
-add Windows distribution [Zac Franken]
-
-v0.t - October 2008
-add WRITE function to mrpkey.py for vonJeek JCOP emulator (http://freeworld.thc.org/thc-epassport/)
-add Makefile and vonJeek.gpsh for installing vonJeek epassport.cap to JCOP
-add VONJEEK declarations for vonJeek emulator to RFIDIOt.py
-set mrpkey file types to binary for windows compatibility [Jeroen van Beek / vonJeek <vonjeek@thc.org>]
-use windows compatible command execution for external commands in mrpkey [Jeroen van Beek / vonJeek <vonjeek@thc.org>]
-add WRITE function to mrpkey.py for JMRTD JCOP emulator (http://jmrtd.org/)
-allow mrpkey to skip objects (e.g. fingerprint (EF.DG3) protected by active authentication)
-add mifarekeys.py - calculate 3DES MifarePWD for Access to Mifare memory/functions on Dual Interface JCOP cards
-    as per Philips Application Note AN02105, http://www.nxp.com/acrobat_download/other/identification/067512.pdf
-add some country codes to iso3166.py [Jeroen van Beek / vonJeek <vonjeek@thc.org>]
-add -g 'No GUI' option to RFIDIOtconfig.py
-
-v0.u - November 2008
-add testlahf.sh script for testing LAHF units
-fix -R reader type override in RFIDIOtconfig.py
-add RFIDIOtconfig.py checking for global overrides in one of the following locations (in search order):
-
-	$(RFIDIOtconfig_opts)
-	./RFIDIOtconfig.opts
-	/etc/RFIDIOtconfig.opts
-
-    options should be specified on the first line as if typed on the command line, e.g.
-
-       -s 9600 -l /dev/ttyUSB0
-
-    command line options will take precedence over this file.
-
-add -n (No Init) command to RFIDIOtconfig.py - allow modules to run without hardware
-add display of checksum-corrected MRZ to mrpkey.py
-add jcop_mifare_access.cap - mifare access applet for JCOP
-add jcop_mifare_access.gpsh and target in Makefile for installation of jcop_mifare_access.cap
-add jcopmifare.py test program for JCOP mifare emulation
-add display of biometric features on FACE in mrpkey.py
-
-v0.v - January 2009
-fix ATS position & length in RFIDIOT.py
-add jcopsetatrhist.py - sets ATR Historical Bytes (ATS) on JCOP cards
-add jcop_set_atr_hist.cap - java applet for setting ATR/ATS
-add JAVA source for jcop_set_atr_hist.cap
-move iso_7816 routines into RFIDIOt (from mrpkey.py)
-fix exit status of all test programs and RFIDIOt (should be True on error)
-
-v0.w
-fix ACG reset/info sequence in RFIDIOt.py
-fix facial image display bug in mrpkey.py where conversion is required [Andreas Schmidt]
-fix RANDOM_UID setting in jcop_mifare_access.cap/jcopmifare.py (you will need a secret key from NXP)
-add jcoptool.py - JCOP toolkit (work in progress)
-mrpkey.py changes:
-  fix binary mode when reading files under Windows (for WRITE to card)
-  fix computation of composite checksum digit
-  support reading non-BAC passports
-  specify a dummy MRZ or simply the keyword 'PLAIN' for Plain Access if there is no Basic Access Control
-  support writing non-BAC passports (only for vonJeek cards)
-  new commands SETBAC and UNSETBAC to toggle the BAC mode on vonJeek cards
-  extract & display signature image stored in DG7, if any
-  fix bug in Jpeg 2000 handling & add Jpeg 2000 support for DG7
-  better error handling if PCSC daemon is down or no reader is found
-  support clone mode by specifying PLAIN/MRZ and WRITE: first read then write
-  support shortened MRZ (as in mrp0wn)
-  strip AA & EAC by default when writing, set STRIP_INDEX=False to disable stripping
-change Makefile to match vonJeek gpshell files (upload2jcop.gpsh & upload2nokia.gpsh)
-
-v0.x
-add support for ACS readers and Alcatel-Lucent Tikitag/Touchatag [props to pytey for http://hackerati.com/post/57314994/rfid-on-the-cheap-hacking-tikitag]
-rationalise PCSC subtypes 
-add hidprox.py for reading HID ProxCards (only tested with OmniKey 5325)
-add pn532.py - definitions for nxp pn532 chip
-add pn532emulate.py - run nxp pn532 in emulator mode
-add pn532mitm.py - relay traffic between reader and emulator, and log APDU and responses 
-
-v0.y
-fix support for ACS PCSC-2 devices (e.g. ACR 122U)
-add writelfx.py - test write LF devices
-fix 3DES key setting for ID cards in mrpkey.py
-allow missing files to be skipped if running in files mode in mrpkey.py
-
-v0.z
-add xorcheck.py - search for valid final byte of rolling LRC [input from Henryk Plötz]
-add transit.py - program Q5 with FDI Matalec 'TRANSIT 500' or 'TRANSIT 999' standard UID [input from Proxmark Community]
-
-v1.0a
-make mrpkey.py slightly easier to add new document types to
-add COPY and RESET functions to readmifaresimple.py
-add automatic keytype and default key checking to readmifaresimple.py
-fix MIFARE KeyA and KeyB handling on all supported readers
-add readmifareultra.py - read Mifare UltraLight tags [Keith Howell]
-add support for libnfc devices [Nick von Dadelszen] (work in progress)
-
-v1.0b
-allow global overrides to be specified in ENV variable, e.g.
-  export RFIDIOtconfig="-s 9600 -l /dev/ttyUSB1 -R RFIDIOt.rfidiot.READER_ACG"
-use latest pynfc.py (ver 0.2) for libnfc devices
-add device listing to libnfc support (-N)
-add more keys to readmifaresimple.py [nethemba]
-strip leading character from ACG LFX UID
-add cosmo card (alternative to jcop) upload files for gpshell
-fix init for pn532mitm.py
-make sure all programs exit with status (also removes annoying PCSC error on close)
-wait for passport in mrpkey.py [Adam Urban]
-add lifecycle data to jcoptool.py
-
-v1.0c
-fix reading unknown block size in readblock()
-detect more ACS readers [Keith Howell]
-
-v1.0d
-port pynfc to new libNFC API (1.6.0-rc1)
-add libnfc mifare command support (TODO: error handling)
-*** note that early ACS devices such as ACR122-V1/TikiTag/TouchaTag are not currently
-    working with native libNFC (V2 seem to work fine). This is a libNFC issue.
-    However, ACR122-V1/TikiTag/TouchaTag devices can be used if libNFC is compiled with
-    acr122_pcsc driver support, and then used in conjunction with pcscd, in chich case 
-    they should work as READER_LIBNFC and/or READER_PCSC types. 
-Android support [Nick von Dadelszen]
-
-v1.0e
-move to a package style implementation
-
-v1.0h
-detect ACS reader type more reliably
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 95ef5a8..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,55 +0,0 @@
-to install:
-
-  sudo python ./setup.py install
-
-this will create a python library called 'rfidiot'.
-
-*** important:
-
-as some scripts have moved from the execution path and into the library, you
-should ensure that no old copies are left lying around. in particular, the
-following files should only exist in your python DIST directory
-(e.g. /usr/local/lib/python2.7/dist-packages/rfidiot), and not in /usr/local/bin:
-
-  iso3166.py
-  iso3166.pyc
-  pn532.py
-  pn532.pyc
-  pyandroid.py
-  pyandroid.pyc
-  pynfc.py
-  pynfc.pyc
-  rfidiotglobals.py  
-  rfidiotglobals.pyc
-  RFIDIOt.py
-  RFIDIOt.pyc
-
-for a brief moment setup was configured to create e.g. /usr/local/lib/python2.7/dist-packages/RFIDIOt
-which was an error, so you can safely remove /usr/local/lib/python2.7/dist-packages/RFIDIOt* or
-your equivelant.
-
-*** note - if you are upgrading from a version that didn't use an install script,
-and you've written your own clients, you'll need to make the following changes:
-
-  replace all instances of 'RFIDIOTconfig' with 'rfidiot'
-
-  e.g.
-
-    import RFIDIOtconfig
-
-  becomes
-
-    import rfidiot
-
-  and
-
-    args= RFIDIOtconfig.args
-
-  becomes
-
-     args= rfidiot.args
-
-  etc.
-
-everything else should behave the same as before. please inform me if you hit any snags!
-
diff --git a/Makefile b/Makefile
deleted file mode 100644
index a9ebb90..0000000
--- a/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-# Makefile for uploading vonJeek epassport emulator and Mifare acccess applet
-# http://freeworld.thc.org/thc-epassport/
-#
-# gpshell can be found here:
-# http://sourceforge.net/project/showfiles.php?group_id=143343&package_id=159897
-#
-# blank JCOP cards can be got here:
-# (note vonJeek applet requires 72K card)
-# http://www.rfidiot.org/
-#
-# This makefile by Adam Laurie, 2008
-
-# GPShell...
-GPSHELL= "gpshell"
-GPSHELL_VONJEEK_SCRIPT="upload2jcop.gpsh"
-GPSHELL_VONJEEK_NOKIA_SCRIPT="upload2nokia.gpsh"
-GPSHELL_MIFARE_SCRIPT="jcop_mifare_access.gpsh"
-GPSHELL_ATR_SCRIPT="jcop_set_atr_hist.gpsh"
-GPSHELL_ATR_UNINSTALL_SCRIPT="jcop_delete_atr_hist.gpsh"
-GPSHELL_NOKIA_MIFARE_SCRIPT="nokia_jcop_mifare_access.gpsh"
-
-# install passport applet
-install-passport:
-	# first clean the script of nasty windows <CR>s
-	tr -d '\r' < $(GPSHELL_VONJEEK_SCRIPT) > /tmp/$(GPSHELL_VONJEEK_SCRIPT)
-	$(GPSHELL) /tmp/$(GPSHELL_VONJEEK_SCRIPT)
-
-# install passport applet to Nokia
-# phone must have been unlocked with the unlock midlet:
-# Nokia NFC Unlock Service MIDlet - http://www.forum.nokia.com
-install-passport-nokia:
-	tr -d '\r' < $(GPSHELL_VONJEEK_NOKIA_SCRIPT) > /tmp/$(GPSHELL_VONJEEK_NOKIA_SCRIPT)
-	$(GPSHELL) /tmp/$(GPSHELL_VONJEEK_NOKIA_SCRIPT)
-
-# install mifare access applet
-install-mifare:
-	$(GPSHELL) $(GPSHELL_MIFARE_SCRIPT)
-
-# install ATR History applet
-install-atr:
-	cd java && $(GPSHELL) $(GPSHELL_ATR_SCRIPT)
-
-# delete ATR History applet
-uninstall-atr:
-	cd java && $(GPSHELL) $(GPSHELL_ATR_UNINSTALL_SCRIPT)
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..9477a52
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: rfidiot
+Version: 1.0
+Summary: RFID IO tools
+Home-page: UNKNOWN
+Author: Adam Laurie
+Author-email: adam@algroup.co.uk
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/README.TXT b/README.TXT
deleted file mode 100644
index 631140c..0000000
--- a/README.TXT
+++ /dev/null
@@ -1,39 +0,0 @@
-/* RFIDIOt.py - RFID IO tools for python
- *
- * Adam Laurie <adam@algroup.co.uk>
- * http://rfidiot.org/
- *
- * This code 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 code 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.
- */
-
-Copyright (c) 2006-2011 Adam Laurie <adam@algroup.co.uk>
-
-q: What is RFIDIOt?
-a: A collection of tools and libraries for exploring RFID technology, written 
-in python.
-
-q: Why RFIDIOt?
-a: I like silly puns. Also, I'm coming at this from an idiot's point of view: 
-I know nothing about RFID tags, and even less about python. As such, I felt a 
-complete idiot when I started. :)
-
-q: How can I contribute?
-a: Send me patches, info, new tools, coffee, money, drugs and/or a Miles Davis song :) 
-
-q: What hardware is supported?
-a: So far this works with the ACG serial readers. I use the CF Card model, 
-but it should also work with the USB version by changing the serial port to 
-/dev/ttyUSB0. You can find more details here:
-
-  http://www.acg.de
-
-q: So what exactly is here?
-a: Please see http://www.rfidiot.org/documentation.html
diff --git a/RFIDIOt-android.patch b/RFIDIOt-android.patch
deleted file mode 100644
index b6c8452..0000000
--- a/RFIDIOt-android.patch
+++ /dev/null
@@ -1,108 +0,0 @@
---- RFIDIOt.py	2011-10-30 10:05:00.770555688 +1300
-+++ RFIDIOt-android.py	2011-10-30 10:04:37.674551272 +1300
-@@ -40,7 +40,8 @@
- from operator import *
- import pynfc
- import signal
--
-+import socket
-+import pyandroid
- 
- try:
- 	import smartcard, smartcard.CardRequest
-@@ -153,6 +154,10 @@
- 			elif self.readertype == self.READER_LIBNFC:
- 				self.nfc = pynfc.NFC()
- 				self.readername = self.nfc.LIBNFC_READER
-+			#Andoid reader
-+			elif self.readertype == self.READER_ANDROID:
-+				self.android = pyandroid.Android()
-+				self.readername = "Android"
- 			elif self.readertype == self.READER_NONE:
- 				self.readername = 'none'
- 			else:	
-@@ -204,6 +209,7 @@
- 	READER_ACS= 0x07
- 	READER_LIBNFC = 0x08
- 	READER_NONE = 0x09
-+	READER_ANDROID = 0x10
- 	# TAG related globals
- 	errorcode= ''
- 	binary= ''
-@@ -765,6 +771,8 @@
- 						os._exit(True)
- 			if self.readertype == self.READER_LIBNFC:			
- 				print 'LibNFC', self.readername
-+			if self.readertype == self.READER_ANDROID:			
-+				print 'Android Reader'
- 			print
- 	#
- 	# reader functions
-@@ -799,6 +807,9 @@
- 		if self.readertype == self.READER_LIBNFC:
- 			self.nfc.powerOff()
- 			self.nfc.powerOn()
-+		if self.readertype == self.READER_ANDROID:
-+			self.android.reset()
-+			
- 	def version(self):
- 		if self.readertype == self.READER_ACG:
- 			self.ser.write('v')
-@@ -819,6 +830,8 @@
- 			else:
- 				print self.FROSCH_Errors[self.errorcode]
- 				os._exit(True)
-+		if self.readertype == self.READER_ANDROID:
-+			print 'Android version: ', self.android.VERSION
- 	def id(self):
- 		return self.readEEPROM(0)[:2] + self.readEEPROM(1)[:2] + self.readEEPROM(2)[:2] + self.readEEPROM(3)[:2]
- 	def station(self):
-@@ -986,6 +999,23 @@
- 					return False
- 			except ValueError:
- 				self.errorcode = 'Error reading card using LIBNFC' + e
-+		
-+		if self.readertype == self.READER_ANDROID:
-+			try:
-+				if DEBUG:
-+					print 'Reading card using Android'
-+				uid = self.android.select()
-+				if uid:
-+					self.uid = uid
-+					if DEBUG:
-+						print '\tUID: ' + self.uid
-+					return True
-+				else:
-+					if DEBUG:
-+						print 'Error selecting card'
-+					return False
-+			except ValueError:
-+				self.errorcode = 'Error reading card using Android' + e
- 		return False
- 	def h2publicselect(self):
- 		"select Hitag2 from Public Mode A/B/C"
-@@ -1007,7 +1037,7 @@
- 			return False
- 		return True
- 	def hsselect(self,speed):
--		if self.readertype == self.READER_PCSC or self.readertype == self.READER_LIBNFC:
-+		if self.readertype == self.READER_PCSC or self.readertype == self.READER_LIBNFC or self.READER_ANDROID:
- 			# low level takes care of this, so normal select only
- 			if self.select():
- 				#fixme - find true speed/framesize
-@@ -1361,7 +1391,14 @@
- 			if self.errorcode == self.ISO_OK:
- 				return True
- 			return False
--		dlength= 5
-+		if self.readertype == self.READER_ANDROID:
-+			result = self.android.sendAPDU(cla+self.ISOAPDU[ins]+p1+p2+lc+data+le)
-+			self.data = result[0:-4]
-+			self.errorcode = result[len(result)-4:len(result)]
-+			if self.errorcode == self.ISO_OK:
-+				return True
-+			return False
-+			dlength= 5
- 		command= pcb+cla+self.ISOAPDU[ins]+p1+p2+lc+data+le
- 		dlength += len(data) / 2
- 		dlength += len(lc) / 2
diff --git a/RFIDIOt.py.orig b/RFIDIOt.py.orig
deleted file mode 100644
index c318cc3..0000000
--- a/RFIDIOt.py.orig
+++ /dev/null
@@ -1,2226 +0,0 @@
-#  RFIDIOt.py - RFID IO tools for python
-# -*- coding: iso-8859-15 -*-
-# 
-#  Adam Laurie <adam@algroup.co.uk>
-#  http://rfidiot.org/
-# 
-#  This code is copyright (c) Adam Laurie, 2006,7,8,9 All rights reserved.
-#  For non-commercial use only, the following terms apply - for all other
-#  uses, please contact the author:
-#
-#    This code 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 code 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.
-#
-
-# use Psyco compiler to speed things up if available
-try:
-	import psyco
-	psyco.profile(0.01)
-        psyco.full()
-except ImportError:
-        pass
-
-
-
-import os
-import sys
-import random
-import string
-import time
-from Crypto.Hash import SHA
-from Crypto.Cipher import DES3
-from Crypto.Cipher import DES
-from operator import *
-import pynfc
-import signal
-
-
-try:
-	import smartcard, smartcard.CardRequest
-	IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE = smartcard.scard.SCARD_CTL_CODE(1)
-except:
-	print '*** Warning - no pyscard installed or pcscd not running'
-
-MASK_CCITT = 0x1021 # CRC-CCITT mask (ISO 3309, used in X25, HDLC)
-MASK_11785 = 0x8408
-MASK_CRC16 = 0xA001 # CRC16 mask (used in ARC files)
-
-DEBUG= False
-#DEBUG= True
-NoInit= False
-NFCReader= None
-
-class rfidiot:
-	"RFIDIOt - RFID I/O tools - http://rfidiot.org"
-	# local imports
-	from iso3166 import ISO3166CountryCodesAlpha
-	from iso3166 import ISO3166CountryCodes
-	#
-	# open reader port
-	#
-	def __init__(self,readernum,reader,port,baud,to,debug,noinit,nfcreader):
-		global NoInit
-		global DEBUG
-		self.readertype= reader
-		self.readersubtype= reader
-		readernum= int(readernum)
-		DEBUG= debug
-		NoInit= noinit
-		NFCReader= nfcreader
-		if not NoInit:
-			if self.readertype == self.READER_PCSC:
-				try:
-					self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T1
-				except:
-					print 'Could not find PCSC daemon, try with option -n if you don\'t have a reader'
-					os._exit(True)
-				# select the reader specified
-				try:
-					self.pcsc= smartcard.System.readers()
-				except:
-					print 'Could not find PCSC daemon, try with option -n if you don\'t have a reader'
-					os._exit(True)
-				if readernum >= len(self.pcsc):
-					print 'There is no such reader #%i, PCSC sees only %i reader(s)' % (readernum, len(self.pcsc))
-					os._exit(True)
-				try:
-					self.readername= self.pcsc[readernum].name
-					self.pcsc_connection= self.pcsc[readernum].createConnection()
-					# debug option will show APDU traffic
-					if DEBUG:
-						from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
-						observer=ConsoleCardConnectionObserver()
-						self.pcsc_connection.addObserver( observer )
-				except:
-					print 'Could not create connection to %s' % self.readername
-					os._exit(True)
-				# determine PCSC subtype
-				if string.find(self.readername,'OMNIKEY') == 0:
-					self.readersubtype= self.READER_OMNIKEY
-				else:
-					if string.find(self.readername,'SDI010') == 0:
-						self.readersubtype= self.READER_SCM
-					else:
-						if string.find(self.readername,'ACS ACR 38U') == 0 or string.find(self.readername,'ACS ACR38U') == 0:
-							self.readersubtype= self.READER_ACS
-							self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T0
-							self.hcard = None
-						elif string.find(self.readername,'ACS ACR122U PICC') == 0:
-							self.readersubtype= self.READER_ACS
-							self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T1
-							self.hcard = None
-						else:
-							# default to Omnikey for now
-							self.readersubtype= self.READER_OMNIKEY
-				if DEBUG:
-					print 'Reader Subtype:',self.readersubtype
-				# create a connection
-				try:
-					self.pcsc_connection.connect()
-				except:
-					# card may be something like a HID PROX which only returns ATR and does not allow connect
-					hresult, hcontext = smartcard.scard.SCardEstablishContext( smartcard.scard.SCARD_SCOPE_USER )
-					if hresult != 0:
-						raise error, 'Failed to establish context: ' + smartcard.scard.SCardGetErrorMessage(hresult)
-					hresult, readers = smartcard.scard.SCardListReaders( hcontext, [] )
-					readerstates= [ (readers[readernum], smartcard.scard.SCARD_STATE_UNAWARE ) ]
-					hresult, newstates = smartcard.scard.SCardGetStatusChange( hcontext, 0, readerstates )
-					if self.readersubtype == self.READER_ACS and self.pcsc_protocol == smartcard.scard.SCARD_PROTOCOL_T1:
-						# SCARD_SHARE_SHARED if there is a PICC otherwise SCARD_SHARE_DIRECT
-						hresult, hcard, dwActiveProtocol = smartcard.scard.SCardConnect(
-							hcontext, readers[readernum], smartcard.scard.SCARD_SHARE_DIRECT, smartcard.scard.SCARD_PROTOCOL_T0 )
-						self.hcard = hcard
-						# Let's test if we can really use SCardControl, e.g. by sending a get_firmware_version APDU
-						apdu = [ 0xFF, 0x00, 0x48, 0x00, 0x00 ]
-						hresult, response = smartcard.scard.SCardControl( self.hcard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, apdu )
-						if hresult != smartcard.scard.SCARD_S_SUCCESS:
-							print 'Failed to control: ' + smartcard.scard.SCardGetErrorMessage(hresult)
-							if hresult == smartcard.scard.SCARD_E_NOT_TRANSACTED:
-								print 'Did you set DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED in ifdDriverOptions in libccid_Info.plist?'
-							os._exit(True)
-					self.pcsc_atr= self.ListToHex(newstates[0][2])
-					pass
-				if self.readersubtype == self.READER_ACS:
-					self.acs_set_retry(to)
-			#libnfc device
-			elif self.readertype == self.READER_LIBNFC:
-				self.nfc = pynfc.NFC()
-				self.readername = self.nfc.LIBNFC_READER
-			elif self.readertype == self.READER_NONE:
-				self.readername = 'none'
-			else:	
-				# frosch always starts at 9600 baud - need to add code to test for selected rate and
-				# switch if required. 
-				try:
-					import serial
-					self.ser = serial.Serial(port, baud, timeout=to)
-					self.ser.readline()
-					self.ser.flushInput()
-					self.ser.flushOutput()
-				except:
-					print 'Could not open serial port %s' % port
-					os._exit(True)
-	#
-	# variables
-	#
-	# VERSION: RFIDIOt.py version number
-	# errorcode: 1 letter errorcode returned by the reader
-	#
-	# MIFAREdata: ASCII HEX representation of data block after successful read
-	# MIFAREbinary: data block converted back to binary
-	# MIFAREBLOCKLEN: constant ASCII HEX block length
-	# MIFAREVALUELEN: constant ASCII HEX value length
-	# MIFAREserialnumber: Unique ID (UID) of card
-	# MIFAREkeyA: KEYA from key block (will always be 000000000000)
-	# MIFAREkeyB: KEYB from key block
-	# MIFAREaccessconditions: access conditions field from Key Block
-	# MIFAREC1: Access conditions bitfield C1
-	# MIFAREC2: Access conditions bitfield C2
-	# MIFAREC3: Access conditions bitfield C3
-	# MIFAREblock0AC: Block 0 Access Conditions
-	# MIFAREblock1AC: Block 1 Access Conditions
-	# MIFAREblock2AC: Block 2 Access Conditions
-	# MIFAREblock3AC: Block 3 Access Conditions
-	# MIFAREACKB: Human readable Key Block Access Conditions
-	# MIFAREACDB: Human readable Data Block Access ConditionsA
-	#
-	# MRPmrzu: Machine Readable Passport - Machine Readable Zone - Upper
-	# MRPmrzl Machine Readable Passport - Machine Readable Zone - Lower
-	VERSION= '1.0c-beta'
-	# Reader types
-	READER_ACG= 0x01
-	READER_FROSCH= 0x02
-	READER_DEMOTAG= 0x03
-	READER_PCSC= 0x04
-	READER_OMNIKEY= 0x05
-	READER_SCM= 0x06
-	READER_ACS= 0x07
-	READER_LIBNFC = 0x08
-	READER_NONE = 0x09
-	# TAG related globals
-	errorcode= ''
-	binary= ''
-	data= ''
-	sel_res= ''
-	sens_res= ''
-	tagtype= ''
-	speed= ''
-	framesize= ''
-	uid= ''
-	MIFAREdata=''
-	MIFAREbinary=''
-	MIFAREBLOCKLEN=32
-	MIFAREVALUELEN=8
-	MIFAREserialnumber= ''
-	MIFAREcheckbyte= ''
-	MIFAREmanufacturerdata= ''
-	MIFAREkeyA= ''
-	MIFAREkeyB= ''
-	MIFAREaccessconditions= ''
-	MIFAREaccessconditionsuserbyte= ' '
-	MIFAREC1= 0
-	MIFAREC2= 0
-	MIFAREC3= 0
-	MIFAREblock0AC= ''
-	MIFAREblock1AC= ''
-	MIFAREblock2AC= ''
-	MIFAREblock3AC= ''
-	# PCSC uses 'External Authentication', whereby keys are stored in the reader and then presented to the card. They only need
-	# to be set up once per session, so login will store them in a global dictionary.
-	# PCSC_Keys= { key : keynum } where keynum is 0 - 31 as per OmniKey docs
-	PCSC_Keys= {}
-	# Static Globals
-	MIFAREACKB= {'000':'Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: NONE, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable)',\
-		     '010':'Write KeyA: NONE, Read Access bits: KEYA, Write Access bits: NONE, Read KeyB: KEYA, Write KeyB: NONE (KEYB readable)',\
-		     '100':'Write KeyA: KEYB, Read Access bits: KEYA/B, Write Access bits: NONE, Read KeyB: NONE, Write KeyB: KEYB',\
-		     '110':'Write KeyA: NONE, Read Access bits: KEYA/B, Write Access bits: NONE, Read KeyB: NONE, Write KeyB: NONE',\
-		     '001':'Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)',\
-		     '011':'Write KeyA: KEYB, Read Access bits: KEYA/B, Write Access bits: KEYB, Read KeyB: NONE, Write KeyB: KEYB',\
-		     '101':'Write KeyA: NONE, Read Access bits: KEYA/B, Write Access bits: KEYB, Read KeyB: NONE, Write KeyB: NONE',\
-		     '111':'Write KeyA: NONE, Read Access bits: KEYA/B, Write Access bits: NONE, Read KeyB: NONE, Write KeyB: NONE'}
-	MIFAREACDB= {'000':'Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)',\
-		     '010':'Read: KEYA/B, Write: NONE, Increment: NONE, Decrement/Transfer/Restore: NONE',\
-		     '100':'Read: KEYA/B, Write: KEYB, Increment: NONE, Decrement/Transfer/Restore: NONE',\
-		     '110':'Read: KEYA/B, Write: KEYB, Increment: KEYB, Decrement/Transfer/Restore: KEYA/B',\
-		     '001':'Read: KEYA/B, Write: NONE, Increment: NONE, Decrement/Transfer/Restore: KEYA/B',\
-		     '011':'Read: KEYB, Write: KEYB, Increment: NONE, Decrement/Transfer/Restore: NONE',\
-		     '101':'Read: KEYB, Write: NONE, Increment: NONE, Decrement/Transfer/Restore: NONE',\
-		     '111':'Read: NONE, Write: NONE, Increment: NONE, Decrement/Transfer/Restore: NONE'}
-	LFXTags= {'U':'EM 4x02 (Unique)',\
-		  'Z':'EM 4x05 (ISO FDX-B)',\
-		  'T':'EM 4x50',\
-		  'h':'Hitag 1 / Hitag S',\
-		  'H':'Hitag 2',\
-		  'Q':'Q5',\
-		  'R':'TI-RFID Systems',\
-		  'N':'No TAG present!'}
-	# number of data blocks for each tag type (including block 0)
-	LFXTagBlocks= {'U':0,\
-		  'Z':0,\
-		  'T':34,\
-		  'h':64,\
-		  'H':8,\
-		  'Q':8,\
-		  'R':18,\
-		  'N':0}
-	ALL= 'all'
-	EM4x02= 'U'
-	EM4x05= 'Z'
-	Q5= 'Q'
-	HITAG1= 'h'
-	HITAG2= 'H'
-	HITAG2_TRANSPORT_RWD='4D494B52'
-	HITAG2_TRANSPORT_TAG='AA4854'
-	HITAG2_TRANSPORT_HIGH='4F4E'
-	HITAG2_PUBLIC_A= '02'
-	HITAG2_PUBLIC_B= '00'
-	HITAG2_PUBLIC_C= '04'
-	HITAG2_PASSWORD= '06'
-	HITAG2_CRYPTO= '0e'
-	ACG_FAIL= 'N'
-	# Mifare transort keys
-	MIFARE_TK= { 'AA' : 'A0A1A2A3A4A5',\
-		     'BB' : 'B0B1B2B3B4B5',\
-		     'FF' : 'FFFFFFFFFFFF'}
-	ISOTags= {'a':'ISO 14443 Type A  ',\
-		  'b':'ISO 14443 Type B  ',\
-		  'd':'ICODE UID         ',\
-		  'e':'ICODE EPC         ',\
-		  'i':'ICODE             ',\
-		  's':'SR176             ',\
-		  'v':'ISO 15693         '}
-	ISOTagsA= {'t':'All Supported Tags'}
-	ISO15693= 'v'
-	# Manufacturer codes (Listed in ISO/IEC 7816-6)
-	ISO7816Manufacturer= { '00':'Not Specified',\
-			       '01':'Motorola',\
-			       '02':'ST Microelectronics',\
-			       '03':'Hitachi, Ltd',\
-			       '04':'Philips Semiconductors (NXP)',\
-			       '05':'Infineon Technologies AG',\
-			       '06':'Cylinc',\
-			       '07':'Texas Instrument',\
-			       '08':'Fujitsu Limited',\
-			       '09':'Matsushita Electronics Corporation',\
-			       '0a':'NEC',\
-			       '0b':'Oki Electric Industry Co. Ltd',\
-			       '0c':'Toshiba Corp.',\
-			       '0d':'Mitsubishi Electric Corp.',\
-			       '0e':'Samsung Electronics Co. Ltd',\
-			       '0f':'Hyundai Electronics Industries Co. Ltd',\
-			       '10':'LG-Semiconductors Co. Ltd',\
-			       '12':'HID Corporation',\
-			       '16':'EM Microelectronic-Marin SA',
-			       }
-	ISOAPDU=  {'ERASE BINARY':'0E',
-		   'VERIFY':'20',
-		   # Global Platform
-		   'INITIALIZE_UPDATE':'50',
-		   # GP end
-                   'MANAGE_CHANNEL':'70',
-                   'EXTERNAL_AUTHENTICATE':'82',
-                   'GET_CHALLENGE':'84',
-                   'INTERNAL_AUTHENTICATE':'88',
-                   'SELECT_FILE':'A4',
-                   #vonjeek start
-                   'VONJEEK_SELECT_FILE':'A5',
-                   'VONJEEK_UPDATE_BINARY':'A6',
-                   'VONJEEK_SET_MRZ':'A7',
-		   'VONJEEK_SET_BAC':'A8',
-		   'VONJEEK_SET_DATASET':'AA',
-                   #vonjeek end
-		   # special for JCOP
-		   'MIFARE_ACCESS':'AA',
-		   'ATR_HIST':'AB',
-		   'SET_RANDOM_UID':'AC',
-		   # JCOP end
-                   'READ_BINARY':'B0',
-                   'READ_RECORD(S)':'B2',
-                   'GET_RESPONSE':'C0',
-                   'ENVELOPE':'C2',
-                   'GET_DATA':'CA',
-                   'WRITE_BINARY':'D0',
-                   'WRITE_RECORD':'D2',
-                   'UPDATE_BINARY':'D6',
-                   'PUT_DATA':'DA',
-                   'UPDATE_DATA':'DC',
-		   'CREATE_FILE':'E0',
-                   'APPEND_RECORD':'E2',
-		   # Global Platform
-		   'GET_STATUS':'F2',
-		   # GP end
-		   'READ_BALANCE':'4C',
-		   'INIT_LOAD': '40',
-		   'LOAD_CMD':'42',
-		   'WRITE_MEMORY':'7A',
-		   'READ_MEMORY':'78',
-		   }
-	# some control parameters
-	ISO_7816_SELECT_BY_NAME= '04'
-	ISO_7816_SELECT_BY_EF= '02'
-	ISO_7816_OPTION_FIRST_OR_ONLY= '00'
-	ISO_7816_OPTION_NEXT_OCCURRENCE= '02'
-
-	# well known AIDs
-	AID_CARD_MANAGER= 'A000000003000000'
-	AID_MRTD= 'A0000002471001'
-	AID_JAVA_LANG= 'A0000000620001'
-	AID_JAVACARD_FRAMEWORK= 'A0000000620101'
-	AID_JAVACARD_SECURITY= 'A0000000620102'
-	AID_JAVARCARDX_CRYPTO= 'A0000000620201'
-	AID_FIPS_140_2= 'A000000167413001'
-	AID_JAVACARD_BIOMETRY= 'A0000001320001'
-	AID_SECURITY_DOMAIN= 'A0000000035350'
-	AID_PKCS_15= 'A000000063'
-	AID_JCOP_IDENTIFY= 'A000000167413000FF'
-
-	# Global Platform
-	CLA_GLOBAL_PLATFORM= '80'
-	GP_MAC_KEY= '404142434445464748494A4B4C4D4E4F'
-	GP_ENC_KEY= '404142434445464748494A4B4C4D4E4F'
-	GP_KEK_KEY= '404142434445464748494A4B4C4D4E4F'
-	GP_NO_ENCRYPTION= '00'
-	GP_C_MAC= '01'
-	GP_C_MAC_DECRYPTION= '02'
-	GP_SCP02= '02'
-	GP_REG_DATA= 'E3'
-	GP_REG_AID= '4F'
-	GP_REG_LCS= '9F70'
-	GP_REG_PRIV= 'C5'
-	GP_FILTER_ISD= '80'
-	GP_FILTER_ASSD= '40'
-	GP_FILTER_ELF= '20'
-
-	ISO_OK= '9000'
-	ISO_SECURE= '6982'
-	ISO_NOINFO= '6200'
-
-	ISO_SPEED= {'00':'106kBaud',\
-		    '02':'212kBaud',\
-		    '04':'424kBaud',\
-		    '08':'848kBaud'}
-	ISO_FRAMESIZE= { '00':'16',\
-			 '01':'24',\
-			 '02':'32',\
-			 '03':'40',\
-			 '04':'48',\
-			 '05':'64',\
-			 '06':'96',\
-			 '07':'128',\
-			 '08':'256'}
-	ISO7816ErrorCodes=  {
-			    '61':'SW2 indicates the number of response bytes still available',
-			    '6200':'No information given',
-			    '6281':'Part of returned data may be corrupted',
-			    '6282':'End of file/record reached before reading Le bytes',
-			    '6283':'Selected file invalidated',
-			    '6284':'FCI not formatted according to ISO7816-4 section 5.1.5',
-			    '6300':'No information given',
-			    '6301':'ACR: PN532 does not respond',
-			    '6327':'ACR: Contacless Response invalid checksum',
-			    '637F':'ACR: PN532 invalid Contactless Command',
-			    '6381':'File filled up by the last write',
-			    '6382':'Card Key not supported',
-			    '6383':'Reader Key not supported',
-			    '6384':'Plain transmission not supported',
-			    '6385':'Secured Transmission not supported',
-			    '6386':'Volatile memory not available',
-			    '6387':'Non Volatile memory not available',
-			    '6388':'Key number not valid',
-			    '6389':'Key length is not correct',
-			    '63C':'Counter provided by X (valued from 0 to 15) (exact meaning depending on the command)',
-			    '64':'State of non-volatile memory unchanged (SW2=00, other values are RFU)',
-			    '6400':'Card Execution error',
-			    '6500':'No information given',
-			    '6581':'Memory failure',
-			    '66':'Reserved for security-related issues (not defined in this part of ISO/IEC 7816)',
-			    '6700':'Wrong length',
-			    '6800':'No information given',
-			    '6881':'Logical channel not supported',
-			    '6882':'Secure messaging not supported',
-			    '6900':'No information given',
-			    '6981':'Command incompatible with file structure',
-			    '6982':'Security status not satisfied',
-			    '6983':'Authentication method blocked',
-			    '6984':'Referenced data invalidated',
-			    '6985':'Conditions of use not satisfied',
-			    '6986':'Command not allowed (no current EF)',
-			    '6987':'Expected SM data objects missing',
-			    '6988':'SM data objects incorrect',
-			    '6A00':'No information given',
-			    '6A80':'Incorrect parameters in the data field',
-			    '6A81':'Function not supported',
-			    '6A82':'File not found',
-			    '6A83':'Record not found',
-			    '6A84':'Not enough memory space in the file',
-			    '6A85':'Lc inconsistent with TLV structure',
-			    '6A86':'Incorrect parameters P1-P2',
-			    '6A87':'Lc inconsistent with P1-P2',
-			    '6A88':'Referenced data not found',
-			    '6B00':'Wrong parameter(s) P1-P2',
-			    '6C':'Wrong length Le: SW2 indicates the exact length',
-			    '6D00':'Instruction code not supported or invalid',
-			    '6E00':'Class not supported',
-			    '6F00':'No precise diagnosis',
-			    '9000':'No further qualification',
-			    'ABCD':'RFIDIOt: Reader does not support this command',
-			    'F':'Read error or Security status not satisfied',
-			    'FFFB':'Mifare (JCOP) Block Out Of Range',
-			    'FFFF':'Unspecified Mifare (JCOP) Error',
-			    'N':'No precise diagnosis',
-			    'PC00':'No TAG present!',
-			    'PC01':'PCSC Communications Error',
-			    'PN00': 'PN531 Communications Error',
-			    'R':'Block out of range',
-			    'X':'Authentication failed',
-			    }
-	DES_IV='\0\0\0\0\0\0\0\0'
-	DES_PAD= [chr(0x80),chr(0),chr(0),chr(0),chr(0),chr(0),chr(0),chr(0)]
-	DES_PAD_HEX= '8000000000000000'
-	KENC= '\0\0\0\1'
-	KMAC= '\0\0\0\2'
-	DO87= '870901'
-	DO8E= '8E08'
-	DO97= '9701'
-	DO99= '99029000'
-	#
-	# frosch command set
-	#
-	#
-	# Reader Key Init Mode (update internal secret key)
-	FR_RWD_Key_Init_Mode= chr(0x4B)
-	# Reader Key Init Mode Reset (exit key init mode)
-	FR_RWD_KI_Reset= chr(0x52)
-	# READER Key Init Mode Read EEPROM
-	FR_RWD_KI_Read_EE_Data= chr(0x58)
-	# Reader Stop
-	FR_RWD_Stop_Cmd= chr(0xA6)
-	# Reader Reset
-	FR_RWD_HF_Reset= chr(0x68)
-	# Reader Version
-	FR_RWD_Get_Version= chr(0x56)
-	# Hitag1 Get Serial Number
-	FR_HT1_Get_Snr= chr(0x47)
-	# Hitag1 Get Serial Number & set tag into Advanced Protocol Mode
-	FR_HT1_Get_Snr_Adv= chr(0xA2)
-	# Hitag1 Select Last Seen
-	FR_HT1_Select_Last= chr(0x53)
-	# Hitag1 Select Serial Number
-	FR_HT1_Select_Snr= chr(0x53)
-	# Hitag1 Read Page
-	FR_HT1_Read_Page= chr(0x50)
-	# Hitag2 Get Serial Number (password mode)
-	FR_HT2_Get_Snr_PWD= chr(0x80) + chr(0x00)
-	# Hitag2 Get Serial Number Reset (to reset for normal access when in public modes)
-	FR_HT2_Get_Snr_Reset= chr(0x80)
-	# Hitag2 Halt Selected
-	FR_HT2_Halt_Selected= chr(0x81)
-	# Hitag2 read page
-	FR_HT2_Read_Page= chr(0x82)
-	# Hitag2 Read Miro (Unique / Public Mode A)
-	FR_HT2_Read_Miro= chr(0x4d)
-	# Hitag2 Read Public B (FDX-B)
-	FR_HT2_Read_PublicB= chr(0x9e)
-	# Hitag2 Write Page
-	FR_HT2_Write_Page= chr(0x84)
-	#
-	# frosch errors
-	#
-	FROSCH_Errors= { '00':'No Error',\
-			 '02':'Error',\
-			 '07':'No Error',\
-			 'eb':'Antenna Overload',\
-			 'f1':'EEPROM Read Protected',\
-			 'f2':'EEPROM Write Protected',\
-			 'f3':'EEPROM Wrong - Old Data',\
-			 'f4':'EEPROM Error',\
-			 'f5':'CryptoBlock not INIT',\
-			 'f6':'Acknowledgement Error',\
-			 'f9':'Authentication Error',\
-			 'fa':'Incorrect Password TAG',\
-			 'fb':'Incorrect Password RWD',\
-			 'fc':'Timeout',\
-			 'fd':'No TAG present!',\
-			 'ff':'Serial port fail or wrong mode'}
-	# 
-	# frosch constants
-	#
-	FR_BAUD_RATE= {   9600:chr(0x01),\
-		   	 14400:chr(0x02),\
-		   	 19200:chr(0x03),\
-		   	 38400:chr(0x04),\
-		   	 57600:chr(0x05),\
-		  	115200:chr(0x06)}
-	FR_NO_ERROR= chr(0x00)
-	FR_PLAIN= chr(0x00)
-	FR_CRYPTO= chr(0x01)
-	FR_TIMEOUT= 'fc'
-	FR_COMMAND_MODE= 0x00
-	FR_KEY_INIT_MODE= 0x01
-	#
-	# frosch statics
-	#
-	FR_BCC_Mode= FR_COMMAND_MODE
-	#
-	# DemoTag command set
-	#
-	DT_SET_UID= 'u'
-	#
-	# DemoTag Errors
-	#
-	DT_ERROR= '?'
-	#
-	# PCSC APDUs
-	#
-	# these are basically standard APDUs but with fields filled in and using OmniKey terminology
-	# should really unify them all, but for now...
-	# COMMAND : [Class, Ins, P1, P2, DATA, LEN]
-	PCSC_APDU= {
-		    'ACS_14443_A' : ['d4','40','01'],
-		    'ACS_14443_B' : ['d4','42','02'],
-		    'ACS_14443_0' : ['d5','86','80', '05'],
-		    'ACS_DISABLE_AUTO_POLL' : ['ff','00','51','3f','00'],
-		    'ACS_DIRECT_TRANSMIT' : ['ff','00','00','00'],
-		    'ACS_GET_SAM_SERIAL' : ['80','14','00','00','08'],
-		    'ACS_GET_SAM_ID' : ['80','14','04','00','06'],
-		    'ACS_GET_READER_FIRMWARE' : ['ff','00','48','00','00'],
-		    'ACS_GET_RESPONSE' : ['ff','c0','00','00'],
-		    'ACS_GET_STATUS' : ['d4','04'],
-		    'ACS_IN_LIST_PASSIVE_TARGET' : ['d4','4a'],
-		    'ACS_LED_GREEN' : ['ff','00','40','0e','04','00','00','00','00'],
-		    'ACS_LED_ORANGE' : ['ff','00','40','0f','04','00','00','00','00'],
-		    'ACS_LED_RED' : ['ff','00','40','0d','04','00','00','00','00'],
-		    'ACS_MIFARE_LOGIN' : ['d4','40','01'],
-		    'ACS_READ_MIFARE' : ['d4','40','01','30'],
-		    'ACS_POLL_MIFARE' : ['d4','4a','01','00'],
-		    'ACS_POWER_OFF' : ['d4','32','01','00'],
-		    'ACS_POWER_ON' : ['d4','32','01','01'],
-		    'ACS_RATS_14443_4_OFF' : ['d4','12','24'],
-		    'ACS_RATS_14443_4_ON' : ['d4','12','34'],
-		    'ACS_SET_PARAMETERS' : ['d4','12'],
-		    'ACS_SET_RETRY' : ['d4','32','05','00','00','00'],
-		    'AUTHENTICATE' : ['ff', ISOAPDU['INTERNAL_AUTHENTICATE']],
-		    'GUID' : ['ff', ISOAPDU['GET_DATA'], '00', '00', '00'],
-		    'ACS_GET_ATS' : ['ff', ISOAPDU['GET_DATA'], '01', '00', '00'],
-		    'LOAD_KEY' : ['ff',  ISOAPDU['EXTERNAL_AUTHENTICATE']],
-		    'READ_BLOCK' : ['ff', ISOAPDU['READ_BINARY']],
-		    'UPDATE_BLOCK' : ['ff', ISOAPDU['UPDATE_BINARY']],
-		    'VERIFY' : ['ff', ISOAPDU['VERIFY']],
-		    'WRITE_BLOCK' : ['ff', ISOAPDU['WRITE_BINARY']],
-		    }
-	# PCSC Errors
-	PCSC_NO_CARD= 'PC00'
-	PCSC_COMMS_ERROR= 'PC01'
-	PCSC_VOLATILE= '00'
-	PCSC_NON_VOLATILE= '20'
-	# PCSC Contactless Storage Cards
-	PCSC_CSC= '804F'
-	# PCSC Workgroup RID
-	PCSC_RID= 'A000000306'
-	# PCSC Storage Standard Byte
-	PCSC_SS= { '00':'No information given',\
-		   '01':'ISO 14443 A, part 1',\
-		   '02':'ISO 14443 A, part 2',\
-		   '03':'ISO 14443 A, part 3',\
-		   '04':'RFU',\
-		   '05':'ISO 14443 B, part 1',\
-		   '06':'ISO 14443 B, part 2',\
-		   '07':'ISO 14443 B, part 3',\
-		   '08':'RFU',\
-		   '09':'ISO 15693, part 1',\
-                   '0A':'ISO 15693, part 2',\
-                   '0B':'ISO 15693, part 3',\
-                   '0C':'ISO 15693, part 4',\
-		   '0D':'Contact (7816-10) I2 C',\
-		   '0E':'Contact (7816-10) Extended I2 C',\
-		   '0F':'Contact (7816-10) 2WBP',\
-		   '10':'Contact (7816-10) 3WBP',\
-		   'FF':'RFU'}
-	# PCSC card names
-	PCSC_NAME= { '0000':'No name given',\
-		     '0001':'Mifare Standard 1K',\
-		     '0002':'Mifare Standard 4K',\
-		     '0003':'Mifare Ultra light',\
-		     '0004':'SLE55R_XXXX',\
-		     '0006':'SR176',\
-		     '0007':'SRI X4K',\
-		     '0008':'AT88RF020',\
-		     '0009':'AT88SC0204CRF',\
-		     '000A':'AT88SC0808CRF',\
-		     '000B':'AT88SC1616CRF',\
-		     '000C':'AT88SC3216CRF',\
-		     '000D':'AT88SC6416CRF',\
-		     '000E':'SRF55V10P',\
-		     '000F':'SRF55V02P',\
-		     '0010':'SRF55V10S',\
-		     '0011':'SRF55V02S',\
-		     '0012':'TAG_IT',\
-		     '0013':'LRI512',\
-		     '0014':'ICODESLI',\
-		     '0015':'TEMPSENS',\
-		     '0016':'I.CODE1',\
-		     '0017':'PicoPass 2K',\
-		     '0018':'PicoPass 2KS',\
-		     '0019':'PicoPass 16K',\
-		     '001A':'PicoPass 16Ks',\
-		     '001B':'PicoPass 16K(8x2)',\
-		     '001C':'PicoPass 16KS(8x2)',\
-		     '001D':'PicoPass 32KS(16+16)',\
-		     '001E':'PicoPass 32KS(16+8x2)',\
-		     '001F':'PicoPass 32KS(8x2+16)',\
-		     '0020':'PicoPass 32KS(8x2+8x2)',\
-		     '0021':'LRI64',\
-		     '0022':'I.CODE UID',\
-		     '0023':'I.CODE EPC',\
-		     '0024':'LRI12',\
-		     '0025':'LRI128',\
-		     '0026':'Mifare Mini'}
-	# ACS Constants
-	ACS_TAG_FOUND= 'D54B'
-	ACS_DATA_OK= 'D541'
-	ACS_NO_SAM= '3B00'
-	ACS_TAG_MIFARE_ULTRA= 'MIFARE Ultralight'
-	ACS_TAG_MIFARE_1K= 'MIFARE 1K'
-	ACS_TAG_MIFARE_MINI= 'MIFARE MINI'
-	ACS_TAG_MIFARE_4K= 'MIFARE 4K'
-	ACS_TAG_MIFARE_DESFIRE= 'MIFARE DESFIRE'
-	ACS_TAG_JCOP30= 'JCOP30'
-	ACS_TAG_JCOP40= 'JCOP40'
-	ACS_TAG_MIFARE_OYSTER= 'London Transport Oyster'
-	ACS_TAG_GEMPLUS_MPCOS= 'Gemplus MPCOS'
-
-	ACS_TAG_TYPES=	{
-			'00':ACS_TAG_MIFARE_ULTRA,
-			'08':ACS_TAG_MIFARE_1K,
-			'09':ACS_TAG_MIFARE_MINI,
-			'18':ACS_TAG_MIFARE_4K,
-			'20':ACS_TAG_MIFARE_DESFIRE,
-			'28':ACS_TAG_JCOP30,
-			'38':ACS_TAG_JCOP40,
-			'88':ACS_TAG_MIFARE_OYSTER,
-			'98':ACS_TAG_GEMPLUS_MPCOS,
-			}
-	# HID constants
-	HID_PROX_H10301= '3B0601'
-	HID_PROX_H10302= '3B0702'
-	HID_PROX_H10304= '3B0704'
-	HID_PROX_H10320= '3B0514'
-	HID_PROX_CORP1K= '3B0764'
-	HID_PROX_TYPES=	{
-			HID_PROX_H10301:'HID Prox H10301 - 26 bit (FAC + CN)',
-			HID_PROX_H10302:'HID Prox H10302 - 37 bit (CN)',
-			HID_PROX_H10304:'HID Prox H10304 - 37 bit (FAC + CN)',
-			HID_PROX_H10320:'HID Prox H10320 - 32 bit clock/data card',
-			HID_PROX_CORP1K:'HID Prox Corp 1000 - 35 bit (CIC + CN)',
-			}
-	#
-	# local/informational functions
-	#
-	def info(self,caller):
-		if len(caller) > 0:
-			print caller + ' (using RFIDIOt v' + self.VERSION + ')'
-		if not NoInit:
-			self.reset()
-			self.version()
-			if len(caller) > 0:
-				print '  Reader:',
-			if self.readertype == self.READER_ACG:
-				print 'ACG ' + self.readername,
-				print ' (serial no: ' + self.id() + ')'
-			if self.readertype == self.READER_FROSCH:
-				print 'Frosch ' + self.ToBinary(self.data[:16]) + ' / ' + self.ToBinary(self.data[16:32]),
-				print ' (serial no: ' + self.data[32:54] + ')'
-			if self.readertype == self.READER_PCSC:
-				print 'PCSC ' + self.readername
-				if self.readersubtype == self.READER_ACS and self.pcsc_protocol == smartcard.scard.SCARD_PROTOCOL_T0:
-					# get ATR to see if we have a SAM
-					self.select()
-					if not self.pcsc_atr[:4] == self.ACS_NO_SAM:
-						if self.acs_get_firmware_revision():
-							print '          (Firmware: %s, ' % self.ToBinary(self.data),
-						else:
-							print "\ncan't get firmware revision!"
-							os._exit(True)
-						if self.acs_get_sam_serial():
-							print 'SAM Serial: %s, ' % self.data,
-						else:
-							print "\ncan't get SAM Serial Number!"
-							os._exit(True)
-						if self.acs_get_sam_id():
-							print 'SAM ID: %s)' % self.ToBinary(self.data)
-						else:
-							print "\ncan't get SAM Serial Number!"
-							os._exit(True)
-				elif self.readersubtype == self.READER_ACS and self.pcsc_protocol == smartcard.scard.SCARD_PROTOCOL_T1:
-					if self.acs_get_firmware_revision():
-						print '          (Firmware: %s)' % self.ToBinary(self.data)
-					else:
-						print "\ncan't get firmware revision!"
-						os._exit(True)
-			if self.readertype == self.READER_LIBNFC:			
-				print 'LibNFC', self.readername
-			print
-	#
-	# reader functions
-	#
-        def reset(self):
-		if self.readertype == self.READER_ACG:
-			# send a select to stop just in case it's in multi-select mode
-			self.ser.write('s')
-			self.ser.readline()
-			self.ser.flushInput()
-			self.ser.flushOutput()
-			# now send a reset and read response
-			self.ser.write('x')
-			self.ser.readline()
-			# now send a select and read remaining lines
-			self.ser.write('s')
-			self.ser.readline()
-			self.ser.flushInput()
-			self.ser.flushOutput()
-			return True
-		if self.readertype == self.READER_FROSCH:
-			if self.frosch(self.FR_RWD_HF_Reset,''):
-				return True
-			else:
-				print self.FROSCH_Errors[self.errorcode]
-				os._exit(True)
-		if self.readertype == self.READER_PCSC:
-			if self.readersubtype == self.READER_ACS:
-				self.acs_power_off()			
-				self.acs_power_on()			
-			self.data= 'A PCSC Reader (need to add reset function!)'
-		if self.readertype == self.READER_LIBNFC:
-			self.nfc.powerOff()
-			self.nfc.powerOn()
-	def version(self):
-		if self.readertype == self.READER_ACG:
-			self.ser.write('v')
-			try:
-				self.data= self.ser.readline()[:-2]
-				self.readername= self.data
-			except:
-				print '\nReader not responding - check baud rate'
-				os._exit(True)
-			# check for garbage data (wrong baud rate)
-			if not self.data or self.data[0] < ' ' or self.data[0] > '~':
-				print '\nGarbage received from reader - check baud rate'
-				os._exit(True)
-			return True
-		if self.readertype == self.READER_FROSCH:
-			if self.frosch(self.FR_RWD_Get_Version,''):
-				return True
-			else:
-				print self.FROSCH_Errors[self.errorcode]
-				os._exit(True)
-	def id(self):
-		return self.readEEPROM(0)[:2] + self.readEEPROM(1)[:2] + self.readEEPROM(2)[:2] + self.readEEPROM(3)[:2]
-	def station(self):
-		return self.readEEPROM(0x0a)[:2]
-	def PCON(self):
-		return self.readEEPROM(0x0b)[:2]
-	def PCON2(self):
-		return self.readEEPROM(0x13)[:2]
-	def PCON3(self):
-		return self.readEEPROM(0x1b)[:2]
-	def BAUD(self):
-		return self.readEEPROM(0x0c)[:2]
-	def CGT(self):
-		return self.readEEPROM(0x0d)[:2]
-	def opmode(self):
-		return self.readEEPROM(0x0e)[:2]
-	def SST(self):
-		return self.readEEPROM(0x0f)[:2]
-	def ROT(self):
-		return self.readEEPROM(0x14)[:2]
-	def RRT(self):
-		return self.readEEPROM(0x15)[:2]
-	def AFI(self):
-		return self.readEEPROM(0x16)[:2]
-	def STOa(self):
-		return self.readEEPROM(0x17)[:2]
-	def STOb(self):
-		return self.readEEPROM(0x18)[:2]
-	def STOs(self):
-		return self.readEEPROM(0x19)[:2]
-	def readEEPROM(self,byte):
-		self.ser.write('rp%02x' % byte)
-		return self.ser.readline()[:2]
-	def writeEEPROM(self,byte,value):
-		self.ser.write('wp%02x%02x' % (byte,value))
-		self.errorcode= self.ser.readline()[:-2]
-		if eval(self.errorcode) == value:
-			return True
-		return False
-	def settagtype(self,type):
-		if self.readertype == self.READER_ACG:
-			# ACG HF reader uses 't' for 'all', LF uses 'a'
-			if type == self.ALL:
-				if string.find(self.readername,'LFX') == 0:
-					type= 'a'
-				else:
-					type= 't'
-			self.ser.write('o' + type)
-			self.errorcode= self.ser.readline()[:-2]
-			if self.errorcode == 'O' + string.upper(type):
-				self.tagtype= type
-				return True
-		if self.readertype == self.READER_FROSCH:
-			if type == self.EM4x02:
-				return self.frosch(self.FR_HT2_Read_Miro,'')			
-			if type == self.EM4x05:
-				return self.frosch(self.FR_HT2_Read_PublicB,'')
-		return False
-	#
-	# card functions
-	#
-	def pcsc_listreaders(self):
-		n= 0
-		print 'PCSC devices:'
-		#for reader in self.pcsc.listReader():
-		for reader in self.pcsc:
-			print '    No: %d\t\t%s' % (n,reader)
-			n += 1
-	def libnfc_listreaders(self):
-		self.nfc.listreaders(NFCReader)
-	def waitfortag(self,message):
-		print message
-		# we need a way to interrupt infinite loop
-		if self.readersubtype == self.READER_OMNIKEY or self.readersubtype == self.READER_SCM:
-			wait=True
-			while wait:
-				try:
-					self.pcsc_connection.connect()
-					self.select()
-					wait=False
-				except:
-					sys.stdin.flush()
-					time.sleep(0.5)
-		else:
-			while not self.select():
-				# do nothing
-				time.sleep(0.1)
-		return True
-	def select(self):
-		self.uid= ''
-		# return True or False and set tag type and data
-		if self.readertype == self.READER_ACG:
-			self.ser.write('s')
-			self.data= self.ser.readline()[:-2]
-			self.tagtype= self.data[:1]
-			if self.tagtype == self.ACG_FAIL:
-				self.errorcode= self.PCSC_NO_CARD
-				return False
-			# strip leading tag type from LFX response
-			if self.readername.find("LFX") == 0:
-				self.uid= self.data[1:]
-			else:
-				self.uid= self.data
-			return True
-		if self.readertype == self.READER_FROSCH:
-			if self.frosch(self.FR_HT2_Get_Snr_PWD,''):
-				# select returns an extra byte on the serial number, so strip it
-				self.data= self.data[:len(self.data) - 2]
-				self.tagtype= self.HITAG2
-				self.uid= self.data
-				return True
-			if self.frosch(self.FR_HT1_Get_Snr,''):
-				# select returns an extra byte on the serial number, so strip it
-				# and preserve for after select command
-				serialno= self.data[:len(self.data) - 2]
-				if self.frosch(self.FR_HT1_Select_Last,''):
-					self.tagtype= self.HITAG1
-					self.data= self.uid= serialno
-					return True
-			return False
-		if self.readertype == self.READER_PCSC:
-			try:
-				# start a new connection in case TAG has been switched
-				self.pcsc_connection.disconnect()
-				self.pcsc_connection.connect()
-				time.sleep(0.6)	
-				self.pcsc_atr= self.ListToHex(self.pcsc_connection.getATR())
-				atslen= 2 * int(self.pcsc_atr[3],16)
-				self.pcsc_ats= self.pcsc_atr[8:8 + atslen]
-				if self.readersubtype == self.READER_ACS:
-					self.acs_select_tag()
-				else:
-					self.pcsc_send_apdu(self.PCSC_APDU['GUID'])
-			except smartcard.Exceptions.NoCardException:
-				self.errorcode= self.PCSC_NO_CARD
-				return False
-			except:
-				self.errorcode= self.PCSC_COMMS_ERROR
-				return False
-			if self.errorcode == self.ISO_OK:
-				self.uid= self.data
-				if not self.readersubtype == self.READER_ACS:
-					self.tagtype= self.PCSCGetTagType(self.pcsc_atr)
-				# pcsc returns ISO15693 tags LSByte first, so reverse
-				if string.find(self.tagtype,'ISO 15693') >= 0:
-					self.data= self.uid= self.HexByteReverse(self.data)
-				return True
-			else:
-				return False
-		if self.readertype == self.READER_LIBNFC:
-			try:
-				if DEBUG:
-					print 'reading card using LIBNFC'
-				result = self.nfc.readISO14443A()
-				if result:
-					self.atr = result.atr
-					self.uid = result.uid
-					if DEBUG:
-						print 'ATR: ' + self.atr
-						print 'UID: ' + self.uid
-					return True
-				else:
-					if DEBUG:
-						print 'Error selecting card'
-					return False
-			except ValueError:
-				self.errorcode = 'Error reading card using LIBNFC' + e
-		return False
-	def h2publicselect(self):
-		"select Hitag2 from Public Mode A/B/C"
-		if self.readertype == self.READER_FROSCH:
-			if (self.frosch(self.FR_HT2_Get_Snr_Reset,self.FR_PLAIN + 'M')):
-				self.tagtype= self.HITAG2
-				self.data= self.data[:8]
-				return True
-		return False
-	def h2login(self,password):
-		"login to hitag2 in password mode"
-		if not self.readertype == self.READER_ACG:
-			print 'Reader type not supported for hitag2login!'
-			return False
-		self.ser.write('l'+password)
-		ret= self.ser.readline()[:-2]
-		if ret == self.ACG_FAIL:
-			self.errorcode= ret
-			return False
-		return True
-	def hsselect(self,speed):
-		if self.readertype == self.READER_PCSC or self.readertype == self.READER_LIBNFC:
-			# low level takes care of this, so normal select only
-			if self.select():
-				#fixme - find true speed/framesize
-				self.speed= '04'
-				self.framesize= '08'
-				return True
-			else:
-				return False
-		"high speed select - 106 (speed= 01), 212 (speed= 02), 424 (speed= 04) or 848 (speed= 08) kBaud"
-		self.ser.write('h'+speed)
-		ret= self.ser.readline()[:-2]
-		if ret == self.ACG_FAIL:
-			self.errorcode= ret
-			return False
-		sizebaud= ret[-2:]
-		self.speed= '%02d' % int(sizebaud[-1:])
-		self.framesize= '%02d' % int(sizebaud[:-1])
-		self.data= ret[:-2]
-		return True
-	# ACS specific commands
-	#
-	# note there are 2 different types of ACS command:
-	#   
-	#    standard APDU for reader - acs_send_reader_apdu
-	#    pseudo APDU for contact or contactless card - acs_send_apdu
-	#	
-	# contact and contacless commands are wrapped and passed to the NXP PN532 for processing
-	def acs_send_apdu(self,apdu):
-		"ACS send APDU to contacless card"
-		myapdu= self.HexArraysToArray(apdu)
-		# determine if this is for direct transmission to the card
-		if myapdu[0] == 'd4':
-			# build pseudo command for ACS contactless interface
-			lc= '%02x' % len(myapdu)
-			apduout= self.HexArrayToList(self.PCSC_APDU['ACS_DIRECT_TRANSMIT']+[lc]+myapdu)
-		else:
-			if  myapdu[0] == 'ff' or myapdu[0] == '80':
-				apduout= self.HexArrayToList(myapdu)
-			else:
-				# build pseudo command for ACS 14443-A
-				lc= '%02x' % (len(myapdu) + len(self.PCSC_APDU['ACS_14443_A']))
-				apduout= self.HexArrayToList(self.PCSC_APDU['ACS_DIRECT_TRANSMIT']+[lc]+self.PCSC_APDU['ACS_14443_A']+myapdu)
-		result, sw1, sw2= self.acs_transmit_apdu(apduout)
-		self.errorcode= '%02X%02X' % (sw1,sw2)
-		if self.errorcode == self.ISO_OK:
-			self.data= self.ListToHex(result)
-			if not myapdu[0] == 'ff' and not myapdu[0] == '80' and not myapdu[0] == 'd4':
-				# this is a 14443-A command, so needs further processing
-				# last 4 data bytes is status of wrapped command
-				if self.data[-4:] == self.ISO_OK and len(self.data) > 6:
-					# strip first 6 hex characters (ACS specific)
-					self.data= self.data[6:]
-					# strip last 4 to remove errorcode
-					self.data= self.data[:-4]
-					return True
-				else:
-					self.errorcode= self.data[-4:]
-					# strip ACS status and errorcode in case there is some data expected despite error
-					self.data= self.data[6:-4]
-					return False
-			return True
-		self.data= ''
-		return False
-	def acs_transmit_apdu(self,apdu):
-		"ACS send APDU and retrieve additional DATA if required"
-		if self.hcard is None:
-			result, sw1, sw2= self.pcsc_connection.transmit(apdu,protocol= self.pcsc_protocol)
-			if sw1 == 0x61:
-				# response bytes waiting
-				apduout= self.HexArrayToList(self.PCSC_APDU['ACS_GET_RESPONSE']+[('%02x' % sw2)])
-				result, sw1, sw2= self.pcsc_connection.transmit(apduout,protocol= self.pcsc_protocol)
-			return result, sw1, sw2
-		else:
-			hresult, response = smartcard.scard.SCardControl( self.hcard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, apdu )
-			if hresult != smartcard.scard.SCARD_S_SUCCESS:
-				return '',0x63,0x00
-				#print 'Failed to control: ' + smartcard.scard.SCardGetErrorMessage(hresult)
-				#os._exit(True)
-			# evil hacky bodge as ACS returns only one byte for this APDU (ACS_DISABLE_AUTO_POLL)
-			# and we ignore failure of we're running on firmware V1 as it doesn't support this command
-			if apdu == [0xff,0x00,0x51,0x3f,0x00]:
-				#print 'here!!!'
-				if response == [0x3f] or self.hcard is not None:
-					return '',0x90,0x00
-				else:
-					return '',0x63,0x00
-			result = response[:-2]
-			sw1 = response[-2]
-			sw2 = response[-1]
-			return result, sw1, sw2
-
-	def acs_send_reader_apdu(self,apdu):
-		"ACS send APDU to reader"
-		myapdu= self.HexArraysToArray(apdu)
-		apduout= self.HexArrayToList(myapdu)
-		result, sw1, sw2= self.acs_transmit_apdu(apduout)
-		self.data= self.ListToHex(result)
-		self.errorcode= '%02X%02X' % (sw1,sw2)
-		return True
-	def acs_send_direct_apdu(self,apdu):
-		"ACS send APDU direct to TAG"
-		myapdu= self.HexArraysToArray(apdu)
-		# build pseudo command for ACS 14443-A via NXP PN532
-		lc= '%02x' % (len(myapdu) + len(self.PCSC_APDU['ACS_14443_A']))
-		apduout= self.HexArrayToList(self.PCSC_APDU['ACS_DIRECT_TRANSMIT']+[lc]+self.PCSC_APDU['ACS_14443_A']+myapdu)		
-		result, sw1, sw2= self.acs_transmit_apdu(apduout)
-		self.errorcode= '%02X%02X' % (sw1,sw2)
-		if self.errorcode == self.ISO_OK:
-			self.data= self.ListToHex(result)
-			# strip direct wrapper response and header to get TAG response and DATA
-			if self.data[-4:] == self.ISO_OK and len(self.data) > 6:
-				self.data= self.data[6:]
-				self.data= self.data[:-4]
-				return True
-			else:
-				self.errorcode= self.data[-4:]
-				# strip ACS status and errorcode in case there is some data expected despite error
-				self.data= self.data[6:-4]
-				return False
-			return True
-		else:
-			self.data= ''
-			return False	
-	def acs_rats(self,control):
-		"ACS RATS on/off"
-		if control:
-			return self.acs_send_apdu(self.PCSC_APDU['ACS_RATS_14443_4_ON'])
-		else:
-			return self.acs_send_apdu(self.PCSC_APDU['ACS_RATS_14443_4_OFF'])
-	def acs_mifare_login(self,block,key,keytype):
-		"ACS Mifare Login"
-		if keytype == 'BB':
-			keytype= '61'
-		else:
-		   keytype= '60'
-		loginblock= '%02x' % block
-		if self.tagtype == self.ACS_TAG_MIFARE_1K or self.tagtype == self.ACS_TAG_MIFARE_4K:
-			status= self.acs_send_apdu(self.PCSC_APDU['ACS_MIFARE_LOGIN']+[keytype]+[loginblock]+[key]+[self.uid])
-		else:
-			self.errorcode= self.ISO_NOINFO
-			return False
-		if not status or not self.data[:4] == self.ACS_DATA_OK or not self.data[4:6] == '00':
-			self.errorcode= self.ISO_NOINFO
-			return False
-		self.errorcode= self.ISO_OK
-		return True
-	def acs_read_block(self,block):
-		"ACS READ Block"
-		readblock= '%02x' % block
-		read= False
-		if self.tagtype == self.ACS_TAG_MIFARE_ULTRA or self.tagtype == self.ACS_TAG_MIFARE_1K or self.tagtype == self.ACS_TAG_MIFARE_4K:
-			status= self.acs_send_apdu(self.PCSC_APDU['ACS_READ_MIFARE']+[readblock])
-			read= True
-		if read:
-			if not status or len(self.data) < 8 or not self.data[:4] == self.ACS_DATA_OK:
-				self.errorcode= self.ISO_NOINFO
-				return False
-			# MIFARE ultralight returns 4 blocks although only asking for one, so truncate
-			if self.tagtype == self.ACS_TAG_MIFARE_ULTRA:
-				self.data= self.data[6:14]
-			else:
-				self.data= self.data[6:]
-			self.errorcode= self.ISO_OK
-			return True
-		print "Can't read %s blocks" % self.ACS_TAG_TYPES[self.tagtype]
-		os._exit(True)
-	def acs_get_sam_serial(self):
-		"ACS get SAM serial"
-		return self.acs_send_apdu(self.PCSC_APDU['ACS_GET_SAM_SERIAL'])
-	def acs_get_sam_id(self):
-		"ACS get SAM id"
-		return self.acs_send_apdu(self.PCSC_APDU['ACS_GET_SAM_ID'])
-	def acs_set_retry(self,time):
-		"ACS set retry"
-		# 'time' currently ignored due to lack of documentation - hard wired to '1'
-		return self.acs_send_apdu(self.PCSC_APDU['ACS_SET_RETRY'])
-	def acs_select_tag(self):
-		"ACS select TAG"
-		# power antenna off and on to reset ISO14443-4 tags
-		self.reset()
-		self.acs_send_apdu(self.PCSC_APDU['ACS_POLL_MIFARE'])
-		if not self.data[:4] == self.ACS_TAG_FOUND:
-			# this shouldn't happen as the command should return number of tags to be 0 instead
-			return False
-		tags= int(self.data[4:6])
-		if tags == 0:
-			self.errorcode= self.PCSC_NO_CARD
-			return False
-		target= self.data[6:8]
-		self.sens_res= self.data[8:12]
-		self.sel_res= self.data[12:14]
-		length= int(self.data[14:16])
-		if length == 0:
-			self.errorcode= self.PCSC_NO_CARD
-			return False
-		uid= self.data[16:16+length*2]
-		try:
-			self.tagtype= self.ACS_TAG_TYPES[self.sel_res]
-		except:
-			print 'unrecognised TAG type:', self.sel_res
-			print 'full ACS return:', self.data
-			self.tagtype= 'Unrecognised'
-		self.data= uid
-		return True
-	def acs_get_firmware_revision(self):
-		"ACS Get Firmware Revision"
-                self.acs_send_reader_apdu(self.PCSC_APDU['ACS_GET_READER_FIRMWARE'])
-		# 'special' APDU that doesn't return in the usual way. sw1,sw2 contains some of the data
-		if len(self.data) > 0:
-	                self.data += self.errorcode
-			self.errorcode= self.ISO_OK
-			return True
-		self.data= ''
-		self.errorcode= self.ISO_NOINFO
-		return False
-	def acs_power_on(self):
-		"ACS Antenna Power On"
-		return self.acs_send_apdu(self.PCSC_APDU['ACS_POWER_ON'])
-	def acs_power_off(self):
-		"ACS Antenna Power Off"
-		return self.acs_send_apdu(self.PCSC_APDU['ACS_POWER_OFF'])
-	# Global Platform specific commands
-	def gp_external_authenticate(self,host_cryptogram,mac_key):
-		"Global Platform external authenticate"
-		cla=  '84'
-		ins= 'EXTERNAL_AUTHENTICATE'
-		p1= '00' # security level 0 - plaintext
-		#p1= '01' # security level 1 - C-MAC
-		p2= '00'
-		data= self.ToHex(host_cryptogram)
-		lc= '10' # needs to include MAC that will be added after mac generation
-		mac= self.ToHex(self.DESMAC(self.ToBinary(cla+'82'+p1+p2+lc+data),mac_key,''))
-		data += mac
-		return self.send_apdu('','','','',cla,ins,p1,p2,lc,data,'')
-	def gp_generate_session_key_01(self,hostchallenge,cardchallenge):
-		"Global Platform generate session key from host and card challenges (SCP01)"
-		derivation= cardchallenge[8:16]
-		derivation += hostchallenge[0:8]
-		derivation += cardchallenge[0:8]
-		derivation += hostchallenge[8:16]
-		return(derivation)
-	def gp_get_data(self,object):
-		"Global Platform get data"
-		cla= self.CLA_GLOBAL_PLATFORM
-		ins= 'GET_DATA'
-		p1= object[0:2]
-		p2= object[2:4]
-		le= '00'
-        	return self.send_apdu('','','','',cla,ins,p1,p2,'','',le)
-	def gp_get_status(self,subset,control,aid):
-		"Global Platform get status"
-		cla= self.CLA_GLOBAL_PLATFORM
-		ins= 'GET_STATUS'
-		p1= subset
-		p2= control
-		data= '4F00' + aid
-		lc= '%02x' % (len(data) / 2)
-		le= '00'
-		return self.send_apdu('','','','',cla,ins,p1,p2,lc,data,le)
-	def gp_initialize_update(self,challenge):
-		"Global Platform initialize update"
-		cla= self.CLA_GLOBAL_PLATFORM
-		ins= 'INITIALIZE_UPDATE'
-		p1= '00'
-		p2= '00'
-		data= challenge
-		lc= '%02x' % (len(data) / 2)
-		le= '00'
-		return self.send_apdu('','','','',cla,ins,p1,p2,lc,data,le)
-	def gp_initialize_update_response_scp02(self,data):
-		"return broken down Initialize Update response (SCP02) - Key Diversification (10), Key Info (2), Sequence Counter (2), Card Challenge (6), Card Cryptogram (8)"
-		return data[0:20],data[20:24],data[24:28],data[28:40],data[40:56]
-	# ISO 7816 commands
-	def iso_7816_external_authenticate(self,response,key):
-	        "7816 external authenticate"
-        	ins= 'EXTERNAL_AUTHENTICATE'
-        	lc= le= '%02x' % (len(response) / 2)
-        	if self.send_apdu('','','','','',ins,'','',lc,response,le):
-                	if self.MACVerify(self.data,key):
-                        	return True
-		return False
-	def iso_7816_fail(self,code):
-		"print 7816 failure code and exit"
-		if code == self.ACG_FAIL:
-			print "Application not implemented!"
-			os._exit(True)
-		print "Failed - reason code " + code + " (" + self.ISO7816ErrorCodes[code] + ")"
-		print
-		os._exit(True)
-	def iso_7816_get_challenge(self,length):
-        	"get random challenge - challenge will be in .data"
-        	ins= 'GET_CHALLENGE'
-        	le= '%02x' % length
-        	if DEBUG:
-                	print "DEBUG: requesting %d byte challenge" % length
-        	return self.send_apdu('','','','','',ins,'','','','',le)
-	def iso_7816_read_binary(self,bytes,offset):
-		"7816 read binary - data read will be in .data"
-	        ins= 'READ_BINARY'
-        	hexoffset= '%04x' % offset
-        	p1= hexoffset[0:2]
-        	p2= hexoffset[2:4]
-        	le= '%02x' % bytes
-        	return self.send_apdu('','','','','',ins,p1,p2,'','',le)
-	def iso_7816_select_file(self,file,control,options):
-        	"7816 select file"
-        	ins= 'SELECT_FILE'
-        	lc= '%02x' % (len(file) / 2)
-		p1= control
-		p2= options
-		data= file
-        	return self.send_apdu('','','','','',ins,p1,p2,lc,data,'')
-	def pcsc_send_apdu(self,apdu):
-		# build and transmit PCSC apdu (list as appropriate, e.g. [cla,ins,p1,p2,lc,data,le...])
-		apdustring= ''
-		if self.readersubtype == self.READER_ACS:
-			return self.acs_send_apdu(apdu)
-		# apdu is a list which may contain long fields such as 'data', so first concatonate into
-		# one long string, then break up into 2 char hex fields
-		for d in apdu:
-			apdustring += d
-		apduout= self.HexToList(apdustring)
-		result, sw1, sw2= self.pcsc_connection.transmit(apduout,protocol= self.pcsc_protocol)
-		self.errorcode= '%02X%02X' % (sw1,sw2)
-		self.data= self.ListToHex(result)
-		# SCM readers need a little time to get over the excertion
-#		if self.readersubtype == self.READER_SCM:
-#			time.sleep(.1)
-		if self.errorcode == self.ISO_OK:
-			return True
-		return False
-	def send_apdu(self,option,pcb,cid,nad,cla,ins,p1,p2,lc,data,le):
-		"send iso-7816-4 apdu"
-		if not option:
-			option= '1f'
-			#option= '00'
-		if not pcb:
-			pcb= '02'
-		if not cla:
-			cla= '00'
-		if not p1:
-			p1= '00'
-		if not p2:
-			p2= '00'
-		if self.readertype == self.READER_PCSC:
-			return self.pcsc_send_apdu(cla+self.ISOAPDU[ins]+p1+p2+lc+data+le)
-		if self.readertype == self.READER_LIBNFC:
-			result = self.nfc.sendAPDU(cla+self.ISOAPDU[ins]+p1+p2+lc+data+le)
-			self.data = result[0:-4]
-			self.errorcode = result[len(result)-4:len(result)]
-			if self.errorcode == self.ISO_OK:
-				return True
-			return False
-		dlength= 5
-		command= pcb+cla+self.ISOAPDU[ins]+p1+p2+lc+data+le
-		dlength += len(data) / 2
-		dlength += len(lc) / 2
-		dlength += len(le) / 2
-		if DEBUG:
-			print 'sending: ' + 't' + '%02x' % dlength + option + command
-		self.ser.write('t' + '%02x' % dlength + option + command)
-		# need check for 'le' length as well
-		ret= self.ser.readline()[:-2] 
-		if DEBUG:
-			print 'received:',ret
-		self.errorcode= ret[len(ret) - 4:len(ret)]
-		# copy data if more than just an error code (JCOP sometimes returns an error with data)
-		if len(ret) > 8:
-			self.data= ret[4:len(ret) - 4]
-		else:
-			self.data= ''
-		if self.errorcode == self.ISO_OK:
-			return True
-		return False	
-#		return ret[4:len(ret) - 4]
-#		if not len(ret) / 2 == int(ret[0:2],16) + 1:
-#			return False
-#		return ret[4:int(le,16) * 2 + 4]
-	def login_iclass(self,page,keynum):
-		"login to an iclass page with a key stored on the reader"
-		if not self.readersubtype == self.READER_OMNIKEY:
-			self.errorcode= 'ABCD'
-			return False
-		ins= 'EXTERNAL_AUTHENTICATE'
-		p1= '00'
-		p2= '%02x' % keynum
-		lc= '08'
-		data= '0000000000000000'
-		if not self.send_apdu('','','','','80',ins,p1,p2,lc,data,''):
-			return False
-		return True			
-	def login(self,sector,keytype,key):
-		"login to specified sector - returns True if successful, False if failed. If failure is due to an error, 'errorcode' will be set." 
-		keytype= string.upper(keytype)
-		# use transport key if none specified
-		if not key:
-			key= self.MIFARE_TK[keytype]
-		if self.readertype == self.READER_ACG:
-			if keytype == 'FF':
-				keytype= 'AA'
-			if not sector == '':
-				if DEBUG:
-					print 'sending:', 'l' + ('%02x' % sector) + keytype + key
-				self.ser.write('l' + ('%02x' % sector) + keytype + key)
-			else:
-				if DEBUG:
-					print 'sending:','l' + keytype + key
-				self.ser.write('l' + keytype + key)
-			if key == '':
-				self.ser.write('\r')
-			self.errorcode= self.ser.readline()[0]
-			if DEBUG:
-				print 'received:', self.errorcode
-			if self.errorcode == 'L':
-				self.errorcode= ''
-				return True
-			return False
-		if self.readertype == self.READER_FROSCH:
-			return self.frosch(self.FR_HTS_TagAuthent,'')
-		if self.readertype == self.READER_PCSC:
-			if self.readersubtype == self.READER_ACS:
-				if self.acs_mifare_login(sector,key,keytype):
-					return True
-				else:
-					return False
-			# PCSC requires key to be loaded to reader, then login with key
-			if not self.PCSC_Keys.has_key(key):
-				# send key to reader and store in global PCSC_KEYS if not already sent
-				apdu= []
-				apdu += self.PCSC_APDU['LOAD_KEY']
-				if self.readersubtype == self.READER_OMNIKEY:	
-					keynum= len(self.PCSC_Keys)
-					apdu += self.PCSC_NON_VOLATILE # load key to non-volatile reader memory
-				else:
-					apdu += self.PCSC_VOLATILE # load key to volatile reader memory
-					keynum= len(self.PCSC_Keys) + 96 # SCM Mifare keys live at hex 60+
-				if keytype == 'BB':
-					keynumoffset= 1
-				else:
-					keynumoffset= 0
-				apdu.append('%02x' % (keynum + keynumoffset)) # p2 - key number
-				apdu.append('%02x' % (len(key) / 2)) # lc
-				apdu.append(key) # data
-				if not self.pcsc_send_apdu(apdu):
-					return False
-				if self.readersubtype == self.READER_OMNIKEY:
-					# readers with non-volatile memory only need the key once
-					self.PCSC_Keys[key]= keynum
-			else:
-				#use stored key if already sent	
-				keynum= self.PCSC_Keys[key]
-			# now try to authenticate
-			return self.authenticate(sector,keytype, keynum)
-	def authenticate(self,sector,keytype, keynum):
-			keytype= string.upper(keytype)
-			apdu= []
-			apdu += self.PCSC_APDU['AUTHENTICATE']
-			block= '%04x' % sector
-			apdu.append(block[0:2]) # p1 sector msb
-			apdu.append(block[2:4]) # p1 sector lsb
-			if keytype == 'AA' or keytype == 'FF':
-				apdu.append('60') # keytype
-			elif keytype == 'BB':
-				apdu.append('61') # keytype
-			else:
-				apdu.append(keytype)
-			apdu.append('%02x' % keynum) # key number
-			ret= self.pcsc_send_apdu(apdu)
-			if ret == False:
-				# let PCSC get over it!
-				time.sleep(0.5)
-			return ret
-	def verify(self,keytype,key):
-		keytype= string.upper(keytype)
-		apdu= []
-		apdu += self.PCSC_APDU['VERIFY']
-		if keytype == 'AA' or keytype == 'FF':
-			apdu.append('60') # keytype
-		elif keytype == 'BB':
-			apdu.append('61') # keytype
-		apdu.append('00')
-		apdu.append('%02x' % (len(key) / 2))
-		apdu.append(key)
-		ret= self.pcsc_send_apdu(apdu)
-		if ret == False:
-			# let PCSC get over it!
-			time.sleep(0.5)
-		return ret
-	def readblock(self,block):
-		if self.readertype == self.READER_FROSCH:
-			if self.tagtype == self.HITAG1:
-				return(self.frosch(self.FR_HT1_Read_Page,self.FR_PLAIN + chr(block))) 	
-			if self.tagtype == self.HITAG2:
-				return(self.frosch(self.FR_HT2_Read_Page,chr(block))) 	
-		if self.readertype == self.READER_ACG:
-			self.ser.write('r%02x' % block)
-			self.data= self.ser.readline()[:-2]
-			self.binary= ''
-			if len(self.data) == 1:
-				self.errorcode= self.data
-				self.data= ''
-				return False
-			count= 0
-			while count * 2 < len(self.data):
-				self.binary += chr(int(self.data[count * 2:(count * 2) + 2],16))
-				count += 1
-			return True	
-		if self.readertype == self.READER_PCSC:
-			if self.readersubtype == self.READER_ACS:
-				return self.acs_read_block(block)
-			apdu= []
-			apdu += self.PCSC_APDU['READ_BLOCK']
-			hexblock= '%04x' % block
-			apdu.append(hexblock[0:2]) # p1
-			apdu.append(hexblock[2:4]) # p2
-			# try reading with block length of 1 to provoke size error
-			apdu.append('01') # le
-			ret= self.pcsc_send_apdu(apdu)
-			# if failure is due to wrong block size, use block size returned by card instead
-			if self.errorcode.upper()[0:2] == '6C':
-				apdu[-1]= self.errorcode[2:4]
-				return self.pcsc_send_apdu(apdu)
-			else:
-				return ret
-	def readMIFAREblock(self,block):
-		if self.readblock(block):
-			self.MIFAREdata= self.data
-		else:
-			return False
-		count= 0
-		while count * 2 < len(self.MIFAREdata):
-			self.MIFAREbinary += chr(int(self.MIFAREdata[count * 2:(count * 2) + 2],16))
-			count += 1
-		return True
-	def readvalueblock(self,block):
-		self.ser.write('rv%02x' % block)
-		self.MIFAREdata= self.ser.readline()[:-2]
-		if len(self.MIFAREdata) != self.MIFAREVALUELEN:
-			self.errorcode= self.MIFAREdata
-			self.MIFAREdata= ''
-			return False
-		count= 0
-		while count * 2 < len(self.MIFAREdata):
-			self.MIFAREbinary += chr(int(self.MIFAREdata[count * 2:(count * 2) + 2],16))
-			count += 1
-		return True
-	def writeblock(self,block,data):
-		if self.readertype == self.READER_FROSCH:
-			#if self.tagtype == self.HITAG1:
-			#	return(self.frosch(self.FR_HT1_Read_Page,self.FR_PLAIN + chr(block))) 	
-			if self.tagtype == self.HITAG2:
-				return(self.frosch(self.FR_HT2_Write_Page,chr(block) + self.ToBinary(data))) 	
-		if self.readertype == self.READER_ACG:
-			self.ser.write('w%02x%s' % (block,data))
-			x= self.ser.readline()[:-2]
-			if x == string.upper(data):
-				self.errorcode= ''
-				return True
-			self.errorcode= x
-			return False
-		if self.readertype == self.READER_PCSC:
-			apdu= []
-			apdu += self.PCSC_APDU['UPDATE_BLOCK']
-			hexblock= '%04x' % block
-			apdu.append(hexblock[0:2]) # p1
-			apdu.append(hexblock[2:4]) # p2
-			apdu.append('%02x' % (len(data) / 2)) # le
-			apdu.append(data)
-			return self.pcsc_send_apdu(apdu)
-	def writevalueblock(self,block,data):
-		self.ser.write('wv%02x%s' % (block,data))
-                x= self.ser.readline()[:-2]
-                if x == string.upper(data):
-                        self.errorcode= ''
-                        return True
-                self.errorcode= x
-                return False
-	def frosch(self,command,data):
-		"send frosch commands with check digit"
-		command += data
-		commandlen= len(command)
-		bcc= self.frosch_bcc_out(command,commandlen + 1)
-		# send length + command + checkdigit
-		if DEBUG:
-			print 'Sending: ', 
-			self.HexPrint(chr(commandlen + 1) + command + chr(bcc))
-		self.ser.write(chr(commandlen + 1) + command + chr(bcc))
-		ret= ''
-		# perform a blocking read - returned byte is number of chars still to read
-		ret += self.ser.read(1)
-		# if read times out, reset may be required for normal read mode
-		if len(ret) == 0:
-			if command == self.FR_HT2_Read_PublicB or command == self.FR_HT2_Read_Miro:
-				self.frosch(self.FR_RWD_Stop_Cmd,'')
-			self.errorcode= self.FR_TIMEOUT
-			return False
-		# now read the rest
-		ret += self.ser.read(ord(ret[0]))
-		if DEBUG:
-			print 'ret: %d ' % len(ret),
-			self.HexPrint(ret)
-		# check integrity of return
-		bcc= self.frosch_bcc_in(ret,0)
-		if not bcc == ord(ret[len(ret) - 1]):
-			# may be reporting an error with wrong BCC set
-			if ret[0] == chr(0x02) and not ret[1] == chr(0x00):
-				self.data= ''
-				self.errorcode= self.ToHex(ret[1])
-				return False
-			print 'Frosch error! Checksum error:',
-			self.HexPrint(ret)
-			print 'Expected BCC: %02x' % bcc
-			os._exit(True)
-		status= ret[1]
-		if status == self.FR_NO_ERROR:
-			self.errorcode= ''
-			# for consistency with ACG, data is converted to printable hex before return
-			self.data= self.ToHex(ret[2:len(ret) - 1])
-			return True
-		else :
-			self.errorcode= self.ToHex(status)
-			self.data= ''
-			if DEBUG:
-				print "Frosch error:", int(self.errorcode,16) - 256
-			# reader may need resetting to normal read mode
-			if command == self.FR_HT2_Read_PublicB or command == self.FR_HT2_Read_Miro:
-				self.frosch(self.FR_RWD_Stop_Cmd,'')
-			return False
-	def frosch_bcc(self,data,seed):
-		bcc= seed
-		if self.FR_BCC_Mode == self.FR_COMMAND_MODE:
-			for x in range(len(data)):
-				bcc= xor(bcc,ord(data[x]))
-		else:
-			for x in range(len(data)):
-				bcc += ord(data[x])
-			bcc= int(bcc & 0xff)
-		return bcc	
-	def frosch_bcc_in(self,data,seed):
-		return self.frosch_bcc(data[:len(data) - 1],seed)
-	def frosch_bcc_out(self,data,seed):
-		return self.frosch_bcc(data,seed)
-	def frosch_key_init_mode(self,passwd):
-		"enter key init mode"
-		status= self.frosch(self.FR_RWD_Key_Init_Mode,self.ToBinary(passwd))
-		# frosch BCC calculation mode changes once we enter key init mode
-		if status:
-			self.FR_BCC_Mode= self.FR_KEY_INIT_MODE
-		return status
-	def frosch_read_ee_data(self,item):
-		"read RWD EEPROM"
-		# item defines which personalization data is to be read
-		# 0x00 ... Password
-		# 0x01 ... Key A
-		# 0x02 ... Key B
-		# 0x03 ... Logdata 0A
-		# 0x04 ... Logdata 0B
-		# 0x05 ... Logdata 1A
-		# 0x06 ... Logdata 1B
-		return self.frosch(self.FR_RWD_KI_Read_EE_Data,self.ToBinary(item))
-	def demotag(self,command,data):
-		"send DemoTag commands"
-		if self.ser.write(command + data):
-                	x= self.ser.readline()[:-2]
-			if x == self.DT_ERROR:
-				self.errorcode= x
-				return False
-			self.data= x
-			return True
-		return False
-	#
-	# data manipulation
-	#
-	def GetRandom(self,size):
-        	data= ''
-        	for x in range(size):
-                	data += '%02x' % int(random.uniform(0,0xff))
-        	return data
-	def Parity(self,data,parity):
-		# return parity bit to make odd or even as required
-		myparity= 0
-		for x in range(len(data)):
-			myparity += int(data[x],2)
-		myparity %= 2
-		return xor(myparity,parity)
-	def Unique64Bit(self,data):
-		"convert binary ID to Unique formatted 64 bit data block"
-		# standard header == 9 bits of '1'
-		out= '111111111'
-		# break output into 4 bit chunks and add parity
-		colparity= [0,0,0,0]
-		for x in range(0,len(data),4):
-			parity= 0
-			chunk= data[x:x+4]
-			for y in range(4):
-				parity += int(chunk[y],2)
-				colparity[y] += int(chunk[y],2)
-			out += chunk + '%s' % (int(parity) % 2)
-		# add column parity
-		for x in range(4):
-			out += '%s' % (int(colparity[x]) % 2)
-		# add stop bit
-		out += '0'
-		return out
-	def UniqueToEM(self,data):
-		"convert Unique ID to raw EM4x02 ID"
-		# swap words
-		tmp= ''
-		for x in range(5):
-			tmp += data[x * 2 + 1] + data[x * 2]
-		# reverse bits
-		return self.ToBinaryString(self.ToBinary(tmp))[::-1]
-	def EMToUnique(self,data):
-		"convert raw EM4x02 ID to Unique"
-		return self.ToHex(self.BitReverse(self.ToBinary(data)))
-	def HexToQ5(self,data):
-		"conver human readable HEX to Q5 ID"
-		return self.ToBinaryString(self.ToBinary(data))
-	def crcccitt(self,data):
-		crcvalue= 0x0000
-		for x in range(len(data)):
-			crcvalue= self.crc(crcvalue,data[x],MASK_CCITT)
-		return crcvalue
-	def crc(self, crc, data, mask=MASK_CRC16):
-		for char in data:
-			c = ord(char)
-			c = c << 8
-		for j in xrange(8):
-			if (crc ^ c) & 0x8000:
-				crc = (crc << 1) ^ mask
-			else:
-				crc = crc << 1
-			c = c << 1
-		return crc & 0xffff
-	def crc16(self,data):
-		crcValue=0x0000
-		crc16tab = (0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280,
-		0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481,
-		0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81,
-		0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880,
-		0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81,
-		0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80,
-		0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680,
-		0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081,
-		0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281,
-		0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480,
-		0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80,
-		0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881,
-		0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80,
-		0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81,
-		0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681,
-		0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080,
-		0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281,
-		0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480,
-		0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80,
-		0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881,
-		0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80,
-		0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81,
-		0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681,
-		0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080,
-		0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280,
-		0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481,
-		0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81,
-		0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880,
-		0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81,
-		0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80,
-		0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680,
-		0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081,
-		0x4040)
-		for ch in data:
-			tmp=crcValue^(ord(ch))
-			crcValue=(crcValue>> 8)^crc16tab[(tmp & 0xff)]
-		return crcValue
-	def MIFAREmfb(self,data):
-		"Set variables from standard MIFARE manufacturer block (block 0 sector 0)"
-		self.MIFAREserialnumber= data[0:8]
-		self.MIFAREcheckbyte= data[8:10]
-		self.MIFAREmanufacturerdata= data[10:32]
-	def MIFAREkb(self,data):
-		"Set variables from standard MIFARE key block (trailing sector)"
-		self.MIFAREkeyA= data[0:12]
-		self.MIFAREaccessconditions= data[12:18]
-		self.MIFAREaccessconditionsuserbyte= data[18:20]
-		self.MIFAREC1= int(data[14:16],16) >> 4
-		self.MIFAREC2= int(data[16:18],16) & 0x0f
-		self.MIFAREC3= (int(data[16:18],16) & 0xf0) >> 4
-		self.MIFAREblock0AC= str(self.MIFAREC1 & 0x01) + str(self.MIFAREC2 & 0x01) + str(self.MIFAREC3 & 0x01)
-		self.MIFAREblock1AC= str((self.MIFAREC1 & 0x02) >> 1) + str((self.MIFAREC2 & 0x02) >> 1) + str((self.MIFAREC3 & 0x02) >> 1)
-		self.MIFAREblock2AC= str((self.MIFAREC1 & 0x04) >> 2) + str((self.MIFAREC2 & 0x04) >> 2) + str((self.MIFAREC3 & 0x04) >> 2)
-		self.MIFAREblock3AC= str((self.MIFAREC1 & 0x08) >> 3) + str((self.MIFAREC2 & 0x08) >> 3) + str((self.MIFAREC3 & 0x08) >> 3)
-		self.MIFAREkeyB= data[20:32]
-	def MIFAREvb(self,data):
-		"Set variables from standard MIFARE value block"
-		self.MIFAREvalue= data[0:4]
-		self.MIFAREvalueinv= data[4:8]
-		self.MIFAREvalue2= data[8:12]
-		self.MIFAREaddr= data[12]
-		self.MIFAREaddrinv= data[13]
-		self.MIFAREaddr2= data[14]
-		self.MIFAREaddrinv2= data[15]
-	def MRPmrzl(self,data):
-		"Set variables from Machine Readable Zone (Lower)"
-		self.MRPnumber= data[0:9]
-		self.MRPnumbercd= data[9]
-		self.MRPnationality= data[10:13]
-		self.MRPdob= data[13:19]
-		self.MRPdobcd= data[19]
-		self.MRPsex= data[20]
-		self.MRPexpiry= data[21:27]
-		self.MRPexpirycd= data[27]
-		self.MRPoptional= data[28:42]
-		self.MRPoptionalcd= data[42]
-		self.MRPcompsoitecd= data[43]
-	def BitReverse(self,data):
-		"Reverse bits - MSB to LSB"
-		output= ''
-		for y in range(len(data)):
-			outchr= ''
-			for x in range(8):
-				outchr += str(ord(data[y]) >> x & 1)
-			output += str(chr(int(outchr,2)))
-		return output
-	def HexReverse(self,data):
-		"Reverse HEX characters"
-		output= ''
-		for y in reversed(range(len(data))):
-			output += data[y]
-		return output
-	def HexBitReverse(self,data):
-		"Convert HEX to Binary then bit reverse and convert back"
-		return self.ToHex(self.BitReverse(self.ToBinary(data)))
-	def HexByteReverse(self,data):
-		"Reverse order of Hex pairs"
-		output= ''
-		y= len(data) - 2
-		while y >= 0:
-			output += data[y:y+2]
-			y -= 2
-		return output
-	def NibbleReverse(self,data):
-		"Reverse Nibbles"
-		output= ''
-		for y in range(len(data)):
-			leftnibble= ''
-			rightnibble= ''
-			for x in range(4):
-				leftnibble += str(ord(data[y]) >> x & 1)
-			for x in range(4,8):
-				rightnibble += str(ord(data[y]) >> x & 1)
-			output += str(chr(int(rightnibble + leftnibble,2)))
-		return output
-	def HexNibbleReverse(self,data):
-		"Convert HEX to Binary then reverse nibbles and convert back"
-		return self.ToHex(self.NibbleReverse(self.ToBinary(data)))
-	def ToHex(self,data):
-		"convert binary data to hex printable"
-        	string= ''
-        	for x in range(len(data)):
-                	string += '%02x' % ord(data[x])
-		return string
-	def HexPrint(self,data):
-        	print self.ToHex(data)
-	def ReadablePrint(self,data):
-		out= ''
-		for x in range(len(data)):
-			if data[x] >= ' ' and data[x] <= '~':
-				out += data[x]
-			else:
-				out += '.'
-		return out
-	def ListToHex(self,data):
-		string= ''
-		for d in data:
-			string += '%02X' % d
-		return string
-	def HexArrayToString(self,array):
-		# translate array of strings to single string
-		out= ''
-		for n in array:
-			out += n
-		return out
-	def HexArraysToArray(self,array):
-		# translate an array of strings to an array of 2 character strings
-		temp= self.HexArrayToString(array)
-		out= []
-		n= 0
-		while n < len(temp):
-			out.append(temp[n:n+2])
-			n += 2
-		return out
-	def HexArrayToList(self,array):
-		# translate array of 2 char HEX to int list
-		# first make sure we're dealing with a single array
-		source= self.HexArraysToArray(array)
-		out= []
-		for n in source:
-			out.append(int(n,16))
-		return out
-	def HexToList(self,string):
-		# translate string of 2 char HEX to int list
-		n= 0
-		out= []
-		while n < len(string):
-			out.append(int(string[n:n+2],16))
-			n += 2
-		return out
-	def ToBinary(self,string):
-		"convert hex string to binary characters"
-        	output= ''
-        	x= 0
-        	while x < len(string):
-                	output += chr(int(string[x:x + 2],16))
-                	x += 2
-        	return output
-	def BinaryPrint(self,data):
-		"print binary representation"
-		print self.ToBinaryString(data)
-	def ToBinaryString(self,data):
-		"convert binary data to printable binary ('01101011')"
-		output= ''
-		string= self.ToHex(data)
-		for x in range(0,len(string),2):
-			for y in range(7,-1,-1):
-				output += '%s' % (int(string[x:x+2],16) >> y & 1)
-		return output
-	def BinaryToManchester(self,data):
-		"convert binary string to manchester encoded string"
-		output= ''
-		for bit in data:
-			if bit == '0':
-				output += '01'
-			else:
-				output += '10'
-		return output
-	def DESParity(self,data):
-        	adjusted= ''
-        	for x in range(len(data)):
-                	y= ord(data[x]) & 0xfe
-                	parity= 0
-                	for z in range(8):
-                        	parity += y >>  z & 1
-                	adjusted += chr(y + (not parity % 2))
-        	return adjusted
-	def DESKey(self,seed,type,length):
-		d= seed + type	
-		kencsha= SHA.new(d)
-		k= kencsha.digest()
-		kp= self.DESParity(k)
-		return(kp[:length])
-	def PADBlock(self,block):
-		"add DES padding to data block"
-		# call with null string to return an 8 byte padding block
-		# call with an unknown sized block to return the block padded to a multiple of 8 bytes
-        	for x in range(8 - (len(block) % 8)):
-                	block += self.DES_PAD[x]
-		return block
-	def DES3MAC(self,message,key,ssc):
-		"iso 9797-1 Algorithm 3 (Full DES3)"
-		tdes= DES3.new(key,DES3.MODE_ECB,self.DES_IV)
-		if(ssc):
-			mac= tdes.encrypt(self.ToBinary(ssc))
-		else:
-			mac= self.DES_IV
-		message += self.PADBlock('')
-		for y in range(len(message) / 8):
-			current= message[y * 8:(y * 8) + 8]
-			left= ''
-			right= ''
-			for x in range(len(mac)):
-				left += '%02x' % ord(mac[x])
-				right += '%02x' % ord(current[x])
-			machex= '%016x' % xor(int(left,16),int(right,16))
-			mac= tdes.encrypt(self.ToBinary(machex))
-		# iso 9797-1 says we should do the next two steps for "Output Transform 3"
-		# but they're obviously redundant for DES3 with only one key, so I don't bother!
-		#mac= tdes.decrypt(mac)
-		#mac= tdes.encrypt(mac)
-		return mac
-	def DESMAC(self,message,key,ssc):
-		"iso 9797-1 Algorithm 3 (Retail MAC)"
-		# DES for all blocks
-		# DES3 for last block
-	        tdesa= DES.new(key[0:8],DES.MODE_ECB,self.DES_IV)
-        	tdesb= DES.new(key[8:16],DES.MODE_ECB,self.DES_IV)
-        	if(ssc):
-                	mac= tdesa.encrypt(self.ToBinary(ssc))
-        	else:
-                	mac= self.DES_IV
-		message += self.PADBlock('')
-        	for y in range(len(message) / 8):
-                	current= message[y * 8:(y * 8) + 8]
-                	left= right= ''
-                	for x in range(len(mac)):
-                        	left += '%02x' % ord(mac[x])
-                        	right += '%02x' % ord(current[x])
-                	machex= '%016x' % xor(int(left,16),int(right,16))
-                	mac= tdesa.encrypt(self.ToBinary(machex))
-        	mac= tdesb.decrypt(mac)
-        	return tdesa.encrypt(mac)
-	def MACVerify(self,message,key):
-		mess= self.ToBinary(message[:len(message)- 16])
-		mac= self.DESMAC(mess,key,'')
-		if not mac == self.ToBinary(message[len(message) -16:]):
-			print 'MAC Error!'
-			print 'Expected MAC: ', message[len(message) -16:]
-			print 'Actual MAC:   ',
-			self.HexPrint(mac)
-			return(False)
-		return(True)
-	def SSCIncrement(self,ssc):
-		out= int(self.ToHex(ssc),16) + 1
-		return self.ToBinary("%016x" % out)
-	def TRANSITIDEncode(self,data):
-		"Encode TRANSIT ID"
-		# start sentinel
-		out= '0000000000000000'
-		# UID
-		out += self.ToBinaryString(self.ToBinary(data))
-		# LRC
-		lrc= self.TRANSITLRC(out[16:48])
-		out += self.ToBinaryString(chr(lrc))
-		# end sentinel
-		out += self.ToBinaryString(chr(0xf2))
-		return out
-	def TRANSITID(self,data):
-		"Decode TRANSIT ID"
-		# check for start sentinel
-		if(data[0:16] != '0000000000000000'):
-			print 'Start sentinel not found! (0000000000000000)'
-			return 0
-		# check for end sentinel
-		if(int(data[56:],2) != 0xf2):
-			print 'End sentinel not found! (11110010)'
-			return 0
-		lrc= self.TRANSITLRC(data[16:48])
-		if(lrc != int(data[48:56],2)):
-			print 'LRC mismatch: %02X should be %02X!' % (int(data[48:56],2),lrc)
-			return 0
-		out= '%08X' % int(data[16:48],2)
-		return out
-	def TRANSITIDPrint(self,data):
-		out= self.TRANSITID(data)
-		if(out != 0):
-			print 'UID:', out
-		else:
-			print 'Invalid ID!'
-	def TRANSITLRC(self,data):
-		"Calculate TRANSIT LRC"
-		i= 0
-		lrc= 0x00
-		# rolling XOR
-                while(i < 4):
-                        lrc ^= (int(data[(i) * 8:(i+1) * 8],2)) & 0xff
-                        i += 1
-		# final byte XOR
-                lrc ^= 0x5a & 0xff
-		return lrc
-	def FDXBID(self,data):
-		"Decode FDX-B ID"
-        	out= self.HexReverse(data)
-        	hexout= self.ToHex(self.NibbleReverse(self.ToBinary(out)))
-		# Application ID
-        	self.FDXBAPP= hexout[:4]
-		# Country Code
-        	ccode= hexout[4:7]
-        	self.FDXBCCODE= int(ccode,16) >> 2
-		# Human Readable CCODE
-		if "%d" % self.FDXBCCODE in self.ISO3166CountryCodes:
-			self.FDXBCCODEHR= self.ISO3166CountryCodes["%d" % self.FDXBCCODE]
-		else:
-			self.FDXBCCODEHR= 'Undefined - see http://www.icar.org/manufacturer_codes.htm'
-		# National ID
-        	natid= hexout[6:16]
-        	self.FDXBNID= int(natid,16) &0x3fffffffff
-	def FDXBIDEncode(self,appid,ccode,natid):
-		"Encode FDX-B ID"
-		hexccode= "%03x" % (int(ccode,10) << 2)
-		glue = int(hexccode[-1:],16) & 0xc
-		hexccode = hexccode[:-1]
-		hexid= "%010x" % int(natid,10)
-		glue = glue | (int(hexid[:1],16) & 0x3)
-		hexglue = "%01x" % glue
-		hexid = hexid[1:]
-		rawid= appid + hexccode + hexglue + hexid
-		nibbleid= self.NibbleReverse(self.ToBinary(rawid))
-		hexout= self.HexReverse(self.ToHex(nibbleid))
-		return hexout 
-	def FDXBIDPrint(self,data):
-		self.FDXBID(data)
-        	print 'Application Identifier: ', self.FDXBAPP
-        	print 'Country Code: ',
-        	print self.FDXBCCODE,
-        	print  "(" + self.FDXBCCODEHR + ")"
-        	print 'National ID: ',
-        	print self.FDXBNID
-	def FDXBID128Bit(self,data):
-		"generate raw 128 bit FDX-B data from FDX-B ID"
-		idbin= self.ToBinaryString(self.ToBinary(data))
-		# construct FDX-B encoded blocks
-		out= ''
-		# header is ten zeros and a '1'
-		header= '00000000001'
-		out += header
-		# break id into 8 bit chunks with a trailing '1' on each
-		for x in range(0,len(idbin),8):
-			out += idbin[x:x+8] + '1'
-		# add 16 CRC-CCITT error detection bits
-		crc= '%04x' % self.crcccitt(self.ToBinary(data))
-		crcbin= self.ToBinaryString(self.ToBinary(crc))
-		# crc is transmitted LSB first with trailing '1's
-		out += crcbin[0:8] + '1'
-		out += crcbin[8:16] + '1'
-		# add 3 sets of trailer bits (RFU)
-		trailer= '000000001'
-		for x in range(3):
-			out += trailer
-		return out
-	def FDXBID128BitDecode(self,data):
-		"convert raw 128 bit FDX-B data to FDX-B ID"
-		#strip off header
-		y= data[11:]
-		#strip off trailing '1' from the first 8 9-bit groups
-		out= ''
-		for x in range(0,72,9):
-			out += y[x:x+8]
-		# ignore the rest - CRC etc.
-		return '%016x' % int(out,2)	
-	def PCSCGetTagType(self,atr):
-		"get currently selected tag type from atr"
-		if atr[8:12] == self.PCSC_CSC:
-			ss= atr[24:26]
-			return self.PCSC_SS[ss]
-		else:
-			return 'SMARTCARD'
-	def PCSCPrintATR(self,data):
-		"print breakdown of HEX ATR"
-		print '    ATR:', data
-		if data[0:2].upper() == '3B':
-			print '         3B  Initial Header' 
-		else:
-			print 'ATR not recognised!'
-			return False
-		if data[2] == '8':
-			print '           8  No TA1, TB1, TC1 only TD1 is following'
-		histlen= int(data[3],16)
-		print '            %s  %d bytes historical data follow' % (data[3] , histlen)
-		if data[4] == '8':
-			print '             8  No TA2, TB2, TC2 only TD2 is following'
-		if data[5] == '0':
-			print '              0  T = 0'
-		if data[6] == '0':
-			print '               0  No TA3, TB3, TC3, TD3 following'
-		if data[7] == '1':
-			print '                1  T = 1'
-		if data[8:12] == self.PCSC_CSC:
-			print '                 Detected STORAGECARD'
-			print '     Historical:', data[8:-2]
-			print '                 80  Status indicator may be present (COMPACT-TLV object)'
-			print '                   4F  Application Identifier presence indicator'
-			applen= int(data[12:14],16)
-			print '                     %s  %d bytes follow' % (data[12:14] , applen) 
-			print '                 RID:  %s ' % data[14:24],
-			if data[14:24].upper() == self.PCSC_RID:
-				print 'PC/SC Workgroup'
-			else:
-				print 'Unknown RID'
-			pixlen= applen - 5
-			print '                           PIX:  %s' % data[24:24 + pixlen * 2]
-			ss= data[24:26]
-			print '                            SS:  %s  %s' % (ss , self.PCSC_SS[ss]),
-			# if card is ISO15693 print manufacturer name
-			if 9 <= int(ss,16) <= 12:
-				try:
-					print '(%s)' % self.ISO7816Manufacturer[self.uid[2:4]]
-				except:
-					print '(Uknown Manufacturer)'
-			else:
-				print
-			print '                            Name:  %s  %s' % (data[26:30] , self.PCSC_NAME[data[26:30]])
-			print '                                 RFU:  %s' % data[30:-2]
-			spaces= histlen * 2
-		else:
-			print '                 Detected SMARTCARD'
-			print '            ATS:',self.pcsc_ats,'-',
-			print self.ReadablePrint(self.ToBinary(self.pcsc_ats))
-			# if ats starts with '00', '10' or '8X' it is an ISO-7816-4 card
-			atsbyte= self.pcsc_ats[0:2]
-			if atsbyte == '00' or atsbyte == '10' or self.pcsc_ats[0] == '8':
-				print '       Category: %s  Format according to ISO/IEC 7816-4' % atsbyte
-			else:
-				print '       Category: %s  Proprietary format' % atsbyte
-			spaces= len(self.pcsc_ats)
-		space= ''
-		for x in range(spaces):
-			space += ' '
-			
-		print space + '   Checksum TCK: ' + data[-2:],
-		# calculate checksum excluding Initial Header and TCK
-		tck= 0
-		x= 2
-		while x < len(data) - 2:
-			tck= xor(tck,int(data[x:x+2],16))
-			x += 2
-		if int(data[-2:],16) == tck:
-			print '(OK)'
-			return True
-		else:
-			print '(Checksum error: %02x)' % tck
-			return False
-
-	def shutdown(self):
-		if self.readertype == self.READER_LIBNFC:
-			self.nfc.powerOff()
-			self.nfc.deconfigure()
-		os._exit(False)
diff --git a/RFIDIOtconfig.opts b/RFIDIOtconfig.opts
deleted file mode 100644
index 7fec1cb..0000000
--- a/RFIDIOtconfig.opts
+++ /dev/null
@@ -1,7 +0,0 @@
-#-s 9600 -l /dev/ttyUSB1
-# uncomment the above line to enable global overrides
-# options should be all on the first line, as if added on the command line
-# this file will be looked for in the following places:
-#   $(RFIDIOtconfig_opts) - note that this environment variable should be set to the full path and filename
-#   ./RFIDIOtconfig.opts
-#   /etc/RFIDIOtconfig.opts
diff --git a/bruteforce.py b/bruteforce.py
deleted file mode 100755
index eba783c..0000000
--- a/bruteforce.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-
-#  bruteforce.py - try random numbers to login to sector 0
-# 
-#  Adam Laurie <adam@algroup.co.uk>
-#  http://rfidiot.org/
-# 
-#  This code is copyright (c) Adam Laurie, 2006, All rights reserved.
-#  For non-commercial use only, the following terms apply - for all other
-#  uses, please contact the author:
-#
-#    This code 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 code 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.
-#
-
-
-import rfidiot
-import random
-import sys
-import os
-
-try:
-        card= rfidiot.card
-except:
-	print "Couldn't open reader!"
-        os._exit(True)
-
-args= rfidiot.args
-help= rfidiot.help
-
-card.info('bruteforce v0.1i')
-card.select()
-print 'Card ID: ' + card.uid
-
-finished = 0
-tries = 0
-print ' Tries: %s\r' % tries,
-sys.stdout.flush()           
-
-while not finished:
-
-	tries += 1
-	if tries % 10 == 0:
-		print ' Tries: %s\r' % tries,
-		sys.stdout.flush()           
-
-	if len(args) == 1:
-		key= args[0]
-		if len(key) != 12:
-			print '  Static Key must be 12 HEX characters!'
-			os._exit(True)
-		print 'Trying static key: ' + key
-	else:
-		key = '%012x' % random.getrandbits(48)
-
-	for type in ['AA', 'BB']:
-		card.select()
-		if card.login(0,type,key):
-			print '\nlogin succeeded after %d tries!' % tries
-			print 'key: ' + type + ' ' + key
-			finished = 1
-			break	
-		elif card.errorcode != 'X' and card.errorcode != '6982' and card.errorcode != '6200':
-			print '\nerror!'
-			print 'key: ' + type +  ' ' + key
-			print 'error code: ' + card.errorcode
-			finished = 1
-			break
-	if finished:
-		break
-os._exit(False)
diff --git a/debian/changelog b/debian/changelog
index 2c3bfc7..f8a302f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+rfidiot (1.0+20190118+git20200701.1.88f2ef9-0kali1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Kali Janitor <janitor@kali.org>  Sat, 29 May 2021 17:51:25 -0000
+
 rfidiot (1.0+20190118-0kali2) kali-dev; urgency=medium
 
   * Add a warning about Python 2 EOL
diff --git a/debian/patches/Add-a-warning-for-Python-2-EOL.patch b/debian/patches/Add-a-warning-for-Python-2-EOL.patch
index e8d5694..629a2a0 100644
--- a/debian/patches/Add-a-warning-for-Python-2-EOL.patch
+++ b/debian/patches/Add-a-warning-for-Python-2-EOL.patch
@@ -6,10 +6,10 @@ Subject: Add a warning for Python 2 EOL
  rfidiot/__init__.py | 2 ++
  1 file changed, 2 insertions(+)
 
-diff --git a/rfidiot/__init__.py b/rfidiot/__init__.py
-index 76af16d..4f87dc7 100755
---- a/rfidiot/__init__.py
-+++ b/rfidiot/__init__.py
+Index: rfidiot/rfidiot/__init__.py
+===================================================================
+--- rfidiot.orig/rfidiot/__init__.py
++++ rfidiot/rfidiot/__init__.py
 @@ -29,6 +29,8 @@ import sys
  import os
  import string
diff --git a/debian/patches/edit-testlahf b/debian/patches/edit-testlahf
index 948ae3d..d8f9cc8 100644
--- a/debian/patches/edit-testlahf
+++ b/debian/patches/edit-testlahf
@@ -7,10 +7,10 @@ Patched testlahf.sh to remove dot-slashes
  testlahf.sh | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
-diff --git a/testlahf.sh b/testlahf.sh
-index 33cd3fa..6fc4cf3 100755
---- a/testlahf.sh
-+++ b/testlahf.sh
+Index: rfidiot/testlahf.sh
+===================================================================
+--- rfidiot.orig/testlahf.sh
++++ rfidiot/testlahf.sh
 @@ -1,4 +1,4 @@
  #!/bin/sh
  
diff --git a/delete-smartcafe.gpsh b/delete-smartcafe.gpsh
deleted file mode 100644
index 0c87e78..0000000
--- a/delete-smartcafe.gpsh
+++ /dev/null
@@ -1,12 +0,0 @@
-// script to install epassport.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -readerNumber 2
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-card_connect
-select -AID A000000003000000
-open_sc -scp 2 -scpimpl 0x15 -security 1 -keyind 0 -keyver 0 -keyDerivation emvcps11 -key 404142434445464748494A4B4C4D4E4F
-delete -AID A00000024710
-card_disconnect
-release_context
diff --git a/fdxbnum.py b/fdxbnum.py
index f16f6a5..e3441c3 100755
--- a/fdxbnum.py
+++ b/fdxbnum.py
@@ -61,7 +61,6 @@ if not help and (len(args) >= 3 or precoded):
 		id= card.FDXBIDEncode(args[0],args[1],args[2])
 		print id
 	out= card.FDXBID128Bit(id)
-	print 'binary is',out
 	if (len(args) == 4 and args[3] == 'WRITE') or precoded:
        		while True:
 			# Q5 must be forced into Q5 mode to be sure of detection so try that first 
diff --git a/froschtest.py b/froschtest.py
index ef093f3..6bff6cd 100755
--- a/froschtest.py
+++ b/froschtest.py
@@ -49,7 +49,7 @@ else:
 	print card.FROSCH_Errors[card.errorcode]
 
 print 'Trying Hitag2: ',
-if card.frosch(card.FR_HT2_Get_Snr_PWD,''):
+if card.frosch(card.FR_HT2_Get_Snr_PWD,'') or card.frosch(card.FR_HT2_Get_Snr_CRYPTO,''):
 	print card.data[:len(card.data) -2]
 	if not card.select():
 		print 'Select failed: ',
diff --git a/isotype.py b/isotype.py
index 786dfbd..7b92cdf 100755
--- a/isotype.py
+++ b/isotype.py
@@ -89,6 +89,10 @@ if card.readertype == card.READER_LIBNFC:
 		print '    CID: ' + card.cid
 		print "       Tag is ISO 14443B"
 		typed= True
+	if card.select('ICLASS'):
+		print '     ID: ' + card.uid
+		print "       Tag is ICLASS"
+		typed= True
 	if card.select('JEWEL'):
 		print 'SENSRES: ' + card.btsensres
 		print '     ID: ' + card.btid
diff --git a/java/Makefile b/java/Makefile
deleted file mode 100644
index 96ea493..0000000
--- a/java/Makefile
+++ /dev/null
@@ -1,111 +0,0 @@
-#
-# Makefile for JAVA applet jcop_set_atr_hist
-#
-# Adam Laurie, 2009
-# http://rfidiot.org
-#
-# See inline comments for instructions on how to set up your environment
-#
-
-APPLET_PACKAGE=jcop_set_atr_hist
-APPLET_CLASS=JCOPSetATRHist
-PACKAGE_AID=0xDC:0x44:0x20:0x06:0x06
-APPLET_AID=0xDC:0x44:0x20:0x06:0x06:0x07
-APPLET_AID_LENGTH=6
-
-#JAVA_HOME=/usr/local/java/jdk
-JAVA=$(JAVA_HOME)/bin/java
-JAVAC=$(JAVA_HOME)/bin/javac
-JAVADOC=$(JAVA_HOME)/bin/javadoc
-
-# Java Card Kit must be version 2.2.1 for gpshell
-# and can be  downloaded here:
-#
-# http://java.sun.com/javacard/downloads/index.jsp
-#
-# download 'Java Card 2.2.1 Development Kit' and set the following variable (JCZIP)
-# to the zipfile name, then run 'make jckit'
-#
-JCZIP=java_card_kit-2_2_1-linux-dom.zip
-JCPATH=./java_card_kit-2_2_1
-
-#
-# Global Platform API can be found here:
-#
-# http://www.globalplatform.org/specificationscard.asp
-#
-# download 'Java Card Export File for Card Specification v2.1' from the
-# 'Archived Card Documentation' section. Make sure you choose v2.1 and NOT v2.1.1,
-# and set the following variable (GPZIP) to the zipfile name, then run 'make gpapi'
-# (GPZIP and GPDIR were correct at time of release, so should not need changing)
-#
-GPZIP=Java_Export_v2_1_or_v2_1_1_API.zip
-GPDIR=GP_exportA00000015100
-#GPDIR=$(shell echo $(GPZIP) | cut -f1 -d'.')
-GPLIB=./gp21.jar
-GPEXPORTPATH=./gp21
-
-JCAPI=$(JCPATH)/lib/api.jar
-JCCONV=$(JCPATH)/lib/converter.jar
-JCVERIFIER=$(JCPATH)/lib/offcardverifier.jar
-EXPORTPATH=$(JCPATH)/api_export_files
-
-#
-# GPShell can be got here:
-#
-# http://sourceforge.net/project/showfiles.php?group_id=143343&package_id=159897
-#
-GPSHELL= "gpshell"
-GPSHELL_SCRIPT="jcop_set_atr_hist.gpsh"
-GPSHELL_UNINSTALL_SCRIPT="jcop_delete_atr_hist.gpsh"
-
-all: jcop_set_atr_hist.cap
-
-classes: build
-	$(JAVAC)\
-	   -g\
-	   -classpath $(JCAPI):$(GPLIB):.\
-	   -d build\
-	   -sourcepath ./src \
-	   -source 1.2 \
-	   -target 1.2 \
-	   src/jcop_set_atr_hist/JCOPSetATRHist.java
-
-jcop_set_atr_hist.cap: classes
-	$(JAVA)\
-	   -classpath $(JCCONV):$(JCVERIFIER)\
-	   com.sun.javacard.converter.Converter\
-	      -classdir build\
-	      -exportpath $(EXPORTPATH):$(GPEXPORTPATH):.\
-	      -applet $(APPLET_AID) $(APPLET_CLASS)\
-	      -d build\
-	      -out CAP\
-	      -v\
-              -debug \
-	      $(APPLET_PACKAGE) $(PACKAGE_AID) 1.0
-	      cp build/jcop_set_atr_hist/javacard/jcop_set_atr_hist.cap .
-
-build:
-	@if ! test -e gp21.jar ; then echo "You need to set up your Global Platform environment! Read Makefile comments for help." ; exit 1 ; fi
-	@if ! test -e $(JCCONV); then echo "You need to set up your Java Card Kit! Read Makefile comments for help."; exit 1; fi
-	mkdir -p build
-
-install:
-	$(GPSHELL) $(GPSHELL_SCRIPT)
-
-uninstall:
-	$(GPSHELL) $(GPSHELL_UNINSTALL_SCRIPT)
-
-clean:
-	rm -f jcop_set_atr_hist.cap
-	rm -rf build
-
-gpapi:
-	@if ! test -e $(GPZIP) ; then echo "Can't find Global Platform API zipfile! Read Makefile comments for help." ; exit 1 ; fi
-	@unzip -x $(GPZIP)
-	cd $(GPDIR) && jar cvf ../gp21.jar *
-	mv $(GPDIR) gp21
-
-jckit:
-	@if ! test -e $(JCZIP) ; then echo "Can't find Java Card Kit zipfile! Read Makefile comments for help." ; exit 1 ; fi
-	@unzip -x $(JCZIP)
diff --git a/java/jcop_delete_atr_hist.gpsh b/java/jcop_delete_atr_hist.gpsh
deleted file mode 100644
index 6a01467..0000000
--- a/java/jcop_delete_atr_hist.gpsh
+++ /dev/null
@@ -1,16 +0,0 @@
-// script to install applet.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-//enable_trace
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (OKCM0022602100142172731750393654) 00 00"
-card_connect
-//card_connect -reader "SDI010 USB Smart Card Reader (21120652200170) 00 01"
-select -AID A000000003000000
-open_sc -security 3 -mac_key 404142434445464748494A4B4C4D4E4F -enc_key 404142434445464748494A4B4C4D4E4F -kek_key 404142434445464748494A4B4C4D4E4F // Open secure channel
-delete -AID DC44200606
-get_status -element 10 
-card_disconnect
-release_context
diff --git a/java/jcop_set_atr_hist.cap b/java/jcop_set_atr_hist.cap
deleted file mode 100644
index c0413f3..0000000
Binary files a/java/jcop_set_atr_hist.cap and /dev/null differ
diff --git a/java/jcop_set_atr_hist.gpsh b/java/jcop_set_atr_hist.gpsh
deleted file mode 100644
index 97a3b38..0000000
--- a/java/jcop_set_atr_hist.gpsh
+++ /dev/null
@@ -1,17 +0,0 @@
-// script to install applet.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-//enable_trace
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (OKCM0022602100142172731750393654) 00 00"
-card_connect
-//card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-//card_connect -reader "SDI010 USB Smart Card Reader (21120652200170) 00 01"
-select -AID A000000003000000
-open_sc -security 3 -mac_key 404142434445464748494A4B4C4D4E4F -enc_key 404142434445464748494A4B4C4D4E4F -kek_key 404142434445464748494A4B4C4D4E4F // Open secure channel
-delete -AID DC44200606
-install -file jcop_set_atr_hist.cap -priv 4
-get_status -element 10 
-card_disconnect
-release_context
diff --git a/java/smartcafe_delete_atr_hist.gpsh b/java/smartcafe_delete_atr_hist.gpsh
deleted file mode 100644
index 7c98821..0000000
--- a/java/smartcafe_delete_atr_hist.gpsh
+++ /dev/null
@@ -1,10 +0,0 @@
-// script to install applet.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-//enable_trace
-establish_context
-card_connect
-select -AID A000000003000000
-open_sc -scp 2 -scpimpl 0x15 -security 1 -keyind 0 -keyver 0 -keyDerivation emvcps11 -key 404142434445464748494A4B4C4D4E4F
-delete -AID DC44200606
-card_disconnect
-release_context
diff --git a/java/smartcafe_set_atr_hist.gpsh b/java/smartcafe_set_atr_hist.gpsh
deleted file mode 100644
index 1313f12..0000000
--- a/java/smartcafe_set_atr_hist.gpsh
+++ /dev/null
@@ -1,11 +0,0 @@
-// script to install applet.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-//enable_trace
-establish_context
-card_connect
-select -AID A000000003000000
-open_sc -scp 2 -scpimpl 0x15 -security 1 -keyind 0 -keyver 0 -keyDerivation emvcps11 -key 404142434445464748494A4B4C4D4E4F
-delete -AID DC44200606
-install -file jcop_set_atr_hist.cap -priv 4
-card_disconnect
-release_context
diff --git a/java/src/jcop_set_atr_hist/ATRGlobal.java b/java/src/jcop_set_atr_hist/ATRGlobal.java
deleted file mode 100644
index bbf2630..0000000
--- a/java/src/jcop_set_atr_hist/ATRGlobal.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
-*     Adam Laurie <adam@algroup.co.uk>
-*     http://rfidiot.org/
-*    
-*     This code is copyright (c) Adam Laurie, 2009, All rights reserved.
-*     For non-commercial use only, the following terms apply - for all other
-*     uses, please contact the author:
-*   
-*       This code 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 code 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.
-*/
-
-
-
-package jcop_set_atr_hist;
-
-/* 15 byte buffer for ATR Historical Bytes (ATS) must be a global */
-
-public class ATRGlobal {
-	public static byte[] ATR_HIST= {(byte) 0x00,(byte) 0x00,(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
-				       	(byte) 0x00,(byte) 0x00,(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
-					(byte) 0x00,(byte) 0x00,(byte) 0x00};
-}
diff --git a/java/src/jcop_set_atr_hist/JCOPSetATRHist.java b/java/src/jcop_set_atr_hist/JCOPSetATRHist.java
deleted file mode 100644
index 527adbb..0000000
--- a/java/src/jcop_set_atr_hist/JCOPSetATRHist.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
-*  JCOPSetATRHist.java - set ATR History bytes on JCOP cards
-*
-*     Must be installed as "default selectable" (priv mode 0x04).
-*   
-*     Adam Laurie <adam@algroup.co.uk>
-*     http://rfidiot.org/
-*   
-*     This code is copyright (c) Adam Laurie, 2009, All rights reserved.
-*     For non-commercial use only, the following terms apply - for all other
-*     uses, please contact the author:
-*   
-*       This code 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 code 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.
-*/
-
-
-package jcop_set_atr_hist;
-
-import javacard.framework.APDU;
-import javacard.framework.ISO7816;
-import javacard.framework.Applet;
-import javacard.framework.ISOException;
-import javacard.framework.Util;
-import org.globalplatform.GPSystem;
-
-public class JCOPSetATRHist extends Applet 
-{
-	public static void install(byte[] bArray, short bOffset, byte bLength) 
-		{
-		new jcop_set_atr_hist.JCOPSetATRHist().register(bArray, (short) (bOffset + 1),
-				bArray[bOffset]);
-		}
-
-	public void process(APDU apdu) 
-		{
-		byte[] buffer = apdu.getBuffer();
-		byte ins = buffer[ISO7816.OFFSET_INS];
-
-		if (selectingApplet()) 
-			{
-			return;
-			}
-
-		byte len = buffer[ISO7816.OFFSET_CDATA];
-		// Max ATS is 15 bytes
-		if (len > (byte) 15)
-			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
-
-		Util.arrayCopy(buffer,(short) (ISO7816.OFFSET_CDATA + 1),ATRGlobal.ATR_HIST,(short) 0x00,len);	
-		switch (ins) 
-			{
-			case (byte) 0xAB:
-				if( ! org.globalplatform.GPSystem.setATRHistBytes(ATRGlobal.ATR_HIST,(short) 0x00, len ))
-					ISOException.throwIt(ISO7816.SW_UNKNOWN);
-				return;
-			default:
-				ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
-			}
-		}
-}
diff --git a/jcop_mifare_access.cap b/jcop_mifare_access.cap
deleted file mode 100644
index 110e31b..0000000
Binary files a/jcop_mifare_access.cap and /dev/null differ
diff --git a/jcop_mifare_access.gpsh b/jcop_mifare_access.gpsh
deleted file mode 100644
index 9e93081..0000000
--- a/jcop_mifare_access.gpsh
+++ /dev/null
@@ -1,20 +0,0 @@
-// script to install jcop_mifare_access.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-//enable_trace
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-//card_connect -reader "PCSC OMNIKEY CardMan 5x21 (OKCM0071403091502571040243996509) 00 01"
-//card_connect -reader "SDI010 USB Smart Card Reader (21120652200170) 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-card_connect 
-//card_connect -readerNumber 3
-select -AID A000000003000000
-open_sc -security 3 -mac_key 404142434445464748494A4B4C4D4E4F -enc_key 404142434445464748494A4B4C4D4E4F -kek_key 404142434445464748494A4B4C4D4E4F // Open secure channel
-delete -AID A00000024710
-delete -AID DC44200606
-install -file jcop_mifare_access.cap -priv 4
-get_status -element 10 
-card_disconnect
-release_context
diff --git a/ls_nfc_client-3.apk b/ls_nfc_client-3.apk
deleted file mode 100644
index c748e8b..0000000
Binary files a/ls_nfc_client-3.apk and /dev/null differ
diff --git a/ls_nfc_client-readme.txt b/ls_nfc_client-readme.txt
deleted file mode 100644
index b5b5e28..0000000
--- a/ls_nfc_client-readme.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-/* LS_NFC_CLient - Android Network NFC Client for use with RFIDIOt
- *
- * Nick von Dadelszen <nick@lateralsecurity.com>
- * https://www.lateralsecurity.com/
- *
- * This code 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 code 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.
- *
- * Copyright (c) 2011 Lateral Security
- */
-
-LS_NFC_CLient is an Android application that detects an NFC card and makes a network connection to obtain commands (APDUs) to run on that card.  It works by registering an intent for detection of ISODEP NFC cards, and then connecting to the server defined the application settings.  This can be changed in the client UI.
-
-
-For the server component, you can use netcat to listen on the port and send APDUs manually.  Or you can use RFIDIOt with the pyandroid patch to send commands to the card.
-
-The application has been tested on a Nexus S with the following types of cards:
-- Electronic passports
-- Paypass creditcards
-- OTher ISO 14443 cards
-
-You can also use RFIDIOt to make calls ro LS_NFC_Client by setting -R RFIDIOt.rfidiot.READER_ANDROID or modifying the RFIDIOtconfig.py
-
diff --git a/mifare.pdf b/mifare.pdf
deleted file mode 100644
index 8fc1e3f..0000000
Binary files a/mifare.pdf and /dev/null differ
diff --git a/mrpkey.py b/mrpkey.py
index 6a5bcc9..0e76082 100755
--- a/mrpkey.py
+++ b/mrpkey.py
@@ -691,6 +691,8 @@ def decode_ef_dg2(data):
 	datahex= passport.ToHex(data)
 	position= 0
 	end= len(datahex)
+	instance = 1
+	instances = 1
 	while position < end:
 		decoded= False
 		# check for presence of tags
@@ -698,7 +700,7 @@ def decode_ef_dg2(data):
 			if DG2_ELEMENTS.has_key(datahex[position:position + length]):
 				decoded= True
 				tag= datahex[position:position + length]
-				print '  Tag:', tag, '('+DG2_ELEMENTS[tag]+')'
+				print '  Tag:', tag, '('+DG2_ELEMENTS[tag]+')', '@', position/2,
 				# don't skip TEMPLATE fields as they contain sub-fields
 				# except BDB which is a special case (CBEFF formatted) so for now
 				# just try and extract the image which is 65 bytes in
@@ -709,6 +711,7 @@ def decode_ef_dg2(data):
 					if tag == BDB or tag == BDB1:
 						# process CBEFF block
 						position += asn1fieldlength(datahex[position:])
+						startposition = position/2
 						# FACE header
 						length= len(FAC)
 						tag= datahex[position:position + length]
@@ -775,12 +778,17 @@ def decode_ef_dg2(data):
                                                 position += 6
 						print '      Image Quality: %s' % ISO19794_5_IMG_QUALITY[datahex[position:position + 2]]
 						position += 2
-						img= open(tempfiles+'EF_DG2.' + Filetype,'wb+')
-						img.write(data[position / 2:position + imagelength])
+						if instances > 1:
+							filename = '%sEF_DG2_%i.%s' % (tempfiles,instance,Filetype)
+							instance += 1
+						else:
+							filename = '%sEF_DG2.%s' % (tempfiles,Filetype)
+						img= open(filename,'wb+')
+						img.write(data[position / 2:startposition + fieldlength])
 						img.flush()
 						img.close()
-						print '     JPEG image stored in %sEF_DG2.%s' % (tempfiles,Filetype)
-						position += imagelength * 2
+						print '     JPEG image stored in %s' % filename
+						position = (startposition + fieldlength) * 2
 					else:
 						position += asn1fieldlength(datahex[position:])
 				else:
@@ -789,9 +797,11 @@ def decode_ef_dg2(data):
 					print '     length:', fieldlength
 					position += asn1fieldlength(datahex[position:])
 					print '     data:', datahex[position:position + fieldlength * 2]
+					if tag == '02':
+						instances = int(datahex[position:position + fieldlength * 2], 16)
 					position += fieldlength * 2
 		if not decoded:
-			print 'Unrecognised element:', datahex[position:position + 4]
+			print 'Unrecognised element @', position/2, ':', datahex[position:position + 4]
 			os._exit(True)
 	return img_features	
 
@@ -1600,6 +1610,7 @@ if not Nogui:
 			os.system("convert %sJP2 %sJPG" % (tempfiles+'EF_DG7.',tempfiles+'EF_DG7.'))
 			print "      (converted %sJP2 to %sJPG for display)" % (tempfiles+'EF_DG7.',tempfiles+'EF_DG7.')
 		Filetype= 'JPG'
+    # TODO need to open EF_DG2_* in case of multiple images??
 	imagedata = ImageTk.PhotoImage(file=tempfiles + 'EF_DG2.' + Filetype)
 	canvas= Canvas(frame, height= imagedata.height(), width= imagedata.width())
 	canvas.grid(row= 3, sticky= NW, rowspan= 20)
diff --git a/multiselect.py b/multiselect.py
index a9ea7dd..e115b0a 100755
--- a/multiselect.py
+++ b/multiselect.py
@@ -48,6 +48,10 @@ else:
 while 42:
 	if card.select('A') or card.select('B'):
 		print '    Tag ID: ' + card.uid,
+		if (card.readertype == card.READER_FROSCH and card.tagtype == card.HITAG2 and card.tagmode == card.HITAG2_PASSWORD):
+			print "    Tag Type: Hitag2 (Password mode)"
+		if (card.readertype == card.READER_FROSCH and card.tagtype == card.HITAG2 and card.tagmode == card.HITAG2_CRYPTO):
+			print "    Tag Type: Hitag2 (Crypto mode)"
 		if (card.readertype == card.READER_ACG and string.find(card.readername,"LFX") == 0):
 			print "    Tag Type:" + card.LFXTags[card.tagtype]
 		else:
diff --git a/nfcid.py b/nfcid.py
deleted file mode 100644
index df6ea43..0000000
--- a/nfcid.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python
-
-#
-# NFC ID.py - Python code for Identifying NFC cards
-# version 0.1
-# Nick von Dadelszen (nick@lateralsecurity.com)
-# Lateral Security (www.lateralsecurity.com)
-
-#
-# This code is copyright (c) Lateral Security, 2011, 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 3 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 RFIDIOtconfig
-import sys
-import os
-import pyandroid
-import datetime
-
-Verbose= True
-Quiet= True
-
-aidlist= 	[
-		['MASTERCARD',		'a0000000041010'],
-		['MASTERCARD',		'a0000000049999'],
-		['VISA',		'a000000003'],
-		['VISA Debit/Credit',	'a0000000031010'],
-		['VISA Credit',		'a000000003101001'],
-		['VISA Debit',		'a000000003101002'],
-		['VISA Electron',	'a0000000032010'],
-		['VISA V Pay',		'a0000000032020'],
-		['VISA Interlink',	'a0000000033010'],
-		['VISA Plus',		'a0000000038010'],
-		['VISA ATM',		'a000000003999910'],
-		['Maestro',		'a0000000043060'],
-		['Maestro UK',		'a0000000050001'],
-		['Maestro TEST',	'b012345678'],
-		['Self Service',	'a00000002401'],
-		['American Express',	'a000000025'],
-		['ExpressPay',		'a000000025010701'],
-		['Link',		'a0000000291010'],
-	    ['Alias AID',		'a0000000291010'],
-		['Cirrus',		'a0000000046000'],
-		['Snapper Card',		'D4100000030001'],		
-		['Passport',		'A0000002471001'],		
-	    	]
-
-
-n = pyandroid.Android()
-
-while(42):
-	uid = n.select()
-	print 'GMT Timestamp: ' + str(datetime.datetime.now())
-
-	if not Quiet:
-		print '\nID: ' + uid
-		print '  Data:'
-
-	current = 0
-	cc_data = False
-
-	while current < len(aidlist):
-		if Verbose:
-			print 'Trying AID: '+ aidlist[current][0]  + ':' + aidlist[current][1]
-		apdu = '00A4040007' + aidlist[current][1]
-		r = n.sendAPDU(apdu)
-		#print r
-		#print r[-4:]	
-		if not r[-4:] == '9000':
-			apdu = apdu + '00'
-			r = n.sendAPDU(apdu)
-			#print r
-			#print r[-4:]
-
-		if r[-4:] == '9000':
-			#print card.data + card.errorcode
-			uid = uid[:-1]
-			n.sendResults("Card found-UID: " + uid + "-Card type: " + aidlist[current][0])
-			break
-			
-		current += 1	
-
-	if not Quiet:			
-		print 'Ending now ...'
-	n.deconfigure()
-	print 
-
diff --git a/pn532mitm.py b/pn532mitm.py
index c9c6cf1..daecde8 100755
--- a/pn532mitm.py
+++ b/pn532mitm.py
@@ -33,7 +33,8 @@ import operator
 
 # try to connect to remote host. if that fails, alternately listen and connect.
 def connect_to(host,port,type):
-	peer= socket.socket()
+	print 'host', host, 'port', port, 'type', type
+	peer= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 	random.seed()
 	first= True
 	while 42:
@@ -41,12 +42,21 @@ def connect_to(host,port,type):
 		print '  Paging %s %s                    \r' % (host, port),
 		sys.stdout.flush()
 		time.sleep(1)
-		if peer.connect_ex((host,port)) == 0:
-			print '  Connected to %s port %d                  ' % (host,port)
-			send_data(peer,type)
-			data= recv_data(peer)
-			connection= peer
-			break
+		try:
+			if peer.connect((host,port)) == 0:
+				print '  Connected to %s port %d                  ' % (host,port)
+				send_data(peer,type)
+				data= recv_data(peer)
+				connection= peer
+				break
+		except Exception, exc:
+			# connection refused - the other end isn't up yet
+			if exc.errno == 111:
+				pass
+			else:
+				print 'Could not open local socket:                    '
+				print exc
+				os._exit(True)
 		try:
 			print '  Listening for REMOTE on port %s              \r' % port,
 			sys.stdout.flush()
@@ -63,10 +73,6 @@ def connect_to(host,port,type):
 				break
 		except socket.timeout:
 			pass
-		except Exception, exc:
-			print 'Could not open local socket:                    '
-			print exc
-			os._exit(True)
 	if data == type:
 		print '  Handshake failed - both ends are set to', type
 		time.sleep(1)
diff --git a/rfidiot/RFIDIOt.py b/rfidiot/RFIDIOt.py
index 2e00244..b626450 100755
--- a/rfidiot/RFIDIOt.py
+++ b/rfidiot/RFIDIOt.py
@@ -120,6 +120,10 @@ class rfidiot:
 							self.readersubtype= self.READER_ACS
 							self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T1
 							self.hcard = None
+						elif string.find(self.readername,'ACS ACR1255U-J1 PICC') == 0:
+							self.readersubtype= self.READER_PCSC
+							self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T1
+							self.hcard = None
 						elif string.find(self.readername,'ACS') == 0:
 							self.readersubtype= self.READER_ACS
 							self.pcsc_protocol= smartcard.scard.SCARD_PROTOCOL_T0
@@ -549,6 +553,8 @@ class rfidiot:
 	FR_HT1_Read_Page= chr(0x50)
 	# Hitag2 Get Serial Number (password mode)
 	FR_HT2_Get_Snr_PWD= chr(0x80) + chr(0x00)
+	# Hitag2 Get Serial Number (crypto mode)
+	FR_HT2_Get_Snr_CRYPTO= chr(0x80) + chr(0x01)
 	# Hitag2 Get Serial Number Reset (to reset for normal access when in public modes)
 	FR_HT2_Get_Snr_Reset= chr(0x80)
 	# Hitag2 Halt Selected
@@ -1004,6 +1010,14 @@ class rfidiot:
 				# select returns an extra byte on the serial number, so strip it
 				self.data= self.data[:len(self.data) - 2]
 				self.tagtype= self.HITAG2
+				self.tagmode= self.HITAG2_PASSWORD
+				self.uid= self.data
+				return True
+			if self.frosch(self.FR_HT2_Get_Snr_CRYPTO,''):
+				# select returns an extra byte on the serial number, so strip it
+				self.data= self.data[:len(self.data) - 2]
+				self.tagtype= self.HITAG2
+				self.tagmode= self.HITAG2_CRYPTO
 				self.uid= self.data
 				return True
 			if self.frosch(self.FR_HT1_Get_Snr,''):
@@ -1083,6 +1097,17 @@ class rfidiot:
 						if self.DEBUG:
 							print 'Error selecting card'
 						return False
+				elif cardtype == 'ICLASS':
+					result = self.nfc.selectICLASS()
+					if result:
+						self.uid = result.uid
+						if self.DEBUG:
+							print 'ID: ' + self.uid
+						return True
+					else:
+						if self.DEBUG:
+							print 'Error selecting card'
+						return False
 				elif cardtype == 'JEWEL':
 					result = self.nfc.selectJEWEL()
 					if result:
diff --git a/rfidiot/pynfc.py b/rfidiot/pynfc.py
index 425e03b..6442611 100755
--- a/rfidiot/pynfc.py
+++ b/rfidiot/pynfc.py
@@ -60,6 +60,9 @@ NMT_ISO14443B2SR	= 0x05
 NMT_ISO14443B2CT	= 0x06
 NMT_FELICA		= 0x07
 NMT_DEP			= 0x08
+NMT_BARCODE		= 0x09
+NMT_ISO14443BICLASS     = 0x0A
+NMT_END_ENUM            = NMT_ISO14443BICLASS # dummy for sizing - always should alias last
 
 # NFC baud rate enumeration
 NBR_UNDEFINED		= 0x00
@@ -121,6 +124,18 @@ DEVICE_NAME_LENGTH	= 256
 DEVICE_PORT_LENGTH	= 64
 NFC_CONNSTRING_LENGTH	= 1024
 
+class NFC_DEP_INFO(ctypes.Structure):
+        _pack_ = 1
+        _fields_ = [('abtNFCID3', ctypes.c_ubyte * 10),
+                    ('btDID', ctypes.c_ubyte),
+                    ('btBS', ctypes.c_ubyte),
+                    ('btBR', ctypes.c_ubyte),
+                    ('btTO', ctypes.c_ubyte),
+                    ('btPP', ctypes.c_ubyte),
+                    ('abtGB', ctypes.c_ubyte * 48),
+                    ('szGB', ctypes.c_size_t),
+                    ('ndm', ctypes.c_ubyte)]
+
 class NFC_ISO14443A_INFO(ctypes.Structure):
 	_pack_ = 1
 	_fields_ = [('abtAtqa', ctypes.c_ubyte * 2),
@@ -153,6 +168,10 @@ class NFC_ISO14443BI_INFO(ctypes.Structure):
 		    ('szAtrLen', ctypes.c_size_t),
 		    ('abtAtr', ctypes.c_ubyte * 33)]
 
+class NFC_ISO14443BICLASS_INFO(ctypes.Structure):
+        _pack_ = 1
+        _fields_ = [('abtUID', ctypes.c_ubyte * 8)]
+
 class NFC_ISO14443B2SR_INFO(ctypes.Structure):
 	_pack_ = 1
 	_fields_ = [('abtUID', ctypes.c_ubyte * 8)]
@@ -169,17 +188,10 @@ class NFC_JEWEL_INFO(ctypes.Structure):
 	_fields_ = [('btSensRes', ctypes.c_ubyte * 2),
 		    ('btId', ctypes.c_ubyte * 4)]
 
-class NFC_DEP_INFO(ctypes.Structure):
+class NFC_BARCODE_INFO(ctypes.Structure):
 	_pack_ = 1
-	_fields_ = [('abtNFCID3', ctypes.c_ubyte * 10),
-		    ('btDID', ctypes.c_ubyte),
-		    ('btBS', ctypes.c_ubyte),
-		    ('btBR', ctypes.c_ubyte),
-		    ('btTO', ctypes.c_ubyte),
-		    ('btPP', ctypes.c_ubyte),
-		    ('abtGB', ctypes.c_ubyte * 48),
-		    ('szGB', ctypes.c_size_t),
-		    ('ndm', ctypes.c_ubyte)]
+	_fields_ = [('szDataLen', ctypes.c_size_t),
+		    ('abtData', ctypes.c_ubyte * 32)]
 
 class NFC_TARGET_INFO(ctypes.Union):
 	_pack_ = 1
@@ -187,9 +199,11 @@ class NFC_TARGET_INFO(ctypes.Union):
 		    ('nfi', NFC_FELICA_INFO),
 		    ('nbi', NFC_ISO14443B_INFO),
 		    ('nii', NFC_ISO14443BI_INFO),
+		    ('nic', NFC_ISO14443BICLASS_INFO),
 		    ('nsi', NFC_ISO14443B2SR_INFO),
 		    ('nci', NFC_ISO14443B2CT_INFO),
 		    ('nji', NFC_JEWEL_INFO),
+		    ('nti', NFC_BARCODE_INFO),
 		    ('ndi', NFC_DEP_INFO)]
 
 class NFC_CONNSTRING(ctypes.Structure):
@@ -251,10 +265,19 @@ class ISO14443B(object):
 		self.protocol= "".join(["%02X" % x for x in ti.abtProtocolInfo[:3]])
 		self.cid= "%02x" % ti.ui8CardIdentifier
 		self.atr = ""        # idem
+
 	def __str__(self):
 		rv = "ISO14443B(pupi='%s')" % (self.pupi)
 		return rv
 
+class ICLASS(object):
+	def __init__(self, ti):
+		self.uid = "".join(["%02X" % x for x in ti.abtUID])
+
+	def __str__(self):
+		rv = "ICLASS(uid='%s')" % (self.uid)
+		return rv
+
 class JEWEL(object):
 	def __init__(self, ti):
 		self.btSensRes = "".join(["%02X" % x for x in ti.btSensRes[:2]])
@@ -268,14 +291,11 @@ class JEWEL(object):
 		rv = "JEWEL(btSensRes='%s', btId='%s')" % (self.btSensRes, self.btId)
 		return rv
 
+
 class NFC(object):
+        tag= (NFC_TARGET * MAX_TARGET_COUNT) ()
 	def __init__(self, nfcreader):
 		self.LIB = ctypes.util.find_library('nfc')
-		#self.LIB = "/usr/local/lib/libnfc.so"
-		#self.LIB = "/usr/local/lib/libnfc_26102009.so.0.0.0"
-		#self.LIB = "./libnfc_nvd.so.0.0.0"
-		#self.LIB = "./libnfc_26102009.so.0.0.0"		
-		#self.LIB = "/data/RFID/libnfc/libnfc-svn-1.3.0/src/lib/.libs/libnfc.so"		
 		self.device = None
 		self.context = ctypes.POINTER(ctypes.c_int)()
 		self.poweredUp = False
@@ -313,6 +333,7 @@ class NFC(object):
 		self.libnfc.nfc_perror.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
 		self.libnfc.nfc_initiator_list_passive_targets.argtypes = [ctypes.c_void_p, ctypes.Structure, ctypes.c_void_p, ctypes.c_size_t]
 		self.libnfc.nfc_initiator_transceive_bytes.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_uint32]
+                self.libnfc.nfc_initiator_target_is_present.argtypes = [ctypes.c_void_p, ctypes.Structure]
 		self.libnfc.nfc_init(ctypes.byref(self.context))
 		return self.libnfc.nfc_version()
 
@@ -331,6 +352,7 @@ class NFC(object):
 			return
 		for i in range(nfc_num_devices):
 			if devices[i]:
+                                self.log.debug("nfc_open: %s" % ctypes.cast(devices[i].connstring,ctypes.c_char_p).value)
 				dev = self.libnfc.nfc_open(self.context, ctypes.byref(devices[i]))
 				devname= self.libnfc.nfc_device_get_name(dev)
 				print '    No: %d\t\t%s' % (i,devname)
@@ -405,27 +427,13 @@ class NFC(object):
 		"""Detect and initialise an ISO14443A card, returns an ISO14443A() object."""
 		if rfidiotglobals.Debug:
 			self.log.debug("Polling for ISO14443A cards")
-		#r = self.libnfc.nfc_initiator_select_tag(self.device, IM_ISO14443A_106, None, None, ctypes.byref(ti))
-		#r = self.libnfc.nfc_initiator_init(self.device)
-		#if RFIDIOtconfig.debug:
-		#	self.log.debug('card Select r: ' + str(r))
-		#if r == None or r < 0:
-		#	if RFIDIOtconfig.debug:
-		#		self.log.error("No cards found, trying again")
-		#	time.sleep(1)
-		#	result = self.readISO14443A()
-		#	return result
-		#else:
-		#	if RFIDIOtconfig.debug:
-		#		self.log.debug("Card found")
 		self.powerOff()
 		self.powerOn()
 		nm= NFC_MODULATION()
-		target= (NFC_TARGET * MAX_TARGET_COUNT) ()
 		nm.nmt = NMT_ISO14443A
 		nm.nbr = NBR_106
-		if self.libnfc.nfc_initiator_list_passive_targets(self.device, nm, ctypes.byref(target), MAX_TARGET_COUNT):
-			return ISO14443A(target[0].nti.nai)
+                if self.libnfc.nfc_initiator_list_passive_targets(self.device, nm, ctypes.byref(self.tag), MAX_TARGET_COUNT):
+			return ISO14443A(self.tag[0].nti.nai)
 		return None
 
 	def selectISO14443B(self):
@@ -435,11 +443,10 @@ class NFC(object):
 		self.powerOff()
 		self.powerOn()
 		nm= NFC_MODULATION()
-		target= (NFC_TARGET * MAX_TARGET_COUNT) ()
 		nm.nmt = NMT_ISO14443B
 		nm.nbr = NBR_106
-		if self.libnfc.nfc_initiator_list_passive_targets(self.device, nm, ctypes.byref(target), MAX_TARGET_COUNT):
-			return ISO14443B(target[0].nti.nbi)
+		if self.libnfc.nfc_initiator_list_passive_targets(self.device, nm, ctypes.byref(self.tag), MAX_TARGET_COUNT):
+			return ISO14443B(self.tag[0].nti.nbi)
 		return None
 
 	def selectJEWEL(self):
@@ -456,6 +463,20 @@ class NFC(object):
 			return JEWEL(target[0].nti.nji)
 		return None
 
+	def selectICLASS(self):
+		"""Detect and initialise an iClass card, returns an ICLASS() object."""
+		if rfidiotglobals.Debug:
+			self.log.debug("Polling for ICLASS cards")
+		self.powerOff()
+		self.powerOn()
+		nm= NFC_MODULATION()
+		target= (NFC_TARGET * MAX_TARGET_COUNT) ()
+		nm.nmt = NMT_ISO14443BICLASS
+		nm.nbr = NBR_106
+		if self.libnfc.nfc_initiator_list_passive_targets(self.device, nm, ctypes.byref(target), MAX_TARGET_COUNT):
+			return ICLASS(target[0].nti.nic)
+		return None
+
 	# set Mifare specific parameters
 	def configMifare(self):
 		self.libnfc.nfc_device_set_property_bool(self.device, NP_AUTO_ISO14443_4, False)
@@ -490,6 +511,10 @@ class NFC(object):
 				self.log.debug("Received %d byte APDU: %s" % (rxlen, rxAPDU))
 			return True, string.upper(rxAPDU)
 
+def target_is_present(self):
+	ret= self.libnfc.nfc_initiator_target_is_present(self.device, self.tag[0])
+	return ret == 0, ret
+
 if __name__ == "__main__":
 	n = NFC()
 	n.powerOn()
diff --git a/script.txt b/script.txt
deleted file mode 100644
index 2cdfc29..0000000
--- a/script.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# example script file for rfidiot-cli
-#
-# commands can be specified one per line:
-select
-aids
-# or combined:
-select aids
-mf key a 112233445566 mf auth a 0
-# commented out:
-#mf write 0 mifare.dat
-# blank lines are ignored
-
-mf dump 0 3
-prompt 'Remove TAG and continue (Y/N)?'
-wait 'Place a TAG on reader...' identify change 'Now provide a different TAG...' identify
-select
-select # comments are allowed on end of lines
-
diff --git a/test.txt b/test.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/testfrosch-serial.sh b/testfrosch-serial.sh
deleted file mode 100755
index d2e49ed..0000000
--- a/testfrosch-serial.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-xterm -T 'Frosch port /dev/ttyS0' -e python ./multiselect.py -s 9600 -l /dev/ttyS0 -R RFIDIOt.rfidiot.READER_FROSCH &
diff --git a/testfrosch.sh b/testfrosch.sh
deleted file mode 100755
index 035a30a..0000000
--- a/testfrosch.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-xterm -T 'Frosch port /dev/ttyUSB0' -e python ./multiselect.py -s 9600 -l /dev/ttyUSB0 -R RFIDIOt.rfidiot.READER_FROSCH &
diff --git a/upload2cosmo.gpsh b/upload2cosmo.gpsh
deleted file mode 100644
index 8025e74..0000000
--- a/upload2cosmo.gpsh
+++ /dev/null
@@ -1,14 +0,0 @@
-// script to install epassport.cap to cosmo card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -readerNumber 2
-card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-//card_connect -reader "ACS ACR 38U-CCID 00 00"
-select -AID A0000001510000
-open_sc -security 3 -mac_key 404142434445464748494A4B4C4D4E4F -enc_key 404142434445464748494A4B4C4D4E4F -kek_key 404142434445464748494A4B4C4D4E4F // Open secure channel
-delete -AID A00000024710
-install -file epassport.cap -priv 2
-card_disconnect
-release_context
diff --git a/upload2jcop.gpsh b/upload2jcop.gpsh
deleted file mode 100644
index 1144384..0000000
--- a/upload2jcop.gpsh
+++ /dev/null
@@ -1,15 +0,0 @@
-// script to install epassport.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -readerNumber 2
-//card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-card_connect
-//card_connect -reader "ACS ACR 38U-CCID 00 00"
-select -AID A000000003000000
-open_sc -security 3 -mac_key 404142434445464748494A4B4C4D4E4F -enc_key 404142434445464748494A4B4C4D4E4F -kek_key 404142434445464748494A4B4C4D4E4F // Open secure channel
-delete -AID A00000024710
-install -file epassport.cap -priv 2
-card_disconnect
-release_context
diff --git a/upload2nokia.gpsh b/upload2nokia.gpsh
deleted file mode 100644
index 7b4ba48..0000000
--- a/upload2nokia.gpsh
+++ /dev/null
@@ -1,15 +0,0 @@
-// script to install epassport.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-// note that the secure element must be unlocked, see the Nokia website at
-// http://www.forum.nokia.com/info/sw.nokia.com/id/a796065d-fa6a-449f-b3de-70d46ff99f19/NFC_Unlock.zip.html
-mode_211
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -readerNumber 3
-//card_connect -reader "OMNIKEY CardMan 5x21 00 01"
-card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-select -AID A000000003000000
-open_sc -security 3 -keyver 42 -mac_key 404142434445464748494a4b4c4d4e4f -enc_key 404142434445464748494a4b4c4d4e4f -kek_key 404142434445464748494a4b4c4d4e4f
-delete -AID A00000024710
-install -file epassport.cap -priv 2
-card_disconnect
-release_context
diff --git a/upload2smartcafe.gpsh b/upload2smartcafe.gpsh
deleted file mode 100644
index 031ab4f..0000000
--- a/upload2smartcafe.gpsh
+++ /dev/null
@@ -1,13 +0,0 @@
-// script to install epassport.cap to jcop card using gpshell (http://sourceforge.net/projects/globalplatform/)
-mode_211
-establish_context
-// edit the following line to match your PCSC reader
-//card_connect -readerNumber 2
-//card_connect -reader "OMNIKEY CardMan 5x21 (USB iClass Reader) 00 01"
-card_connect
-select -AID A000000003000000
-open_sc -scp 2 -scpimpl 0x15 -security 1 -keyind 0 -keyver 0 -keyDerivation emvcps11 -key 404142434445464748494A4B4C4D4E4F
-delete -AID A00000024710
-install -file epassport.cap -priv 2
-card_disconnect
-release_context