diff --git a/drivers/usb/usbccgp/descriptor.c b/drivers/usb/usbccgp/descriptor.c index 9d7df069ce2..58ae0cf4adc 100644 --- a/drivers/usb/usbccgp/descriptor.c +++ b/drivers/usb/usbccgp/descriptor.c @@ -162,6 +162,45 @@ USBCCGP_GetDescriptors( return Status; } +ULONG +CountInterfaceDescriptors( + IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) +{ + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + PVOID CurrentPosition; + ULONG Count = 0; + + // + // enumerate all interfaces + // + CurrentPosition = ConfigurationDescriptor; + do + { + // + // find next descriptor + // + InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1); + if (!InterfaceDescriptor) + break; + + // + // advance to next descriptor + // + CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + + // + // increment descriptor count + // + Count++; + + }while(TRUE); + + // + // done + // + return Count; +} + NTSTATUS NTAPI USBCCGP_ScanConfigurationDescriptor( @@ -170,6 +209,8 @@ USBCCGP_ScanConfigurationDescriptor( { PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; ULONG InterfaceIndex = 0; + PVOID CurrentPosition; + ULONG DescriptorCount; // // sanity checks @@ -177,10 +218,15 @@ USBCCGP_ScanConfigurationDescriptor( ASSERT(ConfigurationDescriptor); ASSERT(ConfigurationDescriptor->bNumInterfaces); + // + // count all interface descriptors + // + DescriptorCount = CountInterfaceDescriptors(ConfigurationDescriptor); + // // allocate array holding the interface descriptors // - FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USB_CONFIGURATION_DESCRIPTOR) * (ConfigurationDescriptor->bNumInterfaces + 1)); + FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (DescriptorCount + 1)); if (!FDODeviceExtension->InterfaceList) { // @@ -189,12 +235,13 @@ USBCCGP_ScanConfigurationDescriptor( return STATUS_INSUFFICIENT_RESOURCES; } + CurrentPosition = ConfigurationDescriptor; do { // // parse configuration descriptor // - InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, 0, -1, -1, -1); + InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1); if (InterfaceDescriptor) { // @@ -202,6 +249,7 @@ USBCCGP_ScanConfigurationDescriptor( // FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor; FDODeviceExtension->InterfaceListCount++; + CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); } // @@ -209,7 +257,7 @@ USBCCGP_ScanConfigurationDescriptor( // InterfaceIndex++; - }while(InterfaceIndex < ConfigurationDescriptor->bNumInterfaces); + }while(InterfaceIndex < DescriptorCount); // // sanity check @@ -347,13 +395,12 @@ USBCCGP_SelectConfiguration( // get interface information // InterfaceInformation = &Urb->UrbSelectConfiguration.Interface; - for(Index = 0; Index < DeviceExtension->InterfaceListCount; Index++) { // // allocate buffer to store interface information // - DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation[Index].Length); + DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation->Length); if (!DeviceExtension->InterfaceList[Index].Interface) { // @@ -366,8 +413,14 @@ USBCCGP_SelectConfiguration( // copy interface information // RtlCopyMemory(DeviceExtension->InterfaceList[Index].Interface, InterfaceInformation, InterfaceInformation->Length); + + // + // move to next interface + // + InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length); } + // // store pipe handle // diff --git a/drivers/usb/usbccgp/fdo.c b/drivers/usb/usbccgp/fdo.c index 49a7deb5857..4415324a00e 100644 --- a/drivers/usb/usbccgp/fdo.c +++ b/drivers/usb/usbccgp/fdo.c @@ -138,7 +138,6 @@ FDO_DeviceRelations( // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - // // get current irp stack location // @@ -376,6 +375,7 @@ FDO_StartDevice( // ASSERT(FDODeviceExtension->FunctionDescriptorCount); ASSERT(FDODeviceExtension->FunctionDescriptor); + DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor, FDODeviceExtension->FunctionDescriptorCount); // // now create the pdo diff --git a/drivers/usb/usbccgp/function.c b/drivers/usb/usbccgp/function.c index 89a328bae35..cebe1d89cb4 100644 --- a/drivers/usb/usbccgp/function.c +++ b/drivers/usb/usbccgp/function.c @@ -411,7 +411,10 @@ USBCCGP_InitFunctionDescriptor( // copy description RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR)); - RtlInitUnicodeString(&FunctionDescriptor->HardwareId, DescriptionBuffer); + FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer; + FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR); + FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR); + // // now init the compatible id @@ -430,10 +433,11 @@ USBCCGP_InitFunctionDescriptor( return STATUS_INSUFFICIENT_RESOURCES; } - // copy description // copy description RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR)); - RtlInitUnicodeString(&FunctionDescriptor->CompatibleId, DescriptionBuffer); + FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer; + FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR); + FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR); // // done @@ -506,13 +510,194 @@ USBCCGP_EnumWithAssociationDescriptor( return Status; } +NTSTATUS +USBCCG_InitIdsWithInterfaceDescriptor( + IN PFDO_DEVICE_EXTENSION FDODeviceExtension, + IN PUSB_INTERFACE_DESCRIPTOR Descriptor, + 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_GetDescriptor(FDODeviceExtension->NextDeviceObject, + USB_STRING_DESCRIPTOR_TYPE, + 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, + Descriptor->bInterfaceNumber) + 1; + Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor, + FDODeviceExtension->DeviceDescriptor->idProduct, + Descriptor->bInterfaceNumber) + 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 * 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_%04x&SubClass_%04x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass) + 1; + Index += swprintf(&Buffer[Index], L"USB\\Class_%04x", 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 * sizeof(WCHAR)); + FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer; + FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR); + FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR); +} + NTSTATUS -USBCCGP_EnumWithAudioLegacy( +USBCCGP_LegacyEnum( IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + 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_ParseConfigurationDescriptor(FDODeviceExtension->ConfigurationDescriptor, Index, 0); + if (InterfaceDescriptor == NULL) + { + // + // failed to find interface descriptor + // + DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index); + 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, &FDODeviceExtension->FunctionDescriptor[Index]); + if (!NT_SUCCESS(Status)) + { + // + // failed to init ids + // + DPRINT1("[USBCCGP] Failed to init ids with %x\n", Status); + return Status; + } + + // + // store function count + // + FDODeviceExtension->FunctionDescriptorCount++; + } + + // + // done + // + return Status; } NTSTATUS @@ -523,6 +708,121 @@ USBCCGP_EnumWithUnionFunctionDescriptors( 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, -1, -1, -1, -1); + 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 + // + DPRINT1("[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; + + // + // FIXME: how many interfaces should be stored? + // + + FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1); + if (!FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // store interface descriptor + // + FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList[0] = InterfaceDescriptor; + + // + // now init the device ids + // + Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, &FDODeviceExtension->FunctionDescriptor[0]); + if (!NT_SUCCESS(Status)) + { + // + // failed to init ids + // + DPRINT1("[USBCCGP] Failed to init ids with %x\n", Status); + return Status; + } + + // + // store function count + // + FDODeviceExtension->FunctionDescriptorCount = 1; + + // + // done + // + return STATUS_SUCCESS; +} NTSTATUS USBCCGP_EnumerateFunctions( @@ -561,6 +861,7 @@ USBCCGP_EnumerateFunctions( return Status; } +#if 0 // // try with union function descriptors // @@ -572,9 +873,22 @@ USBCCGP_EnumerateFunctions( // return Status; } +#endif // // try with legacy audio methods // - return USBCCGP_EnumWithAudioLegacy(DeviceObject); + Status = USBCCGP_EnumWithAudioLegacy(DeviceObject); + if (NT_SUCCESS(Status)) + { + // + // succeeded + // + return Status; + } + + // + // try with legacy enumeration + // + return USBCCGP_LegacyEnum(DeviceObject); } diff --git a/drivers/usb/usbccgp/misc.c b/drivers/usb/usbccgp/misc.c index bf6982e2418..62a411b39cd 100644 --- a/drivers/usb/usbccgp/misc.c +++ b/drivers/usb/usbccgp/misc.c @@ -195,3 +195,23 @@ FreeItem( ExFreePoolWithTag(Item, USBCCPG_TAG); } +VOID +DumpFunctionDescriptor( + IN PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor, + IN ULONG FunctionDescriptorCount) +{ + ULONG Index; + + + DPRINT1("FunctionCount %lu\n", FunctionDescriptorCount); + for(Index = 0; Index < FunctionDescriptorCount; Index++) + { + DPRINT1("Function %lu\n", Index); + DPRINT1("FunctionNumber %lu\n", FunctionDescriptor[Index].FunctionNumber); + DPRINT1("HardwareId %wZ\n", &FunctionDescriptor[Index].HardwareId); + DPRINT1("CompatibleId %wZ\n", &FunctionDescriptor[Index].CompatibleId); + DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor[Index].FunctionDescription); + DPRINT1("NumInterfaces %lu\n", FunctionDescriptor[Index].NumberOfInterfaces); + } + +} \ No newline at end of file diff --git a/drivers/usb/usbccgp/pdo.c b/drivers/usb/usbccgp/pdo.c index f1d011aeb07..4dfe9b56144 100644 --- a/drivers/usb/usbccgp/pdo.c +++ b/drivers/usb/usbccgp/pdo.c @@ -18,7 +18,7 @@ USBCCGP_PdoHandleQueryDeviceText( { LPWSTR Buffer; PPDO_DEVICE_EXTENSION PDODeviceExtension; - + LPWSTR GenericString = L"Composite USB Device"; // // get device extension // @@ -53,7 +53,18 @@ USBCCGP_PdoHandleQueryDeviceText( // FIXME use GenericCompositeUSBDeviceString // UNIMPLEMENTED - return Irp->IoStatus.Status; + Buffer = AllocateItem(PagedPool, (wcslen(GenericString) + 1) * sizeof(WCHAR)); + if (!Buffer) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlCopyMemory(Buffer, GenericString, (wcslen(GenericString) + 1) * sizeof(WCHAR)); + Irp->IoStatus.Information = (ULONG_PTR)Buffer; + + return STATUS_SUCCESS; } NTSTATUS @@ -145,7 +156,7 @@ USBCCGP_PdoHandleQueryId( // // FIXME append interface id // - ASSERT(FALSE); + UNIMPLEMENTED return Status; } else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) diff --git a/drivers/usb/usbccgp/usbccgp.h b/drivers/usb/usbccgp/usbccgp.h index 97647359cab..fbafd9514db 100644 --- a/drivers/usb/usbccgp/usbccgp.h +++ b/drivers/usb/usbccgp/usbccgp.h @@ -95,6 +95,11 @@ VOID FreeItem( IN PVOID Item); +VOID +DumpFunctionDescriptor( + IN PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor, + IN ULONG FunctionDescriptorCount); + /* fdo.c */ NTSTATUS