Allocates memory and fills an asynchronous control setup packet.
This type is used for asynchronous control transfers only.
Inheritance: LibUsbDotNet.Main.SafeContextHandle
Beispiel #1
0
        /// <summary>
        /// Helper function to populate the required <see cref="MonoUsbTransfer"/> 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(MonoUsbDeviceHandle devHandle, MonoUsbControlSetupHandle controlSetupHandle, Delegate callback, IntPtr userData, int timeout)
        {
            PtrDeviceHandle = devHandle.DangerousGetHandle();
            Endpoint        = 0;
            PtrCallbackFn   = Marshal.GetFunctionPointerForDelegate(callback);
            PtrUserData     = userData;
            Timeout         = timeout;
            Type            = EndpointType.Control;
            Flags           = MonoUsbTransferFlags.None;

            IntPtr pSetupPacket = controlSetupHandle.DangerousGetHandle();

            PtrBuffer = pSetupPacket;
            MonoUsbControlSetup w = new MonoUsbControlSetup(pSetupPacket);

            Length = MonoUsbControlSetup.SETUP_PACKET_SIZE + w.Length;
        }
        private static int libusb_control_transfer(MonoUsbDeviceHandle deviceHandle, MonoUsbControlSetupHandle controlSetupHandle, int timeout)
        {
            MonoUsbTransfer transfer = MonoUsbTransfer.Alloc(0);
            ManualResetEvent completeEvent = new ManualResetEvent(false);
            GCHandle gcCompleteEvent = GCHandle.Alloc(completeEvent);

            transfer.FillControl(deviceHandle, controlSetupHandle, controlTransferDelegate, GCHandle.ToIntPtr(gcCompleteEvent), timeout);

            int r = (int) transfer.Submit();
            if (r < 0)
            {
                transfer.Free();
                gcCompleteEvent.Free();
                return r;
            }

            while (!completeEvent.WaitOne(0,false))
            {
                r = MonoUsbApi.HandleEvents(sessionHandle);
                if (r < 0)
                {
                    if (r == (int) MonoUsbError.ErrorInterrupted)
                        continue;
                    transfer.Cancel();
                    while (!completeEvent.WaitOne(0, false))
                        if (MonoUsbApi.HandleEvents(sessionHandle) < 0)
                            break;
                    transfer.Free();
                    gcCompleteEvent.Free();
                    return r;
                }
            }

            if (transfer.Status == MonoUsbTansferStatus.TransferCompleted)
                r = transfer.ActualLength;
            else
                r = (int) MonoUsbApi.MonoLibUsbErrorFromTransferStatus(transfer.Status);

            transfer.Free();
            gcCompleteEvent.Free();
            return r;
        }
        /// <summary>
        /// Perform a USB control transfer for multi-threaded applications using the <see cref="MonoUsbEventHandler"/> class.
        /// </summary>
        /// <remarks>
        /// <para>The direction of the transfer is inferred from the bmRequestType field of the setup packet.</para>
        /// <para>The wValue, wIndex and wLength fields values should be given in host-endian byte order.</para>
        /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
        /// </remarks>
        /// <param name="deviceHandle">A handle for the device to communicate with.</param>
        /// <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="pData">A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</param>
        /// <param name="dataLength">The length field for the setup packet. The data buffer should be at least this size.</param>
        /// <param name="timeout">timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
        /// <returns>
        /// <list type="bullet">
        /// <item>on success, the number of bytes actually transferred</item>
        /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
        /// <item><see cref="MonoUsbError.ErrorPipe"/> if the control request was not supported by the device.</item>
        /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
        /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
        /// </list>
        /// </returns>
        public static int ControlTransferAsync([In] MonoUsbDeviceHandle deviceHandle,
                                                 byte requestType,
                                                 byte request,
                                                 short value,
                                                 short index,
                                                 IntPtr pData,
                                                 short dataLength,
                                                 int timeout)
        {
            MonoUsbControlSetupHandle setupHandle = new MonoUsbControlSetupHandle(requestType, request, value, index, pData, dataLength);
            MonoUsbTransfer transfer = new MonoUsbTransfer(0);
            ManualResetEvent completeEvent = new ManualResetEvent(false);
            GCHandle gcCompleteEvent = GCHandle.Alloc(completeEvent);

            transfer.FillControl(deviceHandle, setupHandle, DefaultAsyncDelegate, GCHandle.ToIntPtr(gcCompleteEvent), timeout);

            int r = (int)transfer.Submit();
            if (r < 0)
            {
                transfer.Free();
                gcCompleteEvent.Free();
                return r;
            }
            IntPtr pSessionHandle;
            MonoUsbSessionHandle sessionHandle = MonoUsbEventHandler.SessionHandle;
            if (sessionHandle == null) 
                pSessionHandle = IntPtr.Zero;
            else
                pSessionHandle = sessionHandle.DangerousGetHandle();

            if (MonoUsbEventHandler.IsStopped)
            {
                while (!completeEvent.WaitOne(0, false))
                {
                    r = HandleEvents(pSessionHandle);
                    if (r < 0)
                    {
                        if (r == (int)MonoUsbError.ErrorInterrupted)
                            continue;
                        transfer.Cancel();
                        while (!completeEvent.WaitOne(0, false))
                            if (HandleEvents(pSessionHandle) < 0)
                                break;
                        transfer.Free();
                        gcCompleteEvent.Free();
                        return r;
                    }
                }
            }
            else
            {
                completeEvent.WaitOne(Timeout.Infinite, UsbConstants.EXIT_CONTEXT);
            }

            if (transfer.Status == MonoUsbTansferStatus.TransferCompleted)
            {
                r = transfer.ActualLength;
                if (r > 0)
                {
                    byte[] ctrlDataBytes = setupHandle.ControlSetup.GetData(r);
                    Marshal.Copy(ctrlDataBytes, 0, pData, Math.Min(ctrlDataBytes.Length, dataLength));
                }

            }
            else
                r = (int)MonoLibUsbErrorFromTransferStatus(transfer.Status);

            transfer.Free();
            gcCompleteEvent.Free();
            return r;
        }
        private static void Main(string[] args)
        {
            // Assign the control transfer delegate to the callback function.
            controlTransferDelegate = ControlTransferCB;

            // Initialize the context.
            sessionHandle = new MonoUsbSessionHandle();
            if (sessionHandle.IsInvalid)
                throw new Exception(String.Format("Failed intializing libusb context.\n{0}:{1}",
                                                  MonoUsbSessionHandle.LastErrorCode,
                                                  MonoUsbSessionHandle.LastErrorString));

            MonoUsbProfileList profileList = new MonoUsbProfileList();
            MonoUsbDeviceHandle myDeviceHandle = null;

            try
            {
                // The list is initially empty.
                // Each time refresh is called the list contents are updated.
                profileList.Refresh(sessionHandle);

                // Use the GetList() method to get a generic List of MonoUsbProfiles
                // Find the first profile that matches in MyVidPidPredicate.
                MonoUsbProfile myProfile = profileList.GetList().Find(MyVidPidPredicate);
                if (myProfile == null)
                {
                    Console.WriteLine("Device not connected.");
                    return;
                }

                // Open the device handle to perform I/O
                myDeviceHandle = myProfile.OpenDeviceHandle();
                if (myDeviceHandle.IsInvalid)
                    throw new Exception(String.Format("Failed opening device handle.\n{0}:{1}",
                                                      MonoUsbDeviceHandle.LastErrorCode,
                                                      MonoUsbDeviceHandle.LastErrorString));
                int ret;
                MonoUsbError e;

                // Set Configuration
                e = (MonoUsbError) (ret = MonoUsbApi.SetConfiguration(myDeviceHandle, 1));
                if (ret < 0) throw new Exception(String.Format("Failed SetConfiguration.\n{0}:{1}", e, MonoUsbApi.StrError(e)));

                // Claim Interface
                e = (MonoUsbError) (ret = MonoUsbApi.ClaimInterface(myDeviceHandle, 0));
                if (ret < 0) throw new Exception(String.Format("Failed ClaimInterface.\n{0}:{1}", e, MonoUsbApi.StrError(e)));

                // Create a vendor specific control setup, allocate 1 byte for return control data.
                byte requestType = (byte)(UsbCtrlFlags.Direction_In | UsbCtrlFlags.Recipient_Device | UsbCtrlFlags.RequestType_Vendor);
                byte request = 0x0F;
                MonoUsbControlSetupHandle controlSetupHandle = new MonoUsbControlSetupHandle(requestType, request, 0, 0, 1);

                // Transfer the control setup packet
                ret = libusb_control_transfer(myDeviceHandle, controlSetupHandle, 1000);
                if (ret > 0)
                {
                    Console.WriteLine("\nSuccess!\n");
                    byte[] ctrlDataBytes = controlSetupHandle.ControlSetup.GetData(ret);
                    string ctrlDataString = Helper.HexString(ctrlDataBytes, String.Empty, "h ");
                    Console.WriteLine("Return Length: {0}", ret);
                    Console.WriteLine("DATA (hex)   : [ {0} ]\n", ctrlDataString.Trim());
                }
                MonoUsbApi.ReleaseInterface(myDeviceHandle, 0);
            }
            finally
            {
                profileList.Close();
                if (myDeviceHandle != null) myDeviceHandle.Close();
                sessionHandle.Close();
            }
        }
        /// <summary>
        /// Helper function to populate the required <see cref="MonoUsbTransfer"/> 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(MonoUsbDeviceHandle devHandle, MonoUsbControlSetupHandle controlSetupHandle, Delegate callback, IntPtr userData, int timeout) 
        {
            PtrDeviceHandle = devHandle.DangerousGetHandle();
            Endpoint = 0;
            PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
            PtrUserData = userData;
            Timeout = timeout;
            Type = EndpointType.Control;
            Flags = MonoUsbTransferFlags.None;

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