private MonoUsbDeviceHandle getUsableAndOpenUsbHandle() { lock (_sync) { if (context != null) { if (!context.IsClosed) { context.Close(); } context.Dispose(); context = null; } context = new MonoUsbSessionHandle(); var usbHandle = MonoUsbApi.OpenDeviceWithVidPid(context, 1406, 12288); if (usbHandle != null) { if (MonoUsbApi.ClaimInterface(usbHandle, 0) == 0) { return(usbHandle); } usbHandle.Close(); } UnityEngine.Debug.Log("Failed"); return(null); } }
private int SendInternal(byte[] buffer) { var handle = getUsableAndOpenUsbHandle(); if (handle == null) { throw new Exception("USB writer is null, you may have disconnected the device during previous function"); } uint pack = (uint)buffer.Length + 2; byte[] packed = BitConverter.GetBytes(pack); var ec = MonoUsbApi.BulkTransfer(handle, WRITEPOINT, packed, packed.Length, out var _, 5000); if (ec != 0) { string err = MonoUsbSessionHandle.LastErrorString; CleanUpHandle(handle); throw new Exception(err); } ec = MonoUsbApi.BulkTransfer(handle, WRITEPOINT, buffer, buffer.Length, out var len, 5000); if (ec != 0) { string err = MonoUsbSessionHandle.LastErrorString; CleanUpHandle(handle); throw new Exception(err); } CleanUpHandle(handle); return(len); }
/// <summary> /// Gets a descriptor from the device. See <see cref="DescriptorType"/> for more information. /// </summary> /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param> /// <param name="index">Descriptor index.</param> /// <param name="langId">Descriptor language id.</param> /// <param name="buffer">Memory to store the returned descriptor in.</param> /// <param name="bufferLength">Length of the buffer parameter in bytes.</param> /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param> /// <returns>True on success.</returns> public override bool GetDescriptor(byte descriptorType, byte index, short langId, IntPtr buffer, int bufferLength, out int transferLength) { transferLength = 0; bool bSuccess = false; bool wasOpen = IsOpen; if (!wasOpen) { Open(); } if (!IsOpen) { return(false); } int ret = MonoUsbApi.GetDescriptor((MonoUsbDeviceHandle)mUsbHandle, descriptorType, index, buffer, (ushort)bufferLength); if (ret < 0) { MonoUsbErrorMessage.Error(ErrorCode.MonoApiError, ret, "GetDescriptor Failed", this); } else { bSuccess = true; transferLength = ret; } if (!wasOpen && IsOpen) { Close(); } return(bSuccess); }
/// <summary> /// Submits this transfer. /// </summary> /// <remarks> /// This functions submits the USB transfer and return immediately. /// <note> /// <see cref="Submit"/> is roughly equivalent to /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gabb0932601f2c7dad2fee4b27962848ce">libusb_submit_transfer()</a>. /// </note> /// </remarks> /// <returns> /// <see cref="MonoUsbError.Success"/> if the submit succeeds, /// otherwise one of the other <see cref="MonoUsbError"/> codes. /// </returns> public MonoUsbError Submit() { if (IsInvalid) { return(MonoUsbError.ErrorNoMem); } return((MonoUsbError)MonoUsbApi.SubmitTransfer(handle)); }
/// <summary> /// Frees this transfer. /// </summary> ///<remarks> /// <note title="Libusb-1.0 API Note:" type="cpp"> /// <see cref="Free"/> is roughly equivalent to /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga6ab8b2cff4de9091298a06b2f4b86cd6">libusb_free_transfer()</a>. /// </note> /// <note type="warning"> /// Calling <see cref="Free"/> on a transfer that has already been freed will result in a double free. /// </note> /// </remarks> public void Free() { if (handle != IntPtr.Zero) { MonoUsbApi.FreeTransfer(handle); handle = IntPtr.Zero; } }
/// <summary> /// Wraps a raw usb device profile handle pointer in a <see cref="MonoUsbProfileHandle"/> class. /// </summary> /// <param name="pProfileHandle">the profile handle to wrap.</param> public MonoUsbProfileHandle(IntPtr pProfileHandle) : base(pProfileHandle, true) { lock (oDeviceProfileRefLock) { MonoUsbApi.RefDevice(pProfileHandle); mDeviceProfileRefCount++; } }
/// <summary> /// Cancels this transfer. /// </summary> /// <remarks> /// <note title="Libusb-1.0 API Note:" type="cpp"> /// <see cref="Cancel"/> is roughly equivalent to /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54">libusb_cancel_transfer()</a>. /// </note> /// </remarks> /// <returns><see cref="MonoUsbError.Success"/> if the cancel succeeds, otherwise one of the other <see cref="MonoUsbError"/> codes.</returns> public MonoUsbError Cancel() { if (IsInvalid) { return(MonoUsbError.ErrorNoMem); } return((MonoUsbError)MonoUsbApi.CancelTransfer(handle)); }
/// <summary> /// /// </summary> /// <returns></returns> protected override bool ReleaseHandle() { if (!IsInvalid) { MonoUsbApi.FreeConfigDescriptor(handle); SetHandleAsInvalid(); } return(true); }
/// <summary> /// Allocate a libusb transfer with a specified number of isochronous packet descriptors /// </summary> /// <remarks> /// <para>The returned transfer is pre-initialized for you. When the new transfer is no longer needed, it should be freed with <see cref="Free"/>.</para> /// <para>Transfers intended for non-isochronous endpoints (e.g. control, bulk, interrupt) should specify an iso_packets count of zero.</para> /// <para>For transfers intended for isochronous endpoints, specify an appropriate number of packet descriptors to be allocated as part of the transfer. The returned transfer is not specially initialized for isochronous I/O; you are still required to set the <see cref="MonoUsbTransfer.NumIsoPackets"/> and <see cref="MonoUsbTransfer.Type"/> fields accordingly.</para> /// <para>It is safe to allocate a transfer with some isochronous packets and then use it on a non-isochronous endpoint. If you do this, ensure that at time of submission, <see cref="MonoUsbTransfer.NumIsoPackets"/> is 0 and that type is set appropriately.</para> /// <note title="Libusb-1.0 API Note:" type="cpp"> /// <see cref="Alloc"/> is roughly equivalent to /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000">libusb_alloc_transfer()</a>. /// </note> /// </remarks> /// <param name="numIsoPackets">number of isochronous packet descriptors to allocate.</param> /// <returns>A newly allocated <see cref="MonoUsbTransfer"/>.</returns> /// <exception cref="OutOfMemoryException">If the transfer was not allocated.</exception> public static MonoUsbTransfer Alloc(int numIsoPackets) { IntPtr p = MonoUsbApi.AllocTransfer(numIsoPackets); if (p == IntPtr.Zero) { throw new OutOfMemoryException("AllocTransfer"); } return(new MonoUsbTransfer(p)); }
/// <summary> /// Sets an alternate interface for the most recent claimed interface. /// </summary> /// <param name="alternateID">The alternate interface to select for the most recent claimed interface See <see cref="ClaimInterface"/>.</param> /// <returns>True on success.</returns> public bool SetAltInterface(int alternateID) { int ret = MonoUsbApi.SetInterfaceAltSetting((MonoUsbDeviceHandle)mUsbHandle, mClaimedInteface, alternateID); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "SetAltInterface Failed", this); return(false); } return(true); }
/// <summary> /// Releases an interface that was previously claimed with <see cref="ClaimInterface"/>. /// </summary> /// <param name="interfaceID">The interface to release.</param> /// <returns>True on success.</returns> public bool ReleaseInterface(int interfaceID) { int ret = MonoUsbApi.ReleaseInterface((MonoUsbDeviceHandle)mUsbHandle, interfaceID); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "ReleaseInterface Failed", this); return(false); } return(true); }
private static string GetErrorMessage(Error errorCode) { if (MonoUsbApi.ErrorCodeFromLibUsbError((int)errorCode, out string errorMessage) == Main.ErrorCode.Success) { return(errorMessage); } else { return($"An unknown error with code {(int)errorCode} has occurred."); } }
/// <summary> /// When overridden in a derived class, executes the code required to free the handle. /// </summary> /// <returns> /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant. /// </returns> protected override bool ReleaseHandle() { if (!IsInvalid) { MonoUsbApi.FreeDeviceList(handle, 1); //Console.WriteLine("FreeDeviceList:{0}", handle); SetHandleAsInvalid(); } return(true); }
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> /// Claims the specified interface of the device. /// </summary> /// <param name="interfaceID">The interface to claim.</param> /// <returns>True on success.</returns> public bool ClaimInterface(int interfaceID) { int ret = MonoUsbApi.ClaimInterface((MonoUsbDeviceHandle)mUsbHandle, interfaceID); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "ClaimInterface Failed", this); return(false); } mClaimedInteface = interfaceID; return(true); }
internal static int RefreshProfileList() { lock (OLockDeviceList) { MonoUsbApi.InitAndStart(); if (mMonoUSBProfileList == null) { mMonoUSBProfileList = new MonoUsbProfileList(); } return((int)mMonoUSBProfileList.Refresh(MonoUsbEventHandler.SessionHandle)); } }
/// <summary> /// Sets the USB devices active configuration value. /// </summary> /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param> /// <returns>True on success.</returns> /// <remarks> /// A USB device can have several different configurations, but only one active configuration. /// </remarks> public bool SetConfiguration(byte config) { int ret = MonoUsbApi.SetConfiguration((MonoUsbDeviceHandle)mUsbHandle, config); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "SetConfiguration Failed", this); return(false); } mCurrentConfigValue = config; return(true); }
/// <summary> /// De-initializes the USB driver. /// </summary> /// <remarks> /// If this method is not called before the application exits, it can cause it to hang indefinitely. /// <para>Calling this method multiple times will have no effect.</para> /// </remarks> public static void Exit() { lock (MonoUsbDevice.OLockDeviceList) { if (MonoUsbDevice.mMonoUSBProfileList != null) { MonoUsbDevice.mMonoUSBProfileList.Close(); } MonoUsbDevice.mMonoUSBProfileList = null; } MonoUsbApi.StopAndExit(); }
/// <summary> /// Sets an alternate interface for the most recent claimed interface. /// </summary> /// <param name="alternateID">The alternate interface to select for the most recent claimed interface See <see cref="ClaimInterface"/>.</param> /// <returns>True on success.</returns> public bool SetAltInterface(int interfaceID, int alternateID) { int ret = MonoUsbApi.SetInterfaceAltSetting((MonoUsbDeviceHandle)mUsbHandle, interfaceID, alternateID); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "SetAltInterface Failed", this); return(false); } UsbAltInterfaceSettings[interfaceID & (UsbConstants.MAX_DEVICES - 1)] = (byte)alternateID; return(true); }
public MonoDeviceServer() { int numDevices = -1; // Initialize the context. if (Session.IsInvalid) { throw new Exception("Failed to initialize context."); } MonoUsbApi.SetDebug(Session, 0); // Create a MonoUsbProfileList instance. profileList = new MonoUsbProfileList(); cts = new CancellationTokenSource(); var ct = cts.Token; Task.Run(async() => { try { while (!ct.IsCancellationRequested) { // The list is initially empty. // Each time refresh is called the list contents are updated. int ret = profileList.Refresh(Session); if (ret < 0) { throw new Exception("Failed to retrieve device list."); } if (numDevices != ret) { numDevices = ret; //Console.WriteLine($"{numDevices} device(s) found."); MonoSetDevice(); } await Task.Delay(1000, ct); } } finally { // Since profile list, profiles, and sessions use safe handles the // code below is not required but it is considered good programming // to explicitly free and close these handle when they are no longer // in-use. profileList.Close(); Session.Close(); } }, ct); }
private Error GetDeviceDescriptor(out MonoUsbDeviceDescriptor monoUsbDeviceDescriptor) { Error ec = Error.Success; monoUsbDeviceDescriptor = new MonoUsbDeviceDescriptor(); //Console.WriteLine("MonoUsbProfile:GetDeviceDescriptor"); ec = (Error)MonoUsbApi.GetDeviceDescriptor(mMonoUSBProfileHandle, monoUsbDeviceDescriptor); if (ec != Error.Success) { MonoUsbErrorMessage.Error(ErrorCode.MonoApiError, (int)ec, "GetDeviceDescriptor Failed", this); monoUsbDeviceDescriptor = null; } return(ec); }
/// <summary> /// When overridden in a derived class, executes the code required to free the handle. /// </summary> /// <returns> /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant. /// </returns> protected override bool ReleaseHandle() { lock (oDeviceProfileRefLock) { if (!IsInvalid) { MonoUsbApi.UnrefDevice(handle); mDeviceProfileRefCount--; SetHandleAsInvalid(); Debug.Print(GetType().Name + " : ReleaseHandle #{0}", mDeviceProfileRefCount); } return(true); } }
internal MonoUsbProfile(MonoUsbProfileHandle monoUSBProfileHandle) { mMonoUSBProfileHandle = monoUSBProfileHandle; mBusNumber = MonoUsbApi.GetBusNumber(mMonoUSBProfileHandle); mDeviceAddress = MonoUsbApi.GetDeviceAddress(mMonoUSBProfileHandle); GetDeviceDescriptor(out mMonoUsbDeviceDescriptor); //#if DEBUG // Console.WriteLine("Vid:{0:X4} Pid:{1:X4} BusNumber:{2} DeviceAddress:{3}", // mMonoUsbDeviceDescriptor.VendorID, // mMonoUsbDeviceDescriptor.ProductID, // mBusNumber, // mDeviceAddress); //#endif }
public static void ShowInfo(RichTextBox rtb) { int ret; MonoUsbProfileList profileList = null; // Initialize the context. if (Session.IsInvalid) { throw new Exception("Failed to initialize context."); } MonoUsbApi.SetDebug(Session, 0); // Create a MonoUsbProfileList instance. profileList = new MonoUsbProfileList(); // The list is initially empty. // Each time refresh is called the list contents are updated. ret = profileList.Refresh(Session); if (ret < 0) { throw new Exception("Failed to retrieve device list."); } rtb.AppendText(string.Format("{0} device(s) found.\r\n", ret)); MonoUsbProfile JagaProfile; // Iterate through the profile list; write the device descriptor to // console output. foreach (MonoUsbProfile profile in profileList) { rtb.AppendText(profile.DeviceDescriptor.ToString() + "\r\n"); if (profile.DeviceDescriptor.VendorID == 0x1915) { JagaProfile = profile; } } // Since profile list, profiles, and sessions use safe handles the // code below is not required but it is considered good programming // to explicitly free and close these handle when they are no longer // in-use. profileList.Close(); Session.Close(); }
/// <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); } }
/// <summary> /// Gets the USB devices active configuration value. /// </summary> /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param> /// <returns>True on success.</returns> public override bool GetConfiguration(out byte config) { config = 0; int iconfig = 0; int ret = MonoUsbApi.GetConfiguration((MonoUsbDeviceHandle)mUsbHandle, ref iconfig); if (ret != 0) { UsbError.Error(ErrorCode.MonoApiError, ret, "GetConfiguration Failed", this); return(false); } config = (byte)iconfig; mCurrentConfigValue = config; return(true); }
/// <summary> /// Cancels pending transfers and clears the halt condition on an enpoint. /// </summary> /// <returns>True on success.</returns> public override bool Reset() { if (IsDisposed) { throw new ObjectDisposedException(GetType().Name); } Abort(); int ret = MonoUsbApi.ClearHalt((MonoUsbDeviceHandle)Device.Handle, EpNum); if (ret < 0) { MonoUsbErrorMessage.Error(ErrorCode.MonoApiError, ret, "Endpoint Reset Failed", this); return(false); } return(true); }
/// <summary> /// Releases an interface that was previously claimed with <see cref="ClaimInterface"/>. /// </summary> /// <param name="interfaceID">The interface to release.</param> /// <returns>True on success.</returns> public bool ReleaseInterface(int interfaceID) { int ret = MonoUsbApi.ReleaseInterface((MonoUsbDeviceHandle)mUsbHandle, interfaceID); if (!mClaimedInterfaces.Remove(interfaceID)) { return(true); } if (ret != 0) { MonoUsbErrorMessage.Error(ErrorCode.MonoApiError, ret, "ReleaseInterface Failed", this); return(false); } return(true); }
private void BeginFreiburgSyncSession() { if (sessionHandle.IsInvalid) { throw new ExternalException("Failed to initialize context."); } MonoUsbApi.SetDebug(sessionHandle, 0); profileList = new MonoLibUsb.Profile.MonoUsbProfileList(); // The list is initially empty. // Each time refresh is called the list contents are updated. int profileListRefreshResult; profileListRefreshResult = profileList.Refresh(sessionHandle); if (profileListRefreshResult < 0) { throw new ExternalException("Failed to retrieve device list."); } Debug.Log(profileListRefreshResult.ToString() + " device(s) found."); // Iterate through the profile list. // If we find the device, write 00000000 to its endpoint 2. foreach (MonoLibUsb.Profile.MonoUsbProfile profile in profileList) { if (profile.DeviceDescriptor.ProductID == FREIBURG_SYNCBOX_PRODUCT_ID && profile.DeviceDescriptor.VendorID == FREIBURG_SYNCBOX_VENDOR_ID) { freiburgSyncboxProfile = profile; } } if (freiburgSyncboxProfile == null) { throw new ExternalException("None of the connected USB devices were identified as a Freiburg syncbox."); } freiburgSyncboxDeviceHandle = new MonoUsbDeviceHandle(freiburgSyncboxProfile.ProfileHandle); freiburgSyncboxDeviceHandle = freiburgSyncboxProfile.OpenDeviceHandle(); if (freiburgSyncboxDeviceHandle == null) { throw new ExternalException("The ftd USB device was found but couldn't be opened"); } StartCoroutine(FreiburgPulse()); }
private static void SendData(MonoUsbDeviceHandle rapidradio, int endpoint, byte[] data, int length, int timeout = 1000000) { Marshal.Copy(data, 0, _unmanagedWriteBuff, Math.Min(length, 32)); int transferred; var r = MonoUsbApi.BulkTransfer(rapidradio, (byte)endpoint, _unmanagedWriteBuff, length, out transferred, timeout); if (r != (int)MonoUsbError.Success) { throw new Exception("Error while sending: " + GetErrorMessage(r)); } }