|
|
/*
******************************************************************************** * * READ.C * * * VXDCLNT - Sample Ring-0 HID device mapper for Memphis * * Copyright 1997 Microsoft Corp. * * (ep) * ******************************************************************************** */
#include "vxdclnt.h"
/*
* WorkItemCallback_Read * */ VOID WorkItemCallback_Read(PVOID context) { deviceContext *device = (deviceContext *)context; NTSTATUS Status;
DBGOUT(("==> WorkItemCallback_Read()"));
device->dataLength.LowPart = device->dataLength.HighPart = 0; device->readPending = TRUE;
/*
* Do an asynchronous read on the device device. * When the device has a delta value to report, we will be called back * via ReadCompletion(). */ Status = _NtKernReadFile( device->devHandle, NULL, ReadCompletion, (PVOID)device, // context for callback
(PIO_STATUS_BLOCK)&device->ioStatusBlock, (PVOID)device->report, device->hidCapabilities.InputReportByteLength, &device->dataLength, NULL );
if (!NT_SUCCESS(Status) && (Status != STATUS_PENDING)) { /*
* Read failed. Since device is no longer usable, shut it down. */ DBGERR(("_NtKernReadFile error (Status=%xh) - SHUTTING DOWN THIS DEVICE", (UINT)Status)); device->readPending = FALSE; DequeueDevice(device); DestroyDevice(device); }
DBGOUT(("<== WorkItemCallback_Read()")); }
/*
* DispatchNtReadFile * * */ VOID _cdecl DispatchNtReadFile(deviceContext *device) { DBGOUT(("==> DispatchNtReadFile()")); /*
* Queue a work item to do the read; this way we'll be on a worker thread * instead of (possibly) the NTKERN thread when we call NtReadFile(). * This prevents a contention bug. */ _NtKernQueueWorkItem(&device->workItemRead, DelayedWorkQueue);
DBGOUT(("<== DispatchNtReadFile()")); }
/*
* ReadCompletion * * */ VOID ReadCompletion(IN PVOID Context, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved) { ULONG dX = 0, dY = 0, Buttons = 0, scrollWheel=0; NTSTATUS ntStatus; deviceContext *device = (deviceContext *)Context; UINT numActualButtons;
DBGOUT(("==> ReadCompletion()"));
device->readPending = FALSE;
/*
* If this callback got to us after we've shut down, just delete this device context. */ if (ShutDown){ TryDestroyAll(); return; }
/*
* If the read succeeded, parse out the report information. */ if (NT_SUCCESS(IoStatusBlock->Status)){
/*
* <<COMPLETE>> * * What types of usage-values will you parse out of the device report? * This is device specific. * The code below would be appropriate for a 2-dimensional pointing * device with buttons (e.g. a mouse or touch screen). * */
/*
* Parse the device "report" for the values we want. * * For each value, try HIDPARSE's scaled function first; * failing that, try the non-scaled function. * (the scaled functions can fail for some devices that don't * report their min and max values correctly). */
ntStatus = pHidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, (PLONG)&dX, device->hidDescriptor, (PUCHAR)device->report, device->hidCapabilities.InputReportByteLength); if (NT_ERROR(ntStatus)){ DBGERR(("pHidP_GetScaledUsageValue failed"));
ntStatus = pHidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &dX, device->hidDescriptor, (PUCHAR)device->report, device->hidCapabilities.InputReportByteLength); if (NT_ERROR(ntStatus)){ DBGERR(("pHidP_GetUsageValue failed")); } }
ntStatus = pHidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, (PLONG)&dY, device->hidDescriptor, (PUCHAR)device->report, device->hidCapabilities.InputReportByteLength); if (NT_ERROR(ntStatus)){ DBGERR(("pHidP_GetScaledUsageValue failed"));
ntStatus = pHidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &dY, device->hidDescriptor, (PUCHAR)device->report, device->hidCapabilities.InputReportByteLength); if (NT_ERROR(ntStatus)){ DBGERR(("pHidP_GetUsageValue failed")); } }
/*
* Parse the button values */ numActualButtons = device->buttonListLength; pHidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, device->buttonValues, &numActualButtons, device->hidDescriptor, (PUCHAR)device->report, device->hidCapabilities.InputReportByteLength);
/*
* <<COMPLETE>> * * What are you going to do with the parsed data from the device? * This is device specific. * */
} else { DBGERR(("ReadCompletion returned ERROR %xh.", (UINT)IoStatusBlock->Status));
/*
* Remove this device and then try to re-open it. */ DequeueDevice(device); DestroyDevice(device); ConnectNTDeviceDrivers(); }
/*
* Set up the next read of the device device. */ DispatchNtReadFile(device);
DBGOUT(("<== ReadCompletion()")); }
|