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>
        /// Submits an internal I/O control request to the client USB device.
        /// </summary>
        /// <param name="device">Device instance for this operation</param>
        /// <param name="input">This value represents the input buffer for the IO control request.</param>
        /// <param name="outputBufferSize">The maximum number of bytes the client can return to the server.</param>
        /// <param name="requestId">This ID uniquely identifies the internal I/O control request.</param>
        public void InternalIoControl(EusbDeviceContext device, UsbInternalIoControlCode ioControlCode, byte[] input, uint outputBufferSize, uint requestId)
        {
            Site.Log.Add(
                LogEntryKind.Debug,
                "Sending INTERNAL_IO_CONTROL. Device: {0}, IO control code: {1}, Input buffer size {2}, Output buffer size {3}, Request ID {4}.",
                device,
                ioControlCode,
                null == input ? 0 : input.Length,
                outputBufferSize,
                requestId
                );

            EusbInternalIoControlPdu requestPdu = new EusbInternalIoControlPdu(device.UsbDeviceInterfaceId);
            requestPdu.IoControlCode = ioControlCode;
            if (input == null)
            {
                requestPdu.InputBuffer = null;
                requestPdu.InputBufferSize = 0;
            }
            else
            {
                requestPdu.InputBuffer = (byte[])input.Clone();
                requestPdu.InputBufferSize = (uint)input.Length;
            }
            requestPdu.OutputBufferSize = outputBufferSize;
            requestPdu.RequestId = requestId;

            SendPdu(requestPdu, device.VirtualChannel);
        }