Class: CTAPI::Cardterminal
Overview
Represents a cardterminal. Mixes in CTAPI methods and constants.
Defined Under Namespace
Classes: Manufacturer
Constant Summary collapse
- LOCK =
Global lock for managment of cardterminals.
Sync.new
Constants included from CTAPI
VERSION, VERSION_ARRAY, VERSION_BUILD, VERSION_MAJOR, VERSION_MINOR
Constants included from CTAPICore
CTAPICore::CT, CTAPICore::CTBCS_CLA, CTAPICore::CTBCS_DATA_STATUS_CARD, CTAPICore::CTBCS_DATA_STATUS_CARD_CONNECT, CTAPICore::CTBCS_DATA_STATUS_NOCARD, CTAPICore::CTBCS_INS_EJECT, CTAPICore::CTBCS_INS_REQUEST, CTAPICore::CTBCS_INS_RESET, CTAPICore::CTBCS_INS_STATUS, CTAPICore::CTBCS_MIN_COMMAND_SIZE, CTAPICore::CTBCS_MIN_RESPONSE_SIZE, CTAPICore::CTBCS_P1_CT_KERNEL, CTAPICore::CTBCS_P1_DISPLAY, CTAPICore::CTBCS_P1_INTERFACE1, CTAPICore::CTBCS_P1_INTERFACE10, CTAPICore::CTBCS_P1_INTERFACE11, CTAPICore::CTBCS_P1_INTERFACE12, CTAPICore::CTBCS_P1_INTERFACE13, CTAPICore::CTBCS_P1_INTERFACE14, CTAPICore::CTBCS_P1_INTERFACE2, CTAPICore::CTBCS_P1_INTERFACE3, CTAPICore::CTBCS_P1_INTERFACE4, CTAPICore::CTBCS_P1_INTERFACE5, CTAPICore::CTBCS_P1_INTERFACE6, CTAPICore::CTBCS_P1_INTERFACE7, CTAPICore::CTBCS_P1_INTERFACE8, CTAPICore::CTBCS_P1_INTERFACE9, CTAPICore::CTBCS_P1_KEYPAD, CTAPICore::CTBCS_P2_REQUEST_GET_ATR, CTAPICore::CTBCS_P2_REQUEST_GET_HIST, CTAPICore::CTBCS_P2_REQUEST_NO_RESP, CTAPICore::CTBCS_P2_RESET_GET_ATR, CTAPICore::CTBCS_P2_RESET_GET_HIST, CTAPICore::CTBCS_P2_RESET_NO_RESP, CTAPICore::CTBCS_P2_STATUS_ICC, CTAPICore::CTBCS_P2_STATUS_MANUFACTURER, CTAPICore::CTBCS_SW1_COMMAND_NOT_ALLOWED, CTAPICore::CTBCS_SW1_EJECT_NOT_REMOVED, CTAPICore::CTBCS_SW1_EJECT_OK, CTAPICore::CTBCS_SW1_EJECT_REMOVED, CTAPICore::CTBCS_SW1_ICC_ERROR, CTAPICore::CTBCS_SW1_OK, CTAPICore::CTBCS_SW1_REQUEST_ASYNC_OK, CTAPICore::CTBCS_SW1_REQUEST_CARD_PRESENT, CTAPICore::CTBCS_SW1_REQUEST_ERROR, CTAPICore::CTBCS_SW1_REQUEST_NO_CARD, CTAPICore::CTBCS_SW1_REQUEST_SYNC_OK, CTAPICore::CTBCS_SW1_REQUEST_TIMER_ERROR, CTAPICore::CTBCS_SW1_RESET_ASYNC_OK, CTAPICore::CTBCS_SW1_RESET_CT_OK, CTAPICore::CTBCS_SW1_RESET_ERROR, CTAPICore::CTBCS_SW1_RESET_SYNC_OK, CTAPICore::CTBCS_SW1_WRONG_CLA, CTAPICore::CTBCS_SW1_WRONG_INS, CTAPICore::CTBCS_SW1_WRONG_LENGTH, CTAPICore::CTBCS_SW1_WRONG_PARAM, CTAPICore::CTBCS_SW2_COMMAND_NOT_ALLOWED, CTAPICore::CTBCS_SW2_EJECT_NOT_REMOVED, CTAPICore::CTBCS_SW2_EJECT_OK, CTAPICore::CTBCS_SW2_EJECT_REMOVED, CTAPICore::CTBCS_SW2_ICC_ERROR, CTAPICore::CTBCS_SW2_OK, CTAPICore::CTBCS_SW2_REQUEST_ASYNC_OK, CTAPICore::CTBCS_SW2_REQUEST_CARD_PRESENT, CTAPICore::CTBCS_SW2_REQUEST_ERROR, CTAPICore::CTBCS_SW2_REQUEST_NO_CARD, CTAPICore::CTBCS_SW2_REQUEST_SYNC_OK, CTAPICore::CTBCS_SW2_REQUEST_TIMER_ERROR, CTAPICore::CTBCS_SW2_RESET_ASYNC_OK, CTAPICore::CTBCS_SW2_RESET_CT_OK, CTAPICore::CTBCS_SW2_RESET_ERROR, CTAPICore::CTBCS_SW2_RESET_SYNC_OK, CTAPICore::CTBCS_SW2_WRONG_CLA, CTAPICore::CTBCS_SW2_WRONG_INS, CTAPICore::CTBCS_SW2_WRONG_LENGTH, CTAPICore::CTBCS_SW2_WRONG_PARAM, CTAPICore::ERR_CT, CTAPICore::ERR_HTSI, CTAPICore::ERR_INVALID, CTAPICore::ERR_MEMORY, CTAPICore::ERR_TRANS, CTAPICore::HOST, CTAPICore::ICC1, CTAPICore::ICC10, CTAPICore::ICC11, CTAPICore::ICC12, CTAPICore::ICC13, CTAPICore::ICC14, CTAPICore::ICC2, CTAPICore::ICC3, CTAPICore::ICC4, CTAPICore::ICC5, CTAPICore::ICC6, CTAPICore::ICC7, CTAPICore::ICC8, CTAPICore::ICC9, CTAPICore::MAX_APDULEN, CTAPICore::OK, CTAPICore::PORT_COM1, CTAPICore::PORT_COM2, CTAPICore::PORT_COM3, CTAPICore::PORT_COM4, CTAPICore::PORT_LPT1, CTAPICore::PORT_LPT2, CTAPICore::PORT_Modem, CTAPICore::PORT_Printer
Instance Attribute Summary collapse
-
#card ⇒ Object
readonly
Card object of the inserted chipcard.
-
#chunk_size ⇒ Object
The maximum size of the chunks of data that are read from/written to the card.
-
#interface ⇒ Object
readonly
The interface this cardterminal is connected to.
-
#manufacturer ⇒ Object
readonly
The Manufacturer object for this cardterminal.
-
#number ⇒ Object
readonly
The cardterminal number assigned to this object.
-
#slot ⇒ Object
The slot of the card terminal where the card is inserted.
Class Method Summary collapse
-
.cardterminals ⇒ Object
Returns the mapping of cardterminal numbers to Cardterminal instances as a hash.
-
.open(interface, number = nil) ⇒ Object
Takes a block and yields to an initialized Cardterminal object.
Instance Method Summary collapse
-
#card_inserted? ⇒ Boolean
Returns true if a card is inserted in the cardterminal at the moment, false if the cardterminal is empty.
-
#card_status ⇒ Object
Returns the card status as symbol: :no_card, :card, :card_connect.
-
#cardterminals ⇒ Object
Convenience method to access Cardterminal.cardterminals.
-
#change_pin(old_pin, new_pin) ⇒ Object
The pin of this card is changed from old_pin to new_pin.
-
#close ⇒ Object
Terminates the communication with the cardterminal associated with this object and releases the assigned cardterminal number.
-
#data(dad, sad, *commands) ⇒ Object
Sends a sequence of commands to the card or the cardterminal (depending on destination/dad and source address/sad) and returns the response (or responses) to the calling program.
-
#eject_icc ⇒ Object
Sends the eject card byte sequence to the card terminal and returns the Response object.
-
#enter_pin(pin) ⇒ Object
The pin is sent to the card.
-
#initialize(interface, number = nil) ⇒ Cardterminal
constructor
Creates a new Cardterminal object for this interface and initializes the card terminal that is connected.
-
#read(address = 0, size = nil) ⇒ Object
Attempts to read data of length size starting at address.
-
#request_card_status ⇒ Object
Requests the card status from the cardterminal.
-
#request_icc ⇒ Object
Sends a byte sequence to the card to get the answer to reset Response object.
-
#reset ⇒ Object
The cardterminal is reset by first calling eject_icc and then request_icc.
-
#select_file(fid = [ 0x3f, 0 ]) ⇒ Object
Sends the select file byte sequence to the card with a default value for the master file.
-
#write(data, address = 0) ⇒ Object
Attempts to write the string data to the card starting at address.
Methods included from CTAPICore
Constructor Details
#initialize(interface, number = nil) ⇒ Cardterminal
Creates a new Cardterminal object for this interface and initializes the card terminal that is connected. If no cardterminal number is given, a number (that is not currently in use) is assigned to this object. Otherwise this object is forced to use the given card terminal number. BTW: number has to be >= 0.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/ctapi.rb', line 31 def initialize(interface, number = nil) LOCK.synchronize do @interface = interface @slot = ICC1 @chunk_size = 255 if number @number = number else @number = 0 while cardterminals.key?(@number) @number += 1 end end ct_init(@number, interface) cardterminals[@number] = true @manufacturer = get_manufacturer reset select_file # master file end end |
Instance Attribute Details
#card ⇒ Object (readonly)
Card object of the inserted chipcard.
97 98 99 |
# File 'lib/ctapi.rb', line 97 def card @card end |
#chunk_size ⇒ Object
The maximum size of the chunks of data that are read from/written to the card. Can be set by calling the chunk_size= method.
83 84 85 |
# File 'lib/ctapi.rb', line 83 def chunk_size @chunk_size end |
#interface ⇒ Object (readonly)
The interface this cardterminal is connected to. This is a value of PORT_COM1, PORT_COM2, PORT_COM3, PORT_COM4, PORT_LPT1, PORT_LPT2, PORT_Modem or PORT_Printer.
74 75 76 |
# File 'lib/ctapi.rb', line 74 def interface @interface end |
#manufacturer ⇒ Object (readonly)
The Manufacturer object for this cardterminal.
94 95 96 |
# File 'lib/ctapi.rb', line 94 def manufacturer @manufacturer end |
#number ⇒ Object (readonly)
The cardterminal number assigned to this object.
69 70 71 |
# File 'lib/ctapi.rb', line 69 def number @number end |
#slot ⇒ Object
The slot of the card terminal where the card is inserted. This is a value in the range of ICC1, ICC2,…, ICC14. Default is ICC1.
79 80 81 |
# File 'lib/ctapi.rb', line 79 def slot @slot end |
Class Method Details
.cardterminals ⇒ Object
Returns the mapping of cardterminal numbers to Cardterminal instances as a hash.
17 18 19 |
# File 'lib/ctapi.rb', line 17 def self.cardterminals @cardterminals ||= {} end |
.open(interface, number = nil) ⇒ Object
Takes a block and yields to an initialized Cardterminal object. After the block has been called, the cardterminal is closed again.
102 103 104 105 106 107 |
# File 'lib/ctapi.rb', line 102 def self.open(interface, number = nil) cardterminal = self.new(interface, cardterminal) yield cardterminal ensure cardterminal.close if cardterminal end |
Instance Method Details
#card_inserted? ⇒ Boolean
Returns true if a card is inserted in the cardterminal at the moment, false if the cardterminal is empty.
339 340 341 342 |
# File 'lib/ctapi.rb', line 339 def card_inserted? cs = card_status cs == :card || cs == :card_connect ? true : false end |
#card_status ⇒ Object
Returns the card status as symbol: :no_card, :card, :card_connect.
325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/ctapi.rb', line 325 def card_status response = request_card_status case response[0] when CTBCS_DATA_STATUS_NOCARD :no_card when CTBCS_DATA_STATUS_CARD :card when CTBCS_DATA_STATUS_CARD_CONNECT :card_connect end end |
#cardterminals ⇒ Object
Convenience method to access Cardterminal.cardterminals.
22 23 24 |
# File 'lib/ctapi.rb', line 22 def cardterminals self.class.cardterminals end |
#change_pin(old_pin, new_pin) ⇒ Object
The pin of this card is changed from old_pin to new_pin. They can be given as strings or arrays of characters. A true result is returned if the sending was successful.
256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/ctapi.rb', line 256 def change_pin(old_pin, new_pin) old_pin = old_pin.unpack("C*") if old_pin.is_a? String new_pin = new_pin.unpack("C*") if new_pin.is_a? String data = old_pin + new_pin unless data.size <= 255 raise ArgumentError.new("size of old and new pin must be <= 255") end change_pin = [ 0, 0x24, 0, 0, data.size ] + data response = data(@slot, HOST, change_pin) response.successful? or return true end |
#close ⇒ Object
Terminates the communication with the cardterminal associated with this object and releases the assigned cardterminal number.
134 135 136 137 138 139 |
# File 'lib/ctapi.rb', line 134 def close LOCK.synchronize do ct_close(@number) cardterminals.delete @number end end |
#data(dad, sad, *commands) ⇒ Object
Sends a sequence of commands to the card or the cardterminal (depending on destination/dad and source address/sad) and returns the response (or responses) to the calling program. A command can be given as an array of bytes [ 0x12, 0x23 ] or as a string of the form ‘12:23:a4’ or ‘12 23 a4’ or as a Command object.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/ctapi.rb', line 114 def data(dad, sad, *commands) responses = [] commands.each do |command| command = case command when String then Command.from_string(command) when Array then Command.from_array(command) else command end $DEBUG and debug(2, command) data = ct_data(@number, dad, sad, command.data) response = Response.new(data) $DEBUG and debug(1, response) responses << response end return *responses end |
#eject_icc ⇒ Object
Sends the eject card byte sequence to the card terminal and returns the Response object. This method is called by the Cardterminal#reset method.
308 309 310 311 |
# File 'lib/ctapi.rb', line 308 def eject_icc eject = [ 0x20, 0x15, 0x01, 0x00, 0x00 ] data(CT, HOST, eject) end |
#enter_pin(pin) ⇒ Object
The pin is sent to the card. It can be given as a string or an array of characters. A true result is returned if the sending was successful.
242 243 244 245 246 247 248 249 250 251 |
# File 'lib/ctapi.rb', line 242 def enter_pin(pin) unless pin.size <= 255 raise ArgumentError.new("size of pin must be <= 255") end pin = pin.unpack("C*") if pin.is_a? String enter_pin = [ 0, 0x20, 0, 0, pin.size ] + pin response = data(@slot, HOST, enter_pin) response.successful? or return true end |
#read(address = 0, size = nil) ⇒ Object
Attempts to read data of length size starting at address. If size is nil, an attempt is made to read the whole card memory.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/ctapi.rb', line 168 def read(address = 0, size = nil) if size == nil if @card size = @card.memory_size - address else size = chunk_size end elsif @card and address + size > @card.memory_size size = @card.memory_size - address end return if size <= 0 data = '' caught = catch(:break) do while size >= chunk_size d = read_chunk(address, chunk_size) if d data << d address += chunk_size size -= chunk_size else break :break end end end if caught != :break and size > 0 d = read_chunk(address, size) and data << d end data end |
#request_card_status ⇒ Object
Requests the card status from the cardterminal. Returns the Response object or nil if the response wasn’t successful. This method is called by the card_inserted? method to find out if a card is inserted into the terminal.
273 274 275 276 277 278 |
# File 'lib/ctapi.rb', line 273 def request_card_status get_card_status = [ CTBCS_CLA, CTBCS_INS_STATUS, CTBCS_P1_CT_KERNEL, CTBCS_P2_STATUS_ICC, 0 ] response = data(CT, HOST, get_card_status) response.successful? ? response : nil end |
#request_icc ⇒ Object
Sends a byte sequence to the card to get the answer to reset Response object. This method is called by the Cardterminal#reset method.
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/ctapi.rb', line 283 def request_icc get_atr = [ CTBCS_CLA, CTBCS_INS_REQUEST, CTBCS_P1_INTERFACE1, CTBCS_P2_REQUEST_GET_ATR, 0 ] @card_old = @card if @card @card, atr = nil, nil begin if card_inserted? atr = data(CT, HOST, get_atr) if atr if atr.not_changed? @card = @card_old return @card.atr end @card = Card.new(atr) end end rescue CTAPIError => e STDERR.puts "Caught: #{e}." end @card.atr end |
#reset ⇒ Object
The cardterminal is reset by first calling eject_icc and then request_icc. If the reset was successful the Response object of request_icc is returned, otherwise a nontrue value is returned.
317 318 319 320 321 322 |
# File 'lib/ctapi.rb', line 317 def reset eject_icc response = request_icc or return response.successful? or return response end |
#select_file(fid = [ 0x3f, 0 ]) ⇒ Object
Sends the select file byte sequence to the card with a default value for the master file. Returns true if the response was successful, false otherwise.
144 145 146 147 148 |
# File 'lib/ctapi.rb', line 144 def select_file(fid = [ 0x3f, 0 ]) select_file = [ 0, 0xa4, 0, 0, 0x02, *fid ] response = data(@slot, HOST, select_file) response.successful? end |
#write(data, address = 0) ⇒ Object
Attempts to write the string data to the card starting at address. On success returns a true value.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/ctapi.rb', line 216 def write(data, address = 0) size = data.size if @card and address + size > @card.memory_size size = @card.memory_size - address end return if size <= 0 offset = 0 caught = catch(:break) do while size >= chunk_size write_chunk(address, data[offset, chunk_size]) or break :break address += chunk_size offset += chunk_size size -= chunk_size end end if caught == :break return false elsif size > 0 write_chunk(address, data[offset, size]) end true end |