?? tlp3nt.c
字號:
SmartcardDebug(
DEBUG_INFO,
( "%s!TLP3RemoveDevice: Exit\n",
DRIVER_NAME)
);
}
VOID
TLP3DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
The driver unload routine. This is called by the I/O system
when the device is unloaded from memory.
Arguments:
DriverObject - Pointer to driver object created by system.
Return Value:
STATUS_SUCCESS.
--*/
{
PAGED_CODE();
SmartcardDebug(
DEBUG_INFO,
("%s!TLP3DriverUnload\n",
DRIVER_NAME)
);
}
NTSTATUS
TLP3ConfigureSerialPort(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine will appropriately configure the serial port.
It makes synchronous calls to the serial port.
Arguments:
SmartcardExtension - Pointer to smart card struct
Return Value:
NTSTATUS
--*/
{
PSERIAL_READER_CONFIG configData = &SmartcardExtension->ReaderExtension->SerialConfigData;
NTSTATUS status = STATUS_SUCCESS;
USHORT i;
PUCHAR request = SmartcardExtension->SmartcardRequest.Buffer;
SmartcardExtension->SmartcardRequest.BufferLength = 0;
SmartcardExtension->SmartcardReply.BufferLength =
SmartcardExtension->SmartcardReply.BufferSize;
for (i = 0; status == STATUS_SUCCESS; i++) {
switch (i) {
case 0:
//
// Set up baudrate for the TLP3 reader
//
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_BAUD_RATE;
SmartcardExtension->SmartcardRequest.Buffer =
(PUCHAR) &configData->BaudRate;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(SERIAL_BAUD_RATE);
break;
case 1:
//
// Set up line control parameters
//
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_LINE_CONTROL;
SmartcardExtension->SmartcardRequest.Buffer =
(PUCHAR) &configData->LineControl;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(SERIAL_LINE_CONTROL);
break;
case 2:
//
// Set serial special characters
//
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_CHARS;
SmartcardExtension->SmartcardRequest.Buffer =
(PUCHAR) &configData->SerialChars;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(SERIAL_CHARS);
break;
case 3:
//
// Set up timeouts
//
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_TIMEOUTS;
SmartcardExtension->SmartcardRequest.Buffer =
(PUCHAR) &configData->Timeouts;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(SERIAL_TIMEOUTS);
break;
case 4:
// Set flowcontrol and handshaking
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_HANDFLOW;
SmartcardExtension->SmartcardRequest.Buffer =
(PUCHAR) &configData->HandFlow;
SmartcardExtension->SmartcardRequest.BufferLength =
sizeof(SERIAL_HANDFLOW);
break;
case 5:
// Set break off
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_BREAK_OFF;
break;
case 6:
// set DTR for the reader
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_DTR;
break;
case 7:
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_SET_RTS;
break;
case 8:
return STATUS_SUCCESS;
}
status = TLP3SerialIo(SmartcardExtension);
// restore pointer to original request buffer
SmartcardExtension->SmartcardRequest.Buffer = request;
}
return status;
}
NTSTATUS
TLP3StartSerialEventTracking(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine initializes serial event tracking.
It calls the serial driver to set a wait mask for CTS and DSR tracking.
--*/
{
NTSTATUS status;
PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PAGED_CODE();
readerExtension->SerialConfigData.SerialWaitMask =
SERIAL_EV_CTS | SERIAL_EV_DSR;
KeInitializeEvent(
&event,
NotificationEvent,
FALSE
);
//
// Send a wait mask to the serial driver. This call only sets the
// wait mask. We want to be informed when CTS or DSR changes its state
//
readerExtension->SerialStatusIrp = IoBuildDeviceIoControlRequest(
IOCTL_SERIAL_SET_WAIT_MASK,
readerExtension->AttachedDeviceObject,
&readerExtension->SerialConfigData.SerialWaitMask,
sizeof(readerExtension->SerialConfigData.SerialWaitMask),
NULL,
0,
FALSE,
&event,
&ioStatus
);
if (readerExtension->SerialStatusIrp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(
readerExtension->AttachedDeviceObject,
readerExtension->SerialStatusIrp,
);
if (status == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
ASSERT(status == STATUS_SUCCESS);
status = ioStatus.Status;
}
if (status == STATUS_SUCCESS) {
KIRQL oldIrql;
LARGE_INTEGER delayPeriod;
PIO_STACK_LOCATION irpSp;
//
// Now tell the serial driver that we want to be informed
// when CTS or DSR changes its state.
//
readerExtension->SerialStatusIrp = IoAllocateIrp(
(CCHAR) (SmartcardExtension->OsData->DeviceObject->StackSize + 1),
FALSE
);
if (readerExtension->SerialStatusIrp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
irpSp = IoGetNextIrpStackLocation( readerExtension->SerialStatusIrp );
irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
irpSp->Parameters.DeviceIoControl.OutputBufferLength =
sizeof(readerExtension->SerialConfigData.SerialWaitMask);
irpSp->Parameters.DeviceIoControl.IoControlCode =
IOCTL_SERIAL_WAIT_ON_MASK;
readerExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
&readerExtension->SerialConfigData.SerialWaitMask;
//
// this artificial delay is necessary to make this driver work
// with digi board cards
//
delayPeriod.HighPart = -1;
delayPeriod.LowPart = 100l * 1000 * (-10);
KeDelayExecutionThread(
KernelMode,
FALSE,
&delayPeriod
);
// We simulate a callback now that triggers the card supervision
TLP3SerialEvent(
SmartcardExtension->OsData->DeviceObject,
readerExtension->SerialStatusIrp,
SmartcardExtension
);
status = STATUS_SUCCESS;
}
return status;
}
VOID
TLP3CompleteCardTracking(
IN PSMARTCARD_EXTENSION SmartcardExtension
)
{
KIRQL ioIrql, keIrql;
PIRP notificationIrp;
IoAcquireCancelSpinLock(&ioIrql);
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&keIrql
);
notificationIrp = SmartcardExtension->OsData->NotificationIrp;
SmartcardExtension->OsData->NotificationIrp = NULL;
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
keIrql
);
if (notificationIrp) {
IoSetCancelRoutine(
notificationIrp,
NULL
);
}
IoReleaseCancelSpinLock(ioIrql);
if (notificationIrp) {
SmartcardDebug(
DEBUG_INFO,
("%s!TLP3CompleteCardTracking: Completing NotificationIrp %lxh\n",
DRIVER_NAME,
notificationIrp)
);
// finish the request
if (notificationIrp->Cancel) {
notificationIrp->IoStatus.Status = STATUS_CANCELLED;
} else {
notificationIrp->IoStatus.Status = STATUS_SUCCESS;
}
notificationIrp->IoStatus.Information = 0;
IoCompleteRequest(
notificationIrp,
IO_NO_INCREMENT
);
}
}
NTSTATUS
TLP3SerialEvent(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine is called in two cases:
a) CTS changed (card inserted or removed) or
b) DSR changed (reader has been removed)
For a) we update the card status and complete outstanding
card tracking requests.
For b) we start to unload the driver
NOTE: This function calls itself using IoCompletion. In the 'first'
callback the serial driver only tells us that something has changed.
We set up a call for 'what has changed' (GetModemStatus) which then
call this function again.
When we updated everything and we don't unload the driver card
tracking is started again.
--*/
{
NTSTATUS status;
KIRQL irql;
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&irql
);
if (SmartcardExtension->ReaderExtension->GetModemStatus) {
//
// This function requested the modem status previously.
// As part of the io-completion, this function is then
// called again. When we're here we can read the actual
// modem-status to figure out if the card is in the reader
//
if ((SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_DSR_STATE) == 0) {
SmartcardDebug(
DEBUG_INFO,
("%s!TLP3SerialEvent: Reader removed\n",
DRIVER_NAME)
);
//
// We set the mask to zero to signal that we can
// release the irp that we use for the serial events
//
SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask = 0;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
} else {
if (SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_CTS_STATE) {
// Card is inserted
SmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_SWALLOWED;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
SmartcardDebug(
DEBUG_INFO,
("%s!TLP3SerialEvent: Smart card inserted\n",
DRIVER_NAME)
);
} else {
// Card is removed
SmartcardExtension->CardCapabilities.ATR.Length = 0;
SmartcardExtension->ReaderCapabilities.CurrentState =
SCARD_ABSENT;
SmartcardExtension->CardCapabilities.Protocol.Selected =
SCARD_PROTOCOL_UNDEFINED;
SmartcardDebug(
DEBUG_INFO,
("%s!TLP3SerialEvent: Smart card removed\n",
DRIVER_NAME)
);
}
}
}
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
irql
);
//
// Only inform the user of a card insertion/removal event
// if this function isn't called due to a power down - power up cycle
//
if (SmartcardExtension->ReaderExtension->PowerRequest == FALSE) {
TLP3CompleteCardTracking(SmartcardExtension);
}
// The wait mask is set to 0 when the driver unloads
if (SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {
// The reader has been unplugged.
PDEVICE_EXTENSION deviceExtension =
SmartcardExtension->OsData->DeviceObject->DeviceExtension;
// schedule our remove thread
IoQueueWorkItem(
deviceExtension->CloseSerial,
(PIO_WORKITEM_ROUTINE) TLP3CloseSerialPort,
DelayedWorkQueue,
NULL
);
SmartcardDebug(
DEBUG_TRAC
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -