diff --git a/drivers/hid/hidclass/fdo.c b/drivers/hid/hidclass/fdo.c index 5f5463d5fb1..d6844315ed6 100644 --- a/drivers/hid/hidclass/fdo.c +++ b/drivers/hid/hidclass/fdo.c @@ -180,8 +180,6 @@ HidClassFDO_DispatchRequestSynchronous( // IoStack->DeviceObject = DeviceObject; - - // // call driver // @@ -409,7 +407,7 @@ HidClassFDO_CopyDeviceRelations( // // allocate result // - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS) + (FDODeviceExtension->DeviceRelations.Count-1) * sizeof(PDEVICE_OBJECT)); + DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS) + (FDODeviceExtension->DeviceRelations->Count-1) * sizeof(PDEVICE_OBJECT)); if (!DeviceRelations) { // @@ -422,24 +420,23 @@ HidClassFDO_CopyDeviceRelations( // // copy device objects // - for(Index = 0; Index < FDODeviceExtension->DeviceRelations.Count; Index++) + for(Index = 0; Index < FDODeviceExtension->DeviceRelations->Count; Index++) { // // reference pdo // - ObReferenceObject(FDODeviceExtension->DeviceRelations.Objects[Index]); + ObReferenceObject(FDODeviceExtension->DeviceRelations->Objects[Index]); // // store object // - DeviceRelations->Objects[Index] = FDODeviceExtension->DeviceRelations.Objects[Index]; + DeviceRelations->Objects[Index] = FDODeviceExtension->DeviceRelations->Objects[Index]; } // // set object count // - DeviceRelations->Count = FDODeviceExtension->DeviceRelations.Count; - + DeviceRelations->Count = FDODeviceExtension->DeviceRelations->Count; // // store result @@ -481,12 +478,12 @@ HidClassFDO_DeviceRelations( return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); } - if (FDODeviceExtension->DeviceRelations.Count == 0) + if (FDODeviceExtension->DeviceRelations == NULL) { // // time to create the pdos // - Status = HidClassPDO_CreatePDO(DeviceObject); + Status = HidClassPDO_CreatePDO(DeviceObject, &FDODeviceExtension->DeviceRelations); if (!NT_SUCCESS(Status)) { // @@ -500,7 +497,7 @@ HidClassFDO_DeviceRelations( // // sanity check // - ASSERT(FDODeviceExtension->DeviceRelations.Count > 0); + ASSERT(FDODeviceExtension->DeviceRelations->Count > 0); } // diff --git a/drivers/hid/hidclass/hidclass.c b/drivers/hid/hidclass/hidclass.c index 9cffb5f725e..e6eb4a9f0ac 100644 --- a/drivers/hid/hidclass/hidclass.c +++ b/drivers/hid/hidclass/hidclass.c @@ -304,8 +304,8 @@ HidClass_ReadCompleteIrp( KIRQL OldLevel; PUCHAR Address; ULONG Offset; - PHIDP_DEVICE_DESC DeviceDescription; - ULONG CollectionIndex; + PHIDP_COLLECTION_DESC CollectionDescription; + PHIDP_REPORT_IDS ReportDescription; // // get irp context @@ -328,20 +328,34 @@ HidClass_ReadCompleteIrp( // // get address // - Address = HidClass_GetSystemAddress(IrpContext->OriginalIrp->MdlAddress); + Address = (PUCHAR)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; + Offset = 0; // - // calculate offset + // get collection description // - ASSERT(DeviceDescription->CollectionDesc[CollectionIndex].InputLength >= DeviceDescription->ReportIDs[CollectionIndex].InputLength); - Offset = DeviceDescription->CollectionDesc[CollectionIndex].InputLength - DeviceDescription->ReportIDs[CollectionIndex].InputLength; + CollectionDescription = HidClassPDO_GetCollectionDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, IrpContext->FileOp->DeviceExtension->CollectionNumber); + ASSERT(CollectionDescription); + + // + // get report description + // + ReportDescription = HidClassPDO_GetReportDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, IrpContext->FileOp->DeviceExtension->CollectionNumber); + ASSERT(ReportDescription); + + if (CollectionDescription && ReportDescription) + { + // + // calculate offset + // + ASSERT(CollectionDescription->InputLength >= ReportDescription->InputLength); + Offset = CollectionDescription->InputLength - ReportDescription->InputLength; + } // // copy result @@ -451,6 +465,8 @@ HidClass_BuildIrp( PIO_STACK_LOCATION IoStack; PHIDCLASS_IRP_CONTEXT IrpContext; PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; + PHIDP_COLLECTION_DESC CollectionDescription; + PHIDP_REPORT_IDS ReportDescription; // // get an irp from fresh list @@ -497,22 +513,35 @@ HidClass_BuildIrp( 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); - // // init irp context // RtlZeroMemory(IrpContext, sizeof(HIDCLASS_IRP_CONTEXT)); - IrpContext->InputReportBufferLength = PDODeviceExtension->Common.DeviceDescription.ReportIDs[PDODeviceExtension->CollectionIndex].InputLength; IrpContext->OriginalIrp = RequestIrp; IrpContext->FileOp = Context; + // + // get collection description + // + CollectionDescription = HidClassPDO_GetCollectionDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, IrpContext->FileOp->DeviceExtension->CollectionNumber); + ASSERT(CollectionDescription); + + // + // get report description + // + ReportDescription = HidClassPDO_GetReportDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, IrpContext->FileOp->DeviceExtension->CollectionNumber); + ASSERT(ReportDescription); + + // + // sanity check + // + ASSERT(CollectionDescription->InputLength >= ReportDescription->InputLength); + + // + // store report length + // + IrpContext->InputReportBufferLength = ReportDescription->InputLength; + // // allocate buffer // @@ -677,11 +706,19 @@ HidClass_DeviceControl( PIO_STACK_LOCATION IoStack; PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; PHID_COLLECTION_INFORMATION CollectionInformation; + PHIDP_COLLECTION_DESC CollectionDescription; + PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; // // get device extension // CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(CommonDeviceExtension->IsFDO == FALSE); + + // + // get pdo device extension + // + PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // get stack location @@ -711,10 +748,16 @@ HidClass_DeviceControl( CollectionInformation = (PHID_COLLECTION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(CollectionInformation); + // + // get collection description + // + CollectionDescription = HidClassPDO_GetCollectionDescription(&CommonDeviceExtension->DeviceDescription, PDODeviceExtension->CollectionNumber); + ASSERT(CollectionDescription); + // // init result buffer // - CollectionInformation->DescriptorSize = CommonDeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength; //FIXME which collection is to be retrieved for composite devices / multi collection devices? + CollectionInformation->DescriptorSize = CollectionDescription->PreparsedDataLength; CollectionInformation->Polled = CommonDeviceExtension->DriverExtension->DevicesArePolled; CollectionInformation->VendorID = CommonDeviceExtension->Attributes.VendorID; CollectionInformation->ProductID = CommonDeviceExtension->Attributes.ProductID; @@ -731,13 +774,15 @@ HidClass_DeviceControl( case IOCTL_HID_GET_COLLECTION_DESCRIPTOR: { // - // FIXME: which collection to use for composite / multi collection devices... + // get collection description // + CollectionDescription = HidClassPDO_GetCollectionDescription(&CommonDeviceExtension->DeviceDescription, PDODeviceExtension->CollectionNumber); + ASSERT(CollectionDescription); // // check if output buffer is big enough // - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < CommonDeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength) + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < CollectionDescription->PreparsedDataLength) { // // invalid buffer size @@ -751,12 +796,12 @@ HidClass_DeviceControl( // copy result // ASSERT(Irp->UserBuffer); - RtlCopyMemory(Irp->UserBuffer, CommonDeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedData, CommonDeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength); + RtlCopyMemory(Irp->UserBuffer, CollectionDescription->PreparsedData, CollectionDescription->PreparsedDataLength); // // complete request // - Irp->IoStatus.Information = CommonDeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength; + Irp->IoStatus.Information = CollectionDescription->PreparsedDataLength; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; diff --git a/drivers/hid/hidclass/pdo.c b/drivers/hid/hidclass/pdo.c index a3678deaaf7..6b8037b5d12 100644 --- a/drivers/hid/hidclass/pdo.c +++ b/drivers/hid/hidclass/pdo.c @@ -9,6 +9,58 @@ */ #include "precomp.h" +PHIDP_COLLECTION_DESC +HidClassPDO_GetCollectionDescription( + PHIDP_DEVICE_DESC DeviceDescription, + ULONG CollectionNumber) +{ + ULONG Index; + + for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++) + { + if (DeviceDescription->CollectionDesc[Index].CollectionNumber == CollectionNumber) + { + // + // found collection + // + return &DeviceDescription->CollectionDesc[Index]; + } + } + + // + // failed to find collection + // + DPRINT1("[HIDCLASS] GetCollectionDescription CollectionNumber %x not found\n", CollectionNumber); + ASSERT(FALSE); + return NULL; +} + +PHIDP_REPORT_IDS +HidClassPDO_GetReportDescription( + PHIDP_DEVICE_DESC DeviceDescription, + ULONG CollectionNumber) +{ + ULONG Index; + + for(Index = 0; Index < DeviceDescription->ReportIDsLength; Index++) + { + if (DeviceDescription->ReportIDs[Index].CollectionNumber == CollectionNumber) + { + // + // found collection + // + return &DeviceDescription->ReportIDs[Index]; + } + } + + // + // failed to find collection + // + DPRINT1("[HIDCLASS] GetReportDescription CollectionNumber %x not found\n", CollectionNumber); + ASSERT(FALSE); + return NULL; +} + NTSTATUS HidClassPDO_HandleQueryDeviceId( IN PDEVICE_OBJECT DeviceObject, @@ -93,6 +145,7 @@ HidClassPDO_HandleQueryHardwareId( WCHAR Buffer[100]; ULONG Offset = 0; LPWSTR Ptr; + PHIDP_COLLECTION_DESC CollectionDescription; // // get device extension @@ -117,15 +170,32 @@ HidClassPDO_HandleQueryHardwareId( return Status; } - // - // store hardware ids - // - Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber) + 1; - Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID) + 1; - - if (PDODeviceExtension->Common.DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].UsagePage == HID_USAGE_PAGE_GENERIC) + if (PDODeviceExtension->Common.DeviceDescription.CollectionDescLength > 1) { - switch(PDODeviceExtension->Common.DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].Usage) + // + // multi-tlc device + // + Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber, PDODeviceExtension->CollectionNumber) + 1; + Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->CollectionNumber) + 1; + } + else + { + // + // single tlc device + // + Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber) + 1; + Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID) + 1; + } + + // + // get collection description + // + CollectionDescription = HidClassPDO_GetCollectionDescription(&PDODeviceExtension->Common.DeviceDescription, PDODeviceExtension->CollectionNumber); + ASSERT(CollectionDescription); + + if (CollectionDescription->UsagePage == HID_USAGE_PAGE_GENERIC) + { + switch(CollectionDescription->Usage) { case HID_USAGE_GENERIC_POINTER: case HID_USAGE_GENERIC_MOUSE: @@ -156,7 +226,7 @@ HidClassPDO_HandleQueryHardwareId( break; } } - else if (PDODeviceExtension->Common.DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].UsagePage == HID_USAGE_PAGE_CONSUMER && PDODeviceExtension->Common.DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].Usage == HID_USAGE_CONSUMERCTRL) + else if (CollectionDescription->UsagePage == HID_USAGE_PAGE_CONSUMER && CollectionDescription->Usage == HID_USAGE_CONSUMERCTRL) { // // Consumer Audio Control @@ -501,12 +571,16 @@ HidClassPDO_PnP( NTSTATUS HidClassPDO_CreatePDO( - IN PDEVICE_OBJECT DeviceObject) + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_RELATIONS *OutDeviceRelations) { PHIDCLASS_FDO_EXTENSION FDODeviceExtension; NTSTATUS Status; PDEVICE_OBJECT PDODeviceObject; PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; + ULONG Index; + PDEVICE_RELATIONS DeviceRelations; + ULONG Length; // // get device extension @@ -515,64 +589,121 @@ HidClassPDO_CreatePDO( ASSERT(FDODeviceExtension->Common.IsFDO); // - // lets create the device object + // first allocate device relations + // + Length = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * FDODeviceExtension->Common.DeviceDescription.CollectionDescLength; + DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, Length); + if (!DeviceRelations) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // zero device relations + // + RtlZeroMemory(DeviceRelations, Length); + + // + // lets create a PDO for top level collection + // + Index = 0; + do + { + // + // lets create the device object + // + Status = IoCreateDevice(FDODeviceExtension->Common.DriverExtension->DriverObject, sizeof(HIDCLASS_PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject); + if (!NT_SUCCESS(Status)) + { + // + // failed to create device + // + DPRINT1("[HIDCLASS] Failed to create PDO %x\n", Status); + break; + } + + // + // patch stack size + // + PDODeviceObject->StackSize = DeviceObject->StackSize + 1; + + // + // get device extension + // + PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; + + // + // init device extension + // + PDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension; + PDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject; + PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject; + PDODeviceExtension->Common.IsFDO = FALSE; + PDODeviceExtension->FDODeviceObject = DeviceObject; + PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension; + PDODeviceExtension->CollectionNumber = FDODeviceExtension->Common.DeviceDescription.CollectionDesc[Index].CollectionNumber; + + // + // copy device data + // + RtlCopyMemory(&PDODeviceExtension->Common.Attributes, &FDODeviceExtension->Common.Attributes, sizeof(HID_DEVICE_ATTRIBUTES)); + RtlCopyMemory(&PDODeviceExtension->Common.DeviceDescription, &FDODeviceExtension->Common.DeviceDescription, sizeof(HIDP_DEVICE_DESC)); + RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES)); + + // + // set device flags + // + PDODeviceObject->Flags |= DO_MAP_IO_BUFFER; + + // + // device is initialized + // + PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + // + // store device object in device relations + // + DeviceRelations->Objects[Index] = PDODeviceObject; + DeviceRelations->Count++; + + // + // move to next + // + Index++; + + }while(Index < FDODeviceExtension->Common.DeviceDescription.CollectionDescLength); + + + // + // check if creating succeeded // - Status = IoCreateDevice(FDODeviceExtension->Common.DriverExtension->DriverObject, sizeof(HIDCLASS_PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject); if (!NT_SUCCESS(Status)) { // - // failed to create device + // failed // - DPRINT1("[HIDCLASS] Failed to create device %x\n", Status); + for(Index = 0; Index < DeviceRelations->Count; Index++) + { + // + // delete device + // + IoDeleteDevice(DeviceRelations->Objects[Index]); + } + + // + // free device relations + // + ExFreePool(DeviceRelations); return Status; } // - // patch stack size + // store device relations // - PDODeviceObject->StackSize = DeviceObject->StackSize + 1; - - // - // get device extension - // - PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; - - // - // init device extension - // - PDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension; - PDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject; - PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject; - PDODeviceExtension->Common.IsFDO = FALSE; - PDODeviceExtension->FDODeviceObject = DeviceObject; - PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension; - RtlCopyMemory(&PDODeviceExtension->Common.Attributes, &FDODeviceExtension->Common.Attributes, sizeof(HID_DEVICE_ATTRIBUTES)); - RtlCopyMemory(&PDODeviceExtension->Common.DeviceDescription, &FDODeviceExtension->Common.DeviceDescription, sizeof(HIDP_DEVICE_DESC)); - RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES)); - - // - // FIXME: support composite devices - // - PDODeviceExtension->CollectionIndex = 0; - ASSERT(PDODeviceExtension->Common.DeviceDescription.CollectionDescLength == 1); - - // - // store in device relations struct - // - FDODeviceExtension->DeviceRelations.Count = 1; - FDODeviceExtension->DeviceRelations.Objects[0] = PDODeviceObject; - - // - // set device flags - // - PDODeviceObject->Flags |= DO_MAP_IO_BUFFER; - - // - // device is initialized - // - PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - ObReferenceObject(PDODeviceObject); + *OutDeviceRelations = DeviceRelations; // // done diff --git a/drivers/hid/hidclass/precomp.h b/drivers/hid/hidclass/precomp.h index 401cd303a1a..db0159c3fa3 100644 --- a/drivers/hid/hidclass/precomp.h +++ b/drivers/hid/hidclass/precomp.h @@ -76,7 +76,7 @@ typedef struct // // device relations // - DEVICE_RELATIONS DeviceRelations; + PDEVICE_RELATIONS DeviceRelations; }HIDCLASS_FDO_EXTENSION, *PHIDCLASS_FDO_EXTENSION; @@ -95,7 +95,7 @@ typedef struct // // collection index // - ULONG CollectionIndex; + ULONG CollectionNumber; // // device interface @@ -176,12 +176,22 @@ HidClassFDO_DispatchRequestSynchronous( /* pdo.c */ NTSTATUS HidClassPDO_CreatePDO( - IN PDEVICE_OBJECT DeviceObject); + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_RELATIONS *OutDeviceRelations); NTSTATUS HidClassPDO_PnP( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +PHIDP_COLLECTION_DESC +HidClassPDO_GetCollectionDescription( + PHIDP_DEVICE_DESC DeviceDescription, + ULONG CollectionNumber); + +PHIDP_REPORT_IDS +HidClassPDO_GetReportDescription( + PHIDP_DEVICE_DESC DeviceDescription, + ULONG CollectionNumber); /* eof */