/// <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); }
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(); }
/// <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); }
// 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); }