?? io.c
字號:
/*++
Copyright (c) 1997-1998 Microsoft Corporation, All Rights Reserved
Module Name:
io.c
Abstract:
Contains functions that communicate to the serial driver below sermouse in
the stack. This includes the read/complete loop mechanism to acquire bytes
and IOCTL calls.
Environment:
Kernel & user mode.
Revision History:
--*/
#include "mouser.h"
#include "debug.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, SerialMousepIoSyncIoctl)
#pragma alloc_text (PAGE, SerialMousepIoSyncIoctlEx)
#endif
//
// Private definitions.
//
NTSTATUS
SerialMouseReadComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension // (PVOID Context)
)
/*++
Routine Description:
This routine is the read IRP completion routine. It is called when the
serial driver satisfies (or rejects) the IRP request we sent it. The
read report is analysed, and a MOUSE_INPUT_DATA structure is built
and sent to the mouse class driver via a callback routine.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Context - Pointer to the device context structure
Return Value:
NTSTATUS result code.
--*/
{
LARGE_INTEGER li;
ULONG inputDataConsumed,
buttonsDelta,
i;
NTSTATUS status;
PMOUSE_INPUT_DATA currentInput;
KIRQL oldIrql;
BOOLEAN startRead = TRUE;
Print(DeviceExtension, DBG_READ_TRACE, ("ReadComplete enter\n"));
//
// Obtain the current status of the IRP.
//
status = Irp->IoStatus.Status;
Print(DeviceExtension, DBG_SS_NOISE,
("Comp Routine: interlock was %d\n", DeviceExtension->ReadInterlock));
//
// If ReadInterlock is == START_READ, this func has been completed
// synchronously. Place IMMEDIATE_READ into the interlock to signify this
// situation; this will notify StartRead to loop when IoCallDriver returns.
// Otherwise, we have been completed async and it is safe to call StartRead()
//
startRead =
(SERIAL_MOUSE_START_READ !=
InterlockedCompareExchange(&DeviceExtension->ReadInterlock,
SERIAL_MOUSE_IMMEDIATE_READ,
SERIAL_MOUSE_START_READ));
//
// Determine if the IRP request was successful.
//
switch (status) {
case STATUS_SUCCESS:
//
// The buffer of the context now contains a single byte from the device.
//
Print(DeviceExtension, DBG_READ_NOISE,
("read, Information = %d\n",
Irp->IoStatus.Information
));
//
// Nothing read, just start another read and return
//
if (Irp->IoStatus.Information == 0) {
break;
}
ASSERT(Irp->IoStatus.Information == 1);
currentInput = &DeviceExtension->InputData;
Print(DeviceExtension, DBG_READ_NOISE,
("byte is 0x%x\n",
(ULONG) DeviceExtension->ReadBuffer[0]
));
if ((*DeviceExtension->ProtocolHandler)(
DeviceExtension,
currentInput,
&DeviceExtension->HandlerData,
DeviceExtension->ReadBuffer[0],
0
)) {
//
// The report is complete, compute the button deltas and send it off
//
// Do we have a button state change?
//
if (DeviceExtension->HandlerData.PreviousButtons ^ currentInput->RawButtons) {
//
// The state of the buttons changed. Make some calculations...
//
buttonsDelta = DeviceExtension->HandlerData.PreviousButtons ^
currentInput->RawButtons;
//
// Button 1.
//
if (buttonsDelta & MOUSE_BUTTON_1) {
if (currentInput->RawButtons & MOUSE_BUTTON_1) {
currentInput->ButtonFlags |= MOUSE_BUTTON_1_DOWN;
}
else {
currentInput->ButtonFlags |= MOUSE_BUTTON_1_UP;
}
}
//
// Button 2.
//
if (buttonsDelta & MOUSE_BUTTON_2) {
if (currentInput->RawButtons & MOUSE_BUTTON_2) {
currentInput->ButtonFlags |= MOUSE_BUTTON_2_DOWN;
}
else {
currentInput->ButtonFlags |= MOUSE_BUTTON_2_UP;
}
}
//
// Button 3.
//
if (buttonsDelta & MOUSE_BUTTON_3) {
if (currentInput->RawButtons & MOUSE_BUTTON_3) {
currentInput->ButtonFlags |= MOUSE_BUTTON_3_DOWN;
}
else {
currentInput->ButtonFlags |= MOUSE_BUTTON_3_UP;
}
}
DeviceExtension->HandlerData.PreviousButtons =
currentInput->RawButtons;
}
Print(DeviceExtension, DBG_READ_NOISE,
("Buttons: %0lx\n",
currentInput->Buttons
));
if (DeviceExtension->EnableCount) {
//
// Synchronization issue - it's not a big deal if .Enabled is set
// FALSE after the condition above, but before the callback below,
// so long as the .MouClassCallback field is not nulled. This is
// guaranteed since the disconnect IOCTL is not implemented yet.
//
// Mouse class callback assumes we are running at DISPATCH level,
// however this IoCompletion routine can be running <= DISPATCH.
// Raise the IRQL before calling the callback.
//
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
//
// Call the callback.
//
(*(PSERVICE_CALLBACK_ROUTINE)
DeviceExtension->ConnectData.ClassService) (
DeviceExtension->ConnectData.ClassDeviceObject,
currentInput,
currentInput+1,
&inputDataConsumed);
//
// Restore the previous IRQL right away.
//
KeLowerIrql(oldIrql);
if (1 != inputDataConsumed) {
//
// oh well, the packet was not consumed, just drop it
//
Print(DeviceExtension, DBG_READ_ERROR,
("packet not consumed!!!\n"));
}
}
//
// Clear the button flags for the next packet
//
currentInput->Buttons = 0;
}
break;
case STATUS_TIMEOUT:
// The IO timed out, this shouldn't happen because we set the timeouts
// to never when the device was initialized
break;
case STATUS_CANCELLED:
// The read IRP was cancelled. Do not send any more read IRPs.
//
// Set the event so that the stop code can continue processing
//
KeSetEvent(&DeviceExtension->StopEvent, 0, FALSE);
case STATUS_DELETE_PENDING:
case STATUS_DEVICE_NOT_CONNECTED:
//
// The serial mouse object is being deleted. We will soon
// receive Plug 'n Play notification of this device's removal,
// if we have not received it already.
//
Print(DeviceExtension, DBG_READ_INFO,
("removing lock on cancel, count is 0x%x\n",
DeviceExtension->EnableCount));
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, DeviceExtension->ReadIrp);
startRead = FALSE;
break;
default:
//
// Unknown device state
//
Print(DeviceExtension, DBG_READ_ERROR, ("read error\n"));
TRAP();
}
if (startRead) {
Print(DeviceExtension, DBG_READ_NOISE, ("calling StartRead directly\n"));
SerialMouseStartRead(DeviceExtension);
}
#if DBG
else {
Print(DeviceExtension, DBG_READ_NOISE, ("StartRead will loop\n"));
}
#endif
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
SerialMouseStartRead (
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Initiates a read to the serial port driver.
Note that the routine does not verify that the device context is in the
OperationPending state, but simply assumes it.
Note the IoCount must be incremented before entering into this read loop.
Arguments:
DeviceExtension - Device context structure
Return Value:
NTSTATUS result code from IoCallDriver().
--*/
{
PIRP irp;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -