/// <summary>
        /// Allocates memory and sets up a control setup packet.
        /// </summary>
        /// <remarks>
        /// <para>This constructor is used when:
        /// <list type="bullet">
        /// <item><paramref name="requestType"/> has the <see cref="UsbCtrlFlags.Direction_In"/> flag and this request will not contain extra data (just the setup packet).</item>
        /// <item><paramref name="requestType"/> does not have the <see cref="UsbCtrlFlags.Direction_In"/> flag.</item>
        /// </list>
        /// </para>
        /// <note title="Libusb-1.0 API Note:" type="cpp">
        /// This contructor is similar to
        /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga5447311149ec2bd954b5f1a640a8e231">libusb_fill_control_setup()</a>.
        /// </note>
        /// <para>Allocates <see cref="LibUsbControlSetup.SETUP_PACKET_SIZE"/> + <paramref name="length"/> for the setup packet. The setup packet is stored first then the control data.</para>
        /// </remarks>
        /// <param name="requestType">The request type field for the setup packet.</param>
        /// <param name="request">The request field for the setup packet.</param>
        /// <param name="value">The value field for the setup packet</param>
        /// <param name="index">The index field for the setup packet.</param>
        /// <param name="length">The length to allocate for the data portion of the setup packet.</param>
        public LibUsbControlSetupHandle(byte requestType, byte request, short value, short index, short length)
            :base(IntPtr.Zero,true)
        {
            ushort wlength = (ushort) length;
            int packetSize;
            if (wlength > 0)
                packetSize = LibUsbControlSetup.SETUP_PACKET_SIZE + wlength + (IntPtr.Size - (wlength % IntPtr.Size));
            else
                packetSize = LibUsbControlSetup.SETUP_PACKET_SIZE;
                
            IntPtr pConfigMem = Marshal.AllocHGlobal(packetSize);
            if (pConfigMem == IntPtr.Zero) throw new OutOfMemoryException(String.Format("Marshal.AllocHGlobal failed allocating {0} bytes", packetSize));
            SetHandle(pConfigMem);

            mSetupPacket = new LibUsbControlSetup(pConfigMem);

            mSetupPacket.RequestType = requestType;
            mSetupPacket.Request = request;
            mSetupPacket.Value = value;
            mSetupPacket.Index = index;
            mSetupPacket.Length = (short) wlength;

        }
        /// <summary>
        /// Helper function to populate the required <see cref="LibUsbTransfer"/> properties for a control transfer.
        /// </summary>
        /// <remarks>
        /// <note type="tip">
        /// <para>Isochronous transfers are not supported on windows.</para>
        /// </note>
        /// <note title="Libusb-1.0 API Note:" type="cpp">
        /// <see cref="FillControl"/> is similar to
        /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga3a8513ed87229fe2c9771ef0bf17206e">libusb_fill_control_transfer()</a>.
        /// </note>
        /// </remarks>
        /// <param name="devHandle">handle of the device that will handle the transfer</param>
        /// <param name="controlSetupHandle">the setup packet/control data to transfer.</param>
        /// <param name="callback">callback function to be invoked on transfer completion</param>
        /// <param name="userData">user data to pass to callback function</param>
        /// <param name="timeout">timeout for the transfer in milliseconds</param>
        public void FillControl(LibUsbDeviceHandle devHandle, LibUsbControlSetupHandle controlSetupHandle, Delegate callback, IntPtr userData, int timeout) 
        {
            PtrDeviceHandle = devHandle.DangerousGetHandle();
            Endpoint = 0;
            PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
            PtrUserData = userData;
            Timeout = timeout;
            Type = EndpointType.Control;
            Flags = LibUsbTransferFlags.None;

            IntPtr pSetupPacket = controlSetupHandle.DangerousGetHandle();
            PtrBuffer = pSetupPacket;
            LibUsbControlSetup w = new LibUsbControlSetup(pSetupPacket);
            Length = LibUsbControlSetup.SETUP_PACKET_SIZE + w.Length;
        }