📄 io.c
字号:
int i, numReads;
KeInitializeEvent(&event, NotificationEvent, FALSE);
if (!NT_SUCCESS(status)) {
return status;
}
self = DeviceExtension->Self;
irp = DeviceExtension->ReadIrp;
Print(DeviceExtension, DBG_SS_TRACE, ("Read pending...\n"));
*ActualBytesRead = 0;
while (*ActualBytesRead < Buflen) {
KeClearEvent(&event);
IoReuseIrp(irp, STATUS_SUCCESS);
irp->AssociatedIrp.SystemBuffer = ReadBuffer;
stack = IoGetNextIrpStackLocation(irp);
stack->Parameters.Read.Length = 1;
stack->Parameters.Read.ByteOffset.QuadPart = (LONGLONG) 0;
stack->MajorFunction = IRP_MJ_READ;
//
// Hook a completion routine for when the device completes.
//
IoSetCompletionRoutine(irp,
SerialMouseReadSerialPortComplete,
&event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(DeviceExtension->TopOfStack, irp);
if (status == STATUS_PENDING) {
//
// Wait for the IRP
//
status = KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
if (status == STATUS_SUCCESS) {
status = irp->IoStatus.Status;
}
}
if (!NT_SUCCESS(status) || status == STATUS_TIMEOUT) {
Print(DeviceExtension, DBG_SS_NOISE,
("IO Call failed with status %x\n", status));
return status;
}
*ActualBytesRead += (USHORT) irp->IoStatus.Information;
ReadBuffer += (USHORT) irp->IoStatus.Information;
}
return status;
}
NTSTATUS
SerialMouseWriteSerialPort (
PDEVICE_EXTENSION DeviceExtension,
PCHAR WriteBuffer,
ULONG NumBytes,
PIO_STATUS_BLOCK IoStatusBlock
)
/*++
Routine Description:
Performs a synchronous write on the serial port. Used during setup so that
the device can be configured.
Return value:
NTSTATUS - STATUS_SUCCESS if the read was successful, error code otherwise
--*/
{
NTSTATUS status;
PIRP irp;
LARGE_INTEGER startingOffset;
KEVENT event;
int i, numReads;
startingOffset.QuadPart = (LONGLONG) 0;
KeInitializeEvent(&event,
NotificationEvent,
FALSE);
Print(DeviceExtension, DBG_SS_TRACE, ("Write pending...\n"));
//
// Create a new IRP because there's a chance that it might get cancelled.
// Can't cancel irps that I received.
// IRP_MJ_READ with completion routine
//
if (NULL == (irp = IoBuildSynchronousFsdRequest(
IRP_MJ_WRITE,
DeviceExtension->TopOfStack,
WriteBuffer,
NumBytes,
&startingOffset,
&event,
IoStatusBlock
))) {
Print(DeviceExtension, DBG_SS_ERROR, ("Failed to allocate IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(DeviceExtension->TopOfStack, irp);
if (status == STATUS_PENDING) {
// I don't know at this time if I can wait with the default time of
// 200 ms as I'm doing. In the help file for IoBuildSynchronousFsdRequest
// I think that it says I can't, but I'm not quite sure.
// Presently I will. I'll cancel the Irp if it isn't done.
status = KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE, // Not alertable
NULL);
}
status = IoStatusBlock->Status;
if (!NT_SUCCESS(status)) {
Print(DeviceExtension, DBG_SS_ERROR,
("IO Call failed with status %x\n",
status
));
return status;
}
if (!NT_SUCCESS(status)) {
Print(DeviceExtension, DBG_SS_ERROR,
("IO Call failed with status %x\n",
status
));
}
return status;
}
NTSTATUS
SerialMouseWait (
IN PDEVICE_EXTENSION DeviceExtension,
IN LONG Timeout
)
/*++
Routine Description:
Performs a wait for the specified time.
NB: Negative time is relative to the current time. Positive time
represents an absolute time to wait until.
Return value:
NTSTATUS
--*/
{
LARGE_INTEGER time;
time.QuadPart = (LONGLONG) Timeout;
Print(DeviceExtension, DBG_READ_NOISE,
("waiting for %d micro secs\n", Timeout));
if (KeSetTimer(&DeviceExtension->DelayTimer,
time,
NULL)) {
Print(DeviceExtension, DBG_SS_INFO, ("Timer already set\n"));
}
return KeWaitForSingleObject(&DeviceExtension->DelayTimer,
Executive,
KernelMode,
FALSE, // Not allertable
NULL); // No timeout structure
}
NTSTATUS
SerialMouseInitializePort(
PDEVICE_EXTENSION DeviceExtension
)
{
NTSTATUS status;
KEVENT event;
IO_STATUS_BLOCK iosb;
SERIAL_TIMEOUTS serialTimeouts;
SERIAL_HANDFLOW serialHandFlow;
KeInitializeEvent(&event, NotificationEvent, FALSE);
status =
SerialMouseIoSyncInternalIoctlEx(IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS,
DeviceExtension->TopOfStack,
&event,
&iosb,
NULL,
0,
&DeviceExtension->SerialBasicSettings,
sizeof(SERIAL_BASIC_SETTINGS));
//
// In case we are running on a port that does not support basic settings
//
if (!NT_SUCCESS(status)) {
SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_GET_TIMEOUTS,
DeviceExtension->TopOfStack,
&event,
&iosb,
NULL,
0,
&DeviceExtension->SerialBasicSettings.Timeouts,
sizeof(SERIAL_TIMEOUTS));
RtlZeroMemory(&serialTimeouts, sizeof(SERIAL_TIMEOUTS));
SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS,
DeviceExtension->TopOfStack,
&event,
&iosb,
&serialTimeouts,
sizeof(SERIAL_TIMEOUTS),
NULL,
0);
SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_GET_HANDFLOW,
DeviceExtension->TopOfStack,
&event,
&iosb,
NULL,
0,
&DeviceExtension->SerialBasicSettings.HandFlow,
sizeof(SERIAL_HANDFLOW));
serialHandFlow.ControlHandShake = SERIAL_DTR_CONTROL;
serialHandFlow.FlowReplace = SERIAL_RTS_CONTROL;
serialHandFlow.XonLimit = 0;
serialHandFlow.XoffLimit = 0;
status = SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_SET_HANDFLOW,
DeviceExtension->TopOfStack,
&event,
&iosb,
&serialHandFlow,
sizeof(SERIAL_HANDFLOW),
NULL,
0);
}
return status;
}
VOID
SerialMouseRestorePort(
PDEVICE_EXTENSION DeviceExtension
)
{
KEVENT event;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
status =
SerialMouseIoSyncInternalIoctlEx(IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS,
DeviceExtension->TopOfStack,
&event,
&iosb,
&DeviceExtension->SerialBasicSettings,
sizeof(SERIAL_BASIC_SETTINGS),
NULL,
0);
//
// 4-24 Once serial.sys supports this new IOCTL, this code can be removed
//
if (!NT_SUCCESS(status)) {
SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS,
DeviceExtension->TopOfStack,
&event,
&iosb,
&DeviceExtension->SerialBasicSettings.Timeouts,
sizeof(SERIAL_TIMEOUTS),
NULL,
0);
SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_SET_HANDFLOW,
DeviceExtension->TopOfStack,
&event,
&iosb,
&DeviceExtension->SerialBasicSettings.HandFlow,
sizeof(SERIAL_HANDFLOW),
NULL,
0);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -