private void allocTransfer(UsbEndpointBase endpointBase, bool ownsTransfer, int isoPacketSize, int count) { int numIsoPackets = 0; if (isoPacketSize > 0) numIsoPackets = count/isoPacketSize; freeTransfer(); mTransfer = MonoUsbTransfer.Alloc(numIsoPackets); mOwnsTransfer = ownsTransfer; mTransfer.Type = endpointBase.Type; mTransfer.Endpoint = endpointBase.EpNum; mTransfer.NumIsoPackets = numIsoPackets; if (!mCompleteEventHandle.IsAllocated) mCompleteEventHandle = GCHandle.Alloc(mTransferCompleteEvent); mTransfer.PtrUserData = GCHandle.ToIntPtr(mCompleteEventHandle); if (numIsoPackets > 0) mTransfer.SetIsoPacketLengths(isoPacketSize); }
/// <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 DefaultAsyncCB(MonoUsbTransfer transfer) { ManualResetEvent completeEvent = GCHandle.FromIntPtr(transfer.PtrUserData).Target as ManualResetEvent; completeEvent.Set(); }
// 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; }
// This function originated from bulk_transfer_cb() // in sync.c of the Libusb-1.0 source code. private static void bulkTransferCB(MonoUsbTransfer transfer) { Marshal.WriteInt32(transfer.PtrUserData, 1); /* caller interprets results and frees transfer */ }
private static void TransferCallback(MonoUsbTransfer pTransfer) { ManualResetEvent completeEvent = GCHandle.FromIntPtr(pTransfer.PtrUserData).Target as ManualResetEvent; completeEvent.Set(); }
private void allocTransfer(UsbEndpointBase endpointBase, bool ownsTransfer, int isoPacketSize, int count) { int numIsoPackets = 0; // Patch for using libusb-1.0 on windows with libusbwK.sys EndpointType endpointType = endpointBase.Type; if (UsbDevice.IsLinux) { if (isoPacketSize > 0) numIsoPackets = count/isoPacketSize; } else { if (endpointType == EndpointType.Isochronous) endpointType = EndpointType.Bulk; } /////////////////////////////////////////////////////////////// freeTransfer(); mTransfer = MonoUsbTransfer.Alloc(numIsoPackets); mOwnsTransfer = ownsTransfer; mTransfer.Type = endpointType; mTransfer.Endpoint = endpointBase.EpNum; mTransfer.NumIsoPackets = numIsoPackets; if (!mCompleteEventHandle.IsAllocated) mCompleteEventHandle = GCHandle.Alloc(mTransferCompleteEvent); mTransfer.PtrUserData = GCHandle.ToIntPtr(mCompleteEventHandle); if (numIsoPackets > 0) mTransfer.SetIsoPacketLengths(isoPacketSize); }