public void S3_EUSB_OperateIo_SelectConfiguration()
        {
            LogComment("S3_EUSB_OperateIo_SelectConfiguration");

            LogComment("1. Creates the control virtual channel, exchanges capabilities then notifies that the channel is created.");
            context.ControlChannel =  CreateVirtualChannel();

            LogComment("2. Receives an add virtual channel request.");
            rdpeusbAdapter.ExpectAddVirtualChannel(context.ControlChannel);

            LogComment("3. Creates a new virtual channel for the device.");
            uint channelId = context.NewChannelId();
            DynamicVirtualChannel channel =  CreateVirtualChannel();

            LogComment("4. Receives an add device request.");
            EusbDeviceContext device = rdpeusbAdapter.ExpectAddDevice(channel);

            LogComment("5. Registers a callback to provide the Request Completion Interface to the client.");
            uint interfaceId = IdGenerator.NewId();
            rdpeusbAdapter.RegisterCallback(device, 1, interfaceId);

            LogComment("6. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the descriptor type of USB_DEVICE_DESCRIPTOR_TYPE.");
            uint requestId = IdGenerator.NewId();
            TS_URB_CONTROL_DESCRIPTOR_REQUEST des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildDeviceDescriptorRequest();
            rdpeusbAdapter.TransferInRequest(device, des, USB_DEVICE_DESCRIPTOR.DefaultSize);

            LogComment("7. Receives a completion message with the result for USB_DEVICE_DESCRIPTOR.");
            EusbPdu pdu = rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            ReqCapturer.VerifyUrbCompletion((EusbUrbCompletionPdu)pdu, des, interfaceId);
            EusbUrbCompletionPdu completionPdu = (EusbUrbCompletionPdu)pdu;
            USB_DEVICE_DESCRIPTOR desDevice = UsbStructParser.Parse<USB_DEVICE_DESCRIPTOR>(completionPdu);

            // A device may support multiple configurations, numbered starting at zero.
            // Test case will assume the device only have a single configuration.
            Site.Assume.AreEqual<byte>(1, desDevice.bNumConfigurations, "This test case only supports the device with the single configuration.");

            LogComment("Retrieved the device descriptor: {0}", desDevice.ToString());

            LogComment("8. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the descriptor type of USB_CONFIGURATION_DESCRIPTOR_TYPE to query " +
                "the total length of the configuration.");
            requestId = IdGenerator.NewId();
            des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(0);
            rdpeusbAdapter.TransferInRequest(device, des, USB_CONFIGURATION_DESCRIPTOR.DefaultSize);

            LogComment("9. Receives a completion message with the result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            ReqCapturer.VerifyUrbCompletion((EusbUrbCompletionPdu)pdu, des, interfaceId);
            completionPdu = (EusbUrbCompletionPdu)pdu;
            USB_CONFIGURATION_DESCRIPTOR desConfig = UsbStructParser.Parse<USB_CONFIGURATION_DESCRIPTOR>(completionPdu);

            LogComment("10. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the actual length of USB_CONFIGURATION_DESCRIPTOR result.");
            requestId = IdGenerator.NewId();
            des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(0);
            rdpeusbAdapter.TransferInRequest(device, des, desConfig.wTotalLength);

            LogComment("11. Receives a completion message with the complete result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            ReqCapturer.VerifyUrbCompletion((EusbUrbCompletionPdu)pdu, des, interfaceId);
            completionPdu = (EusbUrbCompletionPdu)pdu;

            LogComment("12. Sends TS_URB_SELECT_CONFIGURATION URB request.");
            UsbConfigurationParser configParser = new UsbConfigurationParser();
            configParser.ParseAll(completionPdu);
            requestId = IdGenerator.NewId();
            TS_URB_SELECT_CONFIGURATION sel = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildSelectConfigRequest(configParser.Interfaces, configParser.configDescriptor);
            rdpeusbAdapter.TransferInRequest(device, sel, 0);

            LogComment("13. Receives a completion message with the result for configuration selection.");
            pdu = rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            Site.Assert.IsInstanceOfType(
                pdu,
                typeof(EusbUrbCompletionNoDataPdu),
                "The result must be type of EusbUrbCompletionNoDataPdu.");
            EusbUrbCompletionNoDataPdu pduRes = (EusbUrbCompletionNoDataPdu)pdu;
            Site.Assert.IsSuccess((int)pduRes.HResult, "The EusbUrbCompletionNoDataPdu must indicate successful.");
            ReqCapturer.VerifyUrbCompletionNoData(pduRes, sel, true, interfaceId);

            TS_URB_SELECT_CONFIGURATION_RESULT urb = new TS_URB_SELECT_CONFIGURATION_RESULT();
            Site.Assert.IsTrue(
                PduMarshaler.Unmarshal(pduRes.TsUrbResult, urb),
                "The completion PDU must contain the result.");

            LogComment("The configuration-selection result is {0}.", urb);

            LogComment("14. Sends retract device request and the channel for the device is expected to be closed.");
            rdpeusbAdapter.RetractDevice(device, USB_RETRACT_REASON.UsbRetractReason_BlockedByPolicy);
        }
        private bool SelectConfiguration(EusbDeviceContext device, byte configIndex)
        {
            // 6. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the descriptor type of USB_DEVICE_DESCRIPTOR_TYPE.
            uint requestId = IdGenerator.NewId();
            TS_URB_CONTROL_DESCRIPTOR_REQUEST des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildDeviceDescriptorRequest();

            rdpeusbAdapter.TransferInRequest(device, des, USB_DEVICE_DESCRIPTOR.DefaultSize);

            // 7. Receives a completion message with the result for USB_DEVICE_DESCRIPTOR.");
            EusbUrbCompletionPdu pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);

            if (null == pdu || pdu.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return(false);
            }
            USB_DEVICE_DESCRIPTOR desDevice = UsbStructParser.Parse <USB_DEVICE_DESCRIPTOR>(pdu);

            // 8. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST to retrieve the total length of the configuration.
            requestId = IdGenerator.NewId();
            des       = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(configIndex);
            rdpeusbAdapter.TransferInRequest(device, des, USB_CONFIGURATION_DESCRIPTOR.DefaultSize);

            // 9. Receives a completion message with the result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            if (null == pdu || pdu.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return(false);
            }
            USB_CONFIGURATION_DESCRIPTOR desConfig = UsbStructParser.Parse <USB_CONFIGURATION_DESCRIPTOR>(pdu);

            // 10. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the actual length of USB_CONFIGURATION_DESCRIPTOR result.
            requestId = IdGenerator.NewId();
            des       = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(configIndex);
            rdpeusbAdapter.TransferInRequest(device, des, desConfig.wTotalLength);

            // 11. Receives a completion message with the complete result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);

            // 12. Sends TS_URB_SELECT_CONFIGURATION URB request.
            UsbConfigurationParser configParser = new UsbConfigurationParser();

            configParser.ParseAll(pdu);
            requestId = IdGenerator.NewId();
            TS_URB_SELECT_CONFIGURATION sel = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildSelectConfigRequest(configParser.Interfaces, configParser.configDescriptor);

            rdpeusbAdapter.TransferInRequest(device, sel, 0);

            // 13. Receives a completion message with the result for configuration selection.");
            EusbUrbCompletionNoDataPdu pduRes = (EusbUrbCompletionNoDataPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);

            if (null == pduRes || pduRes.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return(false);
            }

            TS_URB_SELECT_CONFIGURATION_RESULT urb = new TS_URB_SELECT_CONFIGURATION_RESULT();

            if (!PduMarshaler.Unmarshal(pduRes.TsUrbResult, urb))
            {
                return(false);
            }

            context.SelectedConfig = urb;
            return(true);
        }
        private bool SelectConfiguration(EusbDeviceContext device, byte configIndex)
        {
            // 6. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the descriptor type of USB_DEVICE_DESCRIPTOR_TYPE.
            uint requestId = IdGenerator.NewId();
            TS_URB_CONTROL_DESCRIPTOR_REQUEST des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildDeviceDescriptorRequest();
            rdpeusbAdapter.TransferInRequest(device, des, USB_DEVICE_DESCRIPTOR.DefaultSize);

            // 7. Receives a completion message with the result for USB_DEVICE_DESCRIPTOR.");
            EusbUrbCompletionPdu pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            if (null == pdu || pdu.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return false;
            }
            USB_DEVICE_DESCRIPTOR desDevice = UsbStructParser.Parse<USB_DEVICE_DESCRIPTOR>(pdu);

            // 8. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST to retrieve the total length of the configuration.
            requestId = IdGenerator.NewId();
            des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(configIndex);
            rdpeusbAdapter.TransferInRequest(device, des, USB_CONFIGURATION_DESCRIPTOR.DefaultSize);

            // 9. Receives a completion message with the result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            if (null == pdu || pdu.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return false;
            }
            USB_CONFIGURATION_DESCRIPTOR desConfig = UsbStructParser.Parse<USB_CONFIGURATION_DESCRIPTOR>(pdu);

            // 10. Sends TS_URB_CONTROL_DESCRIPTOR_REQUEST with the actual length of USB_CONFIGURATION_DESCRIPTOR result.
            requestId = IdGenerator.NewId();
            des = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildConfigurationDescriptorRequest(configIndex);
            rdpeusbAdapter.TransferInRequest(device, des, desConfig.wTotalLength);

            // 11. Receives a completion message with the complete result for USB_CONFIGURATION_DESCRIPTOR.");
            pdu = (EusbUrbCompletionPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);

            // 12. Sends TS_URB_SELECT_CONFIGURATION URB request.
            UsbConfigurationParser configParser = new UsbConfigurationParser();
            configParser.ParseAll(pdu);
            requestId = IdGenerator.NewId();
            TS_URB_SELECT_CONFIGURATION sel = new UrbBuilder(
                URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
                requestId,
                0).BuildSelectConfigRequest(configParser.Interfaces, configParser.configDescriptor);
            rdpeusbAdapter.TransferInRequest(device, sel, 0);

            // 13. Receives a completion message with the result for configuration selection.");
            EusbUrbCompletionNoDataPdu pduRes = (EusbUrbCompletionNoDataPdu)rdpeusbAdapter.ExpectCompletion(device.VirtualChannel);
            if (null == pduRes || pduRes.HResult != (uint)HRESULT_FROM_WIN32.ERROR_SUCCESS)
            {
                return false;
            }

            TS_URB_SELECT_CONFIGURATION_RESULT urb = new TS_URB_SELECT_CONFIGURATION_RESULT();
            if (!PduMarshaler.Unmarshal(pduRes.TsUrbResult, urb))
            {
                return false;
            }

            context.SelectedConfig = urb;
            return true;
        }