Class Smartcard::Iso::PcscTransport
In: lib/smartcard/iso/pcsc_transport.rb
Parent: Object

Implements the transport layer for a smartcard connected to a PC/SC reader.

Methods

card_atr   connect   disconnect   exchange_apdu   new   to_s  

Included Modules

IsoCardMixin

Constants

PCSC = Smartcard::PCSC

Public Class methods

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 18
18:   def initialize(options)
19:     @options = options
20:     @context = nil
21:     @card = nil    
22:     @atr = nil
23:   end

Public Instance methods

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 31
31:   def card_atr
32:     @atr
33:   end

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 35
35:   def connect
36:     @context = PCSC::Context.new(PCSC::SCOPE_SYSTEM) if @context.nil?
37:     
38:     if @options[:reader_name]
39:       @reader_name = @options[:reader_name]
40:     else
41:       # get the first reader      

42:       readers = @context.list_readers nil
43:       @reader_name = readers[@options[:reader_index] || 0]
44:     end
45:     
46:     # get the reader's status

47:     reader_states = PCSC::ReaderStates.new(1)
48:     reader_states.set_reader_name_of!(0, @reader_name)
49:     reader_states.set_current_state_of!(0, PCSC::STATE_UNKNOWN)
50:     @context.get_status_change reader_states, 100
51:     reader_states.acknowledge_events!
52:     
53:     # prompt for card insertion unless that already happened

54:     if (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0
55:       puts "Please insert TEM card in reader #{@reader_name}\n"
56:       while (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0 do
57:         @context.get_status_change reader_states, PCSC::INFINITE_TIMEOUT
58:         reader_states.acknowledge_events!
59:       end
60:       puts "Card detected\n"
61:     end
62:     
63:     # connect to card

64:     @card = PCSC::Card.new @context, @reader_name, PCSC::SHARE_EXCLUSIVE,
65:                            PCSC::PROTOCOL_ANY
66:     
67:     # build the transmit / receive IoRequests

68:     status = @card.status
69:     @xmit_ioreq = @@xmit_iorequest[status[:protocol]]
70:     @atr = status[:atr]
71:     if RUBY_PLATFORM =~ /win/ and (not RUBY_PLATFORM =~ /darwin/)
72:       @recv_ioreq = nil
73:     else
74:       @recv_ioreq = PCSC::IoRequest.new
75:     end
76:   end
77:   
78:   def disconnect
79:     unless @card.nil?
80:       @card.disconnect PCSC::DISPOSITION_LEAVE
81:       @card = nil
82:       @atr = nil
83:     end
84:     unless @context.nil?
85:       @context.release
86:       @context = nil
87:     end
88:   end  
89: 
90:   def to_s
91:     "#<PC/SC Terminal: disconnected>" if @card.nil?
92:     "#<PC/SC Terminal: #{@reader_name}>"
93:   end
94:   
95:   @@xmit_iorequest = {
96:     Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0,
97:     Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1,
98:   }
99: end

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 78
78:   def disconnect
79:     unless @card.nil?
80:       @card.disconnect PCSC::DISPOSITION_LEAVE
81:       @card = nil
82:       @atr = nil
83:     end
84:     unless @context.nil?
85:       @context.release
86:       @context = nil
87:     end
88:   end

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 25
25:   def exchange_apdu(apdu)
26:     xmit_apdu_string = apdu.pack('C*')
27:     result_string = @card.transmit xmit_apdu_string, @xmit_ioreq, @recv_ioreq
28:     return result_string.unpack('C*')
29:   end

[Source]

    # File lib/smartcard/iso/pcsc_transport.rb, line 90
90:   def to_s
91:     "#<PC/SC Terminal: disconnected>" if @card.nil?
92:     "#<PC/SC Terminal: #{@reader_name}>"
93:   end

[Validate]