/* * 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"; static ULONG HidClassDeviceNumber = 0; ULONG NTAPI DllInitialize(ULONG Unknown) { return 0; } ULONG NTAPI DllUnload() { return 0; } NTSTATUS NTAPI HidClassAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { WCHAR CharDeviceName[64]; NTSTATUS Status; UNICODE_STRING DeviceName; PDEVICE_OBJECT NewDeviceObject; PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 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 */ DeviceExtensionSize = sizeof(HIDCLASS_FDO_EXTENSION) + DriverExtension->DeviceExtensionSize; /* 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 */ FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)NewDeviceObject->DeviceExtension; /* zero device extension */ RtlZeroMemory(FDODeviceExtension, sizeof(HIDCLASS_FDO_EXTENSION)); /* initialize device extension */ 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; /* sanity check */ ASSERT(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); /* 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); IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); IoDeleteDevice(NewDeviceObject); return Status; } /* succeeded */ return Status; } VOID NTAPI HidClassDriverUnload( IN PDRIVER_OBJECT DriverObject) { UNIMPLEMENTED ASSERT(FALSE); } NTSTATUS NTAPI 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( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { UNIMPLEMENTED ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED; } 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); } } 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 */ RtlCopyMemory(DriverExtension->MajorFunction, MinidriverRegistration->DriverObject->MajorFunction, sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION+1)); /* 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; }