/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.57 from the
 * contents of PCSC.xs. Do not edit this file, edit PCSC.xs instead.
 *
 *    ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "PCSC.xs"
/**************************************************************************
 *    Authors     : Lionel VICTOR <lionel.victor@unforgettable.com>
 *                                <lionel.victor@free.fr>
 *                  Ludovic ROUSSEAU <ludovic.rousseau@free.fr>
 *    Compiler    : gcc, Visual C++
 *    Target      : Unix, Windows
 *
 *    Description : Perl wrapper to the PCSC API
 *    
 *    Copyright (C) 2001 - Lionel VICTOR
 *    Copyright (c) 2003-2015 Ludovic ROUSSEAU
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *    02111-1307 USA
 *
 **************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include "PCSCperl.h"

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"


/* The following hack helps importing variables from the PCSC library.
 * Those variables are dynamically imported...
 * TODO: see how we can use them anyway...
 */
#ifdef SCARD_PCI_T0
#  undef SCARD_PCI_T0
#  define SCARD_PCI_T0 (gpioSCardT0Pci)
#endif

#ifdef SCARD_PCI_T1
#  undef SCARD_PCI_T1
#  define SCARD_PCI_T1 (gpioSCardT1Pci)
#endif

#ifdef SCARD_PCI_RAW
#  undef SCARD_PCI_RAW
#  define SCARD_PCI_RAW (gpioSCardRawPci)
#endif

#ifdef __cplusplus
}
#endif

/* InitErrorCodes () initializes and creates a few variables describing
 * important values like error codes and constants. Those values are set
 * read-only so the user won't be able to eventually modify them.
 *  Those variables are set in the XS because their numerical value is
 *  platform dependent.
 */
void _InitErrorCodes () {
	SV * tmpSV;

	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_S_SUCCESS", TRUE);
	sv_setiv (tmpSV,      SCARD_S_SUCCESS); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_CANCELLED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_CANCELLED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_CANT_DISPOSE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_CANT_DISPOSE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INSUFFICIENT_BUFFER", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INSUFFICIENT_BUFFER); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INVALID_ATR", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INVALID_ATR); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INVALID_HANDLE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INVALID_HANDLE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INVALID_PARAMETER", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INVALID_PARAMETER); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INVALID_TARGET", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INVALID_TARGET); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_INVALID_VALUE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_INVALID_VALUE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_NO_MEMORY", TRUE);
	sv_setiv (tmpSV,      SCARD_E_NO_MEMORY); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_UNKNOWN_READER", TRUE);
	sv_setiv (tmpSV,      SCARD_E_UNKNOWN_READER); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_TIMEOUT", TRUE);
	sv_setiv (tmpSV,      SCARD_E_TIMEOUT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_SHARING_VIOLATION", TRUE);
	sv_setiv (tmpSV,      SCARD_E_SHARING_VIOLATION); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_NO_SMARTCARD", TRUE);
	sv_setiv (tmpSV,      SCARD_E_NO_SMARTCARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_UNKNOWN_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_E_UNKNOWN_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_PROTO_MISMATCH", TRUE);
	sv_setiv (tmpSV,      SCARD_E_PROTO_MISMATCH); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_NOT_READY", TRUE);
	sv_setiv (tmpSV,      SCARD_E_NOT_READY); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_SYSTEM_CANCELLED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_SYSTEM_CANCELLED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_NOT_TRANSACTED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_NOT_TRANSACTED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_READER_UNAVAILABLE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_READER_UNAVAILABLE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_PCI_TOO_SMALL", TRUE);
	sv_setiv (tmpSV,      SCARD_E_PCI_TOO_SMALL); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_READER_UNSUPPORTED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_READER_UNSUPPORTED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_DUPLICATE_READER", TRUE);
	sv_setiv (tmpSV,      SCARD_E_DUPLICATE_READER); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_CARD_UNSUPPORTED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_CARD_UNSUPPORTED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_NO_SERVICE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_NO_SERVICE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_SERVICE_STOPPED", TRUE);
	sv_setiv (tmpSV,      SCARD_E_SERVICE_STOPPED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_E_UNSUPPORTED_FEATURE", TRUE);
	sv_setiv (tmpSV,      SCARD_E_UNSUPPORTED_FEATURE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_UNSUPPORTED_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_W_UNSUPPORTED_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_UNRESPONSIVE_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_W_UNRESPONSIVE_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_UNPOWERED_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_W_UNPOWERED_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_RESET_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_W_RESET_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_SECURITY_VIOLATION", TRUE);
	sv_setiv (tmpSV,      SCARD_W_SECURITY_VIOLATION); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_W_REMOVED_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_W_REMOVED_CARD); SvREADONLY_on (tmpSV);

	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_F_COMM_ERROR", TRUE);
	sv_setiv (tmpSV,      SCARD_F_COMM_ERROR); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_F_INTERNAL_ERROR", TRUE);
	sv_setiv (tmpSV,      SCARD_F_INTERNAL_ERROR); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_F_UNKNOWN_ERROR", TRUE);
	sv_setiv (tmpSV,      SCARD_F_UNKNOWN_ERROR); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_F_WAITED_TOO_LONG", TRUE);
	sv_setiv (tmpSV,      SCARD_F_WAITED_TOO_LONG); SvREADONLY_on (tmpSV);

	/* PCSC - Perl wrapper specific error codes */
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_P_ALREADY_CONNECTED", TRUE);
	sv_setiv (tmpSV,      SCARD_P_ALREADY_CONNECTED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_P_NOT_CONNECTED", TRUE);
	sv_setiv (tmpSV,      SCARD_P_NOT_CONNECTED); SvREADONLY_on (tmpSV);

	/* PCSC standard constants */
	/*
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_CONVENTION_DIRECT", TRUE);
	sv_setiv (tmpSV,      SCARD_CONVENTION_DIRECT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_CONVENTION_INVERSE", TRUE);
	sv_setiv (tmpSV,      SCARD_CONVENTION_INVERSE); SvREADONLY_on (tmpSV);
	*/
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SCOPE_USER", TRUE);
	sv_setiv (tmpSV,      SCARD_SCOPE_USER); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SCOPE_TERMINAL", TRUE);
	sv_setiv (tmpSV,      SCARD_SCOPE_TERMINAL); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SCOPE_SYSTEM", TRUE);
	sv_setiv (tmpSV,      SCARD_SCOPE_SYSTEM); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_PROTOCOL_T0", TRUE);
	sv_setiv (tmpSV,      SCARD_PROTOCOL_T0); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_PROTOCOL_T1", TRUE);
	sv_setiv (tmpSV,      SCARD_PROTOCOL_T1); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_PROTOCOL_RAW", TRUE);
	sv_setiv (tmpSV,      SCARD_PROTOCOL_RAW); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SHARE_EXCLUSIVE", TRUE);
	sv_setiv (tmpSV,      SCARD_SHARE_EXCLUSIVE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SHARE_SHARED", TRUE);
	sv_setiv (tmpSV,      SCARD_SHARE_SHARED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SHARE_DIRECT", TRUE);
	sv_setiv (tmpSV,      SCARD_SHARE_DIRECT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_LEAVE_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_LEAVE_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_RESET_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_RESET_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_UNPOWER_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_UNPOWER_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_EJECT_CARD", TRUE);
	sv_setiv (tmpSV,      SCARD_EJECT_CARD); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_UNKNOWN", TRUE);
	sv_setiv (tmpSV,      SCARD_UNKNOWN); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_ABSENT", TRUE);
	sv_setiv (tmpSV,      SCARD_ABSENT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_PRESENT", TRUE);
	sv_setiv (tmpSV,      SCARD_PRESENT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SWALLOWED", TRUE);
	sv_setiv (tmpSV,      SCARD_SWALLOWED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_POWERED", TRUE);
	sv_setiv (tmpSV,      SCARD_POWERED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_NEGOTIABLE", TRUE);
	sv_setiv (tmpSV,      SCARD_NEGOTIABLE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_SPECIFIC", TRUE);
	sv_setiv (tmpSV,      SCARD_SPECIFIC); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_UNAWARE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_UNAWARE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_IGNORE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_IGNORE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_CHANGED", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_CHANGED); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_UNKNOWN", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_UNKNOWN); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_UNAVAILABLE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_UNAVAILABLE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_EMPTY", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_EMPTY); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_PRESENT", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_PRESENT); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_ATRMATCH", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_ATRMATCH); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_EXCLUSIVE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_EXCLUSIVE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_INUSE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_INUSE); SvREADONLY_on (tmpSV);
	tmpSV = perl_get_sv ("Chipcard::PCSC::SCARD_STATE_MUTE", TRUE);
	sv_setiv (tmpSV,      SCARD_STATE_MUTE); SvREADONLY_on (tmpSV);
}

/* _StringifyError is copied from pcsc_stringify_error() which is a
 * function taken from PCSClite
 * It has been modified because I added a few internal errors to the
 * wrapper (SCARD_P_NOT_CONNECTED for instance)
 * I also feel like using strong types like const char * const and
 * avoiding to use strcpy() is better from a security point of view.
 *
 * See file debuglog.c from your PCSClite distribution for extra
 * informations
 */
const char * _StringifyError (unsigned long Error) {
	switch ( (DWORD)Error ) {
	case SCARD_S_SUCCESS:             return "Command successful.";
	case SCARD_E_CANCELLED:           return "Command cancelled.";
	case SCARD_E_CANT_DISPOSE:        return "Cannot dispose handle.";
	case SCARD_E_CARD_UNSUPPORTED:    return "Card is unsupported.";
	case SCARD_E_DUPLICATE_READER:    return "Reader already exists.";
	case SCARD_E_INSUFFICIENT_BUFFER: return "Insufficient buffer.";
	case SCARD_E_INVALID_ATR:         return "Invalid ATR.";
	case SCARD_E_INVALID_HANDLE:      return "Invalid handle.";
	case SCARD_E_INVALID_PARAMETER:   return "Invalid parameter given.";
	case SCARD_E_INVALID_TARGET:      return "Invalid target given.";
	case SCARD_E_INVALID_VALUE:       return "Invalid value given.";
	case SCARD_E_NO_MEMORY:           return "Not enough memory.";
	case SCARD_E_NO_SERVICE:          return "Service not available.";
	case SCARD_E_NO_SMARTCARD:        return "No smartcard inserted.";
	case SCARD_E_NOT_READY:           return "Subsystem not ready.";
	case SCARD_E_NOT_TRANSACTED:      return "Transaction failed.";
	case SCARD_E_PCI_TOO_SMALL:       return "PCI struct too small.";
	case SCARD_E_PROTO_MISMATCH:      return "Card protocol mismatch.";
	case SCARD_E_READER_UNAVAILABLE:  return "Reader/s is unavailable.";
	case SCARD_E_READER_UNSUPPORTED:  return "Reader is unsupported.";
	case SCARD_E_SERVICE_STOPPED:     return "Service was stopped.";
	case SCARD_E_SHARING_VIOLATION:   return "Sharing violation.";
	case SCARD_E_SYSTEM_CANCELLED:    return "System cancelled.";
	case SCARD_E_TIMEOUT:             return "Command timeout.";
	case SCARD_E_UNKNOWN_CARD:        return "Unknown card.";
	case SCARD_E_UNKNOWN_READER:      return "Unknown reader specified.";
	case SCARD_E_UNSUPPORTED_FEATURE: return "Feature not supported.";
	case SCARD_F_COMM_ERROR:          return "RPC transport error.";
	case SCARD_F_INTERNAL_ERROR:      return "Unknown internal error.";
	case SCARD_F_UNKNOWN_ERROR:       return "Unknown internal error.";
	case SCARD_F_WAITED_TOO_LONG:     return "Waited too long.";
	case SCARD_W_REMOVED_CARD:        return "Card was removed.";
	case SCARD_W_RESET_CARD:          return "Card was reset.";
	case SCARD_W_SECURITY_VIOLATION:  return "Access denied.";
	case SCARD_W_UNPOWERED_CARD:      return "Card is unpowered.";
	case SCARD_W_UNRESPONSIVE_CARD:   return "Card is unresponsive.";
	case SCARD_W_UNSUPPORTED_CARD:    return "Card is not supported.";

	/* The following errors are specific to the Perl wrapper */
	case SCARD_P_ALREADY_CONNECTED:   return "Object is already connected";
	case SCARD_P_NOT_CONNECTED:       return "Object is not connected";

	/* We finally end with a generic error message */
	default: return "Unknown (reader specific ?) error...";
	};
}

/*************************************************************************/
/*************** Double Typed Magical variable PCSC::errno ***************/
/*************************************************************************/

/* This is an accessor to our internal double-typed magical variable */
I32 gnLastError_get (pTHX_ IV nID, SV *sv) {
	/* We have to set both int and double values */
	sv_setiv (sv, (IV)gnLastError);
	sv_setnv (sv, (double)gnLastError);

	/* Then we set the error message string */
	sv_setpv (sv, _StringifyError(gnLastError));

	/* Then, we eventually put corresponding bits of the SV flag */
	SvNOK_on (sv);
	SvIOK_on (sv);

	/* return value should be ignored (man samples use return 1) */
	return 1;
}

/* This is a modifier to our internal double-typed magical variable */
I32 gnLastError_set (pTHX_ IV nID, SV *sv) {
	/* just store the value in our global variable */
	gnLastError = SvIV (sv);

	/* return value should be ignored (man samples use return 1) */
	return 1;
}

/* Initialize the double-typed magical variable Chipcard::PCSC::errno */
void _InitMagic () {
	struct ufuncs uf_errno;
	SV    *sv;

	/* Build a new immortal scalar */
	sv = perl_get_sv ("Chipcard::PCSC::errno", TRUE);

	/* Construct the magic virtual table */
	uf_errno.uf_val = &gnLastError_get;
	uf_errno.uf_set = &gnLastError_set;
	uf_errno.uf_index = 0;

	/* Then apply magic to it (use uf_eerno as a callback list) */
	sv_magic (sv, 0, 'U', (char *)&uf_errno, sizeof(uf_errno));

	/* Let the scalar be enchanted ! */
	SvMAGICAL_on (sv);
}

#line 346 "PCSC.c"
#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#ifndef dVAR
#  define dVAR		dNOOP
#endif


/* This stuff is not part of the API! You have been warned. */
#ifndef PERL_VERSION_DECIMAL
#  define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#endif
#ifndef PERL_DECIMAL_VERSION
#  define PERL_DECIMAL_VERSION \
	  PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#endif
#ifndef PERL_VERSION_GE
#  define PERL_VERSION_GE(r,v,s) \
	  (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#endif
#ifndef PERL_VERSION_LE
#  define PERL_VERSION_LE(r,v,s) \
	  (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
#endif

/* XS_INTERNAL is the explicit static-linkage variant of the default
 * XS macro.
 *
 * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
 * "STATIC", ie. it exports XSUB symbols. You probably don't want that
 * for anything but the BOOT XSUB.
 *
 * See XSUB.h in core!
 */


/* TODO: This might be compatible further back than 5.10.0. */
#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
#  undef XS_EXTERNAL
#  undef XS_INTERNAL
#  if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
#    define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#    define XS_INTERNAL(name) STATIC XSPROTO(name)
#  endif
#  if defined(__SYMBIAN32__)
#    define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
#    define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
#  endif
#  ifndef XS_EXTERNAL
#    if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
#      define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
#      define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
#    else
#      ifdef __cplusplus
#        define XS_EXTERNAL(name) extern "C" XSPROTO(name)
#        define XS_INTERNAL(name) static XSPROTO(name)
#      else
#        define XS_EXTERNAL(name) XSPROTO(name)
#        define XS_INTERNAL(name) STATIC XSPROTO(name)
#      endif
#    endif
#  endif
#endif

/* perl >= 5.10.0 && perl <= 5.15.1 */


/* The XS_EXTERNAL macro is used for functions that must not be static
 * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
 * macro defined, the best we can do is assume XS is the same.
 * Dito for XS_INTERNAL.
 */
#ifndef XS_EXTERNAL
#  define XS_EXTERNAL(name) XS(name)
#endif
#ifndef XS_INTERNAL
#  define XS_INTERNAL(name) XS(name)
#endif

/* Now, finally, after all this mess, we want an ExtUtils::ParseXS
 * internal macro that we're free to redefine for varying linkage due
 * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
 * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
 */

#undef XS_EUPXS
#if defined(PERL_EUPXS_ALWAYS_EXPORT)
#  define XS_EUPXS(name) XS_EXTERNAL(name)
#else
   /* default to internal */
#  define XS_EUPXS(name) XS_INTERNAL(name)
#endif

#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)

/* prototype to pass -Wmissing-prototypes */
STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params)
{
    const GV *const gv = CvGV(cv);

    PERL_ARGS_ASSERT_CROAK_XS_USAGE;

    if (gv) {
        const char *const gvname = GvNAME(gv);
        const HV *const stash = GvSTASH(gv);
        const char *const hvname = stash ? HvNAME(stash) : NULL;

        if (hvname)
	    Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
        else
	    Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
	Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#define croak_xs_usage        S_croak_xs_usage

#endif

/* NOTE: the prototype of newXSproto() is different in versions of perls,
 * so we define a portable version of newXSproto()
 */
#ifdef newXS_flags
#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
#else
#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
#endif /* !defined(newXS_flags) */

#if PERL_VERSION_LE(5, 21, 5)
#  define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
#else
#  define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
#endif

/* simple backcompat versions of the TARGx() macros with no optimisation */
#ifndef TARGi
#  define TARGi(iv, do_taint) sv_setiv_mg(TARG, iv)
#  define TARGu(uv, do_taint) sv_setuv_mg(TARG, uv)
#  define TARGn(nv, do_taint) sv_setnv_mg(TARG, nv)
#endif

#line 497 "PCSC.c"

XS_EUPXS(XS_Chipcard__PCSC__LoadPCSCLibrary); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__LoadPCSCLibrary)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    {
	bool	RETVAL;
#line 344 "PCSC.xs"
	if (ghDll) {
		/* No need to load the library twice */
		RETVAL = TRUE;
	} else {
		/* Then loads the dynamic library */
		ghDll = LOAD_LIB();
		if (ghDll == NULL) {
			RETVAL = FALSE;
			croak ("Failed to load PCSC library");
		} else {
			hEstablishContext = (TSCardEstablishContext) GET_FCT (ghDll, "SCardEstablishContext");
			hReleaseContext   = (TSCardReleaseContext)   GET_FCT (ghDll, "SCardReleaseContext");
			hReconnect        = (TSCardReconnect)        GET_FCT (ghDll, "SCardReconnect");
			hDisconnect       = (TSCardDisconnect)       GET_FCT (ghDll, "SCardDisconnect");
			hBeginTransaction = (TSCardBeginTransaction) GET_FCT (ghDll, "SCardBeginTransaction");
			hEndTransaction   = (TSCardEndTransaction)   GET_FCT (ghDll, "SCardEndTransaction");
			hTransmit         = (TSCardTransmit)         GET_FCT (ghDll, "SCardTransmit");
			hControl          = (TSCardControl)          GET_FCT (ghDll, "SCardControl");
			hCancel           = (TSCardCancel)           GET_FCT (ghDll, "SCardCancel");
#ifdef WIN32
			hListReaders      = (TSCardListReaders)      GET_FCT (ghDll, "SCardListReadersA");
			hConnect          = (TSCardConnect)          GET_FCT (ghDll, "SCardConnectA");
			hStatus           = (TSCardStatus)           GET_FCT (ghDll, "SCardStatusA");
			hGetStatusChange  = (TSCardGetStatusChange)  GET_FCT (ghDll, "SCardGetStatusChangeA");
#else
			hListReaders      = (TSCardListReaders)      GET_FCT (ghDll, "SCardListReaders");
			hConnect          = (TSCardConnect)          GET_FCT (ghDll, "SCardConnect");
			hStatus           = (TSCardStatus)           GET_FCT (ghDll, "SCardStatus");
			hGetStatusChange  = (TSCardGetStatusChange)  GET_FCT (ghDll, "SCardGetStatusChange");
#endif
			if (
				!hEstablishContext || !hReleaseContext || !hListReaders || !hConnect ||
				!hReconnect || ! hDisconnect || !hBeginTransaction || !hEndTransaction ||
				!hTransmit || !hStatus || !hGetStatusChange || !hCancel || !hControl)
			{
				RETVAL = FALSE;
				croak ("PCSC library does not contain all the required symbols");
			} else {
				RETVAL = TRUE;
			}
		}
		/* Initialize the magical variable */
		_InitMagic ();
		_InitErrorCodes ();
	}
#line 553 "PCSC.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__EstablishContext); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__EstablishContext)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "dwScope, pvReserved1, pvReserved2");
    {
	unsigned long	dwScope = (unsigned long)SvUV(ST(0))
;
	void*	pvReserved1 = INT2PTR(void *,SvIV(ST(1)))
;
	void*	pvReserved2 = INT2PTR(void *,SvIV(ST(2)))
;
#line 411 "PCSC.xs"
		SCARDCONTEXT hContext = 0;
#line 575 "PCSC.c"
	SV *	RETVAL;
#line 413 "PCSC.xs"
		ST(0) = sv_newmortal();
		gnLastError = hEstablishContext (dwScope, pvReserved1, pvReserved2, &hContext);

		/* Then we either return an explicit 'UNDEF' value or the handle */
		if (gnLastError != SCARD_S_SUCCESS) {
			ST(0) = &PL_sv_undef;
		} else {
			sv_setiv (ST(0), hContext);
		}
#line 587 "PCSC.c"
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__ReleaseContext); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__ReleaseContext)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "hContext");
    {
	unsigned long	hContext = (unsigned long)SvUV(ST(0))
;
	bool	RETVAL;
#line 436 "PCSC.xs"
		gnLastError = hReleaseContext (hContext);

		/* Then returns true or false according to the return code */
		if (gnLastError != SCARD_S_SUCCESS) {
			RETVAL = FALSE;
		} else {
			RETVAL = TRUE;
		}
#line 612 "PCSC.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__ListReaders); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__ListReaders)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "hContext, svGroups");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	unsigned long	hContext = (unsigned long)SvUV(ST(0))
;
	SV*	svGroups = ST(1)
;
#line 465 "PCSC.xs"
		DWORD nBufferSize = 0;
		char* szBuffer = NULL;
		char* szCurrentToken = NULL;
		char* mszGroups;
#line 637 "PCSC.c"
	SV *	RETVAL;
#line 470 "PCSC.xs"
		/* Before doing anything, we check that we have a valid group. */
		if (SvPOK(svGroups)) {
			/* TODO : see how this works... multistring stuff with time
			 *svGroups may become a reference to an array of groups... or undef
			 */
			mszGroups = SvPV (svGroups, PL_na);
		} else {
			mszGroups = 0;
		}

		/*   The first call to SCardListReaders gives us the size of the
		 * buffer we must allocate for the list.
		 */
		gnLastError = hListReaders (hContext, mszGroups, 0, &nBufferSize);

		/* In case of any error we immediately return an explicit UNDEF value */
		if (gnLastError != SCARD_S_SUCCESS) {
			XSRETURN_UNDEF;
		}

		if (nBufferSize > 0) {
			/*   At this point, nBufferSize contains the size of the buffer to
		 	 * alloate. We use New as recomended by perlguts(3pm). The
		 	 * buffer will be freed with Safefree()...
		 	 */
			New (2018, szBuffer, nBufferSize, char);
			if (szBuffer == NULL) {
				gnLastError = SCARD_E_NO_MEMORY;
				warn ("Could not allocate buffer at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}

			/*   The buffer is ready, so we can now retrieve the whole list.  */
			gnLastError = hListReaders (hContext, mszGroups, szBuffer, &nBufferSize);

			/* Then check for any error */
			if (gnLastError != SCARD_S_SUCCESS) {
				Safefree (szBuffer);
				XSRETURN_UNDEF;
			}

			/*   The string must be NULL terminated
		 	 * May be just too much paranoid but...
		 	 */
			if (szBuffer[nBufferSize-1] != 0) {
				Safefree (szBuffer);
				gnLastError = SCARD_F_INTERNAL_ERROR;
				warn ("PCSC did not return a NULL terminated multistring at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}

			/*   Now we need to push each reader separately on the stack. If
		 	 * no readers are found, the stack is left empty...
		 	 */
			szCurrentToken = szBuffer;
			while (strlen(szCurrentToken)) {
				XPUSHs (sv_2mortal(newSVpv(szCurrentToken,0)));
				szCurrentToken = strchr (szCurrentToken, 0) + 1;
			}
			/* Free our buffer...
			 * DO NOT USE free() or delete() here ! Let Perl deal with this.
			 */
			Safefree (szBuffer);
		} else {
			gnLastError = SCARD_F_INTERNAL_ERROR;
			warn ("PCSC did not return a valid buffer length at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}
#line 711 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__Connect); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Connect)
{
    dVAR; dXSARGS;
    if (items != 4)
       croak_xs_usage(cv,  "hContext, szReader, dwShareMode, dwPreferredProtocols");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	unsigned long	hContext = (unsigned long)SvUV(ST(0))
;
	const char*	szReader = (const char *)SvPV_nolen(ST(1))
;
	unsigned long	dwShareMode = (unsigned long)SvUV(ST(2))
;
	unsigned long	dwPreferredProtocols = (unsigned long)SvUV(ST(3))
;
#line 562 "PCSC.xs"
		SCARDHANDLE hCard = 0;
		DWORD dwActiveProtocol = 0;
#line 738 "PCSC.c"
	SV *	RETVAL;
#line 565 "PCSC.xs"
		gnLastError = hConnect (hContext, szReader, dwShareMode, dwPreferredProtocols, &hCard, &dwActiveProtocol);

		/* We return immediately in case of an error */
		if (gnLastError != SCARD_S_SUCCESS)
			XSRETURN_UNDEF;

		/* If anything was successful, push the two scalar values */
		XPUSHs (sv_2mortal(newSViv(hCard)));
		XPUSHs (sv_2mortal(newSViv(dwActiveProtocol)));
#line 750 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__Reconnect); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Reconnect)
{
    dVAR; dXSARGS;
    if (items != 4)
       croak_xs_usage(cv,  "hCard, dwShareMode, dwPreferredProtocols, dwInitialization");
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwShareMode = (unsigned long)SvUV(ST(1))
;
	unsigned long	dwPreferredProtocols = (unsigned long)SvUV(ST(2))
;
	unsigned long	dwInitialization = (unsigned long)SvUV(ST(3))
;
#line 594 "PCSC.xs"
		DWORD dwActiveProtocol = 0;
#line 774 "PCSC.c"
	SV *	RETVAL;
#line 596 "PCSC.xs"
		ST(0) = sv_newmortal();
		gnLastError = hReconnect (hCard, dwShareMode, dwPreferredProtocols, dwInitialization, &dwActiveProtocol);
		/* Return either an UNDEF value if an error occurs or the current
		 * active protocol as returned by PCSC
		 */
		if (gnLastError == SCARD_S_SUCCESS)
			sv_setiv (ST(0), dwActiveProtocol);
		else
			ST(0) = &PL_sv_undef;
#line 786 "PCSC.c"
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__Disconnect); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Disconnect)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "hCard, dwDisposition");
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwDisposition = (unsigned long)SvUV(ST(1))
;
	bool	RETVAL;
#line 621 "PCSC.xs"
		gnLastError = hDisconnect (hCard, dwDisposition);

		/* Then check for an error */
		if (gnLastError != SCARD_S_SUCCESS)
			RETVAL = FALSE;
		else
			RETVAL = TRUE;
#line 812 "PCSC.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__Status); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Status)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "hCard");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	long	hCard = (long)SvIV(ST(0))
;
#line 655 "PCSC.xs"
		int            nCount = 0;
#ifdef WIN32
		char           tmpReaderName[200];
		char*          szReaderName = tmpReaderName;
		unsigned long  cchReaderLen = sizeof(tmpReaderName);
		char           tmpAtr[MAX_ATR_SIZE];
		unsigned char* pbAtr = tmpAtr;
		unsigned long  cbAtrLen = sizeof(tmpAtr);
#else
		char*          szReaderName = NULL;
		DWORD cchReaderLen = 0;
		unsigned char* pbAtr = NULL;
		DWORD cbAtrLen = 0;
#endif
		DWORD dwState = 0;
		DWORD dwProtocol = 0;
		AV*            aATR = 0;
#line 848 "PCSC.c"
	SV *	RETVAL;
#line 673 "PCSC.xs"
		/* We call the function with a null cchReaderLen : this should
		 * gives us the length of the buffer to allocate
		 */
		gnLastError = hStatus (hCard, szReaderName, &cchReaderLen,
		                       &dwState, &dwProtocol, (BYTE *)pbAtr, &cbAtrLen);

		/* Behaviour differs here from PCSC and PCSClite :
		 * PCSC returns SUCCESS while PCSClite returns an error
		 */
		if (gnLastError == SCARD_E_INSUFFICIENT_BUFFER || gnLastError == SCARD_S_SUCCESS) {
			/* The call was hopefuly successful, so we allocate the
			 * buffer for the ATR
			 */
#ifndef WIN32
			/* This hack should be temporary as PCSClite should eventually behave like PCSC */
			cbAtrLen = MAX_ATR_SIZE;
#endif
			if (cbAtrLen <= 0) {
				gnLastError = SCARD_F_INTERNAL_ERROR;
				warn ("PCSC did not return a valid buffer length at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}
			New (2018, pbAtr, cbAtrLen, unsigned char);
			if (pbAtr == NULL) {
				gnLastError = SCARD_E_NO_MEMORY;
				warn ("Could not allocate buffer at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}
			/* we then allocate the buffer for the reader name */
			if (cbAtrLen <= 0) {
				gnLastError = SCARD_F_INTERNAL_ERROR;
				warn ("PCSC did not return a valid buffer length at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}
			New (2018, szReaderName, cchReaderLen, char);
			if (szReaderName == NULL) {
				Safefree (pbAtr);
				gnLastError = SCARD_E_NO_MEMORY;
				warn ("Could not allocate buffer at %s line %d\n\t",
				      __FILE__, __LINE__);
				XSRETURN_UNDEF;
			}
			/* Now we perform the real call to SCardStatus */
			gnLastError = hStatus (hCard, szReaderName, &cchReaderLen,
			                       &dwState, &dwProtocol, (BYTE *)pbAtr, &cbAtrLen);
			if (gnLastError != SCARD_S_SUCCESS) {
				Safefree (szReaderName);
				Safefree (pbAtr);
				XSRETURN_UNDEF;
			}
		} else {
			/* As our first call should trigger the SCARD_E_INSUFFICIENT_BUFFER
			 * error or no error, we consider any other case as a failure...
			 */
			XSRETURN_UNDEF;
		}

		/* we fill this array with every byte from the ATR
		 * note that we do not make this data mortal because av_push()
		 * does not increment the reference count. See the note in the
		 * function header above
		 */
		if (cbAtrLen > 0) {
			/* We first create an array for the ATR */
			aATR = (AV*) sv_2mortal((SV*)newAV());

			/* Then we fill it with every byte from the ATR
			 * note that we do not make this data mortal because av_push()
			 * does not increment the reference count. See the note in the
			 * function header above
			 */
			for (nCount=0; nCount < cbAtrLen; nCount++) {
				av_push (aATR, newSViv(pbAtr[nCount]));
			}
		}
		/* In the event that no ATR is available, we used to fill aATR
		 * with '(AV*) &PL_sv_undef' However, pushing a reference to
		 * this seems is hard to handle I therefore prefer to do
		 * nothing and leave aATR with the default null value and
		 * the code below will not push the reference to the ATR array
		 */

		/* eventually, we end up pushing all the values */
		XPUSHs (sv_2mortal(newSVpv(szReaderName,0)));
		XPUSHs (sv_2mortal(newSViv(dwState)));
		XPUSHs (sv_2mortal(newSViv(dwProtocol)));
		/* as well as a reference to the ATR array if available */
		if (aATR) {
			XPUSHs (sv_2mortal(newRV((SV*)aATR)));
		}

		/* As a conclusion, we just free what we took */
		Safefree (szReaderName);
		Safefree (pbAtr);
#line 948 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__Transmit); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Transmit)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "hCard, dwProtocol, psvSendData");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwProtocol = (unsigned long)SvUV(ST(1))
;
	SV*	psvSendData = ST(2)
;
#line 795 "PCSC.xs"
		int                        nCount = 0;
		static char*               pbSendBuffer = NULL;
		static unsigned char       pbRecvBuffer [MAX_BUFFER_SIZE_EXTENDED];
		unsigned long              cbSendLength = 0;
		DWORD                      cbRecvLength = sizeof (pbRecvBuffer);
		SCARD_IO_REQUEST           ioSendPci, ioRecvPci;
		AV*                        aRecvBuffer = NULL;
#line 978 "PCSC.c"
	SV *	RETVAL;
#line 803 "PCSC.xs"
		/* We make sure that the array is sane */
		if (psvSendData == NULL) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvSendData is a NULL pointer at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		/* Should the second parameter not be a reference, we return the
		 * SCARD_E_INVALID_PARAMETER error code.
		 */
		if ((!SvROK(psvSendData))||(SvTYPE(SvRV(psvSendData)) != SVt_PVAV)) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvSendData is not a RVAV at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}
		/* We have to build up our IO_REQUEST structures according to
		 * $dwProtocol
		 */
		switch (dwProtocol) {
		case SCARD_PROTOCOL_T0:
		case SCARD_PROTOCOL_T1:
		case SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1:
		case SCARD_PROTOCOL_RAW:
			ioSendPci.dwProtocol  = dwProtocol;
			ioSendPci.cbPciLength = sizeof(ioSendPci);
			ioRecvPci.dwProtocol  = dwProtocol;
			ioRecvPci.cbPciLength = sizeof(ioRecvPci);
			break;
		default:
			/* If $dwProtocol holds an invalid value, we exist reporting
			 * the error SCARD_E_INVALID_VALUE.
			 */
			gnLastError = SCARD_E_INVALID_VALUE;
			warn ("unknown protocol %ld given at %s line %d\n\t",
			      dwProtocol, __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		/* Let's allocate some space for the send buffer */
		cbSendLength = av_len((AV*)SvRV(psvSendData)) + 1;
		if (cbSendLength <= 0) {
			gnLastError = SCARD_E_INVALID_VALUE;
			warn ("empty array given at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}
 		New (2018, pbSendBuffer, cbSendLength, char);
		if (pbSendBuffer == NULL) {
			gnLastError = SCARD_E_NO_MEMORY;
			warn ("Could not allocate buffer at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		/* We have to extract data from the array referenced by psvSendData */
		for (nCount = 0; nCount < cbSendLength ; nCount++)
			pbSendBuffer[nCount] = (char)SvIV(*av_fetch((AV*)SvRV(psvSendData), nCount, 0));

		/* Everything is ready : call the real function... */
		gnLastError = hTransmit (hCard, &ioSendPci, (BYTE *)pbSendBuffer, cbSendLength, &ioRecvPci, pbRecvBuffer, &cbRecvLength);
		if (gnLastError != SCARD_S_SUCCESS) {
			/* Free the buffer if something went wrong */
			Safefree (pbSendBuffer);
			XSRETURN_UNDEF;
		}

		/* At this point, the command was successful. We still need to
		 * return all the values from our buffer...
		 * so we build an array for the ATR
		 */
		aRecvBuffer = (AV*) sv_2mortal((SV*)newAV());

		/* we fill this array with every byte from the Response
		 * note that we do not make this data mortal because av_push()
		 * does not increment the reference count. See the note in the
		 * function header above
		 */
		for (nCount = 0; nCount < cbRecvLength; nCount++)
 			av_push (aRecvBuffer, newSViv(pbRecvBuffer[nCount]));

		XPUSHs (sv_2mortal(newSViv(ioRecvPci.dwProtocol)));
		XPUSHs (sv_2mortal(newRV((SV*)aRecvBuffer)));

		/* Do not forget to free the dynamically allocated buffer */
		Safefree (pbSendBuffer);
#line 1068 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__Control); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Control)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "hCard, dwControlCode, psvSendData");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwControlCode = (unsigned long)SvUV(ST(1))
;
	SV*	psvSendData = ST(2)
;
#line 910 "PCSC.xs"
		int                        nCount = 0;
		static char*               pbSendBuffer = NULL;
		static unsigned char       pbRecvBuffer [MAX_BUFFER_SIZE];
		unsigned long              cbSendLength = 0;
		DWORD                      cbRecvLength = sizeof (pbRecvBuffer);
		AV*                        aRecvBuffer = NULL;
#line 1097 "PCSC.c"
	SV *	RETVAL;
#line 917 "PCSC.xs"
		/* We make sure that the array is sane */
		if (psvSendData == NULL) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvSendData is a NULL pointer at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		/* Should the second parameter not be a reference, we return the
		 * SCARD_E_INVALID_PARAMETER error code.
		 */
		if ((!SvROK(psvSendData))||(SvTYPE(SvRV(psvSendData)) != SVt_PVAV)) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvSendData is not a RVAV at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		/* Let's allocate some space for the send buffer, if needed */
		cbSendLength = av_len((AV*)SvRV(psvSendData)) + 1;
		if (cbSendLength <= 0) {
			gnLastError = SCARD_E_INVALID_VALUE;
			warn ("empty array given at %s line %d\n\t",
				  __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}
		New (2018, pbSendBuffer, cbSendLength, char);
		if (pbSendBuffer == NULL) {
			gnLastError = SCARD_E_NO_MEMORY;
			warn ("Could not allocate buffer at %s line %d\n\t",
				  __FILE__, __LINE__);
			XSRETURN_UNDEF;
		}

		for (nCount = 0; nCount < cbSendLength ; nCount++)
			pbSendBuffer[nCount] = (char)SvIV(*av_fetch((AV*)SvRV(psvSendData), nCount, 0));

		/* Everything is ready : call the real function... */
		gnLastError = hControl (hCard, dwControlCode,
			(cbSendLength > 0 ? (BYTE *)pbSendBuffer : NULL), cbSendLength, 
			pbRecvBuffer, sizeof(pbRecvBuffer), &cbRecvLength);

		if (gnLastError != SCARD_S_SUCCESS) {
			/* Free the buffer if something went wrong */
			Safefree (pbSendBuffer);
			XSRETURN_UNDEF;
		}

		/* At this point, the command was successful. We still need to
		 * return all the values from our buffer...
		 */
		aRecvBuffer = (AV*) sv_2mortal((SV*)newAV());

		/* we fill this array with every byte from the Response
		 * note that we do not make this data mortal because av_push()
		 * does not increment the reference count. See the note in the
		 * function header above
		 */
		for (nCount = 0; nCount < cbRecvLength; nCount++)
 			av_push (aRecvBuffer, newSViv(pbRecvBuffer[nCount]));

		// XPUSHs (sv_2mortal(newSViv(ioRecvPci.dwProtocol)));
		XPUSHs (sv_2mortal(newRV((SV*)aRecvBuffer)));

		/* Do not forget to free the dynamically allocated buffer */
		Safefree (pbSendBuffer);
#line 1166 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__BeginTransaction); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__BeginTransaction)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "hCard");
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	RETVAL;
	dXSTARG;
#line 998 "PCSC.xs"
		gnLastError = hBeginTransaction (hCard);

		/* Then we check for an error */
		if (gnLastError != SCARD_S_SUCCESS)
			RETVAL = FALSE;
		else
			RETVAL = TRUE;
#line 1192 "PCSC.c"
	TARGu((UV)RETVAL, 1);
	ST(0) = TARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__EndTransaction); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__EndTransaction)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "hCard, dwDisposition");
    {
	unsigned long	hCard = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwDisposition = (unsigned long)SvUV(ST(1))
;
	unsigned long	RETVAL;
	dXSTARG;
#line 1023 "PCSC.xs"
		gnLastError = hEndTransaction (hCard, dwDisposition);

		/* Then we check for an error */
		if (gnLastError != SCARD_S_SUCCESS)
			RETVAL = FALSE;
		else
			RETVAL = TRUE;
#line 1221 "PCSC.c"
	TARGu((UV)RETVAL, 1);
	ST(0) = TARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Chipcard__PCSC__GetStatusChange); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__GetStatusChange)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "hContext, dwTimeout, psvReaderStates");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	unsigned long	hContext = (unsigned long)SvUV(ST(0))
;
	unsigned long	dwTimeout = (unsigned long)SvUV(ST(1))
;
	SV*	psvReaderStates = ST(2)
;
#line 1050 "PCSC.xs"
		static SCARD_READERSTATE *rgReaderStates_t = NULL;
		unsigned int               nCount = 0;
		unsigned int               nATRCount = 0;
		unsigned int               nReaders = 0;
		AV*                        aRecvBuffer = NULL;

#line 1251 "PCSC.c"
	bool	RETVAL;
#line 1057 "PCSC.xs"
		if (psvReaderStates == NULL) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvReaderStates is a NULL pointer at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_NO;
		}

		/* Should the second parameter not be a reference, we return the
		 * SCARD_E_INVALID_PARAMETER error code.
		 */
		if ((!SvROK(psvReaderStates))||(SvTYPE(SvRV(psvReaderStates)) != SVt_PVAV)) {
			gnLastError = SCARD_E_INVALID_PARAMETER;
			warn ("psvReaderStates is not a RVAV at %s line %d\n\t",
			      __FILE__, __LINE__);
			XSRETURN_NO;
		}

		/* Get the total number of elements in our array */
		nReaders = av_len((AV*)SvRV(psvReaderStates)) + 1;

		/* free the memory allocated during previous call to GetStatusChange */
		if (rgReaderStates_t)
			Safefree(rgReaderStates_t);

		/* allocate the Reader States table */
		Newz(2018, rgReaderStates_t, nReaders, SCARD_READERSTATE);
		if (rgReaderStates_t == NULL)
		{
			warn ("Could not allocate buffer at %s line %d\n\t",
				__FILE__, __LINE__);
			XSRETURN_NO;
		}

		for (nCount = 0; nCount < nReaders; nCount++) {
			/* As long as psvReaderStates is a reference to a PVAV we
			 * should be able to use av_fetch() without error
			 */
			SV *svCurrentToken = (*av_fetch((AV*)SvRV(psvReaderStates), nCount, 0));

			/* Now see if the elements in the array are reference to hasharrays */
			if ((!SvROK(svCurrentToken)) || (SvTYPE(SvRV(svCurrentToken)) != SVt_PVHV)) {
				gnLastError = SCARD_E_INVALID_PARAMETER;
				warn ("psvReaderStates[%d] is not a RVHV at %s line %d\n\t", nCount,
				      __FILE__, __LINE__);
				XSRETURN_NO;
			}

			/* Checkout if the 'name' argument has been passed */
			if (hv_exists((HV*)SvRV(svCurrentToken), "reader_name", 11)) {
				SV** psvName         = NULL;

				/* fetch the value of reader_name */
				psvName = hv_fetch((HV*)SvRV(svCurrentToken), "reader_name", 11, 0);

				/* Link the internal structure and the fetched pointer if appropriate */
				if ((psvName != NULL) && (SvTYPE(*psvName) == SVt_PV)) {
//					printf ("We got a name\n");
					rgReaderStates_t[nCount].szReader = SvPV (*psvName, PL_na);
//					printf ("which is : %s\n", rgReaderStates_t[nCount].szReader);
				} else {
					gnLastError = SCARD_E_INVALID_PARAMETER;
					warn ("reader_name is not valid (must be ASCII) at %s line %d\n\t",
					      __FILE__, __LINE__);
					XSRETURN_NO;
				}
			}

			/* Checkout if the 'current_state' argument has been passed */
			if (hv_exists((HV*)SvRV(svCurrentToken), "current_state", 13)) {
				SV** psvCurrentState = NULL;

				/* fetch the value of current_state */
				psvCurrentState = hv_fetch((HV*)SvRV(svCurrentToken), "current_state", 13, 0);

				/* Copy the current status into the struct */
				if (psvCurrentState != NULL) {
					if (SvTYPE(*psvCurrentState) == SVt_IV
						|| SvTYPE(*psvCurrentState) == SVt_PVIV) {
//						printf ("We got a current_state\n");
						rgReaderStates_t[nCount].dwCurrentState = SvIV (*psvCurrentState);
//						printf ("which is : 0x%lX\n", rgReaderStates_t[nCount].dwCurrentState);
					} else {
						gnLastError = SCARD_E_INVALID_PARAMETER;
						warn ("current_state is not valid (must be numeric) at %s line %d\n\t",
						      __FILE__, __LINE__);
						XSRETURN_NO;
					}
				}
			}

			/* Checkout if the 'event_state' argument has been passed */
			if (hv_exists((HV*)SvRV(svCurrentToken), "event_state", 11)) {
				SV** psvEventState   = NULL;

				/* fetch the value of current_state */
				psvEventState = hv_fetch((HV*)SvRV(svCurrentToken), "event_state", 11, 0);

				/* Copy the event status into the struct */
				if (psvEventState != NULL) {
					if (SvTYPE(*psvEventState) == SVt_IV
					|| SvTYPE(*psvEventState) == SVt_PVIV) {
						rgReaderStates_t[nCount].dwEventState = SvIV (*psvEventState);
					} else {
						gnLastError = SCARD_E_INVALID_PARAMETER;
						warn ("event_state is not valid (must be numeric) at %s line %d\n\t",
						      __FILE__, __LINE__);
						XSRETURN_NO;
					}
				}
			}


			/* Checkout if the 'ATR' argument has been passed */
			if (hv_exists((HV*)SvRV(svCurrentToken), "ATR", 3)) {
				SV** psvATR          = NULL;

				/* fetch the value of ATR */
				psvATR = hv_fetch((HV*)SvRV(svCurrentToken), "ATR", 3, 0);

				if (psvATR != NULL) {
					/* Make sure we have a reference to an array */
					if ((SvTYPE(*psvATR) == SVt_RV) && (SvTYPE(SvRV(*psvATR)) == SVt_PVAV)) {
						int nATR = 0;

						/* Fetch the ATR length */
						nATR = av_len((AV*)SvRV(*psvATR)) + 1;

						for (nATRCount=0; nATRCount< nATR; nATRCount++) {
							/* Fetch all bytes of th ATR one by one */
							SV *svCurrentATRToken = (*av_fetch((AV*)SvRV(*psvATR), nATRCount, 0));
							if (SvTYPE(svCurrentATRToken) != SVt_IV) {
								/* Return SCARD_E_INVALID_PARAMETER if
								 * the ATR is not made only of numbers
								 */
								gnLastError = SCARD_E_INVALID_PARAMETER;
								warn ("invalid ATR (not a reference to a numerical array) at %s line %d\n\t",
								      __FILE__, __LINE__);
								XSRETURN_NO;
							}
							rgReaderStates_t[nCount].rgbAtr[nATRCount] = (char)SvIV(svCurrentATRToken);
						}
					} else {
						/* ATR is invalid therefore we return SCARD_E_INVALID_PARAMETER */
						gnLastError = SCARD_E_INVALID_PARAMETER;
						warn ("invalid ATR (not a reference to an array) at %s line %d\n\t",
						      __FILE__, __LINE__);
						XSRETURN_NO;
					}
				}
			}
		}

		/* Eventually call the real PCSC function */
		gnLastError = hGetStatusChange (hContext, dwTimeout, rgReaderStates_t, nReaders);

		/* Stop here upon failure */
		if (gnLastError != SCARD_S_SUCCESS) {
			XSRETURN_NO;
		}

		/* Upon successful completion, we have to propagate changes from
		 * the internalm structs to the hash arays, creating entries if
		 * required
		 */
		for (nCount = 0; nCount < nReaders; nCount++) {
			/* As long as psvReaderStates is a reference to a PVAV we
			 * should be able to use av_fetch() without error
			 */
			SV *svCurrentToken = (*av_fetch((AV*)SvRV(psvReaderStates), nCount, 0));

			/* Propagates changes to the reader_name... */
			/* The name was mandatory so we should have it already
			 * linked to our value...
			 */

			/* Propagate changes to the current_state */
			if (hv_exists((HV*)SvRV(svCurrentToken), "current_state", 13)) {
				/* If the current_state was provided we modify its
				 * entry...
				 * Most checks were performed already so this is a
				 * simplified run...
				 */

				/* Copy the struct into current_state */
				sv_setiv (*hv_fetch((HV*)SvRV(svCurrentToken), "current_state", 13, 0),
				          rgReaderStates_t[nCount].dwCurrentState);
			} else {
				/* If the current_state wasn't provided we create its
				 * entry
				 */
				hv_store ((HV*)SvRV(svCurrentToken), "current_state", 13,
				          newSViv(rgReaderStates_t[nCount].dwCurrentState), 0);
			}

			/* Propagate changes to the event_state */
			if (hv_exists((HV*)SvRV(svCurrentToken), "event_state", 11)) {
				/* If the event_state was provided we modify its
				 * entry...
				 * Most checks were performed already so this is a
				 * simplified run...
				 */

				/* Copy the struct into event_state */
				sv_setiv (*hv_fetch((HV*)SvRV(svCurrentToken), "event_state", 11, 0),
				          rgReaderStates_t[nCount].dwEventState);
			} else {
				/* If the current_state wasn't provided we create its
				 * entry
				 */
				hv_store ((HV*)SvRV(svCurrentToken), "event_state", 11,
				          newSViv(rgReaderStates_t[nCount].dwEventState), 0);
			}

			/* Build the ATR if possible */
			if (rgReaderStates_t[nCount].cbAtr > 0) {
				/* Create an AV* with the ATR */
				aRecvBuffer = (AV*) sv_2mortal((SV*)newAV());

				for (nATRCount = 0; nATRCount <rgReaderStates_t[nCount].cbAtr; nATRCount++)
					av_push (aRecvBuffer, newSViv(rgReaderStates_t[nCount].rgbAtr[nATRCount]));

				/* Propagates changes to the ATR */
				if (hv_exists((HV*)SvRV(svCurrentToken), "ATR", 11)) {
					/* If the ATR was provided we modify its entry...
				 	* Most checks were performed already so this is a
				 	* simplified run...
				 	*/

					/* Copy the struct into the ATR */
					sv_setsv (*hv_fetch((HV*)SvRV(svCurrentToken), "ATR", 3, 0),
				          	sv_2mortal(newRV((SV*)aRecvBuffer)));
				} else {
					hv_store ((HV*)SvRV(svCurrentToken), "ATR", 3,
				          	newRV((SV*)aRecvBuffer), 0);
				}
			} else {
				/* Deletes the variable to make sure we do not keep some
				 * old outdated values
				 */
				hv_delete((HV*)SvRV(svCurrentToken), "ATR", 3, G_DISCARD);
			}
		}
		XSRETURN_YES;
#line 1497 "PCSC.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Chipcard__PCSC__Cancel); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Chipcard__PCSC__Cancel)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "hContext");
    {
	unsigned long	hContext = (unsigned long)SvUV(ST(0))
;
	bool	RETVAL;
#line 1317 "PCSC.xs"
		gnLastError = hCancel (hContext);

		/* Then we check for an error */
		if (gnLastError != SCARD_S_SUCCESS)
			RETVAL = FALSE;
		else
			RETVAL = TRUE;
#line 1522 "PCSC.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C" {
#endif
XS_EXTERNAL(boot_Chipcard__PCSC); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Chipcard__PCSC)
{
#if PERL_VERSION_LE(5, 21, 5)
    dVAR; dXSARGS;
#else
    dVAR; dXSBOOTARGSXSAPIVERCHK;
#endif
#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */
    char* file = __FILE__;
#else
    const char* file = __FILE__;
#endif

    PERL_UNUSED_VAR(file);

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#if PERL_VERSION_LE(5, 21, 5)
    XS_VERSION_BOOTCHECK;
#  ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#  endif
#endif

        (void)newXSproto_portable("Chipcard::PCSC::_LoadPCSCLibrary", XS_Chipcard__PCSC__LoadPCSCLibrary, file, "");
        (void)newXSproto_portable("Chipcard::PCSC::_EstablishContext", XS_Chipcard__PCSC__EstablishContext, file, "$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_ReleaseContext", XS_Chipcard__PCSC__ReleaseContext, file, "$");
        (void)newXSproto_portable("Chipcard::PCSC::_ListReaders", XS_Chipcard__PCSC__ListReaders, file, "$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Connect", XS_Chipcard__PCSC__Connect, file, "$$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Reconnect", XS_Chipcard__PCSC__Reconnect, file, "$$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Disconnect", XS_Chipcard__PCSC__Disconnect, file, "$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Status", XS_Chipcard__PCSC__Status, file, "$");
        (void)newXSproto_portable("Chipcard::PCSC::_Transmit", XS_Chipcard__PCSC__Transmit, file, "$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Control", XS_Chipcard__PCSC__Control, file, "$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_BeginTransaction", XS_Chipcard__PCSC__BeginTransaction, file, "$");
        (void)newXSproto_portable("Chipcard::PCSC::_EndTransaction", XS_Chipcard__PCSC__EndTransaction, file, "$$");
        (void)newXSproto_portable("Chipcard::PCSC::_GetStatusChange", XS_Chipcard__PCSC__GetStatusChange, file, "$$$");
        (void)newXSproto_portable("Chipcard::PCSC::_Cancel", XS_Chipcard__PCSC__Cancel, file, "$");
#if PERL_VERSION_LE(5, 21, 5)
#  if PERL_VERSION_GE(5, 9, 0)
    if (PL_unitcheckav)
        call_list(PL_scopestack_ix, PL_unitcheckav);
#  endif
    XSRETURN_YES;
#else
    Perl_xs_boot_epilog(aTHX_ ax);
#endif
}

#ifdef __cplusplus
}
#endif
