/// <summary>
        /// Builds a request to retrieve the current alternate interface setting for an interface in the current configuration.
        /// </summary>
        /// <param name="interfaceIndex">Specifies the device-defined index of the interface descriptor being retrieved.</param>
        /// <returns>The request to retrieve the current alternate interface setting.</returns>
        public TS_URB_CONTROL_GET_INTERFACE_REQUEST BuildGetInterfaceRequest(ushort interfaceIndex)
        {
            TS_URB_CONTROL_GET_INTERFACE_REQUEST req = new TS_URB_CONTROL_GET_INTERFACE_REQUEST(
                this.requestId,
                0);

            req.Interface = interfaceIndex;
            req.Padding   = PaddingGenerator.GeneratePadding();
            return(req);
        }
        /// <summary>
        /// Builds an interface-selection request.
        /// </summary>
        /// <param name="configuration">The result of configuration-selection.</param>
        /// <param name="index">The index of the interface to be selected.</param>
        /// <returns>The interface-selection request.</returns>
        public TS_URB_SELECT_INTERFACE BuildSelectionInterfaceRequest(TS_URB_SELECT_CONFIGURATION_RESULT configuration, int index)
        {
            if (null == configuration)
            {
                throw new ArgumentNullException("configuration");
            }
            if (index >= configuration.Interface.Length || null == configuration.Interface[index])
            {
                throw new ArgumentException("index specified interface doesn't exist.");
            }

            TS_URB_SELECT_INTERFACE urb = new TS_URB_SELECT_INTERFACE(this.requestId, this.noAck);

            urb.ConfigurationHandle = configuration.ConfigurationHandle;
            urb.Header.Size         = 8 + 4; // Header + ConfigurationHandle
            urb.TsUsbdIInfo         = new TS_USBD_INTERFACE_INFORMATION();
            TS_USBD_INTERFACE_INFORMATION_RESULT inf = configuration.Interface[index];

            if (inf.NumberOfPipes != inf.Pipes.Length)
            {
                throw new ArgumentException(String.Format(
                                                "The selecting interface count doesn't match. NumberOfPipes: {0}, Pipes count: {1}.",
                                                inf.NumberOfPipes,
                                                inf.Pipes.Length
                                                ));
            }

            urb.TsUsbdIInfo.Length = 2 + 2 + 1 + 1 + 2 + 4;
            urb.TsUsbdIInfo.NumberOfPipesExpected = (ushort)inf.NumberOfPipes;
            urb.TsUsbdIInfo.InterfaceNumber       = inf.InterfaceNumber;
            urb.TsUsbdIInfo.AlternateSetting      = inf.AlternateSetting;
            urb.TsUsbdIInfo.Padding       = PaddingGenerator.GeneratePadding();
            urb.TsUsbdIInfo.NumberOfPipes = inf.NumberOfPipes;

            urb.TsUsbdIInfo.Infomations = new TS_USBD_PIPE_INFORMATION[inf.NumberOfPipes];
            for (int i = 0; i < inf.NumberOfPipes; i++)
            {
                urb.TsUsbdIInfo.Length        += 2 + 2 + 4 + 4; // count Pipe sizes
                urb.TsUsbdIInfo.Infomations[i] = new TS_USBD_PIPE_INFORMATION();
                urb.TsUsbdIInfo.Infomations[i].MaximumPacketSize   = inf.Pipes[i].MaximumPacketSize;
                urb.TsUsbdIInfo.Infomations[i].Padding             = PaddingGenerator.GeneratePadding();
                urb.TsUsbdIInfo.Infomations[i].MaximumTransferSize = inf.Pipes[i].MaximumTransferSize;
                urb.TsUsbdIInfo.Infomations[i].PipeFlags           = inf.Pipes[i].PipeFlags;
            }

            urb.Header.Size += urb.TsUsbdIInfo.Length; // interface information size.
            return(urb);
        }
        /// <summary>
        /// Parses all information of the configuration result.
        /// </summary>
        /// <param name="pdu">The EusbUrbCompletionPdu to be parsed.</param>
        /// <returns>true indicates successful.</returns>
        public bool ParseAll(EusbUrbCompletionPdu pdu)
        {
            if (pdu.OutputBuffer == null)
            {
                return(false);
            }
            ms = new MemoryStream(pdu.OutputBuffer);

            USB_CONFIGURATION_DESCRIPTOR cd = UsbStructParser.Parse <USB_CONFIGURATION_DESCRIPTOR>(pdu);

            ms.Seek(USB_CONFIGURATION_DESCRIPTOR.DefaultSize, SeekOrigin.Begin);

            if (ms.Length != cd.wTotalLength)
            {
                return(false);
            }

            configDescriptor = pdu.OutputBuffer;

            USB_INTERFACE_DESCRIPTOR interfaceDes = (USB_INTERFACE_DESCRIPTOR)GetNextDescriptor(UsbDescriptorTypes.USB_INTERFACE_DESCRIPTOR_TYPE);

            while (null != interfaceDes)
            {
                TS_USBD_INTERFACE_INFORMATION interfaceInfo = new TS_USBD_INTERFACE_INFORMATION();
                interfaceInfo.NumberOfPipesExpected = interfaceDes.bNumEndpoints;
                interfaceInfo.InterfaceNumber       = interfaceDes.bInterfaceNumber;
                interfaceInfo.AlternateSetting      = interfaceDes.bAlternateSetting;
                // Padding can be set to any value and MUST be ignored upon receipt.
                interfaceInfo.Padding = PaddingGenerator.GeneratePadding();
                GeneratePipeInformation(interfaceDes, interfaceInfo);
                interfaces.Add(interfaceInfo);

                interfaceDes = (USB_INTERFACE_DESCRIPTOR)GetNextDescriptor(UsbDescriptorTypes.USB_INTERFACE_DESCRIPTOR_TYPE);
            }

            return(true);
        }
        private void GeneratePipeInformation(USB_INTERFACE_DESCRIPTOR interfaceDes, TS_USBD_INTERFACE_INFORMATION interfaceInfo)
        {
            uint pipeCount = interfaceDes.bNumEndpoints;

            interfaceInfo.NumberOfPipes = pipeCount;
            interfaceInfo.Infomations   = new TS_USBD_PIPE_INFORMATION[pipeCount];

            ushort lenExpectPipeInfo = 2 + 2 + 1 + 1 + 2 + 4;

            interfaceInfo.Length = (ushort)(lenExpectPipeInfo + pipeCount * (2 + 2 + 4 + 4));

            for (int i = 0; i < pipeCount; i++)
            {
                interfaceInfo.Infomations[i] = new TS_USBD_PIPE_INFORMATION();
                // TODO:
                // In Windows XP, Windows Server 2003 and later operating system, Alt settings for an interface or restrict the maximum packet size by setting
                // MaximumPacketSize to some value less than or equal to the value of of wMaxPacketSize defined in device firmware for the current Alt settings.
                interfaceInfo.Infomations[i].MaximumPacketSize = 0;
                interfaceInfo.Infomations[i].Padding           = PaddingGenerator.GeneratePadding();
                // In Windows XP, Windows Server 2003 and later operating system, the MaximumTransferSize member of the USBD_PIPE_INFORMATION structure is obsolete.
                interfaceInfo.Infomations[i].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
                interfaceInfo.Infomations[i].PipeFlags           = 0;
            }
        }