public TS_URB ParsePdu(byte[] data)
        {
            TS_URB urb;

            switch (GetTsUrbType(data))
            {
                // Indicates to the host controller driver that a configuration is to be selected
                case URB_FUNCTIONID.URB_FUNCTION_SELECT_CONFIGURATION:
                    urb = new TS_URB_SELECT_CONFIGURATION();
                    break;
                // Indicates to the host controller driver that an alternate interface setting is being selected for an interface.
                // If set, the URB is used with _URB_SELECT_INTERFACE as the data structure.
                case URB_FUNCTIONID.URB_FUNCTION_SELECT_INTERFACE:
                    urb = new TS_URB_SELECT_INTERFACE();
                    break;
                // Indicates that all outstanding requests for a pipe should be canceled.
                case URB_FUNCTIONID.URB_FUNCTION_ABORT_PIPE:

                // Resets the indicated pipe.
                case URB_FUNCTIONID.URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:

                // Clears the halt condition on the host side of a pipe.
                // If set, this URB is used with _URB_PIPE_REQUEST as the data structure.
                case URB_FUNCTIONID.URB_FUNCTION_SYNC_RESET_PIPE:

                // Clears the stall condition on the endpoint. For all pipes except isochronous pipes.
                case URB_FUNCTIONID.URB_FUNCTION_SYNC_CLEAR_STALL:
                    urb = new TS_URB_PIPE_REQUEST();
                    break;

                // Requests the current frame number from the host controller driver.
                case URB_FUNCTIONID.URB_FUNCTION_GET_CURRENT_FRAME_NUMBER:
                    urb = new TS_URB_GET_CURRENT_FRAME_NUMBER();
                    break;

                // Transfers data to or from a control pipe.
                case URB_FUNCTIONID.URB_FUNCTION_CONTROL_TRANSFER:
                    urb = new TS_URB_CONTROL_TRANSFER();
                    break;

                // Transfers data from a bulk pipe or interrupt pipe or to an bulk pipe.
                case URB_FUNCTIONID.URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
                    urb = new TS_URB_BULK_OR_INTERRUPT_TRANSFER();
                    break;

                // Transfers data to or from an isochronous pipe.
                case URB_FUNCTIONID.URB_FUNCTION_ISOCH_TRANSFER:
                    urb = new TS_URB_ISOCH_TRANSFER();
                    break;

                // Retrieves the device descriptor from a specific USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:

                // Retrieves the descriptor from an endpoint on an interface for a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT:

                // Sets a device descriptor on a device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:

                // Sets an endpoint descriptor on an endpoint for an interface.
                case URB_FUNCTIONID.URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:

                // Retrieves the descriptor from an interface for a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:

                // Sets a descriptor for an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
                    urb = new TS_URB_CONTROL_DESCRIPTOR_REQUEST();
                    break;

                // Sets a USB-defined feature on a device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_FEATURE_TO_DEVICE:

                // Sets a USB-defined feature on an endpoint for an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:

                // Sets a USB-defined feature on an interface for a device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_FEATURE_TO_INTERFACE:

                // Sets a USB-defined feature on a device-defined target on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_SET_FEATURE_TO_OTHER:

                // Clears a USB-defined feature on a device.
                case URB_FUNCTIONID.URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:

                // Clears a USB-defined feature on an endpoint, for an interface, on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:

                // Clears a USB-defined feature on an interface for a device.
                case URB_FUNCTIONID.URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:

                // Clears a USB-defined feature on a device defined target on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLEAR_FEATURE_TO_OTHER:
                    urb = new TS_URB_CONTROL_FEATURE_REQUEST();
                    break;

                // Retrieves status from a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_STATUS_FROM_DEVICE:

                // Retrieves status from an endpoint for an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:

                // Retrieves status from an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_STATUS_FROM_INTERFACE:

                // Retrieves status from a device-defined target on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_STATUS_FROM_OTHER:
                    urb = new TS_URB_CONTROL_GET_STATUS_REQUEST();
                    break;

                // Sends a vendor-specific command to a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_VENDOR_DEVICE:

                // Sends a vendor-specific command for an endpoint on an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_VENDOR_ENDPOINT:

                // Sends a vendor-specific command for an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_VENDOR_INTERFACE:

                // Sends a vendor-specific command to a device-defined target on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_VENDOR_OTHER:

                // Sends a USB-defined class-specific command to a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLASS_DEVICE:

                // Sends a USB-defined class-specific command to an endpoint, on an interface, on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLASS_ENDPOINT:

                // Sends a USB-defined class-specific command to an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLASS_INTERFACE:

                // Sends a USB-defined class-specific command to a device defined target on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_CLASS_OTHER:
                    urb = new TS_URB_CONTROL_VENDOR_OR_CLASS_REQUEST();
                    break;

                // Retrieves the current configuration on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_CONFIGURATION:
                    urb = new TS_URB_CONTROL_GET_CONFIGURATION_REQUEST();
                    break;

                // Retrieves the current settings for an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_INTERFACE:
                    urb = new TS_URB_CONTROL_GET_INTERFACE_REQUEST();
                    break;

                // Retrieves a Microsoft OS feature descriptor from a USB device or an interface on a USB device.
                case URB_FUNCTIONID.URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR:
                    urb = new TS_URB_OS_FEATURE_DESCRIPTOR_REQUEST();
                    break;

                // Transfers data to or from a control pipe without a time limit specified by a timeout value.
                case URB_FUNCTIONID.URB_FUNCTION_CONTROL_TRANSFER_EX:
                    urb = new TS_URB_CONTROL_TRANSFER_EX();
                    break;
                default:
                    urb = new TS_URB_UNKNOWN();
                    break;
            }

            if (!PduMarshaler.Unmarshal(data, urb))
            {
                urb = new TS_URB_UNKNOWN();
                PduMarshaler.Unmarshal(data, urb);
            }
            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
        }