[USB-BRINGUP]

- Create PDO for each top level collection found
- Use the specified collection index instead of the first
- add collection id to hardware id when the device has more than one top level collection, see http://msdn.microsoft.com/en-us/windows/hardware/gg487473 for details

svn path=/branches/usb-bringup/; revision=54808
This commit is contained in:
Johannes Anderwald 2012-01-02 12:00:51 +00:00
parent 842fe995ce
commit 07ae01f96c
4 changed files with 277 additions and 94 deletions

View file

@ -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);
}
//

View file

@ -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;

View file

@ -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

View file

@ -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 */