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