/// <summary>
        /// Submits the transfer.
        /// </summary>
        /// <remarks>
        /// This functions submits the USB transfer and return immediately.
        /// </remarks>
        /// <returns>
        /// <see cref="ErrorCode.Success"/> if the submit succeeds,
        /// otherwise one of the other <see cref="ErrorCode"/> codes.
        /// </returns>
        public override ErrorCode Submit()
        {
            if (mTransferCancelEvent.WaitOne(0))
            {
                return(ErrorCode.IoCancelled);
            }

            if (!mTransferCompleteEvent.WaitOne(0))
            {
                return(ErrorCode.ResourceBusy);
            }

            mTransfer.PtrBuffer = NextBufPtr;
            mTransfer.Length    = RequestCount;

            mTransferCompleteEvent.Reset();

            int ret = (int)mTransfer.Submit();

            if (ret < 0)
            {
                mTransferCompleteEvent.Set();
                UsbError usbErr = UsbError.Error(ErrorCode.MonoApiError, ret, "SubmitTransfer", EndpointBase);
                return(usbErr.ErrorCode);
            }

            return(ErrorCode.Success);
        }
        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
        static void config_op(MonoUsbDeviceHandle handle, byte endpoint, byte[] data, int readcnt)
        {
            int actual_length = 0;
            int res;

            byte[] recv_buf = new byte[1024];

            GCHandle data_gc     = GCHandle.Alloc(data, GCHandleType.Pinned);
            GCHandle recv_buf_gc = GCHandle.Alloc(recv_buf, GCHandleType.Pinned);

            MonoUsbTransferDelegate d = noop_usb_callback;

            MonoUsbTransfer transfer = new MonoUsbTransfer(0);

            wait = 0;

            Console.WriteLine("data_gc addr = {0}", data_gc.AddrOfPinnedObject());
            Console.WriteLine("recv_buf_gc addr = {0}", recv_buf_gc.AddrOfPinnedObject());

            // Execute the write operation (asynchronous).
            transfer.FillBulk(handle, endpoint, data_gc.AddrOfPinnedObject(), data.Length, d, recv_buf_gc.AddrOfPinnedObject(), 4000);
            transfer.Submit();

            Thread.Sleep(300);

            // Execute the specified number of read operations (synchronous).
            for (int x = 0; x < readcnt; ++x)
            {
                res = Usb.BulkTransfer(handle, (byte)(endpoint | 0x80), recv_buf_gc.AddrOfPinnedObject(), recv_buf.Length, out actual_length, 4000);
                if (res != 0)
                {
                    throw new Exception("config_op Usb.BulkTransfer failure");
                }
                // Should only be here once the above transfer completes.
            }

            // Wait for the first write asynchronous to return.
            // Do not poll forever. Abort if it takes too long.
            var st = DateTime.Now;

            if (readcnt > 0)
            {
                while (wait == 0 && (DateTime.Now - st).TotalSeconds < 30)
                {
                    Thread.Sleep(100);
                }
            }

            data_gc.Free();
            recv_buf_gc.Free();
        }
예제 #4
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);
        }
예제 #5
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);
        }