To close a device, see the Close method.
/// <summary> /// Perform a USB control transfer. /// </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="data"> /// <para>A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</para> /// This value can be: /// <list type="bullet"> /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item> /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item> /// <item>An <see cref="IntPtr"/>.</item> /// </list> /// </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 ControlTransfer([In] MonoUsbDeviceHandle deviceHandle, byte requestType, byte request, short value, short index, object data, short dataLength, int timeout) { PinnedHandle p = new PinnedHandle(data); int ret = ControlTransfer(deviceHandle, requestType, request, value, index, p.Handle, dataLength, timeout); p.Dispose(); return(ret); }
/// <summary> /// Perform a USB interrupt transfer. /// </summary> /// <remarks> /// <para> /// The direction of the transfer is inferred from the direction bits of the endpoint address. /// </para><para> /// For interrupt reads, the length field indicates the maximum length of data you are expecting to receive. /// If less data arrives than expected, this function will return that data, so be sure to check the /// transferred output parameter. /// </para><para> /// You should also check the transferred parameter for interrupt writes. Not all of the data may have been /// written. Also check transferred when dealing with a timeout error code. libusb may have to split /// your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the /// timeout may expire after the first few chunks have completed. libusb is careful not to lose any /// data that may have been transferred; do not assume that timeout conditions indicate a complete lack /// of I/O. /// </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="endpoint">The address of a valid endpoint to communicate with.</param> /// <param name="data"> /// <para>A suitably-sized data buffer for either input or output (depending on endpoint).</para> /// This value can be: /// <list type="bullet"> /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item> /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item> /// <item>An <see cref="IntPtr"/>.</item> /// </list> /// </param> /// <param name="length">For interrupt writes, the number of bytes from data to be sent. for interrupt reads, the maximum number of bytes to receive into the data buffer.</param> /// <param name="actualLength">Output location for the number of bytes actually transferred.</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>0 on success (and populates <paramref name="actualLength"/>)</item> /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item> /// <item><see cref="MonoUsbError.ErrorPipe"/> if the endpoint halted</item> /// <item><see cref="MonoUsbError.ErrorOverflow"/>if the device offered more data, see <a href="http://libusb.sourceforge.net/api-1.0/packetoverflow.html">Packets and overflows</a></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 InterruptTransfer([In] MonoUsbDeviceHandle deviceHandle, byte endpoint, object data, int length, out int actualLength, int timeout) { PinnedHandle p = new PinnedHandle(data); int ret = InterruptTransfer(deviceHandle, endpoint, p.Handle, length, out actualLength, timeout); p.Dispose(); return(ret); }
/// <summary> /// Retrieve a descriptor from the default control pipe. /// </summary> /// <remarks> /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note> /// </remarks> /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param> /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param> /// <param name="descIndex">The index of the descriptor to retrieve.</param> /// <param name="pData">Output buffer for descriptor.</param> /// <param name="length">Size of data buffer.</param> /// <returns>Number of bytes returned in data, or a <see cref="MonoUsbError"/> code on failure.</returns> public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, IntPtr pData, int length) { return(ControlTransfer(deviceHandle, (byte)UsbEndpointDirection.EndpointIn, (byte)UsbStandardRequest.GetDescriptor, (short)((descType << 8) | descIndex), 0, pData, (short)length, 1000)); }
/// <summary> /// Creates a new ProgrammingConnection; if the Unified Lab Kit can't be found, /// it throws a DeviceNotConnected excpetion. /// </summary> /// <param name="Timeout"> /// The amount of time to wait before the system decides the device isn't connected. /// </param> public ProgrammingConnection(short timeout) { int retries = 5; //store the timeout field from the constructor this.timeout = timeout; //create a new local USB session session = new MonoUsbSessionHandle(); while (retries-- > 0) { try { //find the device by its descriptor device = MonoUsbApi.OpenDeviceWithVidPid(session, VID, PID); } catch (ObjectDisposedException ex) { if (retries == 0) { //DEBUG DebugConsole.WriteLine("Windows could not create the USB connection... try again in a few seconds?"); throw ex; } //DEBUG DebugConsole.WriteLine("Too soon! Retrying in 15s."); System.Threading.Thread.Sleep(15000); continue; } //break on success break; } if (device == null) throw new DeviceNotFoundException(); //if the kernel has a driver operating on our interface, ask it to detach if (MonoUsbApi.KernelDriverActive(device, 0) >= 0) if (MonoUsbApi.DetachKernelDriver(device, 0) < 0) throw new DeviceInUseException(); //claim our interface for exclusive access MonoUsbApi.ClaimInterface(device, 0); }
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()); }
/// <summary> /// Creates a new ProgrammingConnection; if the Unified Lab Kit can't be found, /// it throws a DeviceNotConnected excpetion. /// </summary> /// <param name="Timeout"> /// The amount of time to wait before the system decides the device isn't connected. /// </param> public MonoProgrammingConnection() { //create a new local USB session session = new MonoUsbSessionHandle(); //find the device by its descriptor device = MonoUsbApi.OpenDeviceWithVidPid(session, VID, PID); if(device==null) throw new DeviceNotFoundException(); //if the kernel has a driver operating on our interface, ask it to detach if(MonoUsbApi.KernelDriverActive(device, 0) >=0 ) if(MonoUsbApi.DetachKernelDriver(device, 0) < 0) throw new DeviceInUseException(); //claim our interface for exclusive access MonoUsbApi.ClaimInterface(device, 0); }
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> /// 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); }
/// <summary> /// Get a <see cref="MonoUsbProfileHandle"/> for a <see cref="MonoUsbDeviceHandle"/>. /// </summary> /// <remarks> /// <para> /// This function differs from the Libusb-1.0 C API in that when the new <see cref="MonoUsbProfileHandle"/> is returned, the device profile reference count /// is incremented ensuring the profile will remain valid as long as it is in-use. /// </para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note> /// </remarks> /// <param name="devicehandle">A device handle.</param> /// <returns>The underlying profile handle.</returns> public static MonoUsbProfileHandle GetDevice(MonoUsbDeviceHandle devicehandle) { return(new MonoUsbProfileHandle(GetDeviceInternal(devicehandle))); }
/// <summary> /// Retrieve a descriptor from the default control pipe. /// </summary> /// <remarks> /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note> /// </remarks> /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param> /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param> /// <param name="descIndex">The index of the descriptor to retrieve.</param> /// <param name="data">Output buffer for descriptor. This object is pinned using <see cref="PinnedHandle"/>.</param> /// <param name="length">Size of data buffer.</param> /// <returns>Number of bytes returned in data, or <see cref="MonoUsbError"/> code on failure.</returns> public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, object data, int length) { PinnedHandle p = new PinnedHandle(data); return(GetDescriptor(deviceHandle, descType, descIndex, p.Handle, length)); }
/// <summary> /// Retrieve a descriptor from the default control pipe. /// </summary> /// <remarks> /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note> /// </remarks> /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param> /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param> /// <param name="descIndex">The index of the descriptor to retrieve.</param> /// <param name="data">Output buffer for descriptor. This object is pinned using <see cref="PinnedHandle"/>.</param> /// <param name="length">Size of data buffer.</param> /// <returns>Number of bytes returned in data, or <see cref="MonoUsbError"/> code on failure.</returns> public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, object data, int length) { PinnedHandle p = new PinnedHandle(data); return GetDescriptor(deviceHandle, descType, descIndex, p.Handle, length); }
/// <summary> /// Retrieve a descriptor from the default control pipe. /// </summary> /// <remarks> /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note> /// </remarks> /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param> /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param> /// <param name="descIndex">The index of the descriptor to retrieve.</param> /// <param name="pData">Output buffer for descriptor.</param> /// <param name="length">Size of data buffer.</param> /// <returns>Number of bytes returned in data, or a <see cref="MonoUsbError"/> code on failure.</returns> public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, IntPtr pData, int length) { return ControlTransfer(deviceHandle, (byte) UsbEndpointDirection.EndpointIn, (byte) UsbStandardRequest.GetDescriptor, (short) ((descType << 8) | descIndex), 0, pData, (short) length, 1000); }
/// <summary> /// Get a <see cref="MonoUsbProfileHandle"/> for a <see cref="MonoUsbDeviceHandle"/>. /// </summary> /// <remarks> /// <para> /// This function differs from the Libusb-1.0 C API in that when the new <see cref="MonoUsbProfileHandle"/> is returned, the device profile reference count /// is incremented ensuring the profile will remain valid as long as it is in-use. /// </para> /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note> /// </remarks> /// <param name="devicehandle">A device handle.</param> /// <returns>The underlying profile handle.</returns> public static MonoUsbProfileHandle GetDevice(MonoUsbDeviceHandle devicehandle) { return new MonoUsbProfileHandle(GetDeviceInternal(devicehandle)); }
/// <summary> /// Perform a USB control transfer. /// </summary> /// <remarks> /// The direction of the transfer is inferred from the bmRequestType field of the setup packet. /// The wValue, wIndex and wLength fields values should be given in host-endian byte order. /// </remarks> /// <param name="deviceHandle">A handle for the device to communicate with.</param> /// <param name="setupPacket">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 millseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param> /// <returns>on success, the number of bytes actually transferred, Other wise a <see cref="MonoUsbError"/>.</returns> public static int libusb_control_transfer(MonoUsbDeviceHandle deviceHandle, ref libusb_control_setup setupPacket, IntPtr pData, short dataLength, int timeout) { return libusb_control_transfer(deviceHandle, setupPacket.bmRequestType, setupPacket.bRequest, setupPacket.wValue, setupPacket.wIndex, pData, dataLength, timeout); }
///<summary> /// Opens the USB device handle. ///</summary> ///<returns> ///True if the device is already opened or was opened successfully. ///False if the device does not exists or is no longer valid. ///</returns> public override bool Open() { if (IsOpen) return true; MonoUsbDeviceHandle handle = new MonoUsbDeviceHandle(mMonoUSBProfile.ProfileHandle); if (handle.IsInvalid) { UsbError.Error(ErrorCode.MonoApiError, (int) MonoUsbDeviceHandle.LastErrorCode, "MonoUsbDevice.Open Failed", this); mUsbHandle = null; return false; } mUsbHandle = handle; if (IsOpen) return true; mUsbHandle.Dispose(); return false; }