public override EusbPdu ParsePdu(byte[] data)
        {
            EusbPdu pdu;

            switch (GetPduType(data))
            {
            case EusbType.RIM_EXCHANGE_CAPABILITY_REQUEST:
                pdu = new EusbRimExchangeCapResponsePdu();
                break;

            case EusbType.ADD_VIRTUAL_CHANNEL:
                pdu = new EusbAddVirtualChannelPdu();
                break;

            case EusbType.ADD_DEVICE:
                pdu = new EusbAddDevicePdu();
                break;

            case EusbType.CHANNEL_CREATED:
                pdu = new EusbChannelCreatedPdu(false);
                break;

            case EusbType.QUERY_DEVICE_TEXT:
                pdu = new EusbQueryDeviceTextResponsePdu();
                break;

            case EusbType.IOCONTROL_COMPLETION:
                pdu = new EusbIoControlCompletionPdu();
                break;

            case EusbType.URB_COMPLETION:
                pdu = new EusbUrbCompletionPdu();
                break;

            case EusbType.URB_COMPLETION_NO_DATA:
                pdu = new EusbUrbCompletionNoDataPdu();
                break;

            default:
                return(base.ParsePdu(data));
            }

            if (!PduMarshaler.Unmarshal(data, pdu))
            {
                pdu = new EusbUnknownPdu();
                PduMarshaler.Unmarshal(data, pdu);
            }
            return(pdu);
        }
        /// <summary>
        /// Receives the ADD_DEVICE request from the client.
        /// </summary>
        /// <param name="channel">The channel to be received from.</param>
        /// <returns>The context of the device which is being added.</returns>
        public EusbDeviceContext ExpectAddDevice(DynamicVirtualChannel channel)
        {
            Site.Log.Add(LogEntryKind.Debug, "Receiving ADD_DEVICE, Channel ID {0}.", channel.ChannelId);

            EusbAddDevicePdu        pdu = this.rdpeusbServer.ExpectRdpeusbPdu <EusbAddDevicePdu>(channel.ChannelId, waitTime);
            USB_DEVICE_CAPABILITIES cap = new USB_DEVICE_CAPABILITIES();

            if (!PduMarshaler.Unmarshal(pdu.UsbDeviceCapabilities, cap))
            {
                Site.Assert.Fail(
                    "UsbDeviceCapabilities (size in bytes: {0}) in ADD_DEVICE cannot be decoded.",
                    pdu.UsbDeviceCapabilities.Length
                    );
            }

            #region Verify ADD_DEVICE

            Site.Assert.IsNotNull(
                pdu,
                "Expect that the response from the client is EusbAddDevicePdu."
                );

            Site.Assert.AreEqual <uint>(
                0x00000001,
                pdu.InterfaceId,
                "Expect that the InterfaceId in the response PDU equals 0x00000001. The actual value is 0x{0:x8}.",
                pdu.InterfaceId);

            Site.Assert.AreEqual <Mask_Values>(
                Mask_Values.STREAM_ID_PROXY,
                pdu.Mask,
                "Expect that the Mask in the response PDU is STREAM_ID_PROXY.");

            Site.Assert.AreEqual <FunctionId_Values>(
                FunctionId_Values.ADD_DEVICE,
                (FunctionId_Values)pdu.FunctionId,
                "Expect that the FunctionId in the response PDU is ADD_DEVICE. The actual value is 0x{0:x8}.",
                pdu.FunctionId);

            Site.Assert.AreEqual <uint>(
                0x00000001,
                pdu.NumUsbDevice,
                "Expect that the NumUsbDevice in the response PDU equals 0x00000001. The actual value is 0x{0:x8}.",
                pdu.NumUsbDevice);

            Site.Assert.AreNotEqual <uint>(
                0x00000000,
                pdu.cchDeviceInstanceId,
                "Expect that the cchDeviceInstanceId in the response PDU is zero. The actual value is 0x{0:x8}.",
                pdu.cchDeviceInstanceId);

            if (Config.IsWindowsImplementation)
            {
                Site.Assert.AreNotEqual <uint>(
                    0x00000000,
                    pdu.cchHwIds,
                    "Expect that the cchHwIds in the response PDU is not zero in an implementation of Windows. The actual value is 0x{0:x8}.",
                    pdu.cchHwIds);
            }

            #region Verify UsbDeviceCapabilities

            Site.Assert.AreEqual <uint>(
                (uint)USB_DEVICE_CAPABILITIES.USB_DEVICE_CAPABILITIES_SIZE,
                cap.CbSize,
                "Expect that the CbSize of the USB_DEVICE_CAPABILITIES in the response PDU equals 28. The actual value is {0}.",
                cap.CbSize);

            Site.Assert.IsTrue(
                cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_0 ||
                cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_1 ||
                cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_2,
                "Expect that the UsbBusInterfaceVersion of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x00000000 or 0x00000001 or 0x00000002. The actual value is {0}.",
                cap.UsbBusInterfaceVersion);

            Site.Assert.IsTrue(
                cap.USBDI_Version == (uint)USBDI_VER.USBDI_VERSION_5 || cap.USBDI_Version == (uint)USBDI_VER.USBDI_VERSION_6,
                "Expect that the USBDI_Version of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x00000500 or 0x00000600. The actual value is {0}.",
                cap.USBDI_Version);

            Site.Assert.IsTrue(
                cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_1_0 ||
                cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_1_1 ||
                cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_2_0,
                "Expect that the Supported_USB_Version of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x100 or 0x110 or 0x200. The actual value is {0}.",
                cap.Supported_USB_Version);

            Site.Assert.AreEqual <uint>(
                0,
                cap.HcdCapabilities,
                "Expect that the HcdCapabilities of the USB_DEVICE_CAPABILITIES in the response PDU is zero. The actual value is {0}.",
                cap.HcdCapabilities);

            if (cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_0)
            {
                Site.Assert.AreEqual <uint>(
                    (uint)DeviceSpeed_Values.FULL_SPEED,
                    cap.DeviceIsHighSpeed,
                    "Expect that the DeviceIsHighSpeed of the USB_DEVICE_CAPABILITIES in the response PDU is zero when UsbBusInterfaceVersion is 0x00000000. The actual value is {0}.",
                    cap.HcdCapabilities);
            }
            else
            {
                Site.Assert.IsTrue(
                    cap.DeviceIsHighSpeed == (uint)DeviceSpeed_Values.FULL_SPEED ||
                    cap.DeviceIsHighSpeed == (uint)DeviceSpeed_Values.HIGH_SPEED,
                    "Expect that the DeviceIsHighSpeed of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x100 or 0x110 or 0x200. The actual value is {0}.",
                    cap.DeviceIsHighSpeed);
            }

            if (cap.NoAckIsochWriteJitterBufferSizeInMs != 0)
            {
                Site.Assert.IsTrue(
                    cap.NoAckIsochWriteJitterBufferSizeInMs >= 10 &&
                    cap.NoAckIsochWriteJitterBufferSizeInMs <= 512,
                    "Expect that the NoAckIsochWriteJitterBufferSizeInMs of the USB_DEVICE_CAPABILITIES in the response PDU is greater than or equal to 10 and less than or equal to 512. The actual value is {0}.",
                    cap.NoAckIsochWriteJitterBufferSizeInMs);
            }

            #endregion

            #endregion

            EusbDeviceContext device = new EusbDeviceContext();
            device.VirtualChannel = channel;
            device.NoAckIsochWriteJitterBufferSizeInMs = (cap.NoAckIsochWriteJitterBufferSizeInMs != 0);
            device.UsbDeviceInterfaceId = pdu.UsbDevice;
            device.DeviceInstanceId     = pdu.DeviceInstanceId;

            Site.Log.Add(LogEntryKind.Debug, "Received device request. Device: {0}", device);
            return(device);
        }