📄 tlp3cb.c
字号:
/*++
Copyright (C) 1997, 98 Microsoft Corporation
Module Name:
tlp3cb.c
Abstract:
Callback functions for smart card library
Author:
Klaus U. Schutz
Environment:
Kernel mode
--*/
#include <stdio.h>
#include "bulltlp3.h"
#pragma alloc_text(PAGEABLE, TLP3SetProtocol)
#pragma alloc_text(PAGEABLE, TLP3SetParameters)
#pragma alloc_text(PAGEABLE, TLP3TransmitT0)
#pragma alloc_text(PAGEABLE, TLP3Transmit)
#pragma alloc_text(PAGEABLE, TLP3VendorIoctl)
NTSTATUS
TLP3ReaderPower(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
The smart card lib requires to have this function. It is called
for certain power requests to the card. We do nothing here, because
this action is performed in the StartIo function.
--*/
{
ULONG step, waitTime, TdIndex, numTry = 0, minWaitTime;
NTSTATUS status = STATUS_SUCCESS;
PSERIAL_STATUS serialStatus;
KIRQL oldIrql;
PUCHAR requestBuffer;
PSERIAL_READER_CONFIG serialConfigData =
&SmartcardExtension->ReaderExtension->SerialConfigData;
SmartcardDebug(
DEBUG_TRACE,
("%s!TLP3ReaderPower: Enter (%lx)\n",
DRIVER_NAME,
SmartcardExtension->MinorIoControlCode)
);
_try {
#if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
// we have to call GetCommStatus to reset the error condition
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_GET_COMMSTATUS;
SmartcardExtension->SmartcardRequest.BufferLength = 0;
SmartcardExtension->SmartcardReply.BufferLength =
sizeof(SERIAL_STATUS);
status = TLP3SerialIo(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
#endif
//
// Set standard parameters for serial port
//
serialConfigData->LineControl.Parity = EVEN_PARITY;
serialConfigData->LineControl.StopBits = STOP_BITS_2;
serialConfigData->BaudRate.BaudRate =
SmartcardExtension->ReaderCapabilities.DataRate.Default;
// we set very short timeouts to get the ATR as fast as possible
serialConfigData->Timeouts.ReadIntervalTimeout =
READ_INTERVAL_TIMEOUT_ATR;
serialConfigData->Timeouts.ReadTotalTimeoutConstant =
READ_TOTAL_TIMEOUT_CONSTANT_ATR;
status = TLP3ConfigureSerialPort(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
if (status != STATUS_SUCCESS) {
leave;
}
// We don't send data to the reader, so set Number of bytes to send = 0
SmartcardExtension->SmartcardRequest.BufferLength = 0;
// Default number of bytes we expect to get back
SmartcardExtension->SmartcardReply.BufferLength = 0;
//
// Since power down triggers the UpdateSerialStatus function, we have
// to inform it that we forced the change of the status and not the user
// (who might have removed and inserted a card)
//
// SmartcardExtension->ReaderExtension->PowerRequest = TRUE;
// purge the serial buffer (it can contain the pnp id of the reader)
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_PURGE;
*(PULONG) SmartcardExtension->SmartcardRequest.Buffer =
SERIAL_PURGE_RXCLEAR | SERIAL_PURGE_TXCLEAR;;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(ULONG);
status = TLP3SerialIo(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
if (status != STATUS_SUCCESS) {
leave;
}
SmartcardExtension->CardCapabilities.ATR.Length = 0;
for (step = 0; NT_SUCCESS(status); step++) {
if (SmartcardExtension->MinorIoControlCode ==
SCARD_WARM_RESET &&
step == 0) {
step = 4;
}
switch (step) {
case 0:
// RTS = 0 means reader is in command mode
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_CLR_RTS;
//
// This is the minimum wait time we have to wait before
// we can send commands to the microcontroller.
//
waitTime = 1000;
break;
case 1:
// write power down command to the reader
SmartcardExtension->ReaderExtension->SerialIoControlCode =
SMARTCARD_WRITE;
SmartcardExtension->SmartcardRequest.BufferLength = 1;
SmartcardExtension->SmartcardRequest.Buffer[0] =
READER_CMD_POWER_DOWN;
waitTime = 100;
break;
case 2:
// Read back the echo of the reader
SmartcardExtension->ReaderExtension->SerialIoControlCode =
SMARTCARD_READ;
SmartcardExtension->SmartcardReply.BufferLength = 1;
// Wait the recovery time for the microcontroller
waitTime = 1000;
break;
case 3:
// set RTS again so the microcontroller can execute the command
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_RTS;
waitTime = 10000;
break;
case 4:
if (SmartcardExtension->MinorIoControlCode == SCARD_POWER_DOWN) {
if (SmartcardExtension->ReaderCapabilities.CurrentState >
SCARD_PRESENT) {
SmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_PRESENT;
}
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
status = STATUS_SUCCESS;
leave;
}
// clear RTS to switch to command mode
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_CLR_RTS;
// Wait the recovery time for the microcontroller
waitTime = 1000;
break;
case 5:
// write the appropriate reset command to the reader
SmartcardExtension->ReaderExtension->SerialIoControlCode =
SMARTCARD_WRITE;
SmartcardExtension->SmartcardRequest.BufferLength = 1;
switch (SmartcardExtension->MinorIoControlCode) {
case SCARD_COLD_RESET:
SmartcardExtension->SmartcardRequest.Buffer[0] =
READER_CMD_COLD_RESET;
break;
case SCARD_WARM_RESET:
SmartcardExtension->SmartcardRequest.Buffer[0] =
READER_CMD_WARM_RESET;
break;
}
waitTime = 100;
break;
case 6:
// Read back the echo of the reader
SmartcardExtension->ReaderExtension->SerialIoControlCode =
SMARTCARD_READ;
SmartcardExtension->SmartcardReply.BufferLength = 1;
//
// This is the time we need to wait for the microcontroller
// to recover before we can set RTS again
//
waitTime = 1000;
break;
case 7:
// set RTS again so the microcontroller can execute the command
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_RTS;
waitTime = 10000;
break;
case 8:
//
// We now try to get the ATR as fast as possible.
// Therefor we prev. set a very short read timeout and
// 'hope' that the card delivered its ATR within this
// short time. To verify the correctness of the ATR we call
// SmartcardUpdateCardCapabilities(). If this call returns
// with STATUS_SUCCESS we know that the ATR is complete.
// Otherwise we read again and append the new data to the
// ATR buffer in the CardCapabilities and try again.
//
SmartcardExtension->ReaderExtension->SerialIoControlCode =
SMARTCARD_READ;
SmartcardExtension->SmartcardReply.BufferLength =
MAXIMUM_ATR_LENGTH -
SmartcardExtension->CardCapabilities.ATR.Length;
waitTime = 0;
break;
case 9:
if (SmartcardExtension->SmartcardReply.BufferLength != 0) {
ASSERT(
SmartcardExtension->CardCapabilities.ATR.Length +
SmartcardExtension->SmartcardReply.BufferLength <
MAXIMUM_ATR_LENGTH
);
if( SmartcardExtension->CardCapabilities.ATR.Length +
SmartcardExtension->SmartcardReply.BufferLength >=
MAXIMUM_ATR_LENGTH) {
status = STATUS_UNRECOGNIZED_MEDIA;
leave;
}
// we got some ATR bytes.
RtlCopyMemory(
SmartcardExtension->CardCapabilities.ATR.Buffer +
SmartcardExtension->CardCapabilities.ATR.Length,
SmartcardExtension->SmartcardReply.Buffer,
SmartcardExtension->SmartcardReply.BufferLength
);
SmartcardExtension->CardCapabilities.ATR.Length +=
(UCHAR) SmartcardExtension->SmartcardReply.BufferLength;
status = SmartcardUpdateCardCapabilities(
SmartcardExtension
);
}
if (status != STATUS_SUCCESS && numTry < 25) {
if (SmartcardExtension->SmartcardReply.BufferLength != 0) {
// Because we received some data, we reset our counter
numTry = 0;
} else {
// ATR is incomplete. Try again to get ATR bytes.
numTry += 1;
}
// continue with step 8
step = 7;
status = STATUS_TIMEOUT;
continue;
}
if (status != STATUS_SUCCESS) {
leave;
}
// No break
case 10:
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&oldIrql
);
if (SmartcardExtension->ReaderCapabilities.CurrentState <=
SCARD_ABSENT) {
status = STATUS_MEDIA_CHANGED;
}
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
oldIrql
);
if (status != STATUS_SUCCESS) {
leave;
}
#ifdef SIMULATION
if (SmartcardExtension->ReaderExtension->SimulationLevel &
SIM_ATR_TRASH) {
ULONG index;
LARGE_INTEGER tickCount;
KeQueryTickCount(
&tickCount
);
SmartcardExtension->CardCapabilities.ATR.Length =
(UCHAR) tickCount.LowPart % MAXIMUM_ATR_LENGTH;
for (index = 0;
index < SmartcardExtension->CardCapabilities.ATR.Length;
index++) {
SmartcardExtension->CardCapabilities.ATR.Buffer[index] *=
(UCHAR) tickCount.LowPart;
}
SmartcardDebug(
DEBUG_SIMULATION,
("%s!TLP3ReaderPower: SIM ATR trash\n",
DRIVER_NAME)
);
}
#endif
// Copy ATR to user space
if (SmartcardExtension->IoRequest.ReplyBuffer) {
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->CardCapabilities.ATR.Length
);
// Tell user length of ATR
*SmartcardExtension->IoRequest.Information =
SmartcardExtension->CardCapabilities.ATR.Length;
}
//
// If the card uses invers convention we need to switch
// the serial driver to odd paritiy
//
if (SmartcardExtension->CardCapabilities.InversConvention) {
serialConfigData->LineControl.Parity = ODD_PARITY;
}
//
// If the extra guard time is 255 it means that our
// frame we have to expect from the card has only
// 1 instead of 2 stop bits
// 1start bit + 8data bits + 1parity + 1stop == 11 etu
// see iso 7816-3 6.1.4.4 Extra Guard Time N
//
if (SmartcardExtension->CardCapabilities.PtsData.StopBits == 1) {
serialConfigData->LineControl.StopBits = STOP_BIT_1;
}
// Change data rate according to the new settings
serialConfigData->BaudRate.BaudRate =
SmartcardExtension->CardCapabilities.PtsData.DataRate;
// depending on the protocol set the timeout values
if (SmartcardExtension->CardCapabilities.Protocol.Selected &
SCARD_PROTOCOL_T1) {
// set timeouts
serialConfigData->Timeouts.ReadTotalTimeoutConstant =
SmartcardExtension->CardCapabilities.T1.BWT / 1000;
serialConfigData->Timeouts.ReadIntervalTimeout =
SmartcardExtension->CardCapabilities.T1.CWT / 1000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -