windows-nt/Source/XPSP1/NT/drivers/smartcrd/gcr410/gioctl09.c
2020-09-26 16:20:57 +08:00

2384 lines
79 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************************************************************
* Copyright (c) 1997-1998 Gemplus Development
*
* Name : GIOCTL09.C (Gemplus IOCTL Smart card Reader module 09)
*
* Description : This module holds:
* - the IOCTL functions for a smart card reader driver
* in compliance with PC/SC.
*
* Release : 1.00.015
*
* dd/mm/yy
* Last Modif : 11/02/98: V1.00.015 (GPZ)
* 09/02/98: V1.00.014 (GPZ)
* - GDDK_09Transmit: verify the limits.
* 24/01/98: V1.00.010 (GPZ)
* - GDDK_09Transmit: verify the case T=0 IsoOut with also the
* initial buffer length because the SMCLIB add the P3=00
* for the T=0 case 1 (IsoIn command) and this can be
* interpreted like an IsoOut command.
* 19/01/98: V1.00.009 (TFB)
* - GDDK_09Transmit: modify case where Lexp=0 to max.
* 19/12/97: V1.00.003 (TFB)
* - GDDK_09Transmit: check if buffer is too small to hold
* result-data.
* 04/11/97: V1.00.002 (GPZ)
* - GDDK_09Transmit: the status is always updated.
* 03/07/97: V1.00.001 (GPZ)
* - Start of development.
*
********************************************************************************
*
* Warning :
*
* Remark :
*
*******************************************************************************/
/*------------------------------------------------------------------------------
Include section:
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
- ntddk.h: DDK Windows NT general definitons.
- ntddser.h: DDK Windows NT serial management definitons.
------------------------------------------------------------------------------*/
#include <ntddk.h>
#include <ntddser.h>
/*------------------------------------------------------------------------------
- smclib.h: smart card library definitions.
------------------------------------------------------------------------------*/
#define SMARTCARD_POOL_TAG 'cGCS'
#include <smclib.h>
/*------------------------------------------------------------------------------
- gemcore.h: Gemplus standards definitions for the Gemcore smart card reader.
- gioctl09.h: public interface definition for this module.
- gntser.h: public interface definition for serial management.
------------------------------------------------------------------------------*/
#include "gemcore.h"
#include "gioctl09.h"
#include "gntser.h"
#include "gntscr09.h"
#define min(a,b) (((a) < (b)) ? (a) : (b))
/*------------------------------------------------------------------------------
Static variables declaration section:
- dataRatesSupported: holds all the supported data rates.
------------------------------------------------------------------------------*/
#if SMCLIB_VERSION >= 0x0130
static ULONG
dataRatesSupported[] = {
9909, 13212, 14400, 15855,
19200, 19819, 26425, 28800,
31710, 38400, 39638, 52851,
57600, 76800, 79277, 105703,
115200, 158554
};
#endif
/*------------------------------------------------------------------------------
Static functions declaration section:
- GDDK_09IFDExchange
------------------------------------------------------------------------------*/
static NTSTATUS GDDK_09IFDExchange
(
PSMARTCARD_EXTENSION SmartcardExtension,
ULONG BufferInLen,
BYTE *BufferIn,
ULONG BufferOutLen,
BYTE *BufferOut,
ULONG *LengthOut
);
/*------------------------------------------------------------------------------
Function definition section:
------------------------------------------------------------------------------*/
/*******************************************************************************
* NTSTATUS GDDK_09ReaderPower
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* This function is called by the Smart card library when a
* IOCTL_SMARTCARD_POWER occurs.
* This function provides 3 differents functionnality, depending of the minor
* IOCTL value
* - Cold reset (SCARD_COLD_RESET),
* - Warm reset (SCARD_WARM_RESET),
* - Power down (SCARD_POWER_DOWN).
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09ReaderPower
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status;
/*------------------------------------------------------------------------------
Set the reply buffer length to 0.
------------------------------------------------------------------------------*/
*SmartcardExtension->IoRequest.Information = 0;
SmartcardExtension->ReaderExtension->PTSMode = IFD_DEFAULT_MODE;
/*------------------------------------------------------------------------------
Call the GDDK_09xxxxxSession functions
------------------------------------------------------------------------------*/
switch(SmartcardExtension->MinorIoControlCode)
{
case SCARD_POWER_DOWN:
status = GDDK_09CloseSession(SmartcardExtension);
break;
case SCARD_COLD_RESET:
status = GDDK_09OpenSession(SmartcardExtension);
break;
case SCARD_WARM_RESET:
status = GDDK_09SwitchSession(SmartcardExtension);
break;
default:
status = STATUS_NOT_SUPPORTED;
}
return (status);
}
/*******************************************************************************
* NTSTATUS GDDK_09SetProtocol
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* This function is called by the Smart card library when a
* IOCTL_SMARTCARD_SET_PROTOCOL occurs.
* The minor IOCTL value holds the protocol to set.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09SetProtocol
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status = STATUS_NOT_SUPPORTED;
/*------------------------------------------------------------------------------
Check if the card is already in specific state and if the caller wants to
have the already selected protocol. We return SUCCESS if this is the case.
------------------------------------------------------------------------------*/
if ((SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) &&
(SmartcardExtension->CardCapabilities.Protocol.Selected &
SmartcardExtension->MinorIoControlCode))
{
status = STATUS_SUCCESS;
}
/*------------------------------------------------------------------------------
Else
Check if the card is absent. We return NO_MEDIA if this is the case.
------------------------------------------------------------------------------*/
else if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_ABSENT)
{
status = STATUS_NO_MEDIA;
}
/*------------------------------------------------------------------------------
Else if the Current state is SCARD_NEGOTIABLE
Check if we can support one of the specified protocols; else we
return STATUS_NOT_SUPPORTED.
If we want to negotiate the speed, then we set the PTS1 byte
with the Fl/Dl parameters specified by the SMCLIB.
Send an other reset command with the appropriate PTS request.
------------------------------------------------------------------------------*/
else if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_NEGOTIABLE)
{
if (SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T0)
{
SmartcardExtension->ReaderExtension->PTS0 = IFD_NEGOTIATE_T0;
}
else if (SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T1)
{
SmartcardExtension->ReaderExtension->PTS0 = IFD_NEGOTIATE_T1;
}
else
{
status = STATUS_NOT_SUPPORTED;
}
if (status == STATUS_SUCCESS)
{
SmartcardExtension->ReaderExtension->PTSMode = IFD_NEGOTIATE_PTS_MANUALLY;
SmartcardExtension->ReaderExtension->PTS2 = 0x00;
SmartcardExtension->ReaderExtension->PTS3 = 0x00;
#if (SMCLIB_VERSION >= 0x130)
if ((SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_DEFAULT) == 0)
{
SmartcardExtension->ReaderExtension->PTS0 |= IFD_NEGOTIATE_PTS1;
SmartcardExtension->ReaderExtension->PTS1 =
(0xF0 & (SmartcardExtension->CardCapabilities.PtsData.Fl<<4)) |
(0x0F & SmartcardExtension->CardCapabilities.PtsData.Dl) ;
}
#endif
status = GDDK_09OpenSession(SmartcardExtension);
if (status != STATUS_SUCCESS)
status = STATUS_NOT_SUPPORTED;
}
}
/*------------------------------------------------------------------------------
Else
The mask contains no known protocol. We return INVALID_DEVICE_REQUEST if
this is the case.
------------------------------------------------------------------------------*/
else
{
status = STATUS_INVALID_DEVICE_REQUEST;
}
/*------------------------------------------------------------------------------
Set the reply buffer length to sizeof(ULONG).
Check if status SUCCESS, store the selected protocol.
------------------------------------------------------------------------------*/
*SmartcardExtension->IoRequest.Information = sizeof(ULONG);
if (status == STATUS_SUCCESS)
{
*(ULONG *)SmartcardExtension->IoRequest.ReplyBuffer =
SmartcardExtension->CardCapabilities.Protocol.Selected;
}
/*------------------------------------------------------------------------------
Else
Set the selected protocol to undefined.
------------------------------------------------------------------------------*/
else
{
*(ULONG *)SmartcardExtension->IoRequest.ReplyBuffer =
SCARD_PROTOCOL_UNDEFINED;
}
return (status);
}
/*******************************************************************************
* NTSTATUS GDDK_09Transmit
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* This function is called by the Smart card library when a
* IOCTL_SMARTCARD_TRANSMIT occurs.
* This function is used to transmit a command to the card.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09Transmit
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status;
PUCHAR
requestBuffer = SmartcardExtension->SmartcardRequest.Buffer,
replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
PULONG
requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
PSCARD_IO_REQUEST scardIoRequest = (PSCARD_IO_REQUEST)
SmartcardExtension->OsData->CurrentIrp->AssociatedIrp.SystemBuffer;
USHORT
i,
buffLen,
lenExp,
lenIn;
UCHAR
*buffIn;
INT16
response;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
/*------------------------------------------------------------------------------
Set the reply buffer length to 0.
------------------------------------------------------------------------------*/
*SmartcardExtension->IoRequest.Information = 0;
status = STATUS_SUCCESS;
/*------------------------------------------------------------------------------
Verify if the protocol specified is the same than the protocol selected.
<== STATUS_INVALID_DEVICE_STATE
------------------------------------------------------------------------------*/
*requestLength = 0;
if (SmartcardExtension->CardCapabilities.Protocol.Selected !=
scardIoRequest->dwProtocol)
{
return (STATUS_INVALID_DEVICE_STATE);
}
/*------------------------------------------------------------------------------
Lock the mutex to avoid a call of an other command.
------------------------------------------------------------------------------*/
GDDK_09LockExchange(SmartcardExtension);
/*------------------------------------------------------------------------------
For the different protocols:
------------------------------------------------------------------------------*/
switch (SmartcardExtension->CardCapabilities.Protocol.Selected)
{
/*------------------------------------------------------------------------------
RAW protocol:
<== STATUS_INVALID_DEVICE_STATE
------------------------------------------------------------------------------*/
case SCARD_PROTOCOL_RAW:
status = STATUS_INVALID_DEVICE_STATE;
break;
/*------------------------------------------------------------------------------
T=0 PROTOCOL:
Call the SmartCardT0Request which updates the SmartcardRequest struct.
------------------------------------------------------------------------------*/
case SCARD_PROTOCOL_T0:
SmartcardExtension->SmartcardRequest.BufferLength = 0;
status = SmartcardT0Request(SmartcardExtension);
if (status == STATUS_SUCCESS)
{
rlen = HOR3GLL_BUFFER_SIZE;
/*------------------------------------------------------------------------------
If the length LEx > 0
Then
Is an ISO Out command.
If LEx > SC_IFD_GEMCORE_T0_MAXIMUM_LEX (256)
<== STATUS_BUFFER_TOO_SMALL
Call the G_Oros3IsoOutput
------------------------------------------------------------------------------*/
if (SmartcardExtension->T0.Le > 0)
{
if (SmartcardExtension->T0.Le > SC_IFD_GEMCORE_T0_MAXIMUM_LEX)
{
status = STATUS_BUFFER_TOO_SMALL;
}
if (status == STATUS_SUCCESS)
{
response = G_Oros3IsoOutput
(
param->Handle,
param->APDUTimeOut,
HOR3GLL_IFD_CMD_ICC_ISO_OUT,
(BYTE *)SmartcardExtension->SmartcardRequest.Buffer,
&rlen,
rbuff
);
}
}
/*------------------------------------------------------------------------------
Else
Is an ISO In command.
If LC > SC_IFD_GEMCORE_T0_MAXIMUM_LC (255)
<== STATUS_BUFFER_TOO_SMALL
Call the G_Oros3IsoInput
------------------------------------------------------------------------------*/
else
{
if (SmartcardExtension->T0.Lc > SC_IFD_GEMCORE_T0_MAXIMUM_LC)
{
status = STATUS_BUFFER_TOO_SMALL;
}
if (status == STATUS_SUCCESS)
{
response = G_Oros3IsoInput(
param->Handle,
param->APDUTimeOut,
HOR3GLL_IFD_CMD_ICC_ISO_IN,
(BYTE *)SmartcardExtension->SmartcardRequest.Buffer,
(BYTE *)SmartcardExtension->SmartcardRequest.Buffer + 5,
&rlen,
rbuff
);
}
}
}
/*------------------------------------------------------------------------------
If the response == G_OK
GE_Translate(reader status)
Call the G_DDKTranslate function
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
if (response == G_OK)
response = GE_Translate(rbuff[0]);
status = GDDK_Translate(response,RDF_TRANSMIT);
}
/*------------------------------------------------------------------------------
If the Status is Success
Copy the response in the SmartcardReply buffer. Remove the status
of the reader.
Call the SmartcardT0reply function to update the IORequest struct.
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
ASSERT(SmartcardExtension->SmartcardReply.BufferSize >=
(ULONG) (rlen - 1)
);
RtlCopyMemory(
SmartcardExtension->SmartcardReply.Buffer,
rbuff + 1,
rlen - 1);
SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1);
status = SmartcardT0Reply(SmartcardExtension);
}
break;
/*------------------------------------------------------------------------------
T=1 PROTOCOL:
We don't use the SmartCardT1Request and SmartCardT1Reply functions,
then we must verify the size of the buffers and the command ourselves.
------------------------------------------------------------------------------*/
case SCARD_PROTOCOL_T1:
buffLen = (USHORT)SmartcardExtension->IoRequest.RequestBufferLength -
sizeof(SCARD_IO_REQUEST);
buffIn = (UCHAR *)SmartcardExtension->IoRequest.RequestBuffer +
sizeof(SCARD_IO_REQUEST);
if (buffLen > 5)
{
lenIn = buffIn[4];
if (buffLen > (USHORT)(5 + lenIn))
{
lenExp =((buffIn[5+ lenIn] == 0) ? 256 : buffIn[5 + lenIn]);
}
else
{
lenExp = 0;
}
}
else if (buffLen == 5)
{
lenIn = 0;
lenExp = ((buffIn[4] == 0) ? 256 : buffIn[4]);
}
else
{
lenExp = 0;
lenIn = 0;
}
/*------------------------------------------------------------------------------
If LEx > SC_IFD_GEMCORE_T1_MAXIMUM_LEX (256)
STATUS_BUFFER_TOO_SMALL
If LC > SC_IFD_GEMCORE_T1_MAXIMUM_LC (255)
STATUS_BUFFER_TOO_SMALL
------------------------------------------------------------------------------*/
if (lenExp > SC_IFD_GEMCORE_T1_MAXIMUM_LEX)
{
status = STATUS_BUFFER_TOO_SMALL;
}
else if (lenIn > SC_IFD_GEMCORE_T1_MAXIMUM_LC)
{
status = STATUS_BUFFER_TOO_SMALL;
}
/*------------------------------------------------------------------------------
Call the G_Oros3IsoT1
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IsoT1(
param->Handle,
param->APDUTimeOut,
HOR3GLL_IFD_CMD_ICC_APDU,
buffLen,
buffIn,
&rlen,
rbuff
);
}
/*------------------------------------------------------------------------------
If the response == G_OK
GE_Translate(reader status)
Call the G_DDKTranslate function
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
if (response == G_OK)
response = GE_Translate(rbuff[0]);
status = GDDK_Translate(response,RDF_TRANSMIT);
}
/*------------------------------------------------------------------------------
If the Status is Success
If the length of the returned bytes is greate than the size of the
reply buffer
<== STATUS_BUFFER_OVERFLOW
Copy the response in the IoRequest.ReplyBuffer. Remove the status
of the reader.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
if ( (rlen - 1) >
(WORD16) ( SmartcardExtension->IoRequest.ReplyBufferLength -
sizeof(SCARD_IO_REQUEST)
)
)
{
status = STATUS_BUFFER_TOO_SMALL;
}
if (status == STATUS_SUCCESS)
{
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer + sizeof(SCARD_IO_REQUEST),
rbuff + 1,
rlen - 1
);
*(SmartcardExtension->IoRequest.Information) =
(ULONG) sizeof(SCARD_IO_REQUEST) + rlen - 1;
}
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
/*------------------------------------------------------------------------------
Unlock the mutex.
------------------------------------------------------------------------------*/
GDDK_09UnlockExchange(SmartcardExtension);
return (status);
}
/*******************************************************************************
* NTSTATUS GDDK_09CardTracking
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* This function is called by the Smart card library when an
* IOCTL_SMARTCARD_IS_PRESENT or IOCTL_SMARTCARD_IS_ABSENT occurs.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09CardTracking
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status;
KIRQL
oldIrql;
/*------------------------------------------------------------------------------
Check if the reader can support this function.
------------------------------------------------------------------------------*/
if (SmartcardExtension->ReaderExtension->IFDNumber != 0)
{
return STATUS_PENDING;
}
// Set cancel routine for the notification irp
IoAcquireCancelSpinLock(&oldIrql);
IoSetCancelRoutine(SmartcardExtension->OsData->NotificationIrp,GDDKNT_09Cleanup);
IoReleaseCancelSpinLock(oldIrql);
return STATUS_PENDING;
}
/*******************************************************************************
* NTSTATUS GDDK_09SpecificIOCTL
* (
* PSMARTCARD_EXTENSION SmartcardExtension,
* DWORD IoControlCode,
* DWORD BufferInLen,
* BYTE *BufferIn,
* DWORD BufferOutLen,
* BYTE *BufferOut,
* DWORD *LengthOut
*)
*
* Description :
* -------------
* This function is called when a specific IOCTL occurs.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
* - IoControlCode holds the IOCTL value.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09SpecificIOCTL
(
PSMARTCARD_EXTENSION SmartcardExtension,
DWORD IoControlCode,
ULONG BufferInLen,
BYTE *BufferIn,
DWORD BufferOutLen,
BYTE *BufferOut,
DWORD *LengthOut
)
{
/*------------------------------------------------------------------------------
Set the reply buffer length to 0.
------------------------------------------------------------------------------*/
*LengthOut = 0;
/*------------------------------------------------------------------------------
Switch for the different IOCTL:
------------------------------------------------------------------------------*/
switch(IoControlCode)
{
/*------------------------------------------------------------------------------
IOCTL_SMARTCARD_IFD_EXCHANGE:
<== GDDK_09IFDExchange
------------------------------------------------------------------------------*/
case IOCTL_SMARTCARD_IFD_EXCHANGE:
return GDDK_09IFDExchange(
SmartcardExtension,
BufferInLen,
BufferIn,
BufferOutLen,
BufferOut,
LengthOut
);
break;
default:
return STATUS_NOT_SUPPORTED;
break;
}
}
/*******************************************************************************
* NTSTATUS GDDK_09SpecificTag
* (
* PSMARTCARD_EXTENSION SmartcardExtension,
* DWORD IoControlCode
* DWORD BufferInLen,
* BYTE *BufferIn,
* DWORD BufferOutLen,
* BYTE *BufferOut,
* DWORD *LengthOut
*)
*
* Description :
* -------------
* This function is called when a specific Tag request occurs.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
* - IoControlCode holds the IOCTL value.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDK_09SpecificTag
(
PSMARTCARD_EXTENSION SmartcardExtension,
DWORD IoControlCode,
DWORD BufferInLen,
BYTE *BufferIn,
DWORD BufferOutLen,
BYTE *BufferOut,
DWORD *LengthOut
)
{
ULONG
i,
TagValue;
PREADER_EXTENSION
pReaderExtension = SmartcardExtension->ReaderExtension;
ASSERT(pReaderExtension != NULL);
/*------------------------------------------------------------------------------
Set the reply buffer length to 0.
------------------------------------------------------------------------------*/
*LengthOut = 0;
/*------------------------------------------------------------------------------
Verify the length of the Tag
<== STATUS_BUFFER_TOO_SMALL
------------------------------------------------------------------------------*/
if (BufferInLen < (DWORD) sizeof(TagValue))
{
return(STATUS_BUFFER_TOO_SMALL);
}
TagValue = (ULONG) *((PULONG)BufferIn);
/*------------------------------------------------------------------------------
Switch for the different IOCTL:
Get the value of one tag (IOCTL_SMARTCARD_GET_ATTRIBUTE)
Switch for the different Tags:
------------------------------------------------------------------------------*/
switch(IoControlCode)
{
case IOCTL_SMARTCARD_GET_ATTRIBUTE:
switch (TagValue)
{
/*------------------------------------------------------------------------------
Baud rate of the reader (SCARD_ATTR_SPEC_BAUD_RATE)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_BAUD_RATE:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->IFDBaudRate)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->IFDBaudRate,
sizeof(pReaderExtension->IFDBaudRate)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->IFDBaudRate);
return (STATUS_SUCCESS);
break;
/*------------------------------------------------------------------------------
IFD number of the reader (SCARD_ATTR_SPEC_IFD_NUMBER)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_IFD_NUMBER:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->IFDNumber)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->IFDNumber,
sizeof(pReaderExtension->IFDNumber)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->IFDNumber);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
ICC type (SCARD_ATTR_SPEC_ICC_TYPE)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_ICC_TYPE:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->ICCType)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->ICCType,
sizeof(pReaderExtension->ICCType)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->ICCType);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_POWER_TIMEOUT:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->PowerTimeOut)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->PowerTimeOut,
sizeof(pReaderExtension->PowerTimeOut)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->PowerTimeOut);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_CMD_TIMEOUT:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->CmdTimeOut)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->CmdTimeOut,
sizeof(pReaderExtension->CmdTimeOut)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->CmdTimeOut);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
APDU Timeout (SCARD_ATTR_SPEC_APDU_TIMEOUT)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_APDU_TIMEOUT:
if ( BufferOutLen <
(DWORD) sizeof(pReaderExtension->APDUTimeOut)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->APDUTimeOut,
sizeof(pReaderExtension->APDUTimeOut)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->APDUTimeOut);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
IFD Option (SCARD_ATTR_SPEC_IFD_OPTION)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_IFD_OPTION:
if ( BufferOutLen <
sizeof(pReaderExtension->IFDOption)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->IFDOption,
sizeof(pReaderExtension->IFDOption)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->IFDOption);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
IFD Option (SCARD_ATTR_SPEC_MAXIMAL_IFD)
Verify the length of the output buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the output buffer and the length.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_MAXIMAL_IFD:
if ( BufferOutLen <
sizeof(pReaderExtension->MaximalIFD)
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
BufferOut,
&pReaderExtension->MaximalIFD,
sizeof(pReaderExtension->MaximalIFD)
);
*(LengthOut) =
(ULONG) sizeof(pReaderExtension->MaximalIFD);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Unknown tag
<== STATUS_NOT_SUPPORTED
------------------------------------------------------------------------------*/
default:
return STATUS_NOT_SUPPORTED;
break;
}
break;
/*------------------------------------------------------------------------------
Set the value of one tag (IOCTL_SMARTCARD_SET_ATTRIBUTE)
Switch for the different Tags:
------------------------------------------------------------------------------*/
case IOCTL_SMARTCARD_SET_ATTRIBUTE:
switch (TagValue)
{
/*------------------------------------------------------------------------------
ICC type (SCARD_ATTR_SPEC_ICC_TYPE)
Verify the length of the input buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the value.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_ICC_TYPE:
if ( BufferInLen <
(DWORD) ( sizeof(pReaderExtension->ICCType) + sizeof(TagValue))
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
&pReaderExtension->ICCType,
BufferIn + sizeof(TagValue),
sizeof(pReaderExtension->ICCType)
);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
Verify the length of the input buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the value.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_POWER_TIMEOUT:
if ( BufferInLen <
(DWORD) (sizeof(pReaderExtension->PowerTimeOut) + sizeof(TagValue))
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
&pReaderExtension->PowerTimeOut,
BufferIn + sizeof(TagValue),
sizeof(pReaderExtension->PowerTimeOut)
);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT)
Verify the length of the input buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the value.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_CMD_TIMEOUT:
if ( BufferInLen <
(DWORD) (sizeof(pReaderExtension->CmdTimeOut) + sizeof(TagValue))
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
&pReaderExtension->CmdTimeOut,
BufferIn + sizeof(TagValue),
sizeof(pReaderExtension->CmdTimeOut)
);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Command Timeout (SCARD_ATTR_SPEC_APDU_TIMEOUT)
Verify the length of the input buffer.
<== STATUS_BUFFER_TOO_SMALL
Update the value.
<== STATUS_SUCCESS
------------------------------------------------------------------------------*/
case SCARD_ATTR_SPEC_APDU_TIMEOUT:
if ( BufferInLen <
(DWORD) (sizeof(pReaderExtension->APDUTimeOut) + sizeof(TagValue))
)
{
return(STATUS_BUFFER_TOO_SMALL);
}
memcpy(
&pReaderExtension->APDUTimeOut,
BufferIn + sizeof(TagValue),
sizeof(pReaderExtension->APDUTimeOut)
);
return STATUS_SUCCESS;
break;
/*------------------------------------------------------------------------------
Unknown tag
<== STATUS_NOT_SUPPORTED
------------------------------------------------------------------------------*/
default:
return STATUS_NOT_SUPPORTED;
}
break;
default:
return STATUS_NOT_SUPPORTED;
break;
}
}
/*******************************************************************************
* NTSTATUS GDDK_09OpenChannel
* (
* PSMARTCARD_EXTENSION SmartcardExtension,
* CONST WORD32 DeviceNumber,
* CONST WORD32 PortSerialNumber,
* CONST WORD32 IFDNumber,
* CONST WORD32 MaximalBaudRate
* )
* Description :
* -------------
* This routine try to establish a connection with a reader, and after
* update the characteristic of this reader.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
* - DeviceNumber holds the current device number (0 to MAX_DEVICES).
* - PortSerialNumber holds the port serial number (0 to HGTSER_MAX_PORT).
* - IFDNumber holds the numero of the IFD in the reader (0 to MAX_IFD_BY_READER)
* - MaximalBaudRate holds the maximal speed specified for the reader.
*
* Out :
* -------------
* - SmartcardExtension is updated.
*
* Responses :
* -------------
* If everything is Ok:
* G_OK
*******************************************************************************/
NTSTATUS GDDK_09OpenChannel
(
PSMARTCARD_EXTENSION SmartcardExtension,
CONST WORD32 DeviceNumber,
CONST WORD32 PortSerialNumber,
CONST WORD32 IFDNumber,
CONST WORD32 MaximalBaudRate
)
{
/*------------------------------------------------------------------------------
Local variables:
- handle holds the communication handle to associate to the channel.
- channel_nb holds the number associated to the channel.
- lmod_name and lmod_release are used to control the called library version.
- response holds the called function responses.
- os_string and os_length are used to recognized an OROS2.x IFD on the channel.
- oros_version holds the minor version value of the IFD.
- user, comm and br are used to optimizes the baudrate.
------------------------------------------------------------------------------*/
NTSTATUS
status = STATUS_SUCCESS;
INT16
handle,
portcom,
channel_nb,
i,
oros_version,
response;
char G_FAR
*oros_info;
char
os_string[HOR3GLL_OS_STRING_SIZE];
WORD16
os_length = HOR3GLL_OS_STRING_SIZE;
WORD16
user;
TGTSER_PORT
comm;
WORD32
br;
BYTE
minorVersion,
majorVersion;
BOOL
b_compare = TRUE;
G4_CHANNEL_PARAM
g4_channel;
WORD16
rlen;
BYTE
cmd[5],
rbuff[HOR3GLL_BUFFER_SIZE];
/*------------------------------------------------------------------------------
Update the serial communication channel information:
------------------------------------------------------------------------------*/
g4_channel.Comm.Serial.Port = PortSerialNumber + G_COM1;
g4_channel.Comm.Serial.BaudRate = MaximalBaudRate;
g4_channel.Comm.Serial.ITNumber = DEFAULT_IT;
g4_channel.pSmartcardExtension = SmartcardExtension;
/*------------------------------------------------------------------------------
Initializes a mutex object (in a high level) for the exchange commands with
the smart card reader.
------------------------------------------------------------------------------*/
KeInitializeMutex(
&SmartcardExtension->ReaderExtension->ExchangeMutex,
3
);
/*------------------------------------------------------------------------------
Initializes a mutex object (in a high level) for the long APDU commands with
the smart card reader.
------------------------------------------------------------------------------*/
KeInitializeMutex(
&SmartcardExtension->ReaderExtension->LongAPDUMutex,
3
);
/*------------------------------------------------------------------------------
Opens a serial communication channel:
Open a communication channel (G_Oros3OpenComm).
The reader baudrate is automatically detected by this function.
If the port is already opened
Then
Adds a user on this port (G_SerPortAddUser)
<= Test the last received status (>= G_OK): G_Oros3OpenComm/G_SerPortAddUser
------------------------------------------------------------------------------*/
handle = (INT16)DeviceNumber;
response = G_Oros3OpenComm(&g4_channel,handle);
if (response == GE_HOST_PORT_OPEN)
{
response = portcom = G_SerPortAddUser((WORD16) g4_channel.Comm.Serial.Port);
if (response < G_OK)
{
return (GDDK_Translate(response,(const ULONG) NULL));
}
G_GBPOpen(handle,2,4,portcom);
}
if (response < G_OK)
{
return (GDDK_Translate(response,(const ULONG) NULL));
}
/*------------------------------------------------------------------------------
Verifies that an OROS3.x IFD is connected to the selected port.
Sets the command according to the parameters. Read OROS memory type 0x05,
13 bytes from 0x3FE0.
<= G_Oros3Exchange status.
------------------------------------------------------------------------------*/
cmd[0] = (BYTE) HOR3GLL_IFD_CMD_MEM_RD;
cmd[1] = (BYTE)HOR3GLL_IFD_TYP_VERSION;
cmd[2] = HIBYTE(HOR3GLL_IFD_ADD_VERSION);
cmd[3] = LOBYTE(HOR3GLL_IFD_ADD_VERSION);
cmd[4] = (BYTE)HOR3GLL_IFD_LEN_VERSION;
response = G_Oros3Exchange(
handle,
HOR3GLL_LOW_TIME,
5,
cmd,
&os_length,
os_string
);
if (response < G_OK)
{
G_Oros3CloseComm(handle);
return (GDDK_Translate(response,(const ULONG) NULL));
}
/*------------------------------------------------------------------------------
Verify the Firmware version: this driver support only the GemCore based
readers.
Read the minor version of the reader.
------------------------------------------------------------------------------*/
if (os_length >= (WORD16)strlen(IFD_FIRMWARE_VERSION))
{
if (memcmp(os_string + 1,IFD_FIRMWARE_VERSION,strlen(IFD_FIRMWARE_VERSION)))
{
G_Oros3CloseComm(handle);
return (GDDK_Translate(GE_IFD_UNKNOWN,(const ULONG) NULL));
}
}
else
{
G_Oros3CloseComm(handle);
return (GDDK_Translate(GE_IFD_UNKNOWN,(const ULONG) NULL));
}
majorVersion = os_string[strlen(IFD_FIRMWARE_VERSION)-1] - '0';
minorVersion = 10 * (os_string[strlen(IFD_FIRMWARE_VERSION)+1] - '0') +
os_string[strlen(IFD_FIRMWARE_VERSION)+2] - '0';
/*------------------------------------------------------------------------------
Verify if the reader can support a security module
------------------------------------------------------------------------------*/
if (IFDNumber > 0)
{
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerDown
(
handle,
HOR3GLL_DEFAULT_TIME,
&rlen,
rbuff
);
if ((response != G_OK) || (rlen != 1) || ((rbuff[0] != 0x00) && (rbuff[0] != 0xFB)))
{
G_Oros3CloseComm(handle);
return STATUS_NO_MEDIA;
}
}
/*------------------------------------------------------------------------------
Optimizes the baudrate:
Initializes the comm variable to modify the used baud rate.
The optimization start at the given baudrate, then the used value is divised
by 2 until the communication is possible or the tried baudrate is lower
than 9600.
------------------------------------------------------------------------------*/
comm.Port = (WORD16) g4_channel.Comm.Serial.Port;
response = G_SerPortGetState(&comm,&user);
comm.BaudRate = g4_channel.Comm.Serial.BaudRate;
for(br = g4_channel.Comm.Serial.BaudRate; br >= 9600lu; br = br / 2)
{
/*------------------------------------------------------------------------------
The reader is switched to the selected value (G_Oros3SIOConfigure). The
function status is not tested because, as the IFD has switched
immediatly, it is not possible to read its response.
------------------------------------------------------------------------------*/
comm.BaudRate = br;
rlen = HOR3GLL_BUFFER_SIZE;
G_Oros3SIOConfigure(
handle,
HOR3GLL_LOW_TIME,
0,
8,
comm.BaudRate,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
Host is switched to the selected value (G_SerPortSetState).
If this call is successful,
Then
The last SIO command is re-sent to read the IFD response.
response is optionnaly initialized with the translated IFD status.
------------------------------------------------------------------------------*/
response = G_SerPortSetState(&comm);
if (response == G_OK)
{
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3SIOConfigure(
handle,
HOR3GLL_LOW_TIME,
0,
8,
comm.BaudRate,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
break;
}
}
}
/*------------------------------------------------------------------------------
If the loop is ended without a good communication with IFD,
Then
The port is closed.
<= GE_HI_COMM.
------------------------------------------------------------------------------*/
if ((br < 9600) || (response != G_OK))
{
G_Oros3CloseComm(handle);
return (GDDK_Translate(GE_HI_COMM,(const ULONG) NULL));
}
/*------------------------------------------------------------------------------
Removes the TLP compatibility mode.
<= Sends the SetMode command with parameter 0 to disable TLP compatibility.
Closes the opened port (G_Oros3CloseComm).
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3SetMode(handle,HOR3GLL_LOW_TIME,0x00,&rlen,rbuff);
if (response < G_OK)
{
G_Oros3CloseComm(handle);
return (GDDK_Translate(response,(const ULONG) NULL));
}
/*------------------------------------------------------------------------------
Reader capabilities:
- the type of the reader (SCARD_READER_TYPE_SERIAL)
- the channel for the reader (PortSerialNumber)
- the protocols supported by the reader (SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1)
- the mechanical characteristic of the reader:
Verify if the reader can supports the detection of the card
insertion/removal. Only the main reader supports this functionnality.
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderCapabilities.ReaderType =
SCARD_READER_TYPE_SERIAL;
SmartcardExtension->ReaderCapabilities.Channel =
PortSerialNumber;
#if SMCLIB_VERSION >= 0x0130
SmartcardExtension->ReaderCapabilities.SupportedProtocols =
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
#else
SmartcardExtension->ReaderCapabilities.SupportedProtocols.Async =
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
#endif
SmartcardExtension->ReaderCapabilities.MechProperties = 0;
/*------------------------------------------------------------------------------
Reader capabilities (continue):
- the default clock frequency (SC_IFD_GEMCORE_DEFAULT_CLK_FREQUENCY)
- the maximum clock frequency (SC_IFD_GEMCORE_MAXIMUM_CLK_FREQUENCY)
- the default data rate (SC_IFD_GEMCORE_DEFAULT_DATA_RATE)
- the maximum data rate (SC_IFD_GEMCORE_MAXIMUM_DATA_RATE)
- the maximum IFSD (SC_IFD_GEMCORE_MAXIMUM_IFSD)
- the power management is set to 0.
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderCapabilities.CLKFrequency.Default =
SC_IFD_GEMCORE_DEFAULT_CLK_FREQUENCY;
SmartcardExtension->ReaderCapabilities.CLKFrequency.Max =
SC_IFD_GEMCORE_MAXIMUM_CLK_FREQUENCY;
SmartcardExtension->ReaderCapabilities.DataRate.Default =
SC_IFD_GEMCORE_DEFAULT_DATA_RATE;
SmartcardExtension->ReaderCapabilities.DataRate.Max =
SC_IFD_GEMCORE_MAXIMUM_DATA_RATE;
SmartcardExtension->ReaderCapabilities.MaxIFSD =
SC_IFD_GEMCORE_MAXIMUM_IFSD;
SmartcardExtension->ReaderCapabilities.PowerMgmtSupport = 0;
#if SMCLIB_VERSION >= 0x0130
/*------------------------------------------------------------------------------
Reader capabilities (continue):
- List all the supported data rates
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderCapabilities.DataRatesSupported.List =
dataRatesSupported;
SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries =
sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]);
#endif
/*------------------------------------------------------------------------------
Vendor Attributes:
- the vendor information (SC_VENDOR_NAME)
------------------------------------------------------------------------------*/
strcpy(
SmartcardExtension->VendorAttr.VendorName.Buffer,
SC_VENDOR_NAME
);
SmartcardExtension->VendorAttr.VendorName.Length =
strlen(SmartcardExtension->VendorAttr.VendorName.Buffer);
/*------------------------------------------------------------------------------
Vendor Attributes (continue):
- the IFD Type information (SC_IFD_SAM_TYPE or SC_IFD_TYPE)
------------------------------------------------------------------------------*/
if (IFDNumber > 0)
{
strcpy(SmartcardExtension->VendorAttr.IfdType.Buffer,SC_IFD_SAM_TYPE);
}
else
{
strcpy(SmartcardExtension->VendorAttr.IfdType.Buffer,SC_IFD_TYPE);
}
SmartcardExtension->VendorAttr.IfdType.Length =
strlen(SmartcardExtension->VendorAttr.IfdType.Buffer);
/*------------------------------------------------------------------------------
Vendor Attributes (continue):
- the UnitNo information. Is set to the device number.
- the IFD serial number (is set to a NULL string).
- the IFD version is set.
------------------------------------------------------------------------------*/
SmartcardExtension->VendorAttr.UnitNo = DeviceNumber;
SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0;
SmartcardExtension->VendorAttr.IfdVersion.VersionMajor = (UCHAR)majorVersion;
SmartcardExtension->VendorAttr.IfdVersion.VersionMinor = (UCHAR)minorVersion;
SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = 0;
/*------------------------------------------------------------------------------
Reader Extension:
- the Handle of the reader.
- the IFD number of the reader.
- the ICCType (ISOCARD).
- the ICCVpp (HOR3GLL_DEFAULT_VPP).
- the ICCPresence.
- the command timeout for the reader (HOR3GLL_DEFAULT_TIME).
- the IFD baud rate.
- the power timeout (0).
- the selected VCC power supply voltage value.
- the PTS negotiate mode.
- the parameter PTS0.
- the parameter PTS1.
- the parameter PTS2.
- the parameter PTS3.
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderExtension->Handle = handle;
SmartcardExtension->ReaderExtension->IFDNumber = IFDNumber;
SmartcardExtension->ReaderExtension->ICCType = ISOCARD;
SmartcardExtension->ReaderExtension->ICCVpp = HOR3GLL_DEFAULT_VPP;
SmartcardExtension->ReaderExtension->APDUTimeOut = HOR3GLL_DEFAULT_TIME * 24;
SmartcardExtension->ReaderExtension->CmdTimeOut = HOR3GLL_DEFAULT_TIME;
SmartcardExtension->ReaderExtension->IFDBaudRate = br;
SmartcardExtension->ReaderExtension->PowerTimeOut = ICC_DEFAULT_POWER_TIMOUT;
SmartcardExtension->ReaderExtension->ICCVcc = ICC_VCC_5V;
SmartcardExtension->ReaderExtension->PTSMode = IFD_DEFAULT_MODE;
SmartcardExtension->ReaderExtension->PTS0 = 0;
SmartcardExtension->ReaderExtension->PTS1 = 0;
SmartcardExtension->ReaderExtension->PTS2 = 0;
SmartcardExtension->ReaderExtension->PTS3 = 0;
SmartcardExtension->ReaderExtension->ICCPresence = HOR3GLL_DEFAULT_PRESENCE;
/*------------------------------------------------------------------------------
Define the type of the card (ISOCARD) and set the card presence
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccDefineType(
handle,
HOR3GLL_LOW_TIME,
ISOCARD,
HOR3GLL_DEFAULT_VPP,
SmartcardExtension->ReaderExtension->ICCPresence,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
Verify the response of the reader
------------------------------------------------------------------------------*/
if (response == G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response != G_OK)
{
G_Oros3CloseComm(handle);
return(GDDK_Translate(response,(const ULONG) NULL));
}
/*------------------------------------------------------------------------------
Update the status of the card (only for the main reader).
If a card is inserted:
Set the detection on the remove of the card.
else
Set the detection on the insertion of the card.
------------------------------------------------------------------------------*/
if (IFDNumber == 0)
{
GDDK_09UpdateCardStatus(SmartcardExtension);
}
else
{
/*------------------------------------------------------------------------------
<= Security Module is powered up.
The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerUp(
SmartcardExtension->ReaderExtension->Handle,
HOR3GLL_LOW_TIME,
SmartcardExtension->ReaderExtension->ICCVcc,
SmartcardExtension->ReaderExtension->PTSMode,
SmartcardExtension->ReaderExtension->PTS0,
SmartcardExtension->ReaderExtension->PTS1,
SmartcardExtension->ReaderExtension->PTS2,
SmartcardExtension->ReaderExtension->PTS3,
&rlen,
rbuff
);
// Verify the response of the reader
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
// The card is absent
SmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_ABSENT;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
SmartcardExtension->CardCapabilities.ATR.Length = 0;
}
else
{
// The card is present for use but not powered
SmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_SWALLOWED;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
SmartcardExtension->CardCapabilities.ATR.Length = 0;
// Security module is powered off.
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerDown(
SmartcardExtension->ReaderExtension->Handle,
HOR3GLL_LOW_TIME,
&rlen,
rbuff
);
}
}
return(GDDK_Translate(G_OK,(const ULONG) NULL));
}
/*******************************************************************************
* NTSTATUS GDDK_09CloseChannel
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
* Description :
* -------------
* This routine close a conection previously opened with a reader.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* - SmartcardExtension is updated.
*
* Responses :
* -------------
* If everything is Ok:
* STATUS_SUCCESS
*******************************************************************************/
NTSTATUS GDDK_09CloseChannel
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
/*------------------------------------------------------------------------------
Local variables:
- response holds the called function responses.
------------------------------------------------------------------------------*/
INT16
response;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
/*------------------------------------------------------------------------------
Call power down function:
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerDown(
param->Handle,
HOR3GLL_LOW_TIME,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
<= G_Oros3CloseComm status.
------------------------------------------------------------------------------*/
return (GDDK_Translate(G_Oros3CloseComm(param->Handle),(const ULONG) NULL));
}
/*******************************************************************************
* NTSTATUS GDDK_09OpenSession
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
* Description :
* -------------
* Opens a cold session with the selected ICC type.
* A power off is made on ICC before the call to power up function.
* For the ISO card, during the power up this function negotiates with the
* ICC speed and protocole in accordance with PTS mode and sets the ICC power
* supply voltage.
* The session structure is updated with values found in ATR.
*
* Remarks :
* -------------
* - The security module in OROS 3.x IFD only support the sames cards that main
* reader interface (ISO card T=0, T=1 and Synchronous card).
* - To change PTS mode and parameters used the function G4_09ICCSetPTS.
* - To change ICC power supply voltage used the function G4_09ICCSetVoltage.
* - For a specific card not supported by the OROS system, you must have
* in the GEMPLUS_LIB_PATH directory, or the current directory, the Card driver
* for this card.
* For example ICCDRV04.ORO for the GPM416 (0x04) card.
* GEMPLUS_LIB_PATH is an environnement variable used to defined the directory
* where the Card drivers are located.
* WARNING:
* - The full path name of the card driver is case sensitive in UNIX target.
* - The card driver name is in upper case.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* - SmartcardExtension is updated.
* - Status of the SCMLIB library.
*
* Responses :
* -------------
* If everything is Ok:
* G_OK
*******************************************************************************/
NTSTATUS GDDK_09OpenSession
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
/*------------------------------------------------------------------------------
Local variables:
- response holds the called function responses.
- ifd_type is used for ICC/SM management.
- offset, l and k are used to glance through the ATR.
- i is a counter.
- protocol memorises the ICC protocol.
It is initialized to 0 for T=0 default protocol.
- protocol_set is used to detect the first protocol byte.
It is initialized to FALSE because the first protocol byte has not been
encountered.
- end_time is used to wait for ICC to be really powered off.
- icc_type holds the ICC type translated in OROS value.
------------------------------------------------------------------------------*/
INT16
response,
ifd_type,
icc_supported,
offset,
l;
WORD8
k;
WORD16
protocol = 0,
card_driver_version,
card_driver_protocol,
icc_type;
BOOL
protocol_set = FALSE;
WORD32
end_time;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
NTSTATUS
status;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
KEVENT
event;
LARGE_INTEGER
timeout;
/*---------------------------------------------------------------------------------
Get the ICC type
---------------------------------------------------------------------------------*/
icc_type = param->ICCType;
/*------------------------------------------------------------------------------
<= ICC type is defined.
The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccDefineType(
param->Handle,
HOR3GLL_LOW_TIME,
icc_type,
param->ICCVpp,
param->ICCPresence,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
return (GDDK_Translate(response,RDF_CARD_POWER));
}
/*------------------------------------------------------------------------------
ICC is powered Down (G_Oros3IccPowerDown).
<= The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerDown(
param->Handle,
HOR3GLL_LOW_TIME,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
return (GDDK_Translate(response,RDF_CARD_POWER));
}
/*------------------------------------------------------------------------------
Waits for the Power Timeout to be elapsed.
------------------------------------------------------------------------------*/
KeInitializeEvent(&event,NotificationEvent,FALSE);
timeout.QuadPart = -((LONGLONG) param->PowerTimeOut * 10 * 1000);
status = KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
&timeout);
/*------------------------------------------------------------------------------
ICC is powered up (G_Oros3IccPowerUp).
<= The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerUp(
param->Handle,
param->CmdTimeOut,
param->ICCVcc,
param->PTSMode,
param->PTS0,
param->PTS1,
param->PTS2,
param->PTS3,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
return (GDDK_Translate(response,RDF_CARD_POWER));
}
/*------------------------------------------------------------------------------
Copy ATR to smart card struct (remove the reader status byte)
The lib needs the ATR for evaluation of the card parameters
------------------------------------------------------------------------------*/
ASSERT(SmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (rlen - 1));
memcpy(
SmartcardExtension->SmartcardReply.Buffer,
rbuff + 1,
rlen - 1
);
SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1);
ASSERT(sizeof(SmartcardExtension->CardCapabilities.ATR.Buffer) >=
(UCHAR) SmartcardExtension->SmartcardReply.BufferLength);
memcpy(
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->SmartcardReply.Buffer,
SmartcardExtension->SmartcardReply.BufferLength
);
SmartcardExtension->CardCapabilities.ATR.Length =
(UCHAR) SmartcardExtension->SmartcardReply.BufferLength;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
/*------------------------------------------------------------------------------
Parse the ATR string in order to check if it as valid
and to find out if the card uses invers convention
------------------------------------------------------------------------------*/
status = SmartcardUpdateCardCapabilities(SmartcardExtension);
if (status == STATUS_SUCCESS)
{
ASSERT(SmartcardExtension->IoRequest.ReplyBufferLength >=
SmartcardExtension->SmartcardReply.BufferLength
);
memcpy(
SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->CardCapabilities.ATR.Length
);
*SmartcardExtension->IoRequest.Information =
SmartcardExtension->SmartcardReply.BufferLength;
}
/*------------------------------------------------------------------------------
<= Return the last received status.
------------------------------------------------------------------------------*/
return (status);
}
/*******************************************************************************
* NTSTATUS GDDK_09SwitchSession
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
* Description :
* -------------
* Description :
* -------------
* Opens a warm session with the selected ICC type.
* Only a reset is sent to ICC.
* For the ISO card, during the power up this function negotiates with the
* ICC speed and protocole in accordance with PTS mode and sets the ICC power
* supply voltage.
* The session structure is updated with values found in ATR.
*
* Remarks :
* -------------
* This command is possible only if a G4_09OpenSession has been called before and
* if the ICC type is not changed.
* For the ISO card today, we assumes that only T=0, T=1 or T=0/1 are supported.
* So we memorised the first founded protocol which must be T=0 for bi-protocol
* card according to ISO standard.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* - SmartcardExtension is updated.
*
* Responses :
* -------------
* If everything is Ok:
* STATUS_SUCCESS
*******************************************************************************/
NTSTATUS GDDK_09SwitchSession
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
/*------------------------------------------------------------------------------
Local variables:
- response holds the called function responses.
- ifd_type is used for ICC/SM management.
- icc_type holds the ICC type translated in OROS value.
------------------------------------------------------------------------------*/
INT16
response,
ifd_type,
icc_supported;
WORD16
icc_type;
BOOL
protocol_set = FALSE;
WORD32
end_time;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
NTSTATUS
status;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
/*---------------------------------------------------------------------------------
Get the ICC type
---------------------------------------------------------------------------------*/
icc_type = param->ICCType;
/*------------------------------------------------------------------------------
<= ICC is powered up.
The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerUp(
param->Handle,
param->CmdTimeOut,
param->ICCVcc,
param->PTSMode,
param->PTS0,
param->PTS1,
param->PTS2,
param->PTS3,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
return (GDDK_Translate(response,RDF_CARD_POWER));
}
/*------------------------------------------------------------------------------
Copy ATR to smart card struct (remove the reader status byte)
The lib needs the ATR for evaluation of the card parameters
------------------------------------------------------------------------------*/
ASSERT(SmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (rlen - 1));
memcpy(
SmartcardExtension->SmartcardReply.Buffer,
rbuff + 1,
rlen - 1
);
SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1);
ASSERT(sizeof(SmartcardExtension->CardCapabilities.ATR.Buffer) >=
(UCHAR) SmartcardExtension->SmartcardReply.BufferLength);
memcpy(
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->SmartcardReply.Buffer,
SmartcardExtension->SmartcardReply.BufferLength
);
SmartcardExtension->CardCapabilities.ATR.Length =
(UCHAR) SmartcardExtension->SmartcardReply.BufferLength;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
/*------------------------------------------------------------------------------
Parse the ATR string in order to check if it as valid
and to find out if the card uses invers convention
------------------------------------------------------------------------------*/
status = SmartcardUpdateCardCapabilities(SmartcardExtension);
if (status == STATUS_SUCCESS)
{
ASSERT(SmartcardExtension->IoRequest.ReplyBufferLength >=
SmartcardExtension->SmartcardReply.BufferLength
);
memcpy(
SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->CardCapabilities.ATR.Length
);
*SmartcardExtension->IoRequest.Information =
SmartcardExtension->SmartcardReply.BufferLength;
}
/*------------------------------------------------------------------------------
<= Return the last received status.
------------------------------------------------------------------------------*/
return (status);
}
/*******************************************************************************
* NTSTATUS GDDK_09CloseSession
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* Closes a session and requests IFD to remove the power from ICC.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* If everything is Ok:
* STATUS_SUCCESS
*******************************************************************************/
NTSTATUS GDDK_09CloseSession
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
/*------------------------------------------------------------------------------
Local variables:
- response holds the called function responses.
------------------------------------------------------------------------------*/
INT16
response;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
/*------------------------------------------------------------------------------
If the dispatcher is used to send command and the command is found
in the ORO file.
Then
Send the command Icc Power Down with the micro-code via the dispatcher.
Else
ICC is powered Down (G_Oros3IccPowerDown).
<= The function status and the IFD status are tested.
------------------------------------------------------------------------------*/
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3IccPowerDown(
param->Handle,
HOR3GLL_LOW_TIME,
&rlen,
rbuff
);
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
/*------------------------------------------------------------------------------
Updates card status for ICC or reset Protocol and ATR for Security Module.
------------------------------------------------------------------------------*/
if (param->IFDNumber > 0)
{
SmartcardExtension->CardCapabilities.ATR.Length = 0;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
}
else
{
GDDK_09UpdateCardStatus(SmartcardExtension);
}
/*------------------------------------------------------------------------------
<= Returns the last status.
------------------------------------------------------------------------------*/
return(GDDK_Translate(response,RDF_CARD_POWER));
}
/*******************************************************************************
* void GDDK_09UpdateCardStatus
* (
* PSMARTCARD_EXTENSION pSmartcardExtension
* )
*
* Description :
* -------------
* This function send a command to the reader to known the state of the card.
* Available only for the main reader.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - pSmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* - pSmartcardExtension is updated.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
void GDDK_09UpdateCardStatus
(
PSMARTCARD_EXTENSION pSmartcardExtension
)
{
INT16
response;
WORD8
cmd[1];
READER_EXTENSION
*param = pSmartcardExtension->ReaderExtension;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
/*------------------------------------------------------------------------------
On an OROS 3.x reader we can know the status only on the main IFD
------------------------------------------------------------------------------*/
if (param->IFDNumber == 0)
{
/*------------------------------------------------------------------------------
Read the status of the reader
------------------------------------------------------------------------------*/
cmd[0] = HOR3GLL_IFD_CMD_ICC_STATUS;
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3Exchange(
param->Handle,
HOR3GLL_LOW_TIME,
(const WORD16)1,
(const BYTE *)cmd,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
Verify the response of the reader
------------------------------------------------------------------------------*/
if (response >= G_OK)
{
response = GE_Translate(rbuff[0]);
}
if (response < G_OK)
{
return;
}
if ((rbuff[1] & 0x04) == 0)
{
/*------------------------------------------------------------------------------
The card is absent
------------------------------------------------------------------------------*/
pSmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_ABSENT;
pSmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
pSmartcardExtension->CardCapabilities.ATR.Length = 0;
}
else if ((rbuff[1] & 0x02) == 0)
{
/*------------------------------------------------------------------------------
The card is present
------------------------------------------------------------------------------*/
pSmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_SWALLOWED;
pSmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
pSmartcardExtension->CardCapabilities.ATR.Length = 0;
}
}
}
/*******************************************************************************
* static NTSTATUS GDDK_09IFDExchange
* (
* PSMARTCARD_EXTENSION SmartcardExtension,
* ULONG BufferInLen,
* BYTE *BufferIn,
* ULONG BufferOutLen,
* BYTE *BufferOut,
* ULONG *LengthOut
*)
*
* Description :
* -------------
* This is the system entry point to send a command to the IFD.
* The device-specific handler is invoked to perform any validation
* necessary. The number of bytes in the request are checked against
* the maximum byte counts that the reader supports.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
static NTSTATUS GDDK_09IFDExchange
(
PSMARTCARD_EXTENSION SmartcardExtension,
ULONG BufferInLen,
BYTE *BufferIn,
ULONG BufferOutLen,
BYTE *BufferOut,
ULONG *LengthOut
)
{
INT16
response;
NTSTATUS
status;
READER_EXTENSION
*param = SmartcardExtension->ReaderExtension;
WORD16
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE];
*LengthOut = 0;
/*------------------------------------------------------------------------------
Send the command to the reader
------------------------------------------------------------------------------*/
rlen = (USHORT) BufferOutLen;
response = G_Oros3Exchange(
param->Handle,
HOR3GLL_LOW_TIME,
(USHORT)BufferInLen,
(BYTE *)BufferIn,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
If the response <> G_OK
<== G_DDKTranslate(response)
------------------------------------------------------------------------------*/
if (response != G_OK)
{
return(GDDK_Translate(response,RDF_IOCTL_VENDOR));
}
/*------------------------------------------------------------------------------
Copy the response of the reader in the reply buffer
------------------------------------------------------------------------------*/
ASSERT(*LengthOut >= (ULONG)rlen);
memcpy(BufferOut,rbuff,rlen);
*(LengthOut) = (ULONG)rlen;
return(GDDK_Translate(response,RDF_IOCTL_VENDOR));
}
/*******************************************************************************
* void GDDK_09LockExchange
* (
* PSMARTCARD_EXTENSION SmartcardExtension
*)
*
* Description :
* -------------
* Wait the release of the ExchangeMutex and take this.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* Nothing
*******************************************************************************/
void GDDK_09LockExchange
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
KeWaitForMutexObject(
&SmartcardExtension->ReaderExtension->LongAPDUMutex,
Executive,
KernelMode,
FALSE,
NULL
);
}
/*******************************************************************************
* void GDDK_09UnlockExchange
* (
* PSMARTCARD_EXTENSION SmartcardExtension
*)
*
* Description :
* -------------
* Release of the Exchange mutex.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* Nothing
*******************************************************************************/
void GDDK_09UnlockExchange
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
KeReleaseMutex(
&SmartcardExtension->ReaderExtension->LongAPDUMutex,
FALSE
);
}