Ruby extension for the UNIX PC/SC Lite API (MUSCLE)
---------------------------------------------------
Author: Toni Andjelkovic <toni@soth.at>
Id:     $Id: README.txt,v 1.16 2004/02/22 02:33:52 toni Exp $

Prerequisites
-------------
You need to download and install the PC/SC-Lite library for UNIX,
found on http://pcsclite.alioth.debian.org/. This module has been
tested with PCSC/Lite 1.1.2beta5.

Installing the module
---------------------
Extract the module tarball

    gzip -dc PCSC-ruby-x.x.tar.gz | tar -xf -

and go to the distribution directory:

    ruby extconf.rb --with-pcsclite-dir=/usr/local

The "extconf.rb" invocation expects the pcsc-lite
includes in "/usr/local/include" and the libraries in
"/usr/local/lib". Then,

    make install

After installing the module you might want to
run a test program to get acquainted and check
that everything works:

    ruby examples/pcsclient.rb

Also have a look at "examples/test.rb", it
uses most API functions.

Synopsis
--------
    require "PCSC"
    include PCSC

    ctx = Context.new(SCARD_SCOPE_SYSTEM)
    puts "Readers: %s" % ctx.ListReaders.inspect

    state = ReaderState.new
    state.Reader = ctx.ListReaders[0]
    state.CurrentState = SCARD_STATE_EMPTY
    puts "waiting for card insertion ..."
    ctx.GetStatusChange(INFINITE, [ state ])

    handle = Handle.new
    proto = handle.Connect(ctx, ctx.ListReaders[0],
        SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0)
    handle.SetTimeout(20)
    handle.BeginTransaction
    # send the card's transport key (Cryptoflex 8K)
    result = handle.Transmit(SCARD_PCI_T0,
        "\xF0\x2A\x00\x01\x08\x2C\x15\xE5\x26\xE9\x3E\x8A\x19")
    puts "Result: %s" % hexify(result[0])
    puts "Result IORequest.Protocol: %u" % result[1].Protocol
    handle.EndTransaction(SCARD_LEAVE_CARD)
    handle.Disconnect(SCARD_RESET_CARD)
    ctx.ReleaseContext


Constants
---------
This module exports all constants found in pcsclite.h. Here's an example:

    require "PCSC"
    include PCSC
    puts "Constant SCARD_EJECT_CARD is %d\n" % SCARD_EJECT_CARD
    puts "And this is SCARD_SCOPE_GLOBAL: %d\n" % PCSC::SCARD_SCOPE_GLOBAL

The constants will be automatically loaded into your namespace when
you include the PCSC module. Occasionally you might want to use
"fully-qualified" constant identifiers, like PCSC::SCARD_SCOPE_GLOBAL.

Special constants like SCARD_PCI_T0 or SCARD_PCI_T1 (which
are pointers to a C struct) will be returned as PCSC::IORequest
objects.

There is a special constant PCSC::PCSC_RUBY_VERSION which
surprisingly contains the version number of this module as
a String.


Errors
------
All relevant methods check the return code for SCARD_S_SUCCESS
and raise an exception if something goes wrong.

On success, many methods return the object itself, so you might
do this:

    PCSC::Handle.new.Connect(...).Disconnect.Reconnect(...).Disconnect


------------------------------------------------------------------------
Module functions
------------------------------------------------------------------------


    hexify(string)

        Arguments:
            string          a String

        Description:
            Returns a hexadecimal representation of a String,
            "aa" becomes "4141" and "foo" becomes "666F6F".
            Mainly useful for printing ATRs and card responses.

        Return Value:
            A String containing the hex representation of the argument.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


------------------------------------------------------------------------
Classes
------------------------------------------------------------------------


PCSC::Context
-------------

This is a wrapper class for the SCARDCONTEXT structure.

Class methods:


    new(dwScope, <pvreserved2>, <pvreserved2>)

        Arguments:
            dwScope         a Fixnum/Bignum constant
            pvreserved1     Optional, currently not used
            pvreserved2     Optional, currently not used

        Description:
            This is the constructor for PCSC::Context objects. It takes
            1 - 3 arguments, although currently only the first one is
            actually used. new() allocates the PCSC::Context object and calls
            SCardEstablishContext(scope) immediately.

            The argument "dwScope" is a constant that will be passed to
            SCardEstablishContext(), e. g. SCARD_SCOPE_USER,
            SCARD_SCOPE_TERMINAL or SCARD_SCOPE_SYSTEM.

        Return Value:
            An instance of the PCSC::Context class.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    EstablishContext($scope, [$pvreserved1], [$pvreserved1])

        Arguments:
            see new()

        Description:
            There is no reason to call this method directly, as
            it will be called by the constructor (Context.new(...))


Instance methods:


    ListReaders()

        Arguments:
            none

        Description:
            This method returns the names of all readers.
            It is a wrapper for SCardListReaders().

        Return Value:
            An array of reader Strings.

        Throws:
            rb_eRuntimeError    (other error)


    ListReaderGroups()

        Arguments:
            none

        Description:
            This method returns the names of all readers.
            It is a wrapper for SCardListReaderGroups().

        Return Value:
            A group String.

        Throws:
            rb_eRuntimeError    (other error)


    ReleaseContext()

        Arguments:
            none

        Description:
            Releases the PC/SC context.
            This is a wrapper for SCardReleaseContext().

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eRuntimeError    (other error)


    GetStatusChange(dwTimeout, rgReaderStates)

        Arguments:
            dwTimeout               a Bignum value
            rgReaderStates          an Array of PCSC::ReaderState objects

        Description:
            This method blocks waiting for a change of the reader
            state. It is a wrapper for SCardGetStatusChange().

            dwTimeout is the timeout value that will be passed to
            usleep(). Use the constant INFINITE to block forever.

            rgReaderStates is an Array of pre-allocated PCSC::ReaderState
            objects. Please see the class documentation of PCSC::ReaderState
            for available methods.

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    SetTimeout(dwTimeout)

        Arguments:
            dwTimeout               a Fixnum/Bignum value

        Description:
            This method sets the timeout for a PC/SC context.
            It is a wrapper for SCardSetTimeout().

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    Cancel()

        Arguments:
            none

        Description:
            Cancel all pending blocking requests on the
            GetStatusChange method.
            This is a wrapper for SCardCancel().

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eRuntimeError    (other error)


    Unload()

        Arguments:
            none
        Description:
            This function is not documented.
            This is a wrapper for SCardUnload().

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eRuntimeError    (other error)



------------------------------------------------------------------------


PCSC::Handle
------------

This is a wrapper class for the SCARDHANDLE structure.

Class methods:


    new()

        Arguments:
            none

        Description:
            This is the constructor for PCSC::Handle objects.

        Return Value:
            An instance of the PCSC::Handle class.

        Throws:
            none


Instance methods:


    Connect(PCSC::Context, szReader, dwShareMode, dwPreferredProtocols)

        Arguments:
            PCSC::Context           a PCSC::Context object
            szReader                a String containing the reader name
            dwShareMode             a Fixnum/Bignum constant
            dwPreferredProtocols    a Fixnum/Bignum constant

        Description:
            Connects a Handle through a PCSC::Context object.
            This is a wrapper for SCardConnect().

            dwShareMode is one of SCARD_SHARE_SHARED of
            SCARD_SHARE_EXCLUSIVE.

            dwPreferredProtocols is one of SCARD_PROTOCOL_T0,
            SCARD_PROTOCOL_T1 or SCARD_PROTOCOL_RAW.

        Return Value:
            The protocol number used in the connection.
            This is either SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1
            or SCARD_PROTOCOL_RAW, just like in SCardConnect().

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    Reconnect(dwShareMode, dwPreferredProtocols, dwInitialization)

        Arguments:
            dwShareMode             a Fixnum/Bignum constant
            dwPreferredProtocols    a Fixnum/Bignum constant
            dwInitialization        a Fixnum/Bignum constant

        Description:
            Reconnects a Handle.
            This is a wrapper for SCardReconnect().

            dwShareMode is one of SCARD_SHARE_SHARED of
            SCARD_SHARE_EXCLUSIVE.

            dwPreferredProtocols is one of SCARD_PROTOCOL_T0,
            SCARD_PROTOCOL_T1 or SCARD_PROTOCOL_RAW.

            dwInitialization is one of SCARD_LEAVE_CARD,
            SCARD_RESET_CARD, SCARD_UNPOWER_CARD or
            SCARD_EJECT_CARD.

        Return Value:
            The protocol number used in the connection.
            This is either SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1
            or SCARD_PROTOCOL_RAW, just like in SCardReconnect().

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    Disconnect(dwDisposition)

        Arguments:
            dwDisposition           a Fixnum/Bignum constant

        Description:
            Disconnects a PCSC::Handle.
            This is a wrapper for SCardDisconnect().

            dwDisposition is one of SCARD_LEAVE_CARD,
            SCARD_RESET_CARD, SCARD_UNPOWER_CARD,
            SCARD_EJECT_CARD.

        Return Value:
            The object (PCSC::Handle) itself.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    BeginTransaction()

        Arguments:
            none

        Description:
            Start a series of commands or transaction.
            This is a wrapper for SCardBeginTransaction().

        Return Value:
            The object (PCSC::Handle) itself.

        Throws:
            rb_eRuntimeError    (other error)


    EndTransaction(dwDisposition)

        Arguments:
            dwDisposition           a Fixnum/Bignum constant

        Description:
            Ends a series of commands or transaction.
            This is a wrapper for SCardEndTransaction().

            dwDisposition is one of SCARD_LEAVE_CARD,
            SCARD_RESET_CARD, SCARD_UNPOWER_CARD,
            SCARD_EJECT_CARD.

        Return Value:
            The object (PCSC::Handle) itself.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    Cancel()

        Arguments:
            none

        Description:
            Cancel a pending transaction.
            This is a wrapper for SCardCancelTransaction().

        Return Value:
            The object (PCSC::Context) itself.

        Throws:
            rb_eRuntimeError    (other error)


    Control(pbSendBuffer)

        Arguments:
            pbSendBuffer            a String

        Description:
            Sends a command directly to the IFD Handler to
            be processed by the reader.
            This is a wrapper for SCardControl().

        Return Value:
            A String containing the response.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    SetTimeout(dwTimeout)

        Arguments:
            dwTimeout               a Fixnum/Bignum

        Description:
            This is a wrapper for SCardSetTimeout().

        Return Value:
            The object (PCSC::Handle) itself.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


    Status()

        Arguments:
            none

        Description:
            Returns the current status of the reader
            connected to by the PCSC::Handle.
            This is a wrapper for SCardStatus().

        Return Value:
            An Array:
            [ pdwState, szReaderName, pdwProtocol, pbAtr ]

            pdwState is possibly OR'd of with the constants
            SCARD_ABSENT, SCARD_PRESENT, SCARD_SWALLOWED,
            SCARD_POWERED, SCARD_NEGOTIABLEMODE,
            SCARD_SPECIFICMODE.

            szReaderName is a String containing the reader
            name.

            pdwProtocol is one of SCARD_PROTOCOL_T0,
            SCARD_PROTOCOL_T1.

            pbAtr is a String containing the current ATR
            of a card in this reader.

        Throws:
            rb_eRuntimeError    (other error)


    Transmit(PCSC::IORequest, pbSendBuffer)

        Arguments:
            PCSC::IORequest         a PCSC::IORequest object
            pbSendBuffer            a String containing the send buffer

        Description:
            Sends an APDU to the smartcard.
            This is a wrapper for SCardTransmit().

            PCSC::IORequest is one of SCARD_PCI_T0, SCARD_PCI_T1
            or SCARD_PCI_RAW. These constants are singleton
            objects representing the corresponding SCARD_IO_REQUEST
            constants. Please see the PCSC::IORequest class documentation
            for a description of available methods.

        Return Value:
            An Array:
            [ pbRecvBuffer, pioRecvPci ]

            pbRecvBuffer is a String containing the
            card response.

            pioRecvPci is an instance of PCSC::IORequest
            representing the protocol information. Please
            consult the PCSC::IORequest class documentation.

        Throws:
            rb_eTypeError       (wrong type of argument)
            rb_eArgError        (wrong number of arguments)
            rb_eRuntimeError    (other error)


------------------------------------------------------------------------


PCSC::IORequest
---------------

This is a wrapper class for the SCARD_IO_REQUEST structure.

Class methods:


    new

        Arguments:
            none

        Description:
            This is the class constructor.
            You will probably not use this method in your code.

        Return Value:
            An shrink-wrapped, allocated PCSC::IORequest object.

        Throws:
            none


Accessor methods:


    Protocol

        Arguments:
            None, but you may assign a value with "Protocol ="

        Description:
            Get/Set the dwProtocol member of a SCARD_IO_REQUEST.

        Return Value:
            The Fixnum/Bignum value of dwProtocol.

        Throws:
            rb_eTypeError       (wrong type of argument)


    Length

        Arguments:
            None, but you may assign a value with "Length ="

        Description:
            Get/Set the cbPciLength member of a SCARD_IO_REQUEST.

        Return Value:
            The Fixnum/Bignum value of cbPciLength.

        Throws:
            rb_eTypeError       (wrong type of argument)


------------------------------------------------------------------------


PCSC::ReaderState
-----------------

This is a wrapper class for the SCARD_READERSTATE structure.

Class methods:


    new

        Arguments:
            none

        Description:
            This is the class constructor.
            You will probably not use this method in your code.

        Return Value:
            An shrink-wrapped, allocated PCSC::ReaderState object.

        Throws:
            none


Accessor methods:


    Reader

        Arguments:
            None, but you may assign a value with "Reader ="

        Description:
            Get/Set the szReader member of a SCARD_READERSTATE.

        Return Value:
            The String value of szReader.

        Throws:
            rb_eTypeError       (wrong type of argument)


    UserData

        Arguments:
            None, but you may assign a value with "UserData ="

        Description:
            Get/Set the pvUserData member of a SCARD_READERSTATE.

        Return Value:
            The String value of pvUserData.

        Throws:
            rb_eTypeError       (wrong type of argument)


    CurrentState

        Arguments:
            None, but you may assign a value with "CurrentState ="

        Description:
            Get/Set the dwCurrentState member of a SCARD_READERSTATE.

        Return Value:
            The Bignum value of dwCurrentState.

        Throws:
            rb_eTypeError       (wrong type of argument)


    EventState

        Arguments:
            None, but you may assign a value with "EventState ="

        Description:
            Get/Set the dwEventState member of a SCARD_READERSTATE.

        Return Value:
            The Bignum value of dwEventState.

        Throws:
            rb_eTypeError       (wrong type of argument)


    cbAtr

        Arguments:
            None, but you may assign a value with "cbAtr ="

        Description:
            Get/Set the cbAtr member of a SCARD_READERSTATE.

        Return Value:
            The Bignum value of cbAtr.

        Throws:
            rb_eTypeError       (wrong type of argument)


    rgbAtr

        Arguments:
            None, but you may assign a value with "rgbAtr ="

        Description:
            Get/Set the rgbAtr member of a SCARD_READERSTATE.

        Return Value:
            The Bignum value of rgbAtr.

        Throws:
            rb_eTypeError       (wrong type of argument)


------------------------------------------------------------------------


PCSC
----

This represents the PCSC module namespace.

All constants from pcsclite.h are exported, their type is converted
to a suitable Ruby type, either String or Fixnum.

SCARD_PCI_T0, SCARD_PCI_T1 and SCARD_PCI_RAW are exported as
instances of the PCSC::IORequest class.


------------------------------------------------------------------------


Copyright
---------
Copyright (c) 2001 - 2004 Toni Andjelkovic <toni@soth.at>. All rights reserved.

License
-------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
