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 )
{
2011-12-31 19:09:26 +00:00
PIO_STACK_LOCATION IoStack ;
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension ;
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension ;
PHIDCLASS_FILEOP_CONTEXT Context ;
//
// get device extension
//
CommonDeviceExtension = ( PHIDCLASS_COMMON_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
if ( CommonDeviceExtension - > IsFDO )
{
//
// only supported for PDO
//
Irp - > IoStatus . Status = STATUS_UNSUCCESSFUL ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_UNSUCCESSFUL ;
}
//
// must be a PDO
//
ASSERT ( CommonDeviceExtension - > IsFDO = = FALSE ) ;
//
// get device extension
//
PDODeviceExtension = ( PHIDCLASS_PDO_DEVICE_EXTENSION ) CommonDeviceExtension ;
//
// get stack location
//
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
DPRINT1 ( " ShareAccess %x \n " , IoStack - > Parameters . Create . ShareAccess ) ;
DPRINT1 ( " Options %x \n " , IoStack - > Parameters . Create . Options ) ;
DPRINT1 ( " DesiredAccess %x \n " , IoStack - > Parameters . Create . SecurityContext - > DesiredAccess ) ;
//
// allocate context
//
Context = ( PHIDCLASS_FILEOP_CONTEXT ) ExAllocatePool ( NonPagedPool , sizeof ( HIDCLASS_FILEOP_CONTEXT ) ) ;
if ( ! Context )
{
//
// no memory
//
Irp - > IoStatus . Status = STATUS_INSUFFICIENT_RESOURCES ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
//
// init context
//
RtlZeroMemory ( Context , sizeof ( HIDCLASS_FILEOP_CONTEXT ) ) ;
Context - > DeviceExtension = PDODeviceExtension ;
KeInitializeSpinLock ( & Context - > Lock ) ;
InitializeListHead ( & Context - > ReadPendingIrpListHead ) ;
InitializeListHead ( & Context - > IrpCompletedListHead ) ;
//
// store context
//
ASSERT ( IoStack - > FileObject ) ;
IoStack - > FileObject - > FsContext = ( PVOID ) Context ;
//
// done
//
Irp - > IoStatus . Status = STATUS_SUCCESS ;
2011-12-31 04:13:37 +00:00
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
2011-12-31 19:09:26 +00:00
return STATUS_SUCCESS ;
2011-12-30 14:34:07 +00:00
}
NTSTATUS
NTAPI
HidClass_Close (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP Irp )
{
2011-12-31 19:09:26 +00:00
PIO_STACK_LOCATION IoStack ;
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension ;
PHIDCLASS_IRP_CONTEXT IrpContext ;
//
// get device extension
//
CommonDeviceExtension = ( PHIDCLASS_COMMON_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
//
// is it a FDO request
//
if ( CommonDeviceExtension - > IsFDO )
{
//
// how did the request get there
//
Irp - > IoStatus . Status = STATUS_INVALID_PARAMETER_1 ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return STATUS_INVALID_PARAMETER_1 ;
}
//
// get stack location
//
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
//
// sanity checks
//
ASSERT ( IoStack - > FileObject ) ;
ASSERT ( IoStack - > FileObject - > FsContext ) ;
//
// get irp context
//
IrpContext = ( PHIDCLASS_IRP_CONTEXT ) IoStack - > FileObject - > FsContext ;
//
// cancel pending irps
//
2011-12-30 14:34:07 +00:00
UNIMPLEMENTED
2011-12-31 19:09:26 +00:00
//
// remove context
//
IoStack - > FileObject - > FsContext = NULL ;
//
// free context
//
ExFreePool ( IrpContext ) ;
//
// complete request
//
Irp - > IoStatus . Status = STATUS_SUCCESS ;
2011-12-31 04:13:37 +00:00
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
2011-12-31 19:09:26 +00:00
return STATUS_SUCCESS ;
2011-12-30 14:34:07 +00:00
}
2012-01-01 22:48:08 +00:00
PVOID
HidClass_GetSystemAddress (
IN PMDL ReportMDL )
{
//
// sanity check
//
ASSERT ( ReportMDL ) ;
if ( ReportMDL - > MdlFlags & ( MDL_SOURCE_IS_NONPAGED_POOL | MDL_MAPPED_TO_SYSTEM_VA ) )
{
//
// buffer is non paged pool
//
return ReportMDL - > MappedSystemVa ;
}
else
{
//
// map mdl
//
return MmMapLockedPages ( ReportMDL , KernelMode ) ;
}
}
2011-12-31 19:09:26 +00:00
NTSTATUS
NTAPI
HidClass_ReadCompleteIrp (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP Irp ,
IN PVOID Ctx )
{
PHIDCLASS_IRP_CONTEXT IrpContext ;
KIRQL OldLevel ;
2012-01-01 22:48:08 +00:00
PUCHAR Address ;
ULONG Offset ;
PHIDP_DEVICE_DESC DeviceDescription ;
ULONG CollectionIndex ;
2011-12-31 19:09:26 +00:00
//
// get irp context
//
IrpContext = ( PHIDCLASS_IRP_CONTEXT ) Ctx ;
2012-01-01 22:48:08 +00:00
DPRINT ( " HidClass_ReadCompleteIrp Irql %lu \n " , KeGetCurrentIrql ( ) ) ;
DPRINT ( " HidClass_ReadCompleteIrp Status %lx \n " , Irp - > IoStatus . Status ) ;
DPRINT ( " HidClass_ReadCompleteIrp Length %lu \n " , Irp - > IoStatus . Information ) ;
DPRINT ( " HidClass_ReadCompleteIrp Irp %p \n " , Irp ) ;
DPRINT ( " HidClass_ReadCompleteIrp InputReportBuffer %p \n " , IrpContext - > InputReportBuffer ) ;
DPRINT ( " HidClass_ReadCompleteIrp InputReportBufferLength %li \n " , IrpContext - > InputReportBufferLength ) ;
DPRINT ( " HidClass_ReadCompleteIrp OriginalIrp %p \n " , IrpContext - > OriginalIrp ) ;
2011-12-31 19:09:26 +00:00
//
// copy result
//
if ( Irp - > IoStatus . Information )
{
//
2012-01-01 22:48:08 +00:00
// get address
2011-12-31 19:09:26 +00:00
//
2012-01-01 22:48:08 +00:00
Address = HidClass_GetSystemAddress ( IrpContext - > OriginalIrp - > MdlAddress ) ;
if ( Address )
{
//
// reports may have a report id prepended
//
CollectionIndex = IrpContext - > FileOp - > DeviceExtension - > CollectionIndex ;
DeviceDescription = & IrpContext - > FileOp - > DeviceExtension - > Common . DeviceDescription ;
//
// calculate offset
//
ASSERT ( DeviceDescription - > CollectionDesc [ CollectionIndex ] . InputLength > = DeviceDescription - > ReportIDs [ CollectionIndex ] . InputLength ) ;
Offset = DeviceDescription - > CollectionDesc [ CollectionIndex ] . InputLength - DeviceDescription - > ReportIDs [ CollectionIndex ] . InputLength ;
//
// copy result
//
RtlCopyMemory ( & Address [ Offset ] , IrpContext - > InputReportBuffer , IrpContext - > InputReportBufferLength ) ;
}
2011-12-31 19:09:26 +00:00
}
//
// copy result status
//
IrpContext - > OriginalIrp - > IoStatus . Status = Irp - > IoStatus . Status ;
Irp - > IoStatus . Information = Irp - > IoStatus . Information ;
//
// free input report buffer
//
ExFreePool ( IrpContext - > InputReportBuffer ) ;
//
// remove us from pending list
//
KeAcquireSpinLock ( & IrpContext - > FileOp - > Lock , & OldLevel ) ;
//
// remove from pending list
//
RemoveEntryList ( & Irp - > Tail . Overlay . ListEntry ) ;
2012-01-01 22:48:08 +00:00
//
// insert into completed list
//
InsertTailList ( & IrpContext - > FileOp - > IrpCompletedListHead , & Irp - > Tail . Overlay . ListEntry ) ;
2011-12-31 19:09:26 +00:00
//
// release lock
//
KeReleaseSpinLock ( & IrpContext - > FileOp - > Lock , OldLevel ) ;
2012-01-01 22:48:08 +00:00
//
// complete original request
//
IoCompleteRequest ( IrpContext - > OriginalIrp , IO_NO_INCREMENT ) ;
2011-12-31 19:09:26 +00:00
//
// free irp context
//
ExFreePool ( IrpContext ) ;
//
// done
//
2012-01-01 22:48:08 +00:00
return STATUS_MORE_PROCESSING_REQUIRED ;
}
PIRP
HidClass_GetIrp (
IN PHIDCLASS_FILEOP_CONTEXT Context )
{
KIRQL OldLevel ;
PIRP Irp = NULL ;
PLIST_ENTRY ListEntry ;
//
// acquire lock
//
KeAcquireSpinLock ( & Context - > Lock , & OldLevel ) ;
//
// is list empty?
//
if ( ! IsListEmpty ( & Context - > IrpCompletedListHead ) )
{
//
// grab first entry
//
ListEntry = RemoveHeadList ( & Context - > IrpCompletedListHead ) ;
//
// get irp
//
Irp = ( PIRP ) CONTAINING_RECORD ( ListEntry , IRP , Tail . Overlay . ListEntry ) ;
}
//
// release lock
//
KeReleaseSpinLock ( & Context - > Lock , OldLevel ) ;
//
// done
//
return Irp ;
2011-12-31 19:09:26 +00:00
}
NTSTATUS
HidClass_BuildIrp (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP RequestIrp ,
IN PHIDCLASS_FILEOP_CONTEXT Context ,
IN ULONG DeviceIoControlCode ,
IN ULONG BufferLength ,
OUT PIRP * OutIrp ,
OUT PHIDCLASS_IRP_CONTEXT * OutIrpContext )
{
PIRP Irp ;
PIO_STACK_LOCATION IoStack ;
PHIDCLASS_IRP_CONTEXT IrpContext ;
2012-01-01 22:48:08 +00:00
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension ;
2011-12-31 19:09:26 +00:00
//
2012-01-01 22:48:08 +00:00
// get an irp from fresh list
2011-12-31 19:09:26 +00:00
//
2012-01-01 22:48:08 +00:00
Irp = HidClass_GetIrp ( Context ) ;
2011-12-31 19:09:26 +00:00
if ( ! Irp )
{
//
2012-01-01 22:48:08 +00:00
// build new irp
2011-12-31 19:09:26 +00:00
//
2012-01-01 22:48:08 +00:00
Irp = IoAllocateIrp ( DeviceObject - > StackSize , FALSE ) ;
if ( ! Irp )
{
//
// no memory
//
return STATUS_INSUFFICIENT_RESOURCES ;
}
}
else
{
//
// re-use irp
//
IoReuseIrp ( Irp , STATUS_SUCCESS ) ;
2011-12-31 19:09:26 +00:00
}
//
// allocate completion context
//
IrpContext = ( PHIDCLASS_IRP_CONTEXT ) ExAllocatePool ( NonPagedPool , sizeof ( HIDCLASS_IRP_CONTEXT ) ) ;
if ( ! IrpContext )
{
//
// no memory
//
IoFreeIrp ( Irp ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
2012-01-01 22:48:08 +00:00
//
// get device extension
//
PDODeviceExtension = ( PHIDCLASS_PDO_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
ASSERT ( PDODeviceExtension - > Common . IsFDO = = FALSE ) ;
//
// sanity checks
//
ASSERT ( PDODeviceExtension - > CollectionIndex < PDODeviceExtension - > Common . DeviceDescription . CollectionDescLength ) ;
ASSERT ( PDODeviceExtension - > CollectionIndex < PDODeviceExtension - > Common . DeviceDescription . ReportIDsLength ) ;
ASSERT ( PDODeviceExtension - > Common . DeviceDescription . ReportIDs [ PDODeviceExtension - > CollectionIndex ] . InputLength > 0 ) ;
ASSERT ( PDODeviceExtension - > Common . DeviceDescription . CollectionDesc [ PDODeviceExtension - > CollectionIndex ] . InputLength = = BufferLength ) ;
2011-12-31 19:09:26 +00:00
//
// init irp context
//
RtlZeroMemory ( IrpContext , sizeof ( HIDCLASS_IRP_CONTEXT ) ) ;
2012-01-01 22:48:08 +00:00
IrpContext - > InputReportBufferLength = PDODeviceExtension - > Common . DeviceDescription . ReportIDs [ PDODeviceExtension - > CollectionIndex ] . InputLength ;
2011-12-31 19:09:26 +00:00
IrpContext - > OriginalIrp = RequestIrp ;
IrpContext - > FileOp = Context ;
//
// allocate buffer
//
2012-01-01 22:48:08 +00:00
IrpContext - > InputReportBuffer = ExAllocatePool ( NonPagedPool , IrpContext - > InputReportBufferLength ) ;
2011-12-31 19:09:26 +00:00
if ( ! IrpContext - > InputReportBuffer )
{
//
// no memory
//
IoFreeIrp ( Irp ) ;
ExFreePool ( IrpContext ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
//
// get stack location
//
IoStack = IoGetNextIrpStackLocation ( Irp ) ;
//
// init stack location
//
IoStack - > MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL ;
IoStack - > Parameters . DeviceIoControl . IoControlCode = DeviceIoControlCode ;
IoStack - > Parameters . DeviceIoControl . OutputBufferLength = IrpContext - > InputReportBufferLength ;
IoStack - > Parameters . DeviceIoControl . InputBufferLength = 0 ;
IoStack - > Parameters . DeviceIoControl . Type3InputBuffer = NULL ;
Irp - > UserBuffer = IrpContext - > InputReportBuffer ;
IoStack - > DeviceObject = DeviceObject ;
//
// store result
//
* OutIrp = Irp ;
* OutIrpContext = IrpContext ;
//
// done
//
return STATUS_SUCCESS ;
}
2011-12-30 14:34:07 +00:00
NTSTATUS
NTAPI
HidClass_Read (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP Irp )
{
2011-12-31 19:09:26 +00:00
PIO_STACK_LOCATION IoStack ;
PHIDCLASS_FILEOP_CONTEXT Context ;
KIRQL OldLevel ;
NTSTATUS Status ;
PIRP NewIrp ;
PHIDCLASS_IRP_CONTEXT NewIrpContext ;
2012-01-01 22:48:08 +00:00
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension ;
2011-12-31 19:09:26 +00:00
//
// get current stack location
//
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
2012-01-01 22:48:08 +00:00
//
// get device extension
//
CommonDeviceExtension = ( PHIDCLASS_COMMON_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
ASSERT ( CommonDeviceExtension - > IsFDO = = FALSE ) ;
2011-12-31 19:09:26 +00:00
//
// sanity check
//
ASSERT ( IoStack - > FileObject ) ;
ASSERT ( IoStack - > FileObject - > FsContext ) ;
//
// get context
//
Context = ( PHIDCLASS_FILEOP_CONTEXT ) IoStack - > FileObject - > FsContext ;
ASSERT ( Context ) ;
//
// FIXME support polled devices
//
ASSERT ( Context - > DeviceExtension - > Common . DriverExtension - > DevicesArePolled = = FALSE ) ;
//
// build irp request
//
2012-01-01 22:48:08 +00:00
Status = HidClass_BuildIrp ( DeviceObject , Irp , Context , IOCTL_HID_READ_REPORT , IoStack - > Parameters . Read . Length , & NewIrp , & NewIrpContext ) ;
2011-12-31 19:09:26 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
//
// failed
//
DPRINT1 ( " HidClass_BuildIrp failed with %x \n " , Status ) ;
Irp - > IoStatus . Status = Status ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
return Status ;
}
//
// acquire lock
//
KeAcquireSpinLock ( & Context - > Lock , & OldLevel ) ;
//
// insert irp into pending list
//
InsertTailList ( & Context - > ReadPendingIrpListHead , & NewIrp - > Tail . Overlay . ListEntry ) ;
//
// set completion routine
//
IoSetCompletionRoutine ( NewIrp , HidClass_ReadCompleteIrp , NewIrpContext , TRUE , TRUE , TRUE ) ;
//
// make next location current
//
IoSetNextIrpStackLocation ( NewIrp ) ;
//
// release spin lock
//
KeReleaseSpinLock ( & Context - > Lock , OldLevel ) ;
//
// mark irp pending
//
IoMarkIrpPending ( Irp ) ;
//
// lets dispatch the request
//
ASSERT ( Context - > DeviceExtension ) ;
2012-01-01 22:48:08 +00:00
Status = Context - > DeviceExtension - > Common . DriverExtension - > MajorFunction [ IRP_MJ_INTERNAL_DEVICE_CONTROL ] ( Context - > DeviceExtension - > FDODeviceObject , NewIrp ) ;
2011-12-31 19:09:26 +00:00
//
// complete
//
2012-01-01 22:48:08 +00:00
return STATUS_PENDING ;
2011-12-30 14:34:07 +00:00
}
NTSTATUS
NTAPI
HidClass_Write (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP Irp )
{
UNIMPLEMENTED
ASSERT ( FALSE ) ;
2011-12-31 04:13:37 +00:00
Irp - > IoStatus . Status = STATUS_NOT_IMPLEMENTED ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
2011-12-30 14:34:07 +00:00
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 ;
//
// get device extension
//
CommonDeviceExtension = ( PHIDCLASS_COMMON_DEVICE_EXTENSION ) DeviceObject - > DeviceExtension ;
//
// 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
//
2011-12-31 19:09:26 +00:00
CollectionInformation - > DescriptorSize = CommonDeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ; //FIXME which collection is to be retrieved for composite devices / multi collection devices?
2011-12-31 03:33:14 +00:00
CollectionInformation - > Polled = CommonDeviceExtension - > DriverExtension - > DevicesArePolled ;
2011-12-31 19:09:26 +00:00
CollectionInformation - > VendorID = CommonDeviceExtension - > Attributes . VendorID ;
CollectionInformation - > ProductID = CommonDeviceExtension - > Attributes . ProductID ;
CollectionInformation - > VersionNumber = CommonDeviceExtension - > Attributes . VersionNumber ;
2011-12-31 03:33:14 +00:00
//
// 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
//
2011-12-31 19:09:26 +00:00
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < CommonDeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength )
2011-12-31 03:33:14 +00:00
{
//
// 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 ) ;
2011-12-31 19:09:26 +00:00
RtlCopyMemory ( Irp - > UserBuffer , CommonDeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedData , CommonDeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ) ;
2011-12-31 03:33:14 +00:00
//
// complete request
//
2011-12-31 19:09:26 +00:00
Irp - > IoStatus . Information = CommonDeviceExtension - > DeviceDescription . CollectionDesc [ 0 ] . PreparsedDataLength ;
2011-12-31 03:33:14 +00:00
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 ) ;
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 ) ;
2012-01-01 22:48:08 +00:00
Irp - > IoStatus . Status = STATUS_NOT_IMPLEMENTED ;
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
2011-12-30 14:34:07 +00:00
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
//
2012-01-01 22:48:08 +00:00
return IoCallDriver ( CommonDeviceExtension - > HidDeviceExtension . NextDeviceObject , Irp ) ;
2011-12-30 14:34:07 +00:00
}
NTSTATUS
NTAPI
HidClassDispatch (
IN PDEVICE_OBJECT DeviceObject ,
IN PIRP Irp )
{
PIO_STACK_LOCATION IoStack ;
//
// get current stack location
//
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
2012-01-01 22:48:08 +00:00
DPRINT ( " [HIDCLASS] Dispatch Major %x Minor %x \n " , IoStack - > MajorFunction , IoStack - > MinorFunction ) ;
2011-12-30 14:34:07 +00:00
//
// 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 ;
}