Skip to content

Instantly share code, notes, and snippets.

@rechner
Created November 10, 2016 03:55
Show Gist options
  • Save rechner/61577affb285afa9faff2acbdfbf79fb to your computer and use it in GitHub Desktop.
Save rechner/61577affb285afa9faff2acbdfbf79fb to your computer and use it in GitHub Desktop.
Magtek HID reader software for python
#!/usr/bin/python
"""
Read a MagTek USB HID Swipe Reader in Linux. A description of this
code can be found at: http://www.micahcarrick.com/credit-card-reader-pyusb.html
You must be using the new PyUSB 1.0 branch and not the 0.x branch.
(Install with `pip install pyusb --pre` in a virtualenv. Install libusb first on debian)
Copyright (c) 2010 - Micah Carrick
With additions by Zach Sturgeon, 2016
"""
import sys
import usb.core
import usb.util
VENDOR_ID = 0x0801
PRODUCT_ID = 0x0002
DATA_SIZE = 337
# find the MagTek reader
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if device is None:
sys.exit("Could not find MagTek USB HID Swipe Reader.")
# make sure the hiddev kernel driver is not active
if device.is_kernel_driver_active(0):
try:
device.detach_kernel_driver(0)
except usb.core.USBError as e:
sys.exit("Could not detatch kernel driver: %s" % str(e))
# set configuration
try:
device.set_configuration()
device.reset()
except usb.core.USBError as e:
sys.exit("Could not set configuration: %s" % str(e))
endpoint = device[0][(0,0)][0]
# wait for swipe
data = []
swiped = False
print "Please swipe your card..."
while 1:
try:
chunk = device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)
data += chunk
if not swiped:
print "Reading..."
swiped = True
if chunk.tolist() == [0,]:
break
except usb.core.USBError as e:
if e.args == ('Operation timed out',) and swiped:
if len(data) < DATA_SIZE:
print "Bad swipe, try again. (%d bytes)" % len(data)
print "Data: %s" % ''.join(map(chr, data))
data = []
swiped = False
continue
else:
break # we got it!
# now we have the binary data from the MagReader!
enc_formats = ('ISO/ABA', 'AAMVA', 'CADL', 'Blank', 'Other', 'Undetermined', 'None')
print "Card Encoding Type: %s" % enc_formats[data[6]]
print "Track 1 Decode Status: %r" % bool(not data[0])
print "Track 1 Data Length: %d bytes" % data[3]
print "Track 1 Data: %s" % ''.join(map(chr, data[7:116]))
print "Track 2 Decode Status: %r" % bool(not data[1])
print "Track 2 Data Length: %d bytes" % data[4]
print "Track 2 Data: %s" % ''.join(map(chr, data[117:226]))
print "Track 3 Decode Status: %r" % bool(not data[2])
print "Track 3 Data Length: %d bytes" % data[5]
print "Track 3 Data: %s" % ''.join(map(chr, data[227:336]))
# since this is a bank card we can parse out the cardholder data
track = ''.join(map(chr, data[7:116]))
info = {}
i = track.find('^', 1)
info['account_number'] = track[2:i].strip()
j = track.find('/', i)
info['last_name'] = track[i+1:j].strip()
k = track.find('^', j)
info['first_name'] = track[j+1:k].strip()
info['exp_year'] = track[k+1:k+3]
info['exp_month'] = track[k+3:k+5]
print "Bank card info: ", info
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment