reactos/drivers/usb/usbccgp/function.c

896 lines
26 KiB
C

/*
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbccgp/descriptor.c
* PURPOSE: USB device driver.
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
* Johannes Anderwald (johannes.anderwald@reactos.org)
* Cameron Gutman
*/
#include "usbccgp.h"
#define NDEBUG
#include <debug.h>
NTSTATUS
USBCCGP_QueryInterface(
IN PDEVICE_OBJECT DeviceObject,
OUT PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface)
{
KEVENT Event;
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
PIO_STACK_LOCATION Stack;
/* Sanity checks */
ASSERT(DeviceObject);
/* Initialize event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Init interface */
RtlZeroMemory(BusInterface, sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1));
BusInterface->Version = USBC_DEVICE_CONFIGURATION_INTERFACE_VERSION_1;
BusInterface->Size = sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1);
/* Create irp */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
DeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatus);
//
// was irp built
//
if (Irp == NULL)
{
//
// no memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// initialize request
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_PNP;
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBC_CONFIGURATION_GUID;
Stack->Parameters.QueryInterface.Version = 2;
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)&BusInterface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//
// call driver
//
Status = IoCallDriver(DeviceObject, Irp);
//
// did operation complete
//
if (Status == STATUS_PENDING)
{
//
// wait for completion
//
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
//
// collect status
//
Status = IoStatus.Status;
}
return Status;
}
NTSTATUS
USBCCGP_CustomEnumWithInterface(
IN PDEVICE_OBJECT DeviceObject)
{
PFDO_DEVICE_EXTENSION FDODeviceExtension;
ULONG FunctionDescriptorBufferLength = 0;
NTSTATUS Status;
PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptorBuffer = NULL;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
if (FDODeviceExtension->BusInterface.StartDeviceCallback == NULL)
{
//
// not supported
//
return STATUS_NOT_SUPPORTED;
}
//
// invoke callback
//
Status = FDODeviceExtension->BusInterface.StartDeviceCallback(FDODeviceExtension->DeviceDescriptor,
FDODeviceExtension->ConfigurationDescriptor,
&FunctionDescriptorBuffer,
&FunctionDescriptorBufferLength,
DeviceObject,
FDODeviceExtension->PhysicalDeviceObject);
DPRINT("USBCCGP_CustomEnumWithInterface Status %lx\n", Status);
if (!NT_SUCCESS(Status))
{
//
// failed
//
return Status;
}
DPRINT("FunctionDescriptorBufferLength %lu\n", FunctionDescriptorBufferLength);
DPRINT("FunctionDescriptorBuffer %p\n", FunctionDescriptorBuffer);
//
// assume length % function buffer size
//
ASSERT(FunctionDescriptorBufferLength);
ASSERT(FunctionDescriptorBufferLength % sizeof(USBC_FUNCTION_DESCRIPTOR) == 0);
//
// store result
//
FDODeviceExtension->FunctionDescriptor = FunctionDescriptorBuffer;
FDODeviceExtension->FunctionDescriptorCount = FunctionDescriptorBufferLength / sizeof(USBC_FUNCTION_DESCRIPTOR);
//
// success
//
return STATUS_SUCCESS;
}
ULONG
USBCCGP_CountAssociationDescriptors(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
PUCHAR Offset, End;
ULONG Count = 0;
//
// init offsets
//
Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
while (Offset < End)
{
//
// get association descriptor
//
Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
{
//
// found descriptor
//
Count++;
}
//
// move to next descriptor
//
Offset += Descriptor->bLength;
}
//
// done
//
return Count;
}
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR
USBCCGP_GetAssociationDescriptorAtIndex(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN ULONG Index)
{
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
PUCHAR Offset, End;
ULONG Count = 0;
//
// init offsets
//
Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
while (Offset < End)
{
//
// get association descriptor
//
Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
{
if (Index == Count)
{
//
// found descriptor
//
return Descriptor;
}
//
// not the searched one
//
Count++;
}
//
// move to next descriptor
//
Offset += Descriptor->bLength;
}
//
// failed to find descriptor at the specified index
//
return NULL;
}
NTSTATUS
USBCCGP_InitInterfaceListOfFunctionDescriptor(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR AssociationDescriptor,
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
{
PUSB_INTERFACE_DESCRIPTOR Descriptor;
PUCHAR Offset, End;
ULONG Count = 0;
//
// init offsets
//
Offset = (PUCHAR)AssociationDescriptor + AssociationDescriptor->bLength;
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
while (Offset < End)
{
//
// get association descriptor
//
Descriptor = (PUSB_INTERFACE_DESCRIPTOR)Offset;
if (Descriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
//
// store interface descriptor
//
FunctionDescriptor->InterfaceDescriptorList[Count] = Descriptor;
Count++;
if (Count == AssociationDescriptor->bInterfaceCount)
{
//
// got all interfaces
//
return STATUS_SUCCESS;
}
}
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
{
//
// WTF? a association descriptor which overlaps the next association descriptor
//
DPRINT1("Invalid association descriptor\n");
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
//
// move to next descriptor
//
Offset += Descriptor->bLength;
}
//
// invalid association descriptor
//
DPRINT1("Invalid association descriptor\n");
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
USBCCGP_InitFunctionDescriptor(
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
IN ULONG FunctionNumber,
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
{
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
NTSTATUS Status;
LPWSTR DescriptionBuffer;
WCHAR Buffer[100];
ULONG Index;
// init function number
FunctionDescriptor->FunctionNumber = (UCHAR)FunctionNumber;
// get association descriptor
Descriptor = USBCCGP_GetAssociationDescriptorAtIndex(FDODeviceExtension->ConfigurationDescriptor, FunctionNumber);
ASSERT(Descriptor);
// store number interfaces
FunctionDescriptor->NumberOfInterfaces = Descriptor->bInterfaceCount;
// allocate array for interface count
FunctionDescriptor->InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Descriptor->bInterfaceCount);
if (!FunctionDescriptor->InterfaceDescriptorList)
{
//
// no memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
// init interface list
Status = USBCCGP_InitInterfaceListOfFunctionDescriptor(FDODeviceExtension->ConfigurationDescriptor, Descriptor, FunctionDescriptor);
if (!NT_SUCCESS(Status))
{
//
// failed
//
return Status;
}
//
// now init interface description
//
if (Descriptor->iFunction)
{
//
// get interface description
//
Status = USBCCGP_GetStringDescriptor(FDODeviceExtension->NextDeviceObject,
100 * sizeof(WCHAR),
Descriptor->iFunction,
0x0409, //FIXME
(PVOID*)&DescriptionBuffer);
if (!NT_SUCCESS(Status))
{
//
// no description
//
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
}
else
{
//
// init description
//
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
}
DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
}
//
// now init hardware id
//
Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
FDODeviceExtension->DeviceDescriptor->idProduct,
FDODeviceExtension->DeviceDescriptor->bcdDevice,
Descriptor->bFirstInterface) + 1;
Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
FDODeviceExtension->DeviceDescriptor->idProduct,
Descriptor->bFirstInterface) + 1;
// allocate result buffer
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
if (!DescriptionBuffer)
{
//
// failed to allocate memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy description
RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
//
// now init the compatible id
//
Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass, Descriptor->bFunctionProtocol) + 1;
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x&SubClass_%02x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass) + 1;
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x", Descriptor->bFunctionClass) + 1;
// allocate result buffer
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
if (!DescriptionBuffer)
{
//
// failed to allocate memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy description
RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
USBCCGP_EnumWithAssociationDescriptor(
IN PDEVICE_OBJECT DeviceObject)
{
ULONG DescriptorCount, Index;
PFDO_DEVICE_EXTENSION FDODeviceExtension;
NTSTATUS Status = STATUS_SUCCESS;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
//
// count association descriptors
//
DescriptorCount = USBCCGP_CountAssociationDescriptors(FDODeviceExtension->ConfigurationDescriptor);
if (!DescriptorCount)
{
//
// no descriptors found
//
return STATUS_NOT_SUPPORTED;
}
//
// allocate function descriptor array
//
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * DescriptorCount);
if (!FDODeviceExtension->FunctionDescriptor)
{
//
// no memory
//
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count %x\n", DescriptorCount);
return STATUS_INSUFFICIENT_RESOURCES;
}
for (Index = 0; Index < DescriptorCount; Index++)
{
//
// init function descriptors
//
Status = USBCCGP_InitFunctionDescriptor(FDODeviceExtension, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
if (!NT_SUCCESS(Status))
{
//
// failed
//
return Status;
}
}
//
// store function descriptor count
//
FDODeviceExtension->FunctionDescriptorCount = DescriptorCount;
//
// done
//
return Status;
}
NTSTATUS
USBCCG_InitIdsWithInterfaceDescriptor(
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
IN PUSB_INTERFACE_DESCRIPTOR Descriptor,
IN ULONG FunctionIndex,
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
{
ULONG Index;
WCHAR Buffer[200];
LPWSTR DescriptionBuffer;
NTSTATUS Status;
//
// now init interface description
//
if (Descriptor->iInterface)
{
//
// get interface description
//
Status = USBCCGP_GetStringDescriptor(FDODeviceExtension->NextDeviceObject,
100 * sizeof(WCHAR),
Descriptor->iInterface,
0x0409, //FIXME
(PVOID*)&DescriptionBuffer);
if (!NT_SUCCESS(Status))
{
//
// no description
//
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
}
else
{
//
// init description
//
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
}
DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
}
//
// now init hardware id
//
Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
FDODeviceExtension->DeviceDescriptor->idProduct,
FDODeviceExtension->DeviceDescriptor->bcdDevice,
FunctionIndex) + 1;
Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
FDODeviceExtension->DeviceDescriptor->idProduct,
FunctionIndex) + 1;
// allocate result buffer
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
if (!DescriptionBuffer)
{
//
// failed to allocate memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy description
RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
//
// now init the compatible id
//
Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass, Descriptor->bInterfaceProtocol) + 1;
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x&SubClass_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass) + 1;
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x", Descriptor->bInterfaceClass) + 1;
// allocate result buffer
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
if (!DescriptionBuffer)
{
//
// failed to allocate memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy description
RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
USBCCGP_LegacyEnum(
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PFDO_DEVICE_EXTENSION FDODeviceExtension;
NTSTATUS Status = STATUS_SUCCESS;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
//
// sanity check
//
ASSERT(FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
//
// allocate function array
//
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
if (!FDODeviceExtension->FunctionDescriptor)
{
//
// no memory
//
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor %lu\n", FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// init function descriptors
//
FDODeviceExtension->FunctionDescriptorCount = 0;
for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
{
// get interface descriptor
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
if (InterfaceDescriptor == NULL)
{
//
// failed to find interface descriptor
//
DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index);
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
//
// init function descriptor
//
FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
{
//
// no memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// store interface descriptor
//
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor;
//
// now init the device ids
//
Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
if (!NT_SUCCESS(Status))
{
//
// failed to init ids
//
DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
return Status;
}
//
// store function count
//
FDODeviceExtension->FunctionDescriptorCount++;
}
//
// done
//
return Status;
}
NTSTATUS
USBCCGP_EnumWithUnionFunctionDescriptors(
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
USBCCGP_EnumWithAudioLegacy(
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, FirstDescriptor = NULL;
PFDO_DEVICE_EXTENSION FDODeviceExtension;
NTSTATUS Status = STATUS_SUCCESS;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
//
// first check if all interfaces belong to the same audio class
//
for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
{
//
// get interface descriptor
//
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor);
ASSERT(InterfaceDescriptor);
if (InterfaceDescriptor->bInterfaceClass != 0x1)
{
//
// collection contains non audio class
//
return STATUS_UNSUCCESSFUL;
}
if (FirstDescriptor == NULL)
{
//
// store interface descriptor
//
FirstDescriptor = InterfaceDescriptor;
continue;
}
if (FirstDescriptor->bInterfaceSubClass == InterfaceDescriptor->bInterfaceSubClass)
{
//
// interface subclass must be different from the first interface
//
return STATUS_UNSUCCESSFUL;
}
}
//
// this is an composite audio device
//
DPRINT("[USBCCGP] Audio Composite Device detected\n");
//
// audio interfaces are all grouped into one single function
//
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR));
if (!FDODeviceExtension->FunctionDescriptor)
{
//
// no memory
//
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// init function number
//
FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
//
// store interfaces
//
Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate descriptor array
//
DPRINT1("[USBCCGP] Failed to allocate descriptor array %lx\n", Status);
return Status;
}
//
// now init the device ids
//
Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, FirstDescriptor, 0, &FDODeviceExtension->FunctionDescriptor[0]);
if (!NT_SUCCESS(Status))
{
//
// failed to init ids
//
DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
return Status;
}
//
// number of interfaces
//
FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces;
//
// store function count
//
FDODeviceExtension->FunctionDescriptorCount = 1;
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
USBCCGP_EnumerateFunctions(
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PFDO_DEVICE_EXTENSION FDODeviceExtension;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
//
// first try with filter driver
//
Status = USBCCGP_CustomEnumWithInterface(DeviceObject);
if (NT_SUCCESS(Status))
{
//
// succeeded
//
return Status;
}
//
// enumerate functions with interface association descriptor
//
Status = USBCCGP_EnumWithAssociationDescriptor(DeviceObject);
if (NT_SUCCESS(Status))
{
//
// succeeded
//
return Status;
}
#if 0
//
// try with union function descriptors
//
Status = USBCCGP_EnumWithUnionFunctionDescriptors(DeviceObject);
if (NT_SUCCESS(Status))
{
//
// succeeded
//
return Status;
}
#endif
//
// try with legacy audio methods
//
Status = USBCCGP_EnumWithAudioLegacy(DeviceObject);
if (NT_SUCCESS(Status))
{
//
// succeeded
//
return Status;
}
//
// try with legacy enumeration
//
return USBCCGP_LegacyEnum(DeviceObject);
}