diff --git a/drivers/usb/usbccgp/descriptor.c b/drivers/usb/usbccgp/descriptor.c index 58ae0cf4adc..fcc504b9744 100644 --- a/drivers/usb/usbccgp/descriptor.c +++ b/drivers/usb/usbccgp/descriptor.c @@ -201,6 +201,66 @@ CountInterfaceDescriptors( return Count; } +NTSTATUS +AllocateInterfaceDescriptorsArray( + IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + OUT PUSB_INTERFACE_DESCRIPTOR **OutArray) +{ + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + PVOID CurrentPosition; + ULONG Count = 0; + PUSB_INTERFACE_DESCRIPTOR *Array; + + Count = CountInterfaceDescriptors(ConfigurationDescriptor); + ASSERT(Count); + + // + // allocate array + // + Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Count); + if (!Array) + return STATUS_INSUFFICIENT_RESOURCES; + + // + // enumerate all interfaces + // + CurrentPosition = ConfigurationDescriptor; + Count = 0; + do + { + // + // find next descriptor + // + InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1); + if (!InterfaceDescriptor) + break; + + // + // store descriptor + // + Array[Count] = InterfaceDescriptor; + Count++; + + // + // advance to next descriptor + // + CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + + }while(TRUE); + + // + // store result + // + *OutArray = Array; + + // + // done + // + return STATUS_SUCCESS; +} + + + NTSTATUS NTAPI USBCCGP_ScanConfigurationDescriptor( diff --git a/drivers/usb/usbccgp/fdo.c b/drivers/usb/usbccgp/fdo.c index 4415324a00e..d8885234af2 100644 --- a/drivers/usb/usbccgp/fdo.c +++ b/drivers/usb/usbccgp/fdo.c @@ -279,7 +279,9 @@ FDO_CreateChildPdo( PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index]; PDODeviceExtension->NextDeviceObject = DeviceObject; PDODeviceExtension->FunctionIndex = Index; + PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor; RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES)); + RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, &FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); // // patch the stack size diff --git a/drivers/usb/usbccgp/function.c b/drivers/usb/usbccgp/function.c index 1c531adda5d..e251a2cafc5 100644 --- a/drivers/usb/usbccgp/function.c +++ b/drivers/usb/usbccgp/function.c @@ -787,23 +787,18 @@ USBCCGP_EnumWithAudioLegacy( FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0; // - // FIXME: how many interfaces should be stored? + // store interfaces // - - FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1); - if (!FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList) + Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList); + if (!NT_SUCCESS(Status)) { // - // no memory + // failed to allocate descriptor array // - return STATUS_INSUFFICIENT_RESOURCES; + DPRINT1("[USBCCGP] Failed to allocate descriptor array %x\n", Status); + return Status; } - // - // store interface descriptor - // - FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList[0] = InterfaceDescriptor; - // // now init the device ids // @@ -817,6 +812,11 @@ USBCCGP_EnumWithAudioLegacy( return Status; } + // + // number of interfaces + // + FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = CountInterfaceDescriptors(FDODeviceExtension->ConfigurationDescriptor); + // // store function count // diff --git a/drivers/usb/usbccgp/pdo.c b/drivers/usb/usbccgp/pdo.c index 4dfe9b56144..4e4c5397b55 100644 --- a/drivers/usb/usbccgp/pdo.c +++ b/drivers/usb/usbccgp/pdo.c @@ -323,6 +323,280 @@ PDO_HandlePnp( } +NTSTATUS +USBCCGP_BuildConfigurationDescriptor( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + ULONG TotalSize, Index; + PURB Urb; + PVOID Buffer; + PUCHAR BufferPtr; + + // + // get current stack location + // + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT1("USBCCGP_BuildConfigurationDescriptor\n"); + + // + // get device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // get configuration descriptor + // + ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor; + + // + // calculate size of configuration descriptor + // + TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); + + for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++) + { + // + // get current interface descriptor + // + InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index]; + + // + // add to size and move to next descriptor + // + TotalSize += InterfaceDescriptor->bLength; + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + + do + { + if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) + { + // + // reached end of configuration descriptor + // + break; + } + + // + // association descriptors are removed + // + if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE) + { + if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) + { + // + // reached next descriptor + // + break; + } + + // + // append size + // + TotalSize += InterfaceDescriptor->bLength; + } + + // + // move to next descriptor + // + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + }while(TRUE); + } + + // + // now allocate temporary buffer for the configuration descriptor + // + Buffer = AllocateItem(NonPagedPool, TotalSize); + if (!Buffer) + { + // + // failed to allocate buffer + // + DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // first copy the configuration descriptor + // + RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR)); + BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength); + + for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++) + { + // + // get current interface descriptor + // + InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index]; + + // + // copy descriptor and move to next descriptor + // + RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength); + BufferPtr += InterfaceDescriptor->bLength; + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + + do + { + if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) + { + // + // reached end of configuration descriptor + // + break; + } + + // + // association descriptors are removed + // + if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE) + { + if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) + { + // + // reached next descriptor + // + break; + } + + // + // copy descriptor + // + RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength); + BufferPtr += InterfaceDescriptor->bLength; + } + + // + // move to next descriptor + // + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + }while(TRUE); + } + + // + // modify configuration descriptor + // + ConfigurationDescriptor = Buffer; + ConfigurationDescriptor->wTotalLength = TotalSize; + ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; + + // + // get urb + // + Urb = (PURB)IoStack->Parameters.Others.Argument1; + ASSERT(Urb); + + // + // copy descriptor + // + RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength)); + + // + // store final size + // + Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize; + + // + // free buffer + // + FreeItem(Buffer); + + // + // done + // + return STATUS_SUCCESS; +} + +NTSTATUS +PDO_HandleInternalDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + NTSTATUS Status; + PURB Urb; + + // + // get current stack location + // + IoStack = IoGetCurrentIrpStackLocation(Irp); + + // + // get device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB) + { + // + // get urb + // + Urb = (PURB)IoStack->Parameters.Others.Argument1; + ASSERT(Urb); + + if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE) + { + DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function); + + if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE) + { + // + // is the buffer big enough + // + if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR)) + { + // + // invalid buffer size + // + DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength); + Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR); + Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INVALID_BUFFER_SIZE; + } + + // + // copy device descriptor + // + ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); + RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE) + { + // + // build configuration descriptor + // + Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp); + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + } + } + + + + DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength); + DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength); + DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer); + + ASSERT(FALSE); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NOT_IMPLEMENTED; +} + NTSTATUS PDO_Dispatch( @@ -339,6 +613,8 @@ PDO_Dispatch( { case IRP_MJ_PNP: return PDO_HandlePnp(DeviceObject, Irp); + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + return PDO_HandleInternalDeviceControl(DeviceObject, Irp); default: DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction); ASSERT(FALSE); diff --git a/drivers/usb/usbccgp/usbccgp.h b/drivers/usb/usbccgp/usbccgp.h index fbafd9514db..d25c3d54c45 100644 --- a/drivers/usb/usbccgp/usbccgp.h +++ b/drivers/usb/usbccgp/usbccgp.h @@ -50,6 +50,8 @@ typedef struct PDEVICE_OBJECT NextDeviceObject; // next device object DEVICE_CAPABILITIES Capabilities; // device capabilities ULONG FunctionIndex; // function index + USB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; /* descriptor.c */ @@ -73,6 +75,15 @@ USBCCGP_GetDescriptor( IN LANGID LanguageId, OUT PVOID *OutDescriptor); +ULONG +CountInterfaceDescriptors( + IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); + +NTSTATUS +AllocateInterfaceDescriptorsArray( + IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + OUT PUSB_INTERFACE_DESCRIPTOR **OutArray); + /* misc.c */ NTSTATUS