Class: Smartcard::PCSC::Context
- Inherits:
-
Object
- Object
- Smartcard::PCSC::Context
- Defined in:
- lib/smartcard/pcsc/context.rb
Overview
Connects Ruby to the PC/SC resource manager.
Instance Attribute Summary collapse
-
#_handle ⇒ Object
readonly
The low-level SCARDCONTEXT data.
Class Method Summary collapse
-
.decode_multi_string(strings_ptr) ⇒ Object
Turns a multi-string (concatenated C strings) into an array of Ruby strings.
Instance Method Summary collapse
-
#card(reader_name, sharing_mode = :exclusive, preferred_protocols = :any) ⇒ Object
Establishes a connection to the card in a PC/SC reader.
-
#initialize(scope = :system) ⇒ Context
constructor
Creates an application context connecting to the PC/SC resource manager.
-
#reader_groups ⇒ Object
An array containing the currently available reader groups on the system.
-
#readers(groups = []) ⇒ Object
An array containing the currently available readers in the system.
-
#release ⇒ Object
Releases this PC/SC context.
-
#valid? ⇒ Boolean
Returns
true
if this PC/SC context is still valid, andfalse
otherwise. -
#wait_for_status_change(queries, timeout = FFILib::Consts::INFINITE) ⇒ Object
Queries smart-card readers, blocking until a state change occurs.
Constructor Details
#initialize(scope = :system) ⇒ Context
Creates an application context connecting to the PC/SC resource manager.
A context is required to access every piece of PC/SC functionality.
Args:
scope:: the scope of the smart-card connection; valid values are :system,
:user, and :terminal (see the SCARD_SCOPE_ constants in the PC/SC
API)
21 22 23 24 25 26 27 |
# File 'lib/smartcard/pcsc/context.rb', line 21 def initialize(scope = :system) handle_ptr = FFILib::WordPtr.new status = FFILib.establish_context scope, nil, nil, handle_ptr raise Smartcard::PCSC::Exception, status unless status == :success @_handle = handle_ptr[:value] end |
Instance Attribute Details
#_handle ⇒ Object (readonly)
The low-level SCARDCONTEXT data.
This should not be used by client code.
157 158 159 |
# File 'lib/smartcard/pcsc/context.rb', line 157 def _handle @_handle end |
Class Method Details
.decode_multi_string(strings_ptr) ⇒ Object
Turns a multi-string (concatenated C strings) into an array of Ruby strings.
Args:
strings_ptr:: FFI::Pointer to the buffer containing the multi-string
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/smartcard/pcsc/context.rb', line 139 def self.decode_multi_string(strings_ptr) strings_bytes = strings_ptr.get_bytes 0, strings_ptr.size strings, next_string = [], '' strings_bytes.each_byte do |byte| if byte.ord == 0 break if next_string == '' strings << next_string next_string = '' else next_string << byte end end strings end |
Instance Method Details
#card(reader_name, sharing_mode = :exclusive, preferred_protocols = :any) ⇒ Object
Establishes a connection to the card in a PC/SC reader.
The first connection will power up the card and perform a reset on it.
Args:
context:: the Smartcard::PCSC::Context for the PC/SC resource manager
reader_name:: friendly name of the reader to connect to; reader names can
be obtained from Smartcard::PCSC::Context#readers
sharing_mode:: whether a shared or exclusive lock will be requested on the
reader; the possible values are +:shared+, +:exclusive+ and
+:direct+ (see the SCARD_SHARE_ constants in the PC/SC API)
preferred_protocols:: the desired communication protocol; the possible
values are +:t0+, +:t1+, +:t15+, +:raw+, and +:any+
(see the SCARD_PROTOCOL_ constants in the PC/SC API)
131 132 133 |
# File 'lib/smartcard/pcsc/context.rb', line 131 def card(reader_name, sharing_mode = :exclusive, preferred_protocols = :any) Card.new self, reader_name, sharing_mode, preferred_protocols end |
#reader_groups ⇒ Object
An array containing the currently available reader groups on the system.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/smartcard/pcsc/context.rb', line 49 def reader_groups # Get the length of the readers concatenated string. length_ptr = FFILib::WordPtr.new status = FFILib.list_reader_groups @_handle, nil, length_ptr raise Smartcard::PCSC::Exception, status unless status == :success # Get the readers concatenated string. combined_length = length_ptr[:value] groups_ptr = FFI::MemoryPointer.new :char, combined_length begin status = FFILib.list_reader_groups @_handle, groups_ptr, length_ptr raise Smartcard::PCSC::Exception, status unless status == :success Context.decode_multi_string groups_ptr ensure groups_ptr.free end end |
#readers(groups = []) ⇒ Object
An array containing the currently available readers in the system.
Args:
groups:: restrict the readers array to the given groups
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/smartcard/pcsc/context.rb', line 72 def readers(groups = []) groups_string = groups.join("\0") + "\0\0" groups_ptr = FFI::MemoryPointer.from_string groups_string # Get the length of the readers concatenated string. length_ptr = FFILib::WordPtr.new begin status = FFILib.list_readers @_handle, groups_ptr, nil, length_ptr raise Smartcard::PCSC::Exception, status unless status == :success # Get the readers concatenated string. combined_length = length_ptr[:value] readers_ptr = FFI::MemoryPointer.new :char, combined_length begin status = FFILib.list_readers @_handle, groups_ptr, readers_ptr, length_ptr raise Smartcard::PCSC::Exception, status unless status == :success Context.decode_multi_string readers_ptr ensure readers_ptr.free end ensure groups_ptr.free end end |
#release ⇒ Object
Releases this PC/SC context.
Future calls to this context’s methods will raise errors.
Returns the now-released PC/SC context.
34 35 36 37 38 39 40 41 |
# File 'lib/smartcard/pcsc/context.rb', line 34 def release return unless @_handle status = FFILib.release_context @_handle raise Smartcard::PCSC::Exception, status unless status == :success @_handle = nil self end |
#valid? ⇒ Boolean
Returns true
if this PC/SC context is still valid, and false
otherwise.
44 45 46 |
# File 'lib/smartcard/pcsc/context.rb', line 44 def valid? FFILib.is_valid_context(@_handle) == :success end |
#wait_for_status_change(queries, timeout = FFILib::Consts::INFINITE) ⇒ Object
Queries smart-card readers, blocking until a state change occurs.
Args:
queries:: Smartcard::PCSC::ReaderStateQueries instance
timeout:: maximum ammount of time (in milliseconds) to block; the default
value blocks forever
The method blocks until the state of one of the queried readers becomes different from the query’s current_state. The new state is stored in the query’s event_state.
109 110 111 112 113 114 115 |
# File 'lib/smartcard/pcsc/context.rb', line 109 def wait_for_status_change(queries, timeout = FFILib::Consts::INFINITE) status = FFILib.get_status_change @_handle, timeout, queries._buffer, queries.length raise Smartcard::PCSC::Exception, status unless status == :success queries end |