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

            switch (GetPduType(data))
            {
                case EusbType.RIM_EXCHANGE_CAPABILITY_REQUEST:
                    pdu = new EusbRimExchangeCapRequestPdu();
                    break;
                case EusbType.CHANNEL_CREATED:
                    pdu = new EusbChannelCreatedPdu(true);
                    break;
                case EusbType.REGISTER_REQUEST_CALLBACK:
                    pdu = new EusbRegisterRequestCallbackPdu();
                    break;
                case EusbType.QUERY_DEVICE_TEXT:
                    pdu = new EusbQueryDeviceTextRequestPdu();
                    break;
                case EusbType.IO_CONTROL:
                    pdu = new EusbIoControlPdu();
                    break;
                case EusbType.INTERNAL_IO_CONTROL:
                    pdu = new EusbInternalIoControlPdu();
                    break;
                case EusbType.TRANSFER_IN_REQUEST:
                    pdu = new EusbTransferInRequestPdu();
                    break;
                case EusbType.TRANSFER_OUT_REQUEST:
                    pdu = new EusbTransferOutRequestPdu();
                    break;
                case EusbType.CANCEL_REQUEST:
                    pdu = new EusbCancelRequestPdu();
                    break;
                case EusbType.RETRACT_DEVICE:
                    pdu = new EusbRetractDevicePdu();
                    break;
                default:
                    return base.ParsePdu(data);
            }

            if (!PduMarshaler.Unmarshal(data, pdu))
            {
                pdu = new EusbUnknownPdu();
                PduMarshaler.Unmarshal(data, pdu);
            }
            return pdu;
        }
        /// <summary>
        /// Requests data from the client USB device.
        /// </summary>
        /// <param name="device">The context of the device which is being operated.</param>
        /// <param name="tsUrb">A TS_URB structure.</param>
        /// <param name="outputBufferSize">This value represents the maximum number of bytes of data that is requested from
        /// the USB device.</param>
        public void TransferInRequest(EusbDeviceContext device, TS_URB tsUrb, uint outputBufferSize)
        {
            // TODO: Check this verification.
            //Site.Assume.IsFalse(
            //    tsUrb is TS_URB_ISOCH_TRANSFER && device.NoAckIsochWriteJitterBufferSizeInMs,
            //    "The client does not support TS_URB_ISOCH_TRANSFER messages."
            //    );

            Site.Log.Add(
                LogEntryKind.Debug,
                "Sending TRANSFER_IN_REQUEST. Device: {0}, URB: {1}, Output buffer size: {2}",
                device,
                tsUrb,
                outputBufferSize);

            EusbTransferInRequestPdu requestPdu = new EusbTransferInRequestPdu(device.UsbDeviceInterfaceId);
            byte[] buf = PduMarshaler.Marshal(tsUrb);
            requestPdu.CbTsUrb = (uint)buf.Length;

            // TODO: Need verify for negtive test cases?
            if (tsUrb.Header.Size != (ushort)requestPdu.CbTsUrb)
            {
                throw new ArgumentException(String.Format(
                    "Header.Size ({0}) doesn't match the actual size ({1}).",
                    tsUrb.Header.Size,
                    requestPdu.CbTsUrb
                    ));
            }

            requestPdu.TsUrb = buf;
            requestPdu.OutputBufferSize = outputBufferSize;
            SendPdu(requestPdu, device.VirtualChannel);
        }