示例#1
0
        /// <summary>
        /// Wait for the transfer to complete, timeout, or get cancelled.
        /// </summary>
        /// <param name="transferredCount">The number of bytes transferred on <see cref="ErrorCode.Success"/>.</param>
        /// <param name="cancel">Not used for libusb-1.0. Transfers are always cancelled on timeout or error.</param>
        /// <returns><see cref="ErrorCode.Success"/> if the transfer completes successfully, otherwise one of the other <see cref="ErrorCode"/> codes.</returns>
        public override ErrorCode Wait(out int transferredCount, bool cancel)
        {
            transferredCount = 0;
            int          ret = 0;
            MonoUsbError monoError;
            ErrorCode    ec;

            int iWait = WaitHandle.WaitAny(new WaitHandle[] { mTransferCompleteEvent, mTransferCancelEvent },
                                           Timeout.Infinite,
                                           UsbConstants.EXIT_CONTEXT);

            switch (iWait)
            {
            case 0:     // TransferCompleteEvent

                if (mTransfer.Status == MonoUsbTansferStatus.TransferCompleted)
                {
                    transferredCount = mTransfer.ActualLength;
                    return(ErrorCode.Success);
                }

                string s;
                monoError = MonoUsbApi.MonoLibUsbErrorFromTransferStatus(mTransfer.Status);
                ec        = MonoUsbApi.ErrorCodeFromLibUsbError((int)monoError, out s);
                UsbError.Error(ErrorCode.MonoApiError, (int)monoError, "Wait:" + s, EndpointBase);
                return(ec);

            case 1:     // TransferCancelEvent
                ret = (int)mTransfer.Cancel();
                bool bTransferComplete = mTransferCompleteEvent.WaitOne(100, UsbConstants.EXIT_CONTEXT);
                mTransferCompleteEvent.Set();

                if (ret != 0 || !bTransferComplete)
                {
                    ec = ret == 0 ? ErrorCode.CancelIoFailed : ErrorCode.MonoApiError;
                    UsbError.Error(ec, ret, String.Format("Wait:Unable to cancel transfer or the transfer did not return after it was cancelled. Cancelled:{0} TransferCompleted:{1}", (MonoUsbError)ret, bTransferComplete), EndpointBase);
                    return(ec);
                }
                return(ErrorCode.IoCancelled);

            default:     // Critical failure timeout
                mTransfer.Cancel();
                ec = ((EndpointBase.mEpNum & (byte)UsbCtrlFlags.Direction_In) > 0) ? ErrorCode.ReadFailed : ErrorCode.WriteFailed;
                mTransferCompleteEvent.Set();
                UsbError.Error(ec, ret, String.Format("Wait:Critical timeout failure! The transfer callback function was not called within the allotted time."), EndpointBase);
                return(ec);
            }
        }
        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);
        }
示例#3
0
        /// <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))
                {
                    r = HandleEvents(pSessionHandle);
                    if (r < 0)
                    {
                        if (r == (int)MonoUsbError.ErrorInterrupted)
                        {
                            continue;
                        }
                        transfer.Cancel();
                        while (!completeEvent.WaitOne(0))
                        {
                            if (HandleEvents(pSessionHandle) < 0)
                            {
                                break;
                            }
                        }
                        transfer.Free();
                        gcCompleteEvent.Free();
                        return(r);
                    }
                }
            }
            else
            {
                completeEvent.WaitOne(Timeout.Infinite);
            }

            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);
        }
示例#4
0
        // This function originated from do_sync_bulk_transfer()
        // in sync.c of the Libusb-1.0 source code.
        private static MonoUsbError doBulkAsyncTransfer(MonoUsbDeviceHandle dev_handle,
                                                        byte endpoint,
                                                        byte[] buffer,
                                                        int length,
                                                        out int transferred,
                                                        int timeout)
        {
            transferred = 0;
            MonoUsbTransfer transfer = new MonoUsbTransfer(0);

            if (transfer.IsInvalid)
            {
                return(MonoUsbError.ErrorNoMem);
            }

            MonoUsbTransferDelegate monoUsbTransferCallbackDelegate = bulkTransferCB;

            int[]    userCompleted   = new int[] { 0 };
            GCHandle gcUserCompleted = GCHandle.Alloc(userCompleted, GCHandleType.Pinned);

            MonoUsbError e;
            GCHandle     gcBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            transfer.FillBulk(
                dev_handle,
                endpoint,
                gcBuffer.AddrOfPinnedObject(),
                length,
                monoUsbTransferCallbackDelegate,
                gcUserCompleted.AddrOfPinnedObject(),
                timeout);

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

            Console.WriteLine("Transfer Submitted..");
            while (userCompleted[0] == 0)
            {
                e = (MonoUsbError)(r = Usb.HandleEvents(sessionHandle));
                if (r < 0)
                {
                    if (e == MonoUsbError.ErrorInterrupted)
                    {
                        continue;
                    }
                    transfer.Cancel();
                    while (userCompleted[0] == 0)
                    {
                        if (Usb.HandleEvents(sessionHandle) < 0)
                        {
                            break;
                        }
                    }
                    transfer.Free();
                    gcUserCompleted.Free();
                    return(e);
                }
            }

            transferred = transfer.ActualLength;
            e           = MonoUsbApi.MonoLibUsbErrorFromTransferStatus(transfer.Status);
            transfer.Free();
            gcUserCompleted.Free();
            return(e);
        }