#include "mouhid.h"
-static USHORT MouHid_ButtonDownFlags[] =
+static USHORT MouHid_ButtonUpFlags[] =
{
+ 0xFF, /* unused */
MOUSE_LEFT_BUTTON_DOWN,
MOUSE_RIGHT_BUTTON_DOWN,
MOUSE_MIDDLE_BUTTON_DOWN,
MOUSE_BUTTON_5_DOWN
};
-static USHORT MouHid_ButtonUpFlags[] =
+static USHORT MouHid_ButtonDownFlags[] =
{
+ 0xFF, /* unused */
MOUSE_LEFT_BUTTON_UP,
MOUSE_RIGHT_BUTTON_UP,
MOUSE_MIDDLE_BUTTON_UP,
MOUSE_BUTTON_5_UP
};
+
+VOID
+MouHid_GetButtonMove(
+ IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
+ OUT PLONG LastX,
+ OUT PLONG LastY)
+{
+ NTSTATUS Status;
+ ULONG ValueX, ValueY;
+
+ /* init result */
+ *LastX = 0;
+ *LastY = 0;
+
+ if (!DeviceExtension->MouseAbsolute)
+ {
+ /* get scaled usage value x */
+ Status = HidP_GetScaledUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_X,
+ LastX,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ if (Status != HIDP_STATUS_SUCCESS)
+ {
+ /* FIXME: handle more errors */
+ if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+ {
+ /* FIXME: assume it operates in absolute mode */
+ DeviceExtension->MouseAbsolute = TRUE;
+
+ /* get unscaled value */
+ Status = HidP_GetUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_X,
+ &ValueX,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ /* FIXME handle error */
+ ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+ /* absolute pointing devices values need be in range 0 - 0xffff */
+ ASSERT(DeviceExtension->ValueCapsX.LogicalMax > 0);
+ ASSERT(DeviceExtension->ValueCapsX.LogicalMax > DeviceExtension->ValueCapsX.LogicalMin);
+
+ /* convert to logical range */
+ *LastX = (ValueX * VIRTUAL_SCREEN_SIZE_X) / DeviceExtension->ValueCapsX.LogicalMax;
+ }
+ }
+ }
+ else
+ {
+ /* get unscaled value */
+ Status = HidP_GetUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_X,
+ &ValueX,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ /* FIXME handle error */
+ ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+ /* absolute pointing devices values need be in range 0 - 0xffff */
+ ASSERT(DeviceExtension->ValueCapsX.LogicalMax > 0);
+ ASSERT(DeviceExtension->ValueCapsX.LogicalMax > DeviceExtension->ValueCapsX.LogicalMin);
+
+ /* convert to logical range */
+ *LastX = (ValueX * VIRTUAL_SCREEN_SIZE_X) / DeviceExtension->ValueCapsX.LogicalMax;
+ }
+
+ if (!DeviceExtension->MouseAbsolute)
+ {
+ /* get scaled usage value y */
+ Status = HidP_GetScaledUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_Y,
+ LastY,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ if (Status != HIDP_STATUS_SUCCESS)
+ {
+ // FIXME: handle more errors
+ if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+ {
+ // assume it operates in absolute mode
+ DeviceExtension->MouseAbsolute = TRUE;
+
+ // get unscaled value
+ Status = HidP_GetUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_Y,
+ &ValueY,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ /* FIXME handle error */
+ ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+ /* absolute pointing devices values need be in range 0 - 0xffff */
+ ASSERT(DeviceExtension->ValueCapsY.LogicalMax > 0);
+ ASSERT(DeviceExtension->ValueCapsY.LogicalMax > DeviceExtension->ValueCapsY.LogicalMin);
+
+ /* convert to logical range */
+ *LastY = (ValueY * VIRTUAL_SCREEN_SIZE_Y) / DeviceExtension->ValueCapsY.LogicalMax;
+ }
+ }
+ }
+ else
+ {
+ // get unscaled value
+ Status = HidP_GetUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_Y,
+ &ValueY,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+
+ /* FIXME handle error */
+ ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+ /* absolute pointing devices values need be in range 0 - 0xffff */
+ ASSERT(DeviceExtension->ValueCapsY.LogicalMax > 0);
+ ASSERT(DeviceExtension->ValueCapsY.LogicalMax > DeviceExtension->ValueCapsY.LogicalMin);
+
+ /* convert to logical range */
+ *LastY = (ValueY * VIRTUAL_SCREEN_SIZE_Y) / DeviceExtension->ValueCapsY.LogicalMax;
+ }
+}
+
VOID
MouHid_GetButtonFlags(
- IN PDEVICE_OBJECT DeviceObject,
- OUT PUSHORT ButtonFlags)
+ IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
+ OUT PUSHORT ButtonFlags,
+ OUT PUSHORT Flags)
{
- PMOUHID_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
USAGE Usage;
ULONG Index;
PUSAGE TempList;
ULONG CurrentUsageListLength;
- /* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
/* init flags */
*ButtonFlags = 0;
+ *Flags = 0;
/* get usages */
CurrentUsageListLength = DeviceExtension->UsageListLength;
- Status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &CurrentUsageListLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
+ Status = HidP_GetUsages(HidP_Input,
+ HID_USAGE_PAGE_BUTTON,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ DeviceExtension->CurrentUsageList,
+ &CurrentUsageListLength,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
if (Status != HIDP_STATUS_SUCCESS)
{
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
}
/* extract usage list difference */
- Status = HidP_UsageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
+ Status = HidP_UsageListDifference(DeviceExtension->PreviousUsageList,
+ DeviceExtension->CurrentUsageList,
+ DeviceExtension->BreakUsageList,
+ DeviceExtension->MakeUsageList,
+ DeviceExtension->UsageListLength);
if (Status != HIDP_STATUS_SUCCESS)
{
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
TempList = DeviceExtension->CurrentUsageList;
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
DeviceExtension->PreviousUsageList = TempList;
+
+ if (DeviceExtension->MouseAbsolute)
+ {
+ // mouse operates absolute
+ *Flags |= MOUSE_MOVE_ABSOLUTE;
+ }
}
VOID
MouHid_DispatchInputData(
- IN PDEVICE_OBJECT DeviceObject,
+ IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
IN PMOUSE_INPUT_DATA InputData)
{
- PMOUHID_DEVICE_EXTENSION DeviceExtension;
KIRQL OldIrql;
ULONG InputDataConsumed;
- /* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ if (!DeviceExtension->ClassService)
+ return;
/* sanity check */
ASSERT(DeviceExtension->ClassService);
KeLowerIrql(OldIrql);
}
+NTSTATUS
+NTAPI
+MouHid_ReadCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+ USHORT ButtonFlags;
+ LONG UsageValue;
+ NTSTATUS Status;
+ LONG LastX, LastY;
+ MOUSE_INPUT_DATA MouseInputData;
+ USHORT Flags;
+
+ /* get device extension */
+ DeviceExtension = Context;
+
+ if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
+ Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
+ Irp->IoStatus.Status == STATUS_CANCELLED ||
+ DeviceExtension->StopReadReport)
+ {
+ /* failed to read or should be stopped*/
+ DPRINT1("[MOUHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
+
+ /* report no longer active */
+ DeviceExtension->ReadReportActive = FALSE;
+
+ /* request stopping of the report cycle */
+ DeviceExtension->StopReadReport = FALSE;
+
+ /* signal completion event */
+ KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ /* get mouse change */
+ MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
+
+ /* get mouse change flags */
+ MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags, &Flags);
+
+ /* init input data */
+ RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
+
+ /* init input data */
+ MouseInputData.ButtonFlags = ButtonFlags;
+ MouseInputData.Flags = Flags;
+ MouseInputData.LastX = LastX;
+ MouseInputData.LastY = LastY;
+
+ /* detect mouse wheel change */
+ if (DeviceExtension->MouseIdentifier == WHEELMOUSE_HID_HARDWARE)
+ {
+ /* get usage */
+ UsageValue = 0;
+ Status = HidP_GetScaledUsageValue(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_WHEEL,
+ &UsageValue,
+ DeviceExtension->PreparsedData,
+ DeviceExtension->Report,
+ DeviceExtension->ReportLength);
+ if (Status == HIDP_STATUS_SUCCESS && UsageValue != 0)
+ {
+ /* store wheel status */
+ MouseInputData.ButtonFlags |= MOUSE_WHEEL;
+ MouseInputData.ButtonData = (USHORT)(UsageValue * WHEEL_DELTA);
+ }
+ else
+ {
+ DPRINT("[MOUHID] failed to get wheel status with %x\n", Status);
+ }
+ }
+
+ DPRINT("[MOUHID] ReportData %02x %02x %02x %02x %02x %02x %02x\n",
+ DeviceExtension->Report[0] & 0xFF,
+ DeviceExtension->Report[1] & 0xFF, DeviceExtension->Report[2] & 0xFF,
+ DeviceExtension->Report[3] & 0xFF, DeviceExtension->Report[4] & 0xFF,
+ DeviceExtension->Report[5] & 0xFF, DeviceExtension->Report[6] & 0xFF);
+
+ DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonFlags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.Flags, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
+
+ /* dispatch mouse action */
+ MouHid_DispatchInputData(DeviceExtension, &MouseInputData);
+
+ /* re-init read */
+ MouHid_InitiateRead(DeviceExtension);
+
+ /* stop completion */
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+MouHid_InitiateRead(
+ IN PMOUHID_DEVICE_EXTENSION DeviceExtension)
+{
+ PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status;
+
+ /* re-use irp */
+ IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
+
+ /* init irp */
+ DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
+
+ /* get next stack location */
+ IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
+
+ /* init stack location */
+ IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
+ IoStack->Parameters.Read.Key = 0;
+ IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
+ IoStack->MajorFunction = IRP_MJ_READ;
+ IoStack->FileObject = DeviceExtension->FileObject;
+
+ /* set completion routine */
+ IoSetCompletionRoutine(DeviceExtension->Irp, MouHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
+
+ /* read is active */
+ DeviceExtension->ReadReportActive = TRUE;
+
+ /* start the read */
+ Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
+
+ /* done */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+MouHid_CreateCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ KeSetEvent(Context, 0, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
NTSTATUS
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED
- ASSERT(FALSE);
- return STATUS_NOT_IMPLEMENTED;
+ PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status;
+ KEVENT Event;
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ DPRINT("MOUHID: IRP_MJ_CREATE\n");
+
+ /* get device extension */
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* get stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* copy stack location to next */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ /* init event */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+ /* prepare irp */
+ IoSetCompletionRoutine(Irp, MouHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
+
+ /* call lower driver */
+ Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* request pending */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ }
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ /* failed */
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* is the driver already in use */
+ if (DeviceExtension->FileObject == NULL)
+ {
+ /* did the caller specify correct attributes */
+ ASSERT(IoStack->Parameters.Create.SecurityContext);
+ if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
+ {
+ /* store file object */
+ DeviceExtension->FileObject = IoStack->FileObject;
+
+ /* reset event */
+ KeResetEvent(&DeviceExtension->ReadCompletionEvent);
+
+ /* initiating read */
+ Status = MouHid_InitiateRead(DeviceExtension);
+ DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
+ if (Status == STATUS_PENDING)
+ {
+ /* report irp is pending */
+ Status = STATUS_SUCCESS;
+ }
+ }
+ }
+
+ /* complete request */
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
}
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED
- ASSERT(FALSE);
- return STATUS_NOT_IMPLEMENTED;
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ /* get device extension */
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ DPRINT("[MOUHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
+
+ if (DeviceExtension->ReadReportActive)
+ {
+ /* request stopping of the report cycle */
+ DeviceExtension->StopReadReport = TRUE;
+
+ /* wait until the reports have been read */
+ KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
+
+ /* cancel irp */
+ IoCancelIrp(DeviceExtension->Irp);
+ }
+
+ DPRINT("[MOUHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
+
+ /* remove file object */
+ DeviceExtension->FileObject = NULL;
+
+ /* skip location */
+ IoSkipCurrentIrpStackLocation(Irp);
+
+ /* pass irp to down the stack */
+ return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
}
NTSTATUS
NTAPI
-MouHid_DeviceControl(
+MouHid_InternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
/* get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DPRINT("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* handle requests */
- if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUSE_QUERY_ATTRIBUTES)
+ switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
{
+ case IOCTL_MOUSE_QUERY_ATTRIBUTES:
/* verify output buffer length */
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
{
/* invalid request */
+ DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
/* get output buffer */
- Attributes = (PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
+ Attributes = Irp->AssociatedIrp.SystemBuffer;
/* type of mouse */
Attributes->MouseIdentifier = DeviceExtension->MouseIdentifier;
/* queue length */
Attributes->InputDataQueueLength = 2;
+ DPRINT("[MOUHID] MouseIdentifier %x\n", Attributes->MouseIdentifier);
+ DPRINT("[MOUHID] NumberOfButtons %x\n", Attributes->NumberOfButtons);
+ DPRINT("[MOUHID] SampleRate %x\n", Attributes->SampleRate);
+ DPRINT("[MOUHID] InputDataQueueLength %x\n", Attributes->InputDataQueueLength);
+
/* complete request */
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_CONNECT)
- {
+
+ case IOCTL_INTERNAL_MOUSE_CONNECT:
/* verify input buffer length */
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
{
}
/* get connect data */
- Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ Data = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
/* store connect details */
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT)
- {
+
+ case IOCTL_INTERNAL_MOUSE_DISCONNECT:
/* not supported */
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_ENABLE)
- {
+
+ case IOCTL_INTERNAL_MOUSE_ENABLE:
/* not supported */
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISABLE)
- {
+
+ case IOCTL_INTERNAL_MOUSE_DISABLE:
/* not supported */
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
+ DPRINT1("[MOUHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
/* unknown request not supported */
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
NTSTATUS
NTAPI
-MouHid_InternalDeviceControl(
+MouHid_DeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PMOUHID_DEVICE_EXTENSION DeviceExtension;
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* skip stack location */
IoSkipCurrentIrpStackLocation(Irp);
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED
- ASSERT(FALSE);
- return STATUS_NOT_IMPLEMENTED;
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+ PoStartNextPowerIrp(Irp);
+ IoSkipCurrentIrpStackLocation(Irp);
+ return PoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+}
+
+NTSTATUS
+NTAPI
+MouHid_SystemControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
}
NTSTATUS
IO_STATUS_BLOCK IoStatus;
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* init event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* build request */
- Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
+ Irp = IoBuildDeviceIoControlRequest(IoControlCode,
+ DeviceExtension->NextDeviceObject,
+ InputBuffer,
+ InputBufferSize,
+ OutputBuffer,
+ OutputBufferSize,
+ FALSE,
+ &Event,
+ &IoStatus);
if (!Irp)
{
/* no memory */
HID_COLLECTION_INFORMATION Information;
PVOID PreparsedData;
HIDP_CAPS Capabilities;
- ULONG ValueCapsLength;
+ USHORT ValueCapsLength;
HIDP_VALUE_CAPS ValueCaps;
PMOUHID_DEVICE_EXTENSION DeviceExtension;
- PUSHORT Buffer;
+ PUSAGE Buffer;
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* query collection information */
- Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
+ Status = MouHid_SubmitRequest(DeviceObject,
+ IOCTL_HID_GET_COLLECTION_INFORMATION,
+ 0,
+ NULL,
+ sizeof(HID_COLLECTION_INFORMATION),
+ &Information);
if (!NT_SUCCESS(Status))
{
/* failed to query collection information */
+ DPRINT1("[MOUHID] failed to obtain collection information with %x\n", Status);
return Status;
}
/* lets allocate space for preparsed data */
- PreparsedData = ExAllocatePool(NonPagedPool, Information.DescriptorSize);
- if (PreparsedData)
+ PreparsedData = ExAllocatePoolWithTag(NonPagedPool, Information.DescriptorSize, MOUHID_TAG);
+ if (!PreparsedData)
{
/* no memory */
+ DPRINT1("[MOUHID] no memory size %u\n", Information.DescriptorSize);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* now obtain the preparsed data */
- Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_DRIVER_CONFIG, 0, NULL, Information.DescriptorSize, PreparsedData);
+ Status = MouHid_SubmitRequest(DeviceObject,
+ IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
+ 0,
+ NULL,
+ Information.DescriptorSize,
+ PreparsedData);
if (!NT_SUCCESS(Status))
{
/* failed to get preparsed data */
- ExFreePool(PreparsedData);
+ DPRINT1("[MOUHID] failed to obtain collection information with %x\n", Status);
+ ExFreePoolWithTag(PreparsedData, MOUHID_TAG);
return Status;
}
/* lets get the caps */
Status = HidP_GetCaps(PreparsedData, &Capabilities);
- if (!NT_SUCCESS(Status))
+ if (Status != HIDP_STATUS_SUCCESS)
{
/* failed to get capabilities */
- ExFreePool(PreparsedData);
+ DPRINT1("[MOUHID] failed to obtain caps with %x\n", Status);
+ ExFreePoolWithTag(PreparsedData, MOUHID_TAG);
return Status;
}
+ DPRINT("[MOUHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
+
/* verify capabilities */
- if (Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
+ if ((Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE) || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
{
/* not supported */
- ExFreePool(PreparsedData);
+ ExFreePoolWithTag(PreparsedData, MOUHID_TAG);
return STATUS_UNSUCCESSFUL;
}
- /* init input report*/
+ /* init input report */
DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
ASSERT(DeviceExtension->ReportLength);
- DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
+ DeviceExtension->Report = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->ReportLength, MOUHID_TAG);
ASSERT(DeviceExtension->Report);
RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
- DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
+
+ /* build mdl */
+ DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report,
+ DeviceExtension->ReportLength,
+ FALSE,
+ FALSE,
+ NULL);
ASSERT(DeviceExtension->ReportMDL);
+ /* init mdl */
+ MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
/* get max number of buttons */
- Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
+ Buttons = HidP_MaxUsageListLength(HidP_Input,
+ HID_USAGE_PAGE_BUTTON,
+ PreparsedData);
+ DPRINT("[MOUHID] Buttons %lu\n", Buttons);
ASSERT(Buttons > 0);
/* now allocate an array for those buttons */
- Buffer = ExAllocatePool(NonPagedPool, sizeof(USAGE) * 4 * Buttons);
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(USAGE) * 4 * Buttons, MOUHID_TAG);
if (!Buffer)
{
/* no memory */
- ExFreePool(PreparsedData);
+ ExFreePoolWithTag(PreparsedData, MOUHID_TAG);
return STATUS_INSUFFICIENT_RESOURCES;
}
+ DeviceExtension->UsageListBuffer = Buffer;
/* init usage lists */
RtlZeroMemory(Buffer, sizeof(USAGE) * 4 * Buttons);
DeviceExtension->PreparsedData = PreparsedData;
ValueCapsLength = 1;
- HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
+ HidP_GetSpecificValueCaps(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_X,
+ &DeviceExtension->ValueCapsX,
+ &ValueCapsLength,
+ PreparsedData);
ValueCapsLength = 1;
- HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
+ HidP_GetSpecificValueCaps(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_Y,
+ &DeviceExtension->ValueCapsY,
+ &ValueCapsLength,
+ PreparsedData);
/* now check for wheel mouse support */
ValueCapsLength = 1;
- Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &ValueCaps, &ValueCapsLength, PreparsedData);
+ Status = HidP_GetSpecificValueCaps(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_WHEEL,
+ &ValueCaps,
+ &ValueCapsLength,
+ PreparsedData);
if (Status == HIDP_STATUS_SUCCESS )
{
/* mouse has wheel support */
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
+ DPRINT("[MOUHID] mouse wheel support detected\n", Status);
}
else
{
/* check if the mouse has z-axis */
ValueCapsLength = 1;
- Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Z, &ValueCaps, &ValueCapsLength, PreparsedData);
+ Status = HidP_GetSpecificValueCaps(HidP_Input,
+ HID_USAGE_PAGE_GENERIC,
+ HIDP_LINK_COLLECTION_UNSPECIFIED,
+ HID_USAGE_GENERIC_Z,
+ &ValueCaps,
+ &ValueCapsLength,
+ PreparsedData);
if (Status == HIDP_STATUS_SUCCESS && ValueCapsLength == 1)
{
/* wheel support */
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
+ DPRINT("[MOUHID] mouse wheel support detected with z-axis\n", Status);
}
}
+ /* check if mice is absolute */
+ if (DeviceExtension->ValueCapsY.LogicalMax > DeviceExtension->ValueCapsY.LogicalMin ||
+ DeviceExtension->ValueCapsX.LogicalMax > DeviceExtension->ValueCapsX.LogicalMin)
+ {
+ /* mice is absolute */
+ DeviceExtension->MouseAbsolute = TRUE;
+ }
+
/* completed successfully */
return STATUS_SUCCESS;
}
IN PIRP Irp,
IN PVOID Context)
{
- KeSetEvent((PKEVENT)Context, 0, FALSE);
+ KeSetEvent(Context, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
+NTSTATUS
+NTAPI
+MouHid_FreeResources(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ /* get device extension */
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* free resources */
+ if (DeviceExtension->PreparsedData)
+ {
+ ExFreePoolWithTag(DeviceExtension->PreparsedData, MOUHID_TAG);
+ DeviceExtension->PreparsedData = NULL;
+ }
+
+ if (DeviceExtension->UsageListBuffer)
+ {
+ ExFreePoolWithTag(DeviceExtension->UsageListBuffer, MOUHID_TAG);
+ DeviceExtension->UsageListBuffer = NULL;
+ DeviceExtension->CurrentUsageList = NULL;
+ DeviceExtension->PreviousUsageList = NULL;
+ DeviceExtension->MakeUsageList = NULL;
+ DeviceExtension->BreakUsageList = NULL;
+ }
+
+ if (DeviceExtension->ReportMDL)
+ {
+ IoFreeMdl(DeviceExtension->ReportMDL);
+ DeviceExtension->ReportMDL = NULL;
+ }
+
+ if (DeviceExtension->Report)
+ {
+ ExFreePoolWithTag(DeviceExtension->Report, MOUHID_TAG);
+ DeviceExtension->Report = NULL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+MouHid_Flush(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ /* get device extension */
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* skip current stack location */
+ IoSkipCurrentIrpStackLocation(Irp);
+
+ /* get next stack location */
+ IoStack = IoGetNextIrpStackLocation(Irp);
+
+ /* change request to hid flush queue request */
+ IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
+ IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
+
+ /* call device */
+ return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+}
+
NTSTATUS
NTAPI
MouHid_Pnp(
PMOUHID_DEVICE_EXTENSION DeviceExtension;
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DPRINT("[MOUHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
- if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE)
+ switch (IoStack->MinorFunction)
{
+ case IRP_MN_STOP_DEVICE:
+ case IRP_MN_SURPRISE_REMOVAL:
+ /* free resources */
+ MouHid_FreeResources(DeviceObject);
+ case IRP_MN_CANCEL_REMOVE_DEVICE:
+ case IRP_MN_QUERY_STOP_DEVICE:
+ case IRP_MN_CANCEL_STOP_DEVICE:
+ case IRP_MN_QUERY_REMOVE_DEVICE:
/* indicate success */
Irp->IoStatus.Status = STATUS_SUCCESS;
/* dispatch to lower device */
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
- }
- else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
- {
+
+ case IRP_MN_REMOVE_DEVICE:
/* FIXME synchronization */
+ /* request stop */
+ DeviceExtension->StopReadReport = TRUE;
+
/* cancel irp */
IoCancelIrp(DeviceExtension->Irp);
+ /* free resources */
+ MouHid_FreeResources(DeviceObject);
+
/* indicate success */
Irp->IoStatus.Status = STATUS_SUCCESS;
/* dispatch to lower device */
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+ /* wait for completion of stop event */
+ KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
+
+ /* free irp */
IoFreeIrp(DeviceExtension->Irp);
+
+ /* detach device */
IoDetachDevice(DeviceExtension->NextDeviceObject);
+
+ /* delete device */
IoDeleteDevice(DeviceObject);
+
+ /* done */
return Status;
- }
- else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
- {
+
+ case IRP_MN_START_DEVICE:
/* init event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* lets start the device */
Status = MouHid_StartDevice(DeviceObject);
- DPRINT1("MouHid_StartDevice %x\n", Status);
+ DPRINT("MouHid_StartDevice %x\n", Status);
/* complete request */
Irp->IoStatus.Status = Status;
/* done */
return Status;
- }
- else
- {
+
+ default:
/* skip irp stack location */
IoSkipCurrentIrpStackLocation(Irp);
POWER_STATE State;
/* create device object */
- Status = IoCreateDevice(DriverObject, sizeof(MOUHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &DeviceObject);
+ Status = IoCreateDevice(DriverObject,
+ sizeof(MOUHID_DEVICE_EXTENSION),
+ NULL,
+ FILE_DEVICE_MOUSE,
+ 0,
+ FALSE,
+ &DeviceObject);
if (!NT_SUCCESS(Status))
{
/* failed to create device object */
}
/* get device extension */
- DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = DeviceObject->DeviceExtension;
/* zero extension */
RtlZeroMemory(DeviceExtension, sizeof(MOUHID_DEVICE_EXTENSION));
DeviceExtension->MouseIdentifier = MOUSE_HID_HARDWARE;
DeviceExtension->WheelUsagePage = 0;
DeviceExtension->NextDeviceObject = NextDeviceObject;
- KeInitializeEvent(&DeviceExtension->Event, NotificationEvent, FALSE);
+ KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
/* FIXME handle allocation error */
IN PDRIVER_OBJECT DriverObject)
{
UNIMPLEMENTED
- ASSERT(FALSE);
}
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouHid_Create;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouHid_Close;
+ DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = MouHid_Flush;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MouHid_DeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouHid_InternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = MouHid_Power;
DriverObject->MajorFunction[IRP_MJ_PNP] = MouHid_Pnp;
+ DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = MouHid_SystemControl;
DriverObject->DriverUnload = MouHid_Unload;
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;