📄 tlp3nt.c
字号:
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_TRACE,
("%s!TLP3SerialEvent: Exit (Release IRP)\n",
DRIVER_NAME)
);
//
// We don't need the IRP anymore, so free it and tell the
// io subsystem not to touch it anymore by returning the value below
//
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (SmartcardExtension->ReaderExtension->GetModemStatus == FALSE) {
//
// Setup call for device control to get modem status.
// The CTS signal tells us if the card is inserted or removed.
// CTS is high if the card is inserted.
//
PIO_STACK_LOCATION irpStack;
irpStack = IoGetNextIrpStackLocation(
SmartcardExtension->ReaderExtension->SerialStatusIrp
);
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->MinorFunction = 0UL;
irpStack->Parameters.DeviceIoControl.OutputBufferLength =
sizeof(SmartcardExtension->ReaderExtension->ModemStatus);
irpStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_SERIAL_GET_MODEMSTATUS;
SmartcardExtension->ReaderExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
&SmartcardExtension->ReaderExtension->ModemStatus;
SmartcardExtension->ReaderExtension->GetModemStatus = TRUE;
} else {
PIO_STACK_LOCATION irpStack;
// Setup call for device control to wait for a serial event
irpStack = IoGetNextIrpStackLocation(
SmartcardExtension->ReaderExtension->SerialStatusIrp
);
#if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
if (Irp->IoStatus.Status != STATUS_SUCCESS) {
//
// we need to call the serial driver to reset the internal
// error counters, otherwise the serial driver refuses to work
//
static SERIAL_STATUS serialStatus;
SmartcardDebug(
DEBUG_ERROR,
( "%s!TLP3SerialEvent: Reset of serial error condition...\n",
DRIVER_NAME)
);
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->MinorFunction = 0UL;
irpStack->Parameters.DeviceIoControl.OutputBufferLength =
sizeof(serialStatus);
irpStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_SERIAL_GET_COMMSTATUS;
SmartcardExtension->ReaderExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
&serialStatus;
} else
#endif
{
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->MinorFunction = 0UL;
irpStack->Parameters.DeviceIoControl.OutputBufferLength =
sizeof(SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask);
irpStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_SERIAL_WAIT_ON_MASK;
SmartcardExtension->ReaderExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
&SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask;
}
SmartcardExtension->ReaderExtension->GetModemStatus = FALSE;
}
IoSetCompletionRoutine(
SmartcardExtension->ReaderExtension->SerialStatusIrp,
TLP3SerialEvent,
SmartcardExtension,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(
SmartcardExtension->ReaderExtension->AttachedDeviceObject,
SmartcardExtension->ReaderExtension->SerialStatusIrp
);
return STATUS_MORE_PROCESSING_REQUIRED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -