~# gem install serialport
Once you install the serialport gem and specify the block device of the MSR206 within the code in the "tty_dev" variable (defaults to "/dev/ttyUSB0") executing the application is simple from a shell:
~# ./mr_ms_206-01-alpha.rb
Lights should start flashing on your MSR206 and you should be presented with a menu ;)
# --- COPY BELOW THIS LINE!!!
#!/usr/bin/env ruby
require 'rubygems'
require 'serialport'
# Be Sure to Choose the Appropriate Block Device
# (Typically /dev/ttyUSB0 when Using a Serial to USB Cable
# Specify Serial Device
tty_dev = "/dev/ttyUSB0"
tty_baud_choices = [ 19200, 9600, 4800, 2400, 1200 ]
# 9600 Baud Seems to Work the Best as of 2010-07-06
tty_baud = tty_baud_choices[1]
tty_data_bits = 8
tty_stop_bits = 1
# Can be SerialPort::NONE, HARD, SOFT, SPACE, MARK, EVEN, or ODD
tty_parity = SerialPort::NONE
@sp = SerialPort.new(tty_dev, tty_baud, tty_data_bits, tty_stop_bits, tty_parity)
@sp.read_timeout = 100
# General Reader Commands
@gencmd = {
:g_39=>[:version_report,"39"],
:g_7F=>[:simulate_power_cycle_warm_reset,"7F"],
:g_23=>[:configuration_request,"23"],
:g_25=>[:reproduce_last_command,"25"],
:g_11=>[:resume_transmission_to_host,"11"],
:g_13=>[:pause_transmission_to_host,"13"],
:g_1B=>[:abort_command,"1B"]
}
# LED Commands
@led = {
:l_4D=>[:red_on,"4D"],
:l_6D=>[:red_off,"6D"],
:l_29=>[:red_flash,"29"],
:l_4C=>[:green_on,"4C"],
:l_6C=>[:green_off,"6C"],
:l_28=>[:green_flash,"28"],
:l_4B=>[:yellow_on,"4B"],
:l_6B=>[:yellow_off,"6B"],
:l_7C=>[:yellow_flash,"7C"]
}
# Magnetic Reading Commands
@readcmd = {
:r_50=>[:arm_to_read,"50"], # P
:r_70=>[:arm_to_read_w_speed_prompts,"70"],
:r_51=>[:tx_iso_std_data_track1,"51"], # Q
:r_52=>[:tx_iso_std_data_track2,"52"], # R
:r_53=>[:tx_iso_std_data_track3,"53"], # S
:r_71=>[:alt_tx_iso_std_data_track1,"71"], # q
:r_72=>[:alt_tx_iso_std_data_track2,"72"], # r
:r_73=>[:alt_tx_iso_std_data_track3,"73"], # s
:r_49=>[:tx_error_data,"49"],
:r_45=>[:tx_custom_data_forward_track1,"45"],
:r_46=>[:tx_custom_data_forward_track2,"46"],
:r_47=>[:tx_custom_data_forward_track3,"47"],
:r_58=>[:tx_passbook_data,"58"],
:r_78=>[:alt_tx_passbook_data,"78"],
:r_3F=>[:write_verify,"3F"],
:r_26=>[:card_edge_detect,"26"]
}
# Magnetic Writing Commands
@writecmd = {
:w_41=>[:load_iso_std_data_for_writing_track1,"41"],
:w_42=>[:load_iso_std_data_for_writing_track2,"42"],
:w_43=>[:load_iso_std_data_for_writing_track3,"43"],
:w_61=>[:alt_load_iso_std_data_for_writing_track1,"61"],
:w_62=>[:alt_load_iso_std_data_for_writing_track2,"62"],
:w_63=>[:alt_load_iso_std_data_for_writing_track3,"63"],
:w_6A=>[:load_passbook_data_for_writing,"6A"],
:w_45=>[:load_custom_data_for_writing_track1,"45"],
:w_46=>[:load_custom_data_for_writing_track2,"46"],
:w_47=>[:load_custom_data_for_writing_track3,"47"],
:w_3B=>[:set_write_density,"3B"],
:w_4F=>[:set_write_density_210_bpi_tracks_1_3,"4F"],
:w_6F=>[:set_write_density_75_bpi_tracks_1_3,"6F"],
:w_4E=>[:set_write_density_210_bpi_tracks_2,"4E"],
:w_6E=>[:set_write_density_75_bpi_tracks_2,"6E"],
:w_5B=>[:set_default_write_current,"5B"],
:w_5D=>[:view_default_write_current,"5D"],
:w_3C=>[:set_temp_write_current,"3C"],
:w_3E=>[:view_temp_write_current,"3E"],
:w_40=>[:arm_to_write_with_raw,"40"],
:w_5A=>[:arm_to_write_no_raw,"5A"],
:w_7A=>[:arm_to_write_with_raw_speed_prompts,"7A"]
}
@solicited_unsolicited_response = {
:s_5E=>"Command Completed (ACK)",
:s_21=>"Invalid Command",
:s_2A=>"Error",
:s_2B=>"No Data Found",
:s_2D=>"Insufficient Leading Zeros for Custom Writing",
:s_2F=>"lsb of First Character Not a '1' for Custom Writing",
:s_3F=>"Communications Error",
:s_7E=>"Can't Execute - Hardware Does Not Support Command",
:u_3A=>"Power on Report",
:u_5E=>"Card Swipe Occurred when Armed to Read or Write",
:u_31=>"Unsuccessful Read After Write - Track1",
:u_32=>"Unsuccessful Read After Write - Track2",
:u_33=>"Unsuccessful Read After Write - Track3",
:u_28=>"Card Speed Measurement Start",
:u_29=>"Card Speed Measurement End",
:u_3E=>"Card Edge Detected"
}
@charset = {
:c_10110000=>"0", # Confirmed
:c_00110001=>"1", # Confirmed
:c_00110010=>"2", # Confirmed
:c_10110011=>"3", # Confirmed
:c_00110100=>"4", # Confirmed
:c_10110101=>"5", # Confirmed
:c_10110110=>"6", # Confirmed
:c_00110111=>"7", # Confirmed
:c_00111000=>"8", # Confirmed
:c_10111001=>"9", # Confirmed
:c_11000001=>"A", # Confirmed
:c_11000010=>"B", # Confirmed
:c_01000011=>"C", # Confirmed
:c_11000100=>"D", # Confirmed
:c_01000101=>"E", # Confirmed
:c_01000110=>"F", # Confirmed
:c_11000111=>"G", # Confirmed
:c_11001000=>"H", # Confirmed
:c_01001001=>"I", # Confirmed
:c_01001010=>"J", # Confirmed
:c_11001011=>"K", # Confirmed
:c_01001100=>"L", # Confirmed
:c_11001101=>"M", # Confirmed
:c_11001110=>"N", # Confirmed
:c_01001111=>"O", # Confirmed
:c_11010000=>"P", # Confirmed
:c_01010001=>"Q", # Confirmed
:c_01010010=>"R", # Confirmed
:c_11010011=>"S", # Confirmed
:c_01010100=>"T", # Confirmed
:c_11010101=>"U", # Confirmed
:c_11010110=>"V", # Confirmed
:c_01010111=>"W", # Confirmed
:c_01011000=>"X", # Confirmed
:c_11011001=>"Y", # Confirmed
:c_11011010=>"Z", # Confirmed
:c_00100000=>" ", # Confirmed
:c_01000000=>"@", # Confirmed
:c_10100001=>"!", # Confirmed
:c_10100010=>'"', # Confirmed
:c_00100011=>"#", # Confirmed
:c_10100100=>"$", # Confirmed
:c_00100101=>"%", # Confirmed
:c_00100110=>"&", # Confirmed
:c_000111=>"/", # Confirmed
:c_00101111=>"/", # Confirmed
:c_11011100=>"\\", # Confirmed
:c_10101000=>"(", # Confirmed
:c_00101001=>")", # Confirmed
:c_01011011=>"[", # Confirmed
:c_01011101=>"]", # Confirmed
:c_10111100=>"<", # Confirmed
:c_00111110=>">", # Confirmed
:c_10111010=>":", # Confirmed
:c_00111011=>";", # Confirmed
:c_00101010=>"*", # Confirmed
:c_10101011=>"+", # Confirmed
:c_00101100=>",", # Confirmed
:c_10101101=>"-", # Confirmed
:c_00111101=>"=", # Confirmed
:c_10101110=>".", # Confirmed
:c_01011110=>"^", # Confirmed
:c_011111=>"?", # Unconfirmed
:c_111111=>"DEL" # Unconfirmed
}
# Initialize or Invoke a Command
def init_cmd(current_cmd,opt_param=nil,track=nil,verbose=false,trackdebug=false)
@sp.write "#{current_cmd.hex.chr}#{opt_param}"
#response = @sp.read.encoding.inspect
response = @sp.read.force_encoding("US-ASCII")
#response = @sp.read.force_encoding("ISO-8859-1")
#response = @sp.read
if (verbose == true)
if (trackdebug == true)
puts "Raw Request: #{current_cmd.hex.chr}#{opt_param}"
puts "Hex Request: #{current_cmd}#{opt_param}"
end
@formatted_hex_response = ""
@hex_response = ""
@formatted_bin_response = ""
@bin_response = ""
response.each_char do |hex_char|
@formatted_hex_response << "#{hex_char.unpack('H*')[0].upcase} "
@hex_response << "#{hex_char.unpack('H*')[0].upcase}"
@formatted_bin_response << "#{hex_char.unpack('B*')[0].upcase} "
@bin_response << "#{hex_char.unpack('B*')[0].upcase}"
end
chunk_binary = @bin_response.to_s.scan(/.{8}/)
puts "Encoding: #{response.encoding.name}"
if (trackdebug == true)
puts "ASCII Hex Response (Raw): #{@hex_response}"
puts "ASCII Hex Response (Formatted): #{@formatted_hex_response}"
puts "Binary Response (Raw): #{@bin_response}"
puts "Binary Response (Formatted): #{chunk_binary}"
puts "Binary Response Formatted Array Count: #{chunk_binary.size}"
end
puts "Raw Response: #{response}"
puts "Raw Character Length: #{response.size}"
case track
when 1
decoded_response = ""
puts "Decoded Track 1: "
chunk_binary.each do |bin_arr_value|
t1_key = "c_#{bin_arr_value}".to_sym
if (@charset[t1_key])
decoded_response << @charset[t1_key]
print @charset[t1_key]
end
end
print "\n"
puts "Decoded Track 1 Character Length: #{decoded_response.size}"
when 2
decoded_response = ""
puts "Decoded Track 2: "
chunk_binary.each do |bin_arr_value|
t2_key = "c_#{bin_arr_value}".to_sym
if (@charset[t2_key])
decoded_response << @charset[t2_key]
print @charset[t2_key]
end
end
print "\n"
puts "Decoded Track 2 Character Length: #{decoded_response.size}"
when 3
decoded_response = ""
puts "Decoded Track 3: "
chunk_binary.each do |bin_arr_value|
t3_key = "c_#{bin_arr_value}".to_sym
if (@charset[t3_key])
decoded_response << @charset[t3_key]
print @charset[t3_key]
end
end
print "\n"
puts "Decoded Track 3 Character Length: #{decoded_response.size}"
else
decoded_response = ""
puts "Decoded #{track} Response: "
chunk_binary.each do |bin_arr_value|
key = "c_#{bin_arr_value}".to_sym
if (@charset[key])
decoded_response << @charset[key]
print @charset[key]
end
end
print "\n"
puts "Decoded #{track} Response Character Length: #{decoded_response.size}"
end
s_key = "s_#{@hex_response}".to_sym
u_key = "u_#{@hex_response}".to_sym
if (@solicited_unsolicited_response[s_key])
puts "Solicited Response: #{@solicited_unsolicited_response[s_key]}"
else
if (trackdebug == true)
puts "Solicited Response: nil"
end
end
if (@solicited_unsolicited_response[u_key])
puts "Unsolicited Response: #{@solicited_unsolicited_response[u_key]}"
else
if (trackdebug == true)
puts "Unsolicited Response: nil"
end
end
print "\n"
end
return 0
end
# Startup Light Intro - Used to Ensure All LEDs are Turning On/Off/Blinking i.e. Working Properly
def led_test
sleep 1
init_cmd(@led[:l_4D][1])
init_cmd(@led[:l_4B][1])
init_cmd(@led[:l_4C][1])
sleep 1.5
init_cmd(@led[:l_29][1])
init_cmd(@led[:l_7C][1])
init_cmd(@led[:l_28][1])
sleep 1.5
init_cmd(@led[:l_6D][1])
init_cmd(@led[:l_6B][1])
init_cmd(@led[:l_6C][1])
return 0
end
def load_file(file)
puts File.read(file)
main_menu_options
end
def invalid_menu_option
puts "Invalid Menu Option!"
init_cmd(@led[:l_6C][1])
init_cmd(@led[:l_6B][1])
init_cmd(@led[:l_29][1])
sleep 2
init_cmd(@led[:l_6D][1])
end
def advanced_menu_options
while true
puts "\n>> ADVANCED MENU OPTIONS:"
puts "[(G)eneral Commands]"
puts "[(R)ead Commands]"
puts "[(W)rite Commands]"
puts "[(L)ED Commands]"
puts "[(E)xecute a Command]"
puts "[(B)ack]"
print ">> SELECT A MENU OPTION OR ENTER A COMMAND: "
option = gets.chomp
case option
when "G","g" then
puts "\tGENERAL COMMANDS:"
puts "\t\tcmd\tdesc"
@gencmd.each do |key,val|
puts "\t\t#{key}\t#{val.inspect}"
end
when "R","r" then
puts "\tREAD COMMANDS:"
puts "\t\tcmd\tdesc"
@readcmd.each do |key,val|
puts "\t\t#{key}\t#{val.inspect}"
end
when "W","w" then
puts "\tWRITE COMMANDS:"
puts "\t\tcmd\tdesc"
@writecmd.each do |key,val|
puts "\t\t#{key}\t#{val.inspect}"
end
when "L","l" then
puts "\tLED COMMANDS:"
puts "\t\tcmd\tdesc"
@led.each do |key,val|
puts "\t\t#{key}\t#{val.inspect}"
end
when "B","b" then
main_menu_options
else
if (@gencmd[option.to_sym])
init_cmd(@gencmd[option.to_sym][1],nil,nil,true,false)
elsif (@writecmd[option.to_sym])
init_cmd(@writecmd[option.to_sym][1],nil,nil,true,false)
elsif (@readcmd[option.to_sym])
init_cmd(@readcmd[option.to_sym][1],nil,nil,true,false)
elsif (@led[option.to_sym])
init_cmd(@led[option.to_sym][1])
else
invalid_menu_option
end
end
end
end
def main_menu_options
while true
puts "\n>> MAIN MENU OPTIONS:"
puts "[(A)dvanced Menu Options]"
puts "[(R)ead Card]"
puts "[(O)pen File]"
puts "[(E)dit Card Data]"
puts "[(W)rite Card]"
puts "[(S)ave to File]"
puts "[(Q)uit]"
print ">> SELECT A MENU OPTION: "
option = gets.chomp
case option
when "A","a" then
advanced_menu_options
when "R","r" then
init_cmd(@led[:l_4C][1])
wait_for_swipe(:read)
when "O", "o" then
print "File Location: "
file = gets.chomp
load_file(file)
when "W","w" then
puts "Coming Soon..."
wait_for_swipe(:write)
when "Q","q" then
init_cmd(@led[:l_6C][1])
init_cmd(@led[:l_6B][1])
exit
else
invalid_menu_option
end
end
end
def dump_read_response(extra_formats=false)
puts "*** ISO Track Format: Standard #{'*'*17}"
print ">> Track 1\n"
# Toggle last two bool params to increase verbosity for debugging
#init_cmd(@readcmd[:r_51][1],nil,1,true,true)
init_cmd(@readcmd[:r_51][1],nil,1,true,false)
print "\n>> Track 2\n"
#init_cmd(@readcmd[:r_52][1],nil,2,true,true)
init_cmd(@readcmd[:r_52][1],nil,2,true,false)
print "\n>> Track 3\n"
#init_cmd(@readcmd[:r_53][1],nil,3,true,true)
init_cmd(@readcmd[:r_53][1],nil,3,true,false)
if (extra_formats == true)
3.times do |i|
i+=1
puts "*** ISO Track Format: #{i} #{'*'*24}"
print ">> Track 1\n"
#init_cmd(@readcmd[:r_71][1],i,1,true,true)
init_cmd(@readcmd[:r_71][1],i,1,true,false)
print "\n>> Track 2\n"
#init_cmd(@readcmd[:r_72][1],i,2,true,true)
init_cmd(@readcmd[:r_71][1],i,1,true,false)
print "\n>> Track 3\n"
#init_cmd(@readcmd[:r_73][1],i,3,true,true)
init_cmd(@readcmd[:r_71][1],i,1,true,false)
print "\n"
end
end
main_menu_options
end
def wait_for_swipe(type)
case type
when :read then
init_cmd(@readcmd[:r_50][1])
when :write then
init_cmd(@writecmd[:w_40][1])
else
puts "Unknown 'wait_for_swipe' method: 'type' parameter. Goodbye."
return 1
end
print "Ready. Please Swipe Card Now:"
while true do
response = @sp.read.unpack('H*')[0].upcase
if (response == "5E")
break
end
s_key = "s_#{response.unpack('H*')[0].upcase}".to_sym
u_key = "u_#{response.unpack('H*')[0].upcase}".to_sym
if (@solicited_unsolicited_response[s_key])
puts "Solicited Response: (#{response}) #{@solicited_unsolicited_response[s_key]}"
end
if (@solicited_unsolicited_response[u_key])
puts "Unsolicited Response: (#{response}) #{@solicited_unsolicited_response[u_key]}"
end
if (response != "")
puts "Attention Potential SUResponse Received: #{response}"
end
end
print "\n"
init_cmd(@led[:l_4B][1])
dump_read_response
end
puts "Welcome to #{$0} - Enjoy the Lightshow!"
puts "Connected to Device: #{tty_dev} #{tty_baud}bps #{tty_data_bits} #{tty_stop_bits} #{tty_parity}"
# Reset Everything in Case the MSR206-7HLR is Powered in a Weird State
init_cmd(@gencmd[:g_7F][1])
#init_cmd(@gencmd[:g_13][1])
#init_cmd(@gencmd[:g_23][1])
sleep 1
# Test LEDs
#led_test
# Starting Application
init_cmd(@gencmd[:g_39][1],nil,"Version",true,true)
# Turn on Green LED
#init_cmd(@led[:l_4C][1])
main_menu_options
@sp.close
# --- END OF CODE
If you enjoyed this post, send us = kudos =
(Bitcoin Addr: 19n6q3GZfoM64oqv5HsDnhzqvcEvJUvmdx)