WidcommBtIf.cs :  » Business-Application » 32feet.NET » InTheHand » Net » Bluetooth » Widcomm » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Business Application » 32feet.NET 
32feet.NET » InTheHand » Net » Bluetooth » Widcomm » WidcommBtIf.cs
// 32feet.NET - Personal Area Networking for .NET
//
// InTheHand.Net.Bluetooth.Widcomm.WidcommBtIf
// 
// Copyright (c) 2008-2010 In The Hand Ltd, All rights reserved.
// Copyright (c) 2008-2010 Alan J. McFarlane, All rights reserved.
// This source code is licensed under the In The Hand Community License - see License.txt

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace InTheHand.Net.Bluetooth.Widcomm{
    sealed class WidcommBtIf : IBtIf
    {
        internal static class NativeMethods
        {
            internal delegate void OnDeviceResponded(IntPtr/*byte[]*/ bdAddr, 
                IntPtr/*byte[]*/ devClass, IntPtr/*byte[]*/ deviceName, bool connected);
            internal delegate void OnInquiryComplete(bool success, UInt16 numResponses);
            internal delegate void OnDiscoveryComplete();

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_Create(out IntPtr ppBtIf,
                OnDeviceResponded deviceResponded, OnInquiryComplete handleInquiryCompleted,
                OnDiscoveryComplete handleDiscoveryComplete);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_StartInquiry(IntPtr pBtIf);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern void BtIf_StopInquiry(IntPtr pBtIf);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_StartDiscovery(IntPtr pObj,
                byte[] p_bda, ref Guid p_service_guid,
                out int sizeofSdpDiscoveryRec);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern DISCOVERY_RESULT BtIf_GetLastDiscoveryResult(IntPtr pObj,
                [Out]byte[] p_bda, out UInt16 p_num_recs);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern int BtIf_ReadDiscoveryRecords(IntPtr pObj, 
                byte[] p_bda, int max_size, out IntPtr pSdpDiscoveryRecArray);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern int BtIf_ReadDiscoveryRecordsServiceClassOnly(IntPtr pObj,
                byte[] p_bda, int max_size, out IntPtr pSdpDiscoveryRecArray,
                ref Guid p_guid_filter);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern REM_DEV_INFO_RETURN_CODE BtIf_GetRemoteDeviceInfo(IntPtr pObj,
                IntPtr p_rem_dev_info, int cb);
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern REM_DEV_INFO_RETURN_CODE BtIf_GetNextRemoteDeviceInfo(IntPtr pObj,
                IntPtr p_rem_dev_info, int cb);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_GetLocalDeviceVersionInfo(IntPtr pObj,
                ref DEV_VER_INFO pBuf, int cb);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_GetLocalDeviceInfoBdAddr(IntPtr m_pBtIf, 
                [Out]byte[] bdAddr, int cb);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_GetLocalDeviceName(IntPtr pObj, 
                [Out]byte[] pBdName, int cb);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_IsStackUpAndRadioReady(IntPtr pObj,
                [MarshalAs(UnmanagedType.Bool)] out bool stackServerUp,
                [MarshalAs(UnmanagedType.Bool)] out bool deviceReady);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_IsDeviceConnectableDiscoverable(IntPtr pObj,
                [MarshalAs(UnmanagedType.Bool)] out bool conno,
                [MarshalAs(UnmanagedType.Bool)] out bool disco);

#if !WinXP
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_SetDeviceConnectableDiscoverable(IntPtr pObj,
                [MarshalAs(UnmanagedType.Bool)] bool connectable,
                [MarshalAs(UnmanagedType.Bool)] bool forPairedOnly,
                [MarshalAs(UnmanagedType.Bool)] bool discoverable);
#endif

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_GetConnectionStats(IntPtr pObj,
                byte[] bdAddr, out tBT_CONN_STATS pStats, int cb);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_BondQuery(IntPtr pObj,
                byte[] bdAddr);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern int BtIf_Bond(IntPtr pObj,
                byte[] bdAddr, byte[] pin_code);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_UnBond(IntPtr pObj,
                byte[] bdAddr);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern uint BtIf_GetExtendedError(IntPtr pBtIf);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern int BtIf_IsRemoteDevicePresent(IntPtr pObj, byte[] bdAddr);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool BtIf_IsRemoteDeviceConnected(IntPtr pObj, byte[] bdAddr);

            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_IsRemoteDevicePresentConnected(IntPtr pObj, byte[] bdAddr,
                out int pPresent, [MarshalAs(UnmanagedType.Bool)] out bool pConnected);

            //----
            [DllImport(WidcommRfcommPort.NativeMethods.WidcommDll)]
            internal static extern void BtIf_Destroy(IntPtr pBtIf);

            //--------
#if NETCF
            const string KernelCoreLibrary = "coredll.dll";
#else
            const string KernelCoreLibrary = "kernel32.dll";
#endif
            //[DllImport(KernelCoreLibrary, CharSet = CharSet.Unicode)]
            //internal static extern IntPtr LoadLibrary(string fileName);

            [DllImport(KernelCoreLibrary, CharSet = CharSet.Unicode)]
            internal static extern IntPtr LoadLibraryEx(string fileName, IntPtr hFile, LoadLibraryExFlags dwFlags);

            [DllImport(KernelCoreLibrary , CharSet = CharSet.Unicode)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool FreeLibrary(IntPtr hModule);

            [DllImport(KernelCoreLibrary, CharSet = CharSet.Unicode)]
            internal static extern IntPtr GetModuleHandle(string moduleName);

            [Flags]
            internal enum LoadLibraryExFlags
            {
                DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
                LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
                LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008,
                LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
                //
                VISTA_AND_LATER__LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
            }

        }

        // From the Widcomm documentation:
        //   An object of this class must be instantiated before any other DK 
        //   classes are used (typically at application startup). An object
        //   of this class should not be deleted until the application has 
        //   finished all interactions with the stack (typically at application
        //   exit). *** Only one object of this class should be instantiated by 
        //   the application. ***
        static volatile bool s_alreadyExists;
        IntPtr m_pBtIf;
        // So do we need a list of parents (as WeakReferences) and notify each on 
        // each event?
        WidcommBtInterface m_parent;
        //
        // Stop the delegates being GC'd, as the native code is calling their thunks.
        NativeMethods.OnDeviceResponded m_handleDeviceResponded;
        NativeMethods.OnInquiryComplete m_handleInquiryComplete;
        NativeMethods.OnDiscoveryComplete m_handleDiscoveryComplete;


        internal WidcommBtIf()
        {
            if (s_alreadyExists)
                throw new InvalidOperationException("May only be one instance of WidcommBtIf.");
            s_alreadyExists = true;
        }

        public void SetParent(WidcommBtInterface parent)
        {
            if (m_parent != null)
                throw new InvalidOperationException("Can only have one parent.");
            m_parent = parent;
        }

        [SuppressMessage("Microsoft.Design", "CA1031", Justification = "Is rethrown by method call CheckDependencies.")]
        public void Create()
        {
            WidcommBtInterface.ReportIfWidcommThread("BtIf_Create");
            if (m_pBtIf != IntPtr.Zero)// Singleton!
                throw new InvalidOperationException("Create already called.");
            m_handleDeviceResponded = HandleDeviceResponded;
            m_handleInquiryComplete = HandleInquiryComplete;
            m_handleDiscoveryComplete = HandleDiscoveryComplete;
            bool success = false;
            try {
                NativeMethods.BtIf_Create(out m_pBtIf, m_handleDeviceResponded, m_handleInquiryComplete,
                    m_handleDiscoveryComplete);
                if (m_pBtIf == IntPtr.Zero)
                    throw new InvalidOperationException("Failed to initialise CBtIf.");
                success = true;
            } catch (Exception ex) {
                CheckDependencies(ex);
            } finally {
                if (!success) {
                    Debug.Assert(m_pBtIf == IntPtr.Zero, "but failed!");
                    s_alreadyExists = false;
                }
            }
#if DEBUG
            CheckDependencies(null);
#endif
        }

        public void Destroy(bool disposing)
        {
            WidcommBtInterface.ReportIfWidcommThread("BtIf_Destroy");
            WidcommUtils.Trace_WriteLine("WidcommBtIf.Destroy");
            Debug.Assert(m_pBtIf != IntPtr.Zero, "WidcommBtIf Already Destroyed");
            if (m_pBtIf != IntPtr.Zero) {
                NativeMethods.BtIf_Destroy(m_pBtIf);
                m_pBtIf = IntPtr.Zero;
            }
            s_alreadyExists = false;
        }

        //-------------
        const string ModuleName32feet = "32feetWidcomm";
#if WinXP
        //const string ModuleNameWidcomm1 = "btwapi";
        const string ModuleNameWidcomm0 = "wbtapi";
#else
            const string ModuleNameWidcommWM = "BtSdkCe50";
            const string ModuleNameWidcommPPC = "BtSdkCe30";
#endif

        private static string GetWidcommModuleName()
        {
            string moduleNameWidcomm;
#if WinXP
            moduleNameWidcomm = ModuleNameWidcomm0;
#else
            OperatingSystem ver = Environment.OSVersion;
            if (ver.Version.Major < 5) // Think this is correct...
                moduleNameWidcomm = ModuleNameWidcommPPC;
            else
                moduleNameWidcomm = ModuleNameWidcommWM;
#endif
            return moduleNameWidcomm;
        }

        // This one!
        private static LibraryStatus CheckDependencies(Exception wrapException)
        {
            string[] nameList = { ModuleName32feet, GetWidcommModuleName() };
            foreach (string moduleName in nameList) {
                LibraryStatus status;
                try {
                    status = CheckLibraryDependency(moduleName);
                } catch (Exception ex) {
                    string msg1 = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "'{0}' status exception: {1}!", moduleName, ex);
                    WidcommUtils.Trace_WriteLine(msg1);
                    Debug.Fail(msg1);
                    if (wrapException != null)
                        throw new PlatformNotSupportedException(msg1, ex);
                    status = LibraryStatus.Exception;
                    Debug.Assert(false, msg1);
                    //return status; Or continue to check next dependency
                }
                string msg = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Dependency DLL '{0}' status: {1}.", moduleName, status);
                WidcommUtils.Trace_WriteLine(msg);
                if (wrapException != null) {
                    if (!IsFound(status))
                        throw new PlatformNotSupportedException(msg, wrapException);
                } else {
                    if (status != LibraryStatus.ModuleLoaded) {
                        // Being called when start-up was ok, but we're apparently
                        // looking for the wrong dependencies.
                        Debug.Assert(false, msg);
                        return status;
                    }
                }
            }
            if (wrapException != null)
                throw new PlatformNotSupportedException(wrapException.Message, wrapException);
            else
                return LibraryStatus.AggregateOk;
        }

        // This one!
        public static Exception IsWidcommStackPresentButNotInterfaceDll()
        {
            const Exception Success = null;
            string moduleNameWidcomm = GetWidcommModuleName();
            LibraryStatus wcDll = CheckLibraryDependency(moduleNameWidcomm);
            if (wcDll == LibraryStatus.NotFound) {
                // Widcomm stack not installed.
                return Success;
            }
            Debug.Assert(wcDll == LibraryStatus.ModuleLoaded || wcDll == LibraryStatus.LoadLibraryAccessible,
                "wcDll unexpected: " + wcDll);
            LibraryStatus ifaceDll = CheckLibraryDependency(ModuleName32feet);
            if (ifaceDll == LibraryStatus.NotFound) {
                // Ignore on Vista, no 'real' Widcomm support there.
                OperatingSystem os = Environment.OSVersion;
                Version osv = os.Version;
                const int VistaMajor = 6;
                if (osv.Major >= VistaMajor && os.Platform == PlatformID.Win32NT) {
                    bool forceCheckOnAllPlatforms = BluetoothFactoryConfig.WidcommICheckIgnorePlatform;
                    if (!forceCheckOnAllPlatforms)
                        return Success;
                }
                //
                // But not our interface DLL.
                return new PlatformNotSupportedException("Widcomm stack seems to be present, need to install 32feetWidcomm.dll alongside.");
            }
            // Both installed.
            return Success;
        }

        enum LibraryStatus
        {
            ModuleLoaded,
            LoadLibraryAccessible,
            AggregateOk,
            NotFound,
            Exception,
        }

        static bool IsFound(LibraryStatus status)
        {
            if (status == LibraryStatus.ModuleLoaded
                    || status == LibraryStatus.LoadLibraryAccessible)
                return true;
            return false;
        }

        static LibraryStatus CheckLibraryDependency(string moduleName)
        {
            IntPtr hG = NativeMethods.GetModuleHandle(moduleName);
            if (hG != IntPtr.Zero) {
                // (Must NOT free the handle).
                return LibraryStatus.ModuleLoaded;
            }
            //
            NativeMethods.LoadLibraryExFlags loadFlags = NativeMethods.LoadLibraryExFlags.LOAD_LIBRARY_AS_DATAFILE;
            IntPtr hL = NativeMethods.LoadLibraryEx(moduleName, IntPtr.Zero, loadFlags);
            if (hL != IntPtr.Zero) {
                bool success = NativeMethods.FreeLibrary(hL); // Must free the handle.
                Debug.Assert(success);
                return LibraryStatus.LoadLibraryAccessible;
            } else { // COVERAGE
            }
            //
            return LibraryStatus.NotFound;
        }

        //-------------
        public bool StartInquiry()
        {
            WidcommBtInterface.ReportIfWidcommThread("BtIf_StartInquiry");
            return NativeMethods.BtIf_StartInquiry(m_pBtIf);
        }

        public void StopInquiry()
        {
            WidcommBtInterface.ReportIfWidcommThread("BtIf_StopInquiry");
            NativeMethods.BtIf_StopInquiry(m_pBtIf);
        }

        void HandleDeviceResponded(IntPtr bdAddr, IntPtr devClass, IntPtr deviceName, bool connected)
        {
            byte[] bdAddrArr;
            byte[] devClassArr;
            byte[] deviceNameArr;
            WidcommUtils.GetBluetoothCallbackValues(bdAddr, devClass, deviceName,
                out bdAddrArr, out devClassArr, out deviceNameArr);
            m_parent.HandleDeviceResponded(bdAddrArr, devClassArr, deviceNameArr, connected);
        }

        void HandleInquiryComplete(bool success, UInt16 numResponses)
        {
            m_parent.HandleInquiryComplete(success, numResponses);
        }

        //-------------
        public bool StartDiscovery(BluetoothAddress address, Guid serviceGuid)
        {
            WidcommBtInterface.ReportIfWidcommThread("BtIf_StartDiscovery");
            WidcommUtils.Trace_WriteLine("WidcommBtIf.StartDiscovery");
            byte[] bdaddr = WidcommUtils.FromBluetoothAddress(address);
            int sizeofSdpDiscoveryRec; // just for interests sake
            bool ret = NativeMethods.BtIf_StartDiscovery(m_pBtIf, bdaddr, ref serviceGuid,
                out sizeofSdpDiscoveryRec);
            return ret;
        }

        public DISCOVERY_RESULT GetLastDiscoveryResult(out BluetoothAddress address, out UInt16 p_num_recs)
        {
            byte[] bdaddr = WidcommUtils.FromBluetoothAddress(BluetoothAddress.None);
            DISCOVERY_RESULT ret = NativeMethods.BtIf_GetLastDiscoveryResult(m_pBtIf, bdaddr, out p_num_recs);
            address = WidcommUtils.ToBluetoothAddress(bdaddr);
            return ret;
        }

        public ISdpDiscoveryRecordsBuffer ReadDiscoveryRecords(BluetoothAddress address, int maxRecords, ServiceDiscoveryParams args)
        {
            byte[] bdaddr = WidcommUtils.FromBluetoothAddress(address);
            // Does this boy need to be 8-aligned in this case!!!  Looks ok in the 
            // native debugger and then we call CBtIf::ReadDiscoveryRecords -> crash!!
            IntPtr pList;
            Guid filter = args.serviceGuid;
            int count;
            if (args.searchScope == SdpSearchScope.Anywhere) {
                count = NativeMethods.BtIf_ReadDiscoveryRecords(m_pBtIf, bdaddr,
                    maxRecords, out pList);
            } else {
                Debug.Assert(args.searchScope == SdpSearchScope.ServiceClassOnly, "the other enum");
                try {
                    count = NativeMethods.BtIf_ReadDiscoveryRecordsServiceClassOnly(m_pBtIf, bdaddr,
                        maxRecords, out pList, ref filter);
                } catch (EntryPointNotFoundException ex) {
                    string msg = "Need to upgrade your 32feetWidcomm.dll!";
                    Debug.Fail(msg);
                    WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
                    count = NativeMethods.BtIf_ReadDiscoveryRecords(m_pBtIf, bdaddr,
                        maxRecords, out pList);
                } catch (MissingMethodException ex) { // for NETCF
                    string msg = "Need to upgrade your 32feetWidcomm.dll!";
                    Debug.Fail(msg);
                    WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
                    count = NativeMethods.BtIf_ReadDiscoveryRecords(m_pBtIf, bdaddr,
                        maxRecords, out pList);
                }
            }
            ISdpDiscoveryRecordsBuffer recBuf = new SdpDiscoveryRecordsBuffer(pList, count, args);
            return recBuf;
        }

        void HandleDiscoveryComplete()
        {
            m_parent.HandleDiscoveryComplete();
        }


        //-------------


        //-------------

        public REM_DEV_INFO_RETURN_CODE GetRemoteDeviceInfo(ref REM_DEV_INFO remDevInfo, IntPtr p_rem_dev_info, int cb)
        {
#if NETCF    // Not supported on my test device
            return REM_DEV_INFO_RETURN_CODE.ERROR;
#else
            WidcommUtils.Trace_WriteLine("enter GetRemoteDeviceInfo, pBuf=0x{0:X}", p_rem_dev_info.ToInt64());
            REM_DEV_INFO_RETURN_CODE ret = NativeMethods.BtIf_GetRemoteDeviceInfo(m_pBtIf, p_rem_dev_info, cb);
            WidcommUtils.Trace_WriteLine("exit GetRemoteDeviceInfo");
            remDevInfo = (REM_DEV_INFO)Marshal.PtrToStructure(p_rem_dev_info, typeof(REM_DEV_INFO));
            return ret;
#endif
        }

        public REM_DEV_INFO_RETURN_CODE GetNextRemoteDeviceInfo(ref REM_DEV_INFO remDevInfo, IntPtr p_rem_dev_info, int cb)
        {
            WidcommUtils.Trace_WriteLine("enter GetNextRemoteDeviceInfo, pBuf=0x{0:X}", p_rem_dev_info.ToInt64());
            REM_DEV_INFO_RETURN_CODE ret = NativeMethods.BtIf_GetNextRemoteDeviceInfo(m_pBtIf, p_rem_dev_info, cb);
            WidcommUtils.Trace_WriteLine("exit GetNextRemoteDeviceInfo");
            remDevInfo = (REM_DEV_INFO)Marshal.PtrToStructure(p_rem_dev_info, typeof(REM_DEV_INFO));
            return ret;
        }

        //-------------
        public bool GetLocalDeviceVersionInfo(ref DEV_VER_INFO devVerInfo)
        {
            int cb = Marshal.SizeOf(devVerInfo);
            bool success = NativeMethods.BtIf_GetLocalDeviceVersionInfo(m_pBtIf,
                ref devVerInfo, cb);
            return success;
        }

        public bool GetLocalDeviceName(byte[] bdName)
        {
            bool success = NativeMethods.BtIf_GetLocalDeviceName(m_pBtIf, bdName, bdName.Length);
            return success;
        }

        public bool GetLocalDeviceInfoBdAddr(byte[] bdAddr)
        {
            return NativeMethods.BtIf_GetLocalDeviceInfoBdAddr(m_pBtIf, bdAddr, bdAddr.Length);
        }

        public void IsStackUpAndRadioReady(out bool stackServerUp, out bool deviceReady)
        {
            try {
                NativeMethods.BtIf_IsStackUpAndRadioReady(m_pBtIf, out stackServerUp, out deviceReady);
            } catch (EntryPointNotFoundException ex) {
                string msg = "Need to upgrade your 32feetWidcomm.dll!";
                Debug.Fail(msg);
                WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
                stackServerUp = deviceReady = true;
            } catch (MissingMethodException ex) { // for NETCF
                string msg = "Need to upgrade your 32feetWidcomm.dll!";
                Debug.Fail(msg);
                WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
                stackServerUp = deviceReady = true;
            }
        }

        public void IsDeviceConnectableDiscoverable(out bool conno, out bool disco)
        {
            NativeMethods.BtIf_IsDeviceConnectableDiscoverable(m_pBtIf, out conno, out disco);
        }

        public void SetDeviceConnectableDiscoverable(bool connectable, bool forPairedOnly, bool discoverable)
        {
#if WinXP
            throw new NotSupportedException("No Widcomm API support.");
#else
            try {
                NativeMethods.BtIf_SetDeviceConnectableDiscoverable(m_pBtIf, connectable, forPairedOnly, discoverable);
                return;
            } catch (EntryPointNotFoundException ex) {
                string msg = "Need to upgrade your 32feetWidcomm.dll!";
                Debug.Fail(msg);
                WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
            } catch (MissingMethodException ex) { // for NETCF
                string msg = "Need to upgrade your 32feetWidcomm.dll!";
                Debug.Fail(msg);
                WidcommUtils.Trace_WriteLine(msg + "\n" + ex);
            }
#endif
        }

        public int GetRssi(byte[] bd_addr)
        {
            Debug.Assert(bd_addr.Length == WidcommStructs.BD_ADDR_LEN, "bd_addr.Length: " + bd_addr.Length);
            tBT_CONN_STATS stats = new tBT_CONN_STATS();
            bool success = NativeMethods.BtIf_GetConnectionStats(m_pBtIf, bd_addr, 
                out stats, Marshal.SizeOf(stats));
            if (!success) {
                // Occurs mostly.  Apparently a connection must exist for Rssi to 
                // be read, both from observation and from the Widcomm docs:
                //   "TRUE, if a connection attempt has been initiated; FALSE, if 
                //    a connection attempt has not been initiated"
                return int.MinValue;
            } else {
                return stats.rssi;
            }
        }

        public bool BondQuery(byte[] bd_addr)
        {
            bool arePaired = NativeMethods.BtIf_BondQuery(m_pBtIf, bd_addr);
            return arePaired;
        }

        public BOND_RETURN_CODE Bond(BluetoothAddress address, string passphrase)
        {
            byte[] bdaddr = WidcommUtils.FromBluetoothAddress(address);
            byte[] pinUtf8;
            byte[] pinUtf16; // As seen used in WM sample with CString::GetBuffer().
            if (passphrase != null) {
                // TODO should be ASCII??
                pinUtf8 = Encoding.UTF8.GetBytes(passphrase + "\0");
                pinUtf16 = Encoding.Unicode.GetBytes(passphrase + "\0");
            } else {
                // ?????????
                pinUtf8 = null;
                pinUtf16 = null;
            }
            //
            BOND_RETURN_CODE ret2;
#if !NETCF
            int retBtw = NativeMethods.BtIf_Bond(m_pBtIf, bdaddr, pinUtf8);
            ret2 = (BOND_RETURN_CODE)retBtw;
#else
            int retWce = NativeMethods.BtIf_Bond(m_pBtIf, bdaddr, pinUtf16 );
            ret2 = Convert((BOND_RETURN_CODE__WCE)retWce);
#endif
            return ret2;
        }

        static BOND_RETURN_CODE Convert(BOND_RETURN_CODE__WCE wce)
        {
            BOND_RETURN_CODE ret;
            switch (wce) {
                case BOND_RETURN_CODE__WCE.ALREADY_BONDED:
                    ret = BOND_RETURN_CODE.ALREADY_BONDED;
                    break;
                case BOND_RETURN_CODE__WCE.BAD_PARAMETER:
                    ret = BOND_RETURN_CODE.BAD_PARAMETER;
                    break;
                case BOND_RETURN_CODE__WCE.FAIL:
                    ret = BOND_RETURN_CODE.FAIL;
                    break;
                case BOND_RETURN_CODE__WCE.SUCCESS:
                    ret = BOND_RETURN_CODE.SUCCESS;
                    break;
                default:
                    Debug.Fail(string.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Unknown BOND_RETURN_CODE__WCE code: 0x{1:X}", wce, (int)wce));
                    ret = (BOND_RETURN_CODE)99;
                    break;
            }
            return ret;
        }

        public bool UnBond(BluetoothAddress address)
        {
            byte[] bdaddr = WidcommUtils.FromBluetoothAddress(address);
            bool ret = NativeMethods.BtIf_UnBond(m_pBtIf, bdaddr);
            return ret;
        }

        //-------------
        public WBtRc GetExtendedError()
        {
            uint ret = NativeMethods.BtIf_GetExtendedError(m_pBtIf);
            return checked((WBtRc)ret);
        }

        //----
        public SDK_RETURN_CODE IsRemoteDevicePresent(byte[] bd_addr)
        {
            int ret0 = NativeMethods.BtIf_IsRemoteDevicePresent(m_pBtIf, bd_addr);
            SDK_RETURN_CODE ret = (SDK_RETURN_CODE)ret0;
            return ret;
        }

        public bool IsRemoteDeviceConnected(byte[] bd_addr)
        {
            bool ret = NativeMethods.BtIf_IsRemoteDeviceConnected(m_pBtIf, bd_addr);
            return ret;
        }

    }


    enum DISCOVERY_RESULT
    {
        SUCCESS,
        /// <summary>
        /// Could not connect to remote device 
        /// </summary>
        CONNECT_ERR,
        /// <summary>
        /// Remote device rejected the connection 
        /// </summary>
        CONNECT_REJ,
        /// <summary>
        /// Security failed 
        /// </summary>
        SECURITY,
        /// <summary>
        /// Remote Service Record Error 
        /// </summary>
        BAD_RECORD,
        /// <summary>
        /// Other error
        /// </summary>
        OTHER_ERROR
    }

    enum REM_DEV_INFO_RETURN_CODE
    {
        /// <summary>
        /// success response
        /// </summary>
        SUCCESS,
        /// <summary>
        /// no more devices found
        /// </summary>
        EOF,
        /// <summary>
        /// can not find exsiting entry for bda provided as input
        /// </summary>
        ERROR,
        /// <summary>
        /// out of memory
        /// </summary>
        MEM_ERROR
    };

#if TEST_EARLY
    public
#endif
    enum BOND_RETURN_CODE
    {
        SUCCESS,
        BAD_PARAMETER,
        NO_BT_SERVER,
        ALREADY_BONDED,     // maintained for compatibility, BTW stack allows rebonding
        FAIL,
        REPEATED_ATTEMPTS   // pairing has failed repeatedly, and further attempts will
        // continue to return this code until after the device security
        // timeout                  - added BTW 5.0.1.700, SDK 5.0
    };

    enum BOND_RETURN_CODE__BTW
    {
        SUCCESS,
        BAD_PARAMETER,
        NO_BT_SERVER,
        ALREADY_BONDED,     // maintained for compatibility, BTW stack allows rebonding
        FAIL,
        REPEATED_ATTEMPTS   // pairing has failed repeatedly, and further attempts will
                            // continue to return this code until after the device security
                            // timeout                  - added BTW 5.0.1.700, SDK 5.0
    };

    enum BOND_RETURN_CODE__WCE
    {
        SUCCESS,
        ALREADY_BONDED,
        BAD_PARAMETER,
        FAIL
    };

}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.