static USHORT MouHid_ButtonUpFlags[] =
{
+ 0xFF, /* unused */
MOUSE_LEFT_BUTTON_DOWN,
MOUSE_RIGHT_BUTTON_DOWN,
MOUSE_MIDDLE_BUTTON_DOWN,
static USHORT MouHid_ButtonDownFlags[] =
{
+ 0xFF, /* unused */
MOUSE_LEFT_BUTTON_UP,
MOUSE_RIGHT_BUTTON_UP,
MOUSE_MIDDLE_BUTTON_UP,
OUT PLONG LastY)
{
NTSTATUS Status;
+ ULONG ValueX, ValueY;
/* init result */
*LastX = 0;
/* get scaled usage value x */
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
- /* FIXME handle error */
- ASSERT(Status == HIDP_STATUS_SUCCESS);
+ 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, (PULONG)&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);
+
+ *LastX = (ValueX * 0xFFFF) / DeviceExtension->ValueCapsX.LogicalMax;
+ }
+ }
/* get scaled usage value y */
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
- /* FIXME handle error */
- ASSERT(Status == HIDP_STATUS_SUCCESS);
+ 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, (PULONG)&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);
+ *LastY = (ValueY * 0xFFFF) / DeviceExtension->ValueCapsY.LogicalMax;
+ }
+ }
+}
VOID
MouHid_GetButtonFlags(
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
- OUT PUSHORT ButtonFlags)
+ OUT PUSHORT ButtonFlags,
+ OUT PUSHORT Flags)
{
NTSTATUS Status;
USAGE Usage;
/* init flags */
*ButtonFlags = 0;
+ *Flags = 0;
/* get usages */
CurrentUsageListLength = DeviceExtension->UsageListLength;
TempList = DeviceExtension->CurrentUsageList;
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
DeviceExtension->PreviousUsageList = TempList;
+
+ if (DeviceExtension->MouseAbsolute)
+ {
+ // mouse operates absolute
+ *Flags |= MOUSE_MOVE_ABSOLUTE;
+ }
}
VOID
NTSTATUS Status;
LONG LastX, LastY;
MOUSE_INPUT_DATA MouseInputData;
+ USHORT Flags;
/* get device extension */
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)Context;
return STATUS_MORE_PROCESSING_REQUIRED;
}
- /* get mouse change flags */
- MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
-
/* 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;
/* 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)
+ if (Status == HIDP_STATUS_SUCCESS && UsageValue != 0)
{
/* store wheel status */
MouseInputData.ButtonFlags |= MOUSE_WHEEL;
- MouseInputData.ButtonData = (USHORT)UsageValue; /* FIXME */
+ MouseInputData.ButtonData = (USHORT)(UsageValue * WHEEL_DELTA);
}
else
{
- DPRINT1("[MOUHID] failed to get wheel status with %x\n", Status);
+ DPRINT("[MOUHID] failed to get wheel status with %x\n", Status);
}
}
- DPRINT1("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
+ 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 ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
/* dispatch mouse action */
MouHid_DispatchInputData(DeviceExtension, &MouseInputData);
KEVENT Event;
PMOUHID_DEVICE_EXTENSION DeviceExtension;
- DPRINT1("MOUHID: IRP_MJ_CREATE\n");
+ DPRINT("MOUHID: IRP_MJ_CREATE\n");
/* get device extension */
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* initiating read */
Status = MouHid_InitiateRead(DeviceExtension);
- DPRINT1("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
+ DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
if (Status == STATUS_PENDING)
{
/* report irp is pending */
NTSTATUS
NTAPI
-MouHid_DeviceControl(
+MouHid_InternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
/* get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("[MOUHID] DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+ DPRINT("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
/* get device extension */
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
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;
/* 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;
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)
{
IN PIRP Irp)
{
UNIMPLEMENTED
- ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
/* lets get the caps */
Status = HidP_GetCaps(PreparsedData, &Capabilities);
- if (!NT_SUCCESS(Status))
+ if (Status != HIDP_STATUS_SUCCESS)
{
/* failed to get capabilities */
DPRINT1("[MOUHID] failed to obtain caps with %x\n", Status);
return Status;
}
- DPRINT1("[MOUHID] Usage %x UsagePage %x\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
+ 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);
/* init input report*/
DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
ASSERT(DeviceExtension->ReportLength);
- DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
+ DeviceExtension->Report = (PCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
ASSERT(DeviceExtension->Report);
RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
/* get max number of buttons */
Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
- DPRINT1("[MOUHID] Buttons %lu\n", Buttons);
+ DPRINT("[MOUHID] Buttons %lu\n", Buttons);
ASSERT(Buttons > 0);
/* now allocate an array for those 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;
/* mouse has wheel support */
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
- DPRINT1("[MOUHID] mouse wheel support detected\n", Status);
+ DPRINT("[MOUHID] mouse wheel support detected\n", Status);
}
else
{
/* wheel support */
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
- DPRINT1("[MOUHID] mouse wheel support detected with z-axis\n", Status);
+ DPRINT("[MOUHID] mouse wheel support detected with z-axis\n", Status);
}
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
+NTSTATUS
+NTAPI
+MouHid_Flush(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PMOUHID_DEVICE_EXTENSION DeviceExtension;
+
+ /* get device extension */
+ DeviceExtension = (PMOUHID_DEVICE_EXTENSION)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(
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("[MOUHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
+ 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)
+ 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 ||
+ IoStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
{
/* indicate success */
Irp->IoStatus.Status = STATUS_SUCCESS;
{
/* FIXME synchronization */
+ /* request stop */
+ DeviceExtension->StopReadReport = TRUE;
+
/* cancel irp */
IoCancelIrp(DeviceExtension->Irp);
/* 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)
/* 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;
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;