Class: Mifare::Classic::Tag

Inherits:
Tag show all
Defined in:
lib/ruby-nfc/tags/mifare/classic.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tag

#name, #sak, #to_s

Methods inherited from NFC::Tag

#present?, #processed!, #processed?, #to_s, #uid, #uid_hex

Constructor Details

#initialize(target, reader) ⇒ Tag

Returns a new instance of Tag.



37
38
39
40
41
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 37

def initialize(target, reader)
  super(target, reader)

  @auth_block = nil #last authenticated block
end

Class Method Details

.match?(target) ⇒ Boolean

Check’s if our tag class is able to handle this LibNFC::Target

Returns:

  • (Boolean)


166
167
168
169
170
171
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 166

def self.match?(target)
  keys = [:CLASSIC_1K, :CLASSIC_1K_EMULATED, :CLASSIC_1K_ANDROID,
    :INFINEON_CLASSIC_1k, :CLASSIC_4K, :CLASSIC_4K_EMULATED]

  Mifare::SAKS.values_at(*keys).include? target.sak
end

Instance Method Details

#auth(block_num, key_type, key) ⇒ Object

keytype can be :key_a or :key_b key - hexadecimal string key representation like “FFFFFFFFFFFF”

Raises:



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 61

def auth(block_num, key_type, key)
  raise Mifare::Error, "Wrong key type" unless [:key_a, :key_b].include? key_type
  raise Mifare::Error, "Wrong key length" unless [6, 12].include? key.size

  key_ptr = FFI::MemoryPointer.new(:uchar, 6)
  key_ptr.put_bytes(0, 6 == key.size ? key : [key].pack("H*"))

  res = Mifare.mifare_classic_authenticate(@pointer, block_num, key_ptr,
                                           key_type)
        raise Mifare::Error, "Can't autenticate to block 0x%02x" % block_num if 0 != res

        @auth_block = block_num
end

#connect(&block) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 43

def connect(&block)
  @reader.set_flag(:NP_AUTO_ISO14443_4, false)

  res = Mifare.mifare_classic_connect(@pointer)
  if 0 == res 
          super
        else
          raise Mifare::Error, "Can't connect to tag: #{res}"
  end
end

#dec(amount = 1, block_num = nil) ⇒ Object

Mifare classic decrement

Raises:



149
150
151
152
153
154
155
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 149

def dec(amount = 1, block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num
        
        res = Mifare.mifare_classic_decrement(@pointer, block_num, amount)
  raise Mifare::Error, "Can't decrement block 0x%02x" % block_num if 0 != res
end

#disconnectObject



54
55
56
57
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 54

def disconnect
        Mifare.mifare_classic_disconnect(@pointer)
        super
end

#inc(amount = 1, block_num = nil) ⇒ Object

Mifare classic increment

Raises:



140
141
142
143
144
145
146
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 140

def inc(amount = 1, block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num
        
        res = Mifare.mifare_classic_increment(@pointer, block_num, amount)
  raise Mifare::Error, "Can't increment block 0x%02x" % block_num if 0 != res
end

#init_value(value, addr = nil, block_num = nil) ⇒ Object

Create value block structure and write it to block

Raises:



110
111
112
113
114
115
116
117
118
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 110

def init_value(value, addr = nil, block_num = nil)
  block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num

  addr ||= 0

        res = Mifare.mifare_classic_init_value(@pointer, block_num, value, addr)
  raise Mifare::Error, "Can't init value block 0x%02x" % block_num if 0 != res
end

#read(block_num = nil) ⇒ Object

block number to read

Raises:



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 76

def read(block_num = nil)
  block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num

        data_ptr = FFI::MemoryPointer.new(:uchar, 16)
  res = Mifare.mifare_classic_read(@pointer, block_num, data_ptr)

  raise Mifare::Error, "Can't read block 0x%02x" % block_num if 0 != res

  data_ptr.get_bytes(0, 16).force_encoding("ASCII-8BIT")
end

#transfer(block_num = nil) ⇒ Object

Raises:



157
158
159
160
161
162
163
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 157

def transfer(block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num

        res = Mifare.mifare_classic_transfer(@pointer, block_num)
  raise Mifare::Error, "Can't transfer to block 0x%02x" % block_num if 0 != res
end

#value(block_num = nil) ⇒ Object

returns only value part of value block



121
122
123
124
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 121

def value(block_num = nil)
  v, _ = value_with_addr(block_num)
  v
end

#value_with_addr(block_num = nil) ⇒ Object

returns value and addr

Raises:



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 127

def value_with_addr(block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num

        value_ptr = FFI::MemoryPointer.new(:int32, 1)
        addr_ptr = FFI::MemoryPointer.new(:uchar, 1)
        res = Mifare.mifare_classic_read_value(@pointer, block_num, value_ptr, addr_ptr)
  raise Mifare::Error, "Can't read value block 0x%02x" % block_num if 0 != res

        [value_ptr.get_int32(0), addr_ptr.get_uchar(0)]
end

#write(data, block_num = nil) ⇒ Object

Raises:



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 90

def write(data, block_num = nil)
  block_num ||= @auth_block
  raise Mifare::Error, "Not authenticated" unless block_num

        write_data = if data =~ /^[\da-f]{32}$/i
                 [data].pack("H*")
         elsif 16 == data.size 
            data.dup
         else
          raise Mifare::Error, "Wrong data given"
         end

        data_ptr = FFI::MemoryPointer.new(:uchar, 16)
        data_ptr.put_bytes(0, write_data)

        res = Mifare.mifare_classic_write(@pointer, block_num, data_ptr)
  raise Mifare::Error, "Can't write block 0x%02x" % block_num if 0 != res
end