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 ;
2011-12-31 03:33:14 +00:00
FDODeviceExtension - > Common . 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 )
{
2011-12-31 03:33:14 +00:00
PIO_STACK_LOCATION IoStack ;
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension ;
PHID_COLLECTION_INFORMATION CollectionInformation ;
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension ;
//
// get device extension
//
CommonDeviceExtension = ( PHIDCLASS_COMMON_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
ASSERT ( CommonDeviceExtension - > IsFDO = = FALSE ) ;
PDODeviceExtension = ( PHIDCLASS_PDO_DEVICE_EXTENSION ) CommonDeviceExtension ;
//
// get stack location
//
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
switch ( IoStack - > Parameters . DeviceIoControl . IoControlCode )
{
case IOCTL_HID_GET_COLLECTION_INFORMATION :
{
//
// check if output buffer is big enough
//
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( HID_COLLECTION_INFORMATION ) )
{
//
// invalid buffer size
//
Irp - > IoStatus . Status = STATUS_INVALID_BUFFER_SIZE ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_INVALID_BUFFER_SIZE ;
}
//
// get output buffer
//
CollectionInformation = ( PHID_COLLECTION_INFORMATION ) Irp - > AssociatedIrp . SystemBuffer ;
ASSERT ( CollectionInformation ) ;
//
// init result buffer
//
CollectionInformation - > DescriptorSize = PDODeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ; //FIXME which collection is to be retrieved for composite devices / multi collection devices?
CollectionInformation - > Polled = CommonDeviceExtension - > DriverExtension - > DevicesArePolled ;
CollectionInformation - > VendorID = PDODeviceExtension - > Attributes . VendorID ;
CollectionInformation - > ProductID = PDODeviceExtension - > Attributes . ProductID ;
CollectionInformation - > VersionNumber = PDODeviceExtension - > Attributes . VersionNumber ;
//
// complete request
//
Irp - > IoStatus . Information = sizeof ( HID_COLLECTION_INFORMATION ) ;
Irp - > IoStatus . Status = STATUS_SUCCESS ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_SUCCESS ;
}
case IOCTL_HID_GET_COLLECTION_DESCRIPTOR :
{
//
// FIXME: which collection to use for composite / multi collection devices...
//
//
// check if output buffer is big enough
//
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < PDODeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength )
{
//
// invalid buffer size
//
Irp - > IoStatus . Status = STATUS_INVALID_BUFFER_SIZE ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_INVALID_BUFFER_SIZE ;
}
//
// copy result
//
ASSERT ( Irp - > UserBuffer ) ;
RtlCopyMemory ( Irp - > UserBuffer , PDODeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedData , PDODeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ) ;
//
// complete request
//
Irp - > IoStatus . Information = PDODeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ;
Irp - > IoStatus . Status = STATUS_SUCCESS ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_SUCCESS ;
}
default :
{
DPRINT1 ( " [HIDCLASS] DeviceControl IoControlCode 0x%x not implemented \n " , IoStack - > Parameters . DeviceIoControl . IoControlCode ) ;
ASSERT ( FALSE ) ;
Irp - > IoStatus . Status = STATUS_NOT_IMPLEMENTED ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_NOT_IMPLEMENTED ;
}
}
2011-12-30 14:34:07 +00:00
}
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 ;
//
2011-12-31 03:33:14 +00:00
// check type of device object
2011-12-30 14:34:07 +00:00
//
2011-12-31 03:33:14 +00:00
if ( CommonDeviceExtension - > IsFDO )
{
//
// handle request
//
return HidClassFDO_PnP ( DeviceObject , Irp ) ;
}
else
{
//
// handle request
//
return HidClassPDO_PnP ( DeviceObject , Irp ) ;
}
2011-12-30 14:34:07 +00:00
}
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 ;
}