/// <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> /// This method is used to verify the URB_COMPLETION_NO_DATA PDU. /// </summary> /// <param name="responsePdu">The PDU from the client.</param> /// <param name="tsUrb">The TS_URB in the request.</param> /// <param name="isTransferInRequest">This specify if the request is TRANSFER_IN_REQUEST or TRANSFER_OUT_REQUEST.</param> /// <param name="requestCompletion">A unique InterfaceID to be set in the Register Request Callback Message.</param> public static void VerifyUrbCompletionNoData(EusbUrbCompletionNoDataPdu responsePdu, TS_URB tsUrb, bool isTransferInRequest, uint requestCompletion) { Site.Assert.AreEqual<uint>( requestCompletion, responsePdu.InterfaceId, "Expect that the InterfaceId in the response PDU equals the RequestCompletion field of the REGISTER_REQUEST_CALLBACK PDU. The actual value is 0x{0:x8}.", responsePdu.InterfaceId); Site.Assert.AreEqual<Mask_Values>( Mask_Values.STREAM_ID_PROXY, responsePdu.Mask, "Expect that the Mask in the response PDU is STREAM_ID_PROXY."); Site.Assert.AreEqual<FunctionId_Values>( FunctionId_Values.URB_COMPLETION_NO_DATA, (FunctionId_Values)responsePdu.FunctionId, "Expect that the FunctionId in the response PDU is CHANNEL_CREATED. The actual value is 0x{0:x8}.", responsePdu.FunctionId); Site.Assert.AreEqual<uint>( tsUrb.Header.RequestId, responsePdu.RequestId, "Expect that the RequestId in the response PDU equals the RequestId in the request PDU. The actual value is 0x{0:x8}.", responsePdu.RequestId); if (isTransferInRequest) { #region Verify Response For TRANSFER_IN_REQUEST Site.Assert.AreEqual<uint>( 0, responsePdu.OutputBufferSize, "Expect that the OutputBufferSize in the response PDU is zero. The actual value is 0x{0:x8}.", responsePdu.OutputBufferSize); if (tsUrb is TS_URB_SELECT_CONFIGURATION) { #region Verify TS_URB_SELECT_CONFIGURATION_RESULT Site.Log.Add(LogEntryKind.Debug, "Expect the TsUrbResult is TS_URB_SELECT_CONFIGURATION_RESULT when the TsUrb in the request is TS_URB_SELECT_CONFIGURATION."); TS_URB_SELECT_CONFIGURATION_RESULT urb = new TS_URB_SELECT_CONFIGURATION_RESULT(); if (!PduMarshaler.Unmarshal(responsePdu.TsUrbResult, urb)) { // TsUrbResult can not be unmarshaled to TS_URB_SELECT_CONFIGURATION_RESULT TS_URB_UNKNOWN unknowUrb = new TS_URB_UNKNOWN(); Site.Assume.IsTrue(PduMarshaler.Unmarshal(responsePdu.TsUrbResult, unknowUrb), "Marshaling the data to an unknown PDU MUST succeed."); Site.Log.Add(LogEntryKind.CheckFailed, "The TsUrbResult is not valid TS_URB_SELECT_CONFIGURATION_RESULT. The data is:\r\n{0}", unknowUrb.ToString()); } else { Site.Log.Add(LogEntryKind.CheckSucceeded, "The TsUrbResult is expected TS_URB_SELECT_CONFIGURATION_RESULT."); } #endregion } else if (tsUrb is TS_URB_SELECT_INTERFACE) { #region Verify TS_URB_SELECT_INTERFACE_RESULT Site.Log.Add(LogEntryKind.Debug, "Expect the TsUrbResult is TS_URB_SELECT_INTERFACE_RESULT when the TsUrb in the request is TS_URB_SELECT_INTERFACE."); TS_URB_SELECT_INTERFACE_RESULT urb = new TS_URB_SELECT_INTERFACE_RESULT(); if (!PduMarshaler.Unmarshal(responsePdu.TsUrbResult, urb)) { // TsUrbResult can not be unmarshaled to TS_URB_SELECT_INTERFACE_RESULT TS_URB_UNKNOWN unknowUrb = new TS_URB_UNKNOWN(); Site.Assume.IsTrue(PduMarshaler.Unmarshal(responsePdu.TsUrbResult, unknowUrb), "Marshaling the data to an unknown PDU MUST succeed."); Site.Log.Add(LogEntryKind.CheckFailed, "The TsUrbResult is not valid TS_URB_SELECT_INTERFACE_RESULT. The data is:\r\n{0}", unknowUrb.ToString()); } else { Site.Log.Add(LogEntryKind.CheckSucceeded, "The TsUrbResult is expected TS_URB_SELECT_INTERFACE_RESULT."); } #endregion } else if (tsUrb is TS_URB_GET_CURRENT_FRAME_NUMBER) { #region Verify TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT Site.Log.Add(LogEntryKind.Debug, "Expect the TsUrbResult is TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT when the TsUrb in the request is TS_URB_GET_CURRENT_FRAME_NUMBER."); TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT urb = new TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT(); if (!PduMarshaler.Unmarshal(responsePdu.TsUrbResult, urb)) { // TsUrbResult can not be unmarshaled to TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT TS_URB_UNKNOWN unknowUrb = new TS_URB_UNKNOWN(); Site.Assume.IsTrue(PduMarshaler.Unmarshal(responsePdu.TsUrbResult, unknowUrb), "Marshaling the data to an unknown PDU MUST succeed."); Site.Log.Add(LogEntryKind.CheckFailed, "The TsUrbResult is not valid TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT. The data is:\r\n{0}", unknowUrb.ToString()); } else { Site.Log.Add(LogEntryKind.CheckSucceeded, "The TsUrbResult is expected TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT."); } #endregion } #endregion } else { #region Verify Response For TRANSFER_OUT_REQUEST Site.Assert.AreNotEqual<uint>( 0, responsePdu.OutputBufferSize, "Expect that the OutputBufferSize in the response PDU is not zero. The actual value is 0x{0:x8}.", responsePdu.OutputBufferSize); #endregion } #region Verify TS_URB_ISOCH_TRANSFER_RESULT if (tsUrb is TS_URB_ISOCH_TRANSFER) { Site.Log.Add(LogEntryKind.Debug, "Expect the TsUrbResult is TS_URB_ISOCH_TRANSFER_RESULT when the TsUrb in the request is TS_URB_ISOCH_TRANSFER."); TS_URB_ISOCH_TRANSFER_RESULT urb = new TS_URB_ISOCH_TRANSFER_RESULT(); if (!PduMarshaler.Unmarshal(responsePdu.TsUrbResult, urb)) { // TsUrbResult can not be unmarshaled to TS_URB_ISOCH_TRANSFER_RESULT TS_URB_UNKNOWN unknowUrb = new TS_URB_UNKNOWN(); Site.Assume.IsTrue(PduMarshaler.Unmarshal(responsePdu.TsUrbResult, unknowUrb), "Marshaling the data to an unknown PDU MUST succeed."); Site.Log.Add(LogEntryKind.CheckFailed, "The TsUrbResult is not valid TS_URB_ISOCH_TRANSFER_RESULT. The data is:\r\n{0}", unknowUrb.ToString()); } else { Site.Log.Add(LogEntryKind.CheckSucceeded, "Expect that the TsUrbResult is TS_URB_ISOCH_TRANSFER_RESULT."); } } #endregion }
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; }