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

#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)


162
163
164
165
166
167
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 162

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
74
75
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 61

def auth(block_num, key_type, key)
  raise Mifare::Error.new('Wrong key type') unless [:key_a, :key_b].include? key_type
  raise Mifare::Error.new('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)
        if 0 == res
    @auth_block = block_num
  else
          raise Mifare::Error.new("Can't autenticate to block 0x%02x" % block_num)
        end
end

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

Mifare classic decrement

Raises:



145
146
147
148
149
150
151
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 145

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

#deselectObject



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

def deselect
        Mifare.mifare_classic_disconnect(@pointer)
        super
end

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

Mifare classic increment

Raises:



136
137
138
139
140
141
142
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 136

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

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

Create value block structure and write it to block

Raises:



106
107
108
109
110
111
112
113
114
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 106

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

  addr ||= 0

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

#read(block_num = nil) ⇒ Object

block number to read

Raises:



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

def read(block_num = nil)
  block_num ||= @auth_block
  raise Mifare::Error.new('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.new("Can't read block 0x%02x" % block_num) unless 0 == res

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

#select(&block) ⇒ Object



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

def select(&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 select tag: #{res}"
  end
end

#transfer(block_num = nil) ⇒ Object

Raises:



153
154
155
156
157
158
159
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 153

def transfer(block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error.new('Not authenticated') unless block_num

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

#value(block_num = nil) ⇒ Object

returns only value part of value block



117
118
119
120
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 117

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:



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ruby-nfc/tags/mifare/classic.rb', line 123

def value_with_addr(block_num = nil)
        block_num ||= @auth_block
  raise Mifare::Error.new('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.new("Can't read value block 0x%02x" % block_num) unless 0 == res

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

#write(data, block_num = nil) ⇒ Object

Raises:



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

def write(data, block_num = nil)
        raise Mifare::Error.new('Wrong data given') if data !~ /^[\da-f]{32}$/i

  block_num ||= @auth_block
  raise Mifare::Error.new('Not authenticated') unless block_num

        data_ptr = FFI::MemoryPointer.new(:uchar, 16)
        data_ptr.put_bytes(0, [data].pack('H*'))

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