2011-12-25 20:21:34 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: drivers/hid/hidclass/hidclass.c
|
|
|
|
* PURPOSE: HID Class Driver
|
|
|
|
* PROGRAMMERS:
|
|
|
|
* Michael Martin (michael.martin@reactos.org)
|
|
|
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
|
|
static LPWSTR ClientIdentificationAddress = L"HIDCLASS";
|
2011-12-25 23:07:50 +00:00
|
|
|
static ULONG HidClassDeviceNumber = 0;
|
2011-12-25 20:21:34 +00:00
|
|
|
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
DllInitialize(ULONG Unknown)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
DllUnload()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClassAddDevice(
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|
|
|
{
|
2011-12-25 23:07:50 +00:00
|
|
|
WCHAR CharDeviceName[64];
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING DeviceName;
|
|
|
|
PDEVICE_OBJECT NewDeviceObject;
|
2011-12-30 14:34:07 +00:00
|
|
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
2011-12-25 23:07:50 +00:00
|
|
|
ULONG DeviceExtensionSize;
|
|
|
|
PHIDCLASS_DRIVER_EXTENSION DriverExtension;
|
|
|
|
|
|
|
|
|
|
|
|
/* increment device number */
|
|
|
|
InterlockedIncrement((PLONG)&HidClassDeviceNumber);
|
|
|
|
|
|
|
|
/* construct device name */
|
|
|
|
swprintf(CharDeviceName, L"\\Device\\_HID%08x", HidClassDeviceNumber);
|
|
|
|
|
|
|
|
/* initialize device name */
|
|
|
|
RtlInitUnicodeString(&DeviceName, CharDeviceName);
|
|
|
|
|
|
|
|
/* get driver object extension */
|
|
|
|
DriverExtension = (PHIDCLASS_DRIVER_EXTENSION) IoGetDriverObjectExtension(DriverObject, ClientIdentificationAddress);
|
|
|
|
if (!DriverExtension)
|
|
|
|
{
|
|
|
|
/* device removed */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate device extension size */
|
2011-12-30 14:34:07 +00:00
|
|
|
DeviceExtensionSize = sizeof(HIDCLASS_FDO_EXTENSION) + DriverExtension->DeviceExtensionSize;
|
2011-12-25 23:07:50 +00:00
|
|
|
|
|
|
|
/* now create the device */
|
|
|
|
Status = IoCreateDevice(DriverObject, DeviceExtensionSize, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &NewDeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* failed to create device object */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get device extension */
|
2011-12-30 14:34:07 +00:00
|
|
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)NewDeviceObject->DeviceExtension;
|
2011-12-25 23:07:50 +00:00
|
|
|
|
|
|
|
/* zero device extension */
|
2011-12-30 14:34:07 +00:00
|
|
|
RtlZeroMemory(FDODeviceExtension, sizeof(HIDCLASS_FDO_EXTENSION));
|
2011-12-25 23:07:50 +00:00
|
|
|
|
|
|
|
/* initialize device extension */
|
2011-12-30 14:34:07 +00:00
|
|
|
FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = PhysicalDeviceObject;
|
|
|
|
FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = (PVOID)((ULONG_PTR)FDODeviceExtension + sizeof(HIDCLASS_FDO_EXTENSION));
|
|
|
|
FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = IoAttachDeviceToDeviceStack(NewDeviceObject, PhysicalDeviceObject);
|
|
|
|
FDODeviceExtension->Common.IsFDO = TRUE;
|
|
|
|
FDODeviceExtension->DriverExtension = DriverExtension;
|
2011-12-25 23:07:50 +00:00
|
|
|
|
|
|
|
/* sanity check */
|
2011-12-30 14:34:07 +00:00
|
|
|
ASSERT(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject);
|
2011-12-25 23:07:50 +00:00
|
|
|
|
|
|
|
/* increment stack size */
|
|
|
|
NewDeviceObject->StackSize++;
|
|
|
|
|
|
|
|
/* init device object */
|
|
|
|
NewDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
|
|
|
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
|
|
/* now call driver provided add device routine */
|
|
|
|
ASSERT(DriverExtension->AddDevice != 0);
|
|
|
|
Status = DriverExtension->AddDevice(DriverObject, NewDeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* failed */
|
|
|
|
DPRINT1("HIDCLASS: AddDevice failed with %x\n", Status);
|
2011-12-30 14:34:07 +00:00
|
|
|
IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject);
|
2011-12-25 23:07:50 +00:00
|
|
|
IoDeleteDevice(NewDeviceObject);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* succeeded */
|
|
|
|
return Status;
|
2011-12-25 20:21:34 +00:00
|
|
|
}
|
|
|
|
|
2011-12-26 03:37:22 +00:00
|
|
|
VOID
|
2011-12-25 20:21:34 +00:00
|
|
|
NTAPI
|
|
|
|
HidClassDriverUnload(
|
|
|
|
IN PDRIVER_OBJECT DriverObject)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2011-12-30 14:34:07 +00:00
|
|
|
HidClass_Create(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_Close(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_Read(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_Write(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_DeviceControl(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_InternalDeviceControl(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_Power(
|
2011-12-25 20:21:34 +00:00
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2011-12-30 14:34:07 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_PnP(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get common device extension
|
|
|
|
//
|
|
|
|
CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// FIXME: support PDO
|
|
|
|
//
|
|
|
|
ASSERT(CommonDeviceExtension->IsFDO == TRUE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// handle request
|
|
|
|
//
|
|
|
|
return HidClassFDO_PnP(DeviceObject, Irp);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClass_DispatchDefault(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get common device extension
|
|
|
|
//
|
|
|
|
CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// FIXME: support PDO
|
|
|
|
//
|
|
|
|
ASSERT(CommonDeviceExtension->IsFDO == TRUE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// skip current irp stack location
|
|
|
|
//
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// dispatch to lower device object
|
|
|
|
//
|
|
|
|
return IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, Irp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidClassDispatch(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get current stack location
|
|
|
|
//
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DPRINT1("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
|
|
|
|
|
|
|
//
|
|
|
|
// dispatch request based on major function
|
|
|
|
//
|
|
|
|
switch(IoStack->MajorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MJ_CREATE:
|
|
|
|
return HidClass_Create(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_CLOSE:
|
|
|
|
return HidClass_Close(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_READ:
|
|
|
|
return HidClass_Read(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_WRITE:
|
|
|
|
return HidClass_Write(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
return HidClass_DeviceControl(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
|
|
|
return HidClass_InternalDeviceControl(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_POWER:
|
|
|
|
return HidClass_Power(DeviceObject, Irp);
|
|
|
|
case IRP_MJ_PNP:
|
|
|
|
return HidClass_PnP(DeviceObject, Irp);
|
|
|
|
default:
|
|
|
|
return HidClass_DispatchDefault(DeviceObject, Irp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-25 20:21:34 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
HidRegisterMinidriver(
|
|
|
|
IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PHIDCLASS_DRIVER_EXTENSION DriverExtension;
|
|
|
|
|
|
|
|
/* check if the version matches */
|
|
|
|
if (MinidriverRegistration->Revision > HID_REVISION)
|
|
|
|
{
|
|
|
|
/* revision mismatch */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now allocate the driver object extension */
|
|
|
|
Status = IoAllocateDriverObjectExtension(MinidriverRegistration->DriverObject, (PVOID)ClientIdentificationAddress, sizeof(HIDCLASS_DRIVER_EXTENSION), (PVOID*)&DriverExtension);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* failed to allocate driver extension */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* zero driver extension */
|
|
|
|
RtlZeroMemory(DriverExtension, sizeof(HIDCLASS_DRIVER_EXTENSION));
|
|
|
|
|
|
|
|
/* init driver extension */
|
|
|
|
DriverExtension->DriverObject = MinidriverRegistration->DriverObject;
|
|
|
|
DriverExtension->DeviceExtensionSize = MinidriverRegistration->DeviceExtensionSize;
|
|
|
|
DriverExtension->DevicesArePolled = MinidriverRegistration->DevicesArePolled;
|
|
|
|
DriverExtension->AddDevice = MinidriverRegistration->DriverObject->DriverExtension->AddDevice;
|
|
|
|
DriverExtension->DriverUnload = MinidriverRegistration->DriverObject->DriverUnload;
|
|
|
|
|
|
|
|
/* copy driver dispatch routines */
|
2011-12-30 14:34:07 +00:00
|
|
|
RtlCopyMemory(DriverExtension->MajorFunction, MinidriverRegistration->DriverObject->MajorFunction, sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION+1));
|
2011-12-25 20:21:34 +00:00
|
|
|
|
|
|
|
/* initialize lock */
|
|
|
|
KeInitializeSpinLock(&DriverExtension->Lock);
|
|
|
|
|
|
|
|
/* now replace dispatch routines */
|
|
|
|
DriverExtension->DriverObject->DriverExtension->AddDevice = HidClassAddDevice;
|
|
|
|
DriverExtension->DriverObject->DriverUnload = HidClassDriverUnload;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_CREATE] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_READ] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_WRITE] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_POWER] = HidClassDispatch;
|
|
|
|
DriverExtension->DriverObject->MajorFunction[IRP_MJ_PNP] = HidClassDispatch;
|
|
|
|
|
|
|
|
/* done */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|