Represents a Libusb-1.0 device handle.

To close a device, see the Close method.

A MonoUsbDeviceHandle is roughly equivalent to a libusb_device_handle.
Inheritance: LibUsbDotNet.Main.SafeContextHandle
Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
 /// <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);
        }
Exemple #5
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;
        }
Exemple #8
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);
        }
Exemple #9
0
 /// <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)));
 }
Exemple #10
0
        /// <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;
        }