Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: 21c940982e
...
compare: 441735b652
  • 8 commits
  • 1 file changed
  • 0 commit comments
  • 1 contributor
Showing with 71 additions and 48 deletions.
  1. +71 −48 msr605.py
View
119 msr605.py
@@ -28,19 +28,16 @@ class MSR605(serial.Serial):
ESC_CHR = '\x1B'
FS_CHR = '\x1C'
+ TRACK_SENTINELS = (('%', '?'), (';', '?'), (';', '?'))
- enabled_tracks = [1, 2, 3]
-
- def __init__(self, dev):
- super(LLMSR605, self).__init__(dev, 9600, 8, serial.PARITY_NONE, timeout=10)
- self.reset()
- if not self.communication_test():
- raise MSRException('Communication test failed.')
- if not self.ram_test():
- raise MSRException('RAM test failed.')
- if not self.sensor_test():
- raise MSRException('Sensor test failed.')
+ def __init__(self, dev, test=True):
+ super(MSR605, self).__init__(dev, 9600, 8, serial.PARITY_NONE, timeout=10)
self.reset()
+ if test:
+ self.communication_test()
+ self.ram_test()
+ self.sensor_test()
+ self.reset()
def _read_status(self):
exceptions = {
@@ -62,7 +59,7 @@ def _expect(self, data):
raise ReadError('Expected %s, got %s.' % (repr(data), repr(read_data)))
def _read_until(self, end):
- data = ""
+ data = ''
while True:
data += self.read(1)
if data.endswith(end):
@@ -90,39 +87,31 @@ def led_red_on(self):
def sensor_test(self):
self._send_command('\x86')
- return self.read(2) == (self.ESC_CHR + '\x30')
+ if self.read(2) != (self.ESC_CHR + '\x30'):
+ raise MSRException('Sensor test failed.')
def communication_test(self):
self._send_command('\x65')
- return self.read(2) == (self.ESC_CHR + '\x79')
+ if self.read(2) != (self.ESC_CHR + '\x79'):
+ raise MSRException('Communication test failed.')
def ram_test(self):
self._send_command('\x87')
- return self.read(2) == (self.ESC_CHR + '\x30')
+ if self.read(2) != (self.ESC_CHR + '\x30'):
+ raise MSRException('RAM test failed.')
def reset(self):
self._send_command('\x61')
- def read_iso(self):
- self.set_bpc(7, 5, 5)
- self.select_bpi(True, False, True)
- self._send_command('\x72')
- self._expect(self.ESC_CHR + '\x73')
- self._expect(self.ESC_CHR + '\x01')
- track1 = self._read_until(self.ESC_CHR + '\x02')[:-2]
- track2 = self._read_until(self.ESC_CHR + '\x03')[:-2]
- track3 = self._read_until(self.FS_CHR)[:-1]
- self._read_status()
- return track1, track2, track3
-
def read_raw(self):
+ def read_tracks():
+ for tn in xrange(1, 4):
+ self._expect(self.ESC_CHR + chr(tn))
+ str_len = ord(self.read(1))
+ yield self.read(str_len)
self._send_command('\x6D')
self._expect(self.ESC_CHR + '\x73')
- tracks = [''] * 3
- for tn in self.enabled_tracks:
- self._expect(self.ESC_CHR + chr(tn))
- str_len = ord(self.read(1))
- tracks[tn - 1] = self.read(str_len)
+ tracks = tuple(get_tracks())
self._expect('\x3F' + self.FS_CHR)
self._read_status()
return tracks
@@ -164,7 +153,7 @@ def check_leading_zero(self):
return t13, t2
def erase_card(self, t1=True, t2=True, t3=True):
- flags = (t1 and 1 or 0) | ((t2 and 1 or 0) << 1) | ((t3 and 1 or 0) << 2)
+ flags = (t1 and 1 or 0) | (t2 and 2 or 0) | (t3 and 4 or 0)
self._send_command('\x63', chr(flags))
self._read_status()
@@ -181,6 +170,7 @@ def set_bpc(self, t1, t2, t3):
self._expect(self.ESC_CHR + '\x30' + chr(t1) + chr(t2) + chr(t3))
def write_raw(self, *tracks):
+ assert len(tracks) == 3
raw_data_block = self.ESC_CHR + '\x73'
for tn, track in enumerate(tracks):
raw_data_block += \
@@ -192,8 +182,25 @@ def write_raw(self, *tracks):
self._send_command('\x6E', raw_data_block)
self._read_status()
- def write_iso(self, *tracks):
- tracks = (re.sub(r'^%|^;|\?$', '', track) for track in tracks)
+ def _set_iso_mode(self):
+ self.select_bpi(True, False, True)
+ self.set_bpc(7, 5, 5)
+ self.set_leading_zero(61, 22)
+
+ def write_iso(self, *tracks, soft=False):
+ assert len(tracks) == 3
+ if soft:
+ return self._write_iso_soft(*tracks)
+ return self._write_iso_native(*tracks)
+
+ def _clean_iso_track_data(tracks):
+ return [
+ re.sub(r'^%s|%s$' % map(re.escape, sentinels), '', track)
+ for sentinels, track in zip(self.TRACK_SENTINELS, tracks)):
+ ]
+
+ def _write_iso_native(self, *tracks):
+ tracks = self._clean_iso_track_data(tracks)
data_block = self.ESC_CHR + '\x73'
data_block += ''.join(
self.ESC_CHR + chr(tn + 1) + track
@@ -203,21 +210,37 @@ def write_iso(self, *tracks):
self._send_command('\x77', raw_data_block)
self._read_status()
- def read_iso_soft(self):
- track1, track2, track3 = self.read_raw()
- return (
- track1.decode('iso7811-2-track1'),
- track2.decode('iso7811-2-track2'),
- track3.decode('iso7811-2-track3'),
- )
-
- def write_iso_soft(self, *tracks):
- tracks = [re.sub(r'^%|^;|\?$', '', track) for track in tracks]
- tracks[0] = ('%' + tracks[0] + '?').encode('iso7811-2-track1')
- tracks[1] = (';' + tracks[1] + '?').encode('iso7811-2-track2')
- tracks[2] = (';' + tracks[2] + '?').encode('iso7811-2-track3')
+ def _write_iso_soft(self, *tracks):
+ self._set_iso_mode()
+ tracks = self._clean_iso_track_data(tracks)
+ tracks = [
+ (ss + track + es).encode('iso7811-2-track%d' % (tn + 1))
+ for tn, ((ss, es), track) in enumerate(zip(self.TRACK_SENTINELS, tracks))
+ ]
return self.write_raw(*tracks)
+ def read_iso(self, soft=False):
+ if soft:
+ return self._read_iso_soft()
+ return self._read_iso_native()
+
+ def _read_iso_native(self):
+ self._send_command('\x72')
+ self._expect(self.ESC_CHR + '\x73')
+ self._expect(self.ESC_CHR + '\x01')
+ track1 = self._read_until(self.ESC_CHR + '\x02')[:-2]
+ track2 = self._read_until(self.ESC_CHR + '\x03')[:-2]
+ track3 = self._read_until(self.FS_CHR)[:-1]
+ self._read_status()
+ return track1, track2, track3
+
+ def _read_iso_soft(self):
+ self._set_iso_mode()
+ return [
+ track.decode('iso7811-2-track%d' % (tn + 1))
+ for tn, track in enumerate(self.read_raw())
+ ]
+
class ISO7811_2(codecs.Codec):
TRACK1_CHARS = ' !"#$%&\'()*+`,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'

No commit comments for this range

Something went wrong with that request. Please try again.