WidcommBtInterface.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 » WidcommBtInterface.cs
// 32feet.NET - Personal Area Networking for .NET
//
// InTheHand.Net.Widcomm.WidcommSocketExceptions
// 
// 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.Net.Sockets;
using InTheHand.Net.Sockets;
using System.Diagnostics;
using Microsoft.Win32;
using System.Diagnostics.CodeAnalysis;
using InTheHand.Net.Bluetooth.Factory;
using List_IBluetoothDeviceInfoSystem.Collections.Generic.ListInTheHand.Net.Bluetooth.Factory.IBluetoothDeviceInfo;
using AR_InquiryInTheHand.Net.AsyncResultSystem.Collections.Generic.ListInTheHand.Net.Bluetooth.Factory.IBluetoothDeviceInfo;
using System.Threading;

namespace InTheHand.Net.Bluetooth.Widcomm{
    internal sealed class WidcommBtInterface : IDisposable
    {
        readonly WidcommBluetoothFactoryBase m_factory;
        readonly IBtIf m_btIf;
        //
#if WIDCOMM_SINGLE_THREADING
        // The Win32 Widcomm documentation says 'don't call back into the API on a
        // thread where the API raised a callback'.  So we have to detect this situation
        // and launch the API call on a new thread.
        //   This is apparently not the case on CE/WM,
        // and here they don't support ThreadStatic anyway.
        //   Note because this is ThreadStatic it obviously doesn't need thread-safe access.
#if !NETCF
        [ThreadStatic]
        static int _InWidcommCallbackThreadCount;
        [ThreadStatic]
        public static bool _IsWidcommSingleThread;
#endif
        static readonly LocalDataStoreSlot _slotIsWidcommSingleThread, _slotInWidcommCallbackThreadCount;
#endif


        static WidcommBtInterface()
        {
#if WIDCOMM_SINGLE_THREADING
            _slotIsWidcommSingleThread = Thread.AllocateNamedDataSlot("_IsWidcommSingleThread");
            _slotInWidcommCallbackThreadCount = Thread.AllocateNamedDataSlot("_InWidcommCallbackThreadCount");
#endif
        }

        internal WidcommBtInterface(IBtIf btIf, WidcommBluetoothFactoryBase factory)
        {
            m_factory = factory;
            bool created = false;
            try {
                m_btIf = btIf;
                m_btIf.SetParent(this);
                // "An object of this class must be instantiated before any other DK classes are used"
                m_btIf.Create();
                created = true;
            } finally {
                if (!created) { GC.SuppressFinalize(this); }
            }
        }

        //----
        void IDisposable.Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~WidcommBtInterface()
        {
            Dispose(false);
        }

        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")]
        void Dispose(bool disposing)
        {
            m_btIf.Destroy(disposing);
        }

        //-----------------------------
        object lockInquiry = new object();
        AR_Inquiry m_arInquiry;
        List_IBluetoothDeviceInfo m_inquiryDevices;
        List<AR_Inquiry> m_arInquiryFollowers;


        //----------
        internal IAsyncResult BeginInquiry(int maxDevices, bool authenticated, bool remembered, bool unknown,
            TimeSpan inquiryLength,
            AsyncCallback asyncCallback, Object state)
        {
            int fakeUseI = maxDevices;
            bool fackUseB = authenticated = remembered = unknown;
            AR_Inquiry ar;
            AR_Inquiry sacAr = null;
            List_IBluetoothDeviceInfo sacResult = null;
            lock (lockInquiry) {
                if (m_arInquiry != null) {
                    Debug.Fail("This use of multiple concurrent DiscoverDevices calls on Widcomm is COMPLETELY untested!");
                    // Just give any new request the same results as the outstanding Inquiry.
                    ar = new AR_Inquiry(asyncCallback, state);
                    if (m_arInquiry.IsCompleted) {
                        // This can never occur (is nulled before SAC'd), but leave in anyway...
                        sacAr = ar;
                        sacResult = m_inquiryDevices;
                    } else {
                        if (m_arInquiryFollowers == null)
                            m_arInquiryFollowers = new List<AR_Inquiry>();
                        m_arInquiryFollowers.Add(ar);
                    }
                } else { // New inquiry process.
                    ar = new AR_Inquiry(asyncCallback, state);
                    m_arInquiry = ar;
                    m_arInquiryFollowers = null;
                    m_inquiryDevices = new List_IBluetoothDeviceInfo();
                    bool siSuccess=false;
                    try {
                        StartInquiry();
                        siSuccess = true;
                    } finally {
                        if (!siSuccess) { m_arInquiry = null; }
                    }
                    if (inquiryLength.CompareTo(TimeSpan.Zero) > 0) {
                        System.Threading.ThreadPool.QueueUserWorkItem(_InquiryTimeoutRunner,
                            new InquiryTimeoutParams(ar, inquiryLength));
                    }
                }
            }//lock
            if (sacAr != null) {
                sacAr.SetAsCompleted(sacResult, true);
            }
            return ar;
        }

        private void StartInquiry() // We are inside the lock.
        {
            // TO-DO Need to use the InquiryLength property and then return whatever devices 
            // we've got by that point.
            //
            bool success = m_btIf.StartInquiry();
            if (!success)
                throw WidcommSocketExceptions.Create_StartInquiry("StartInquiry");
        }

        internal void HandleDeviceResponded(byte[] bdAddr, byte[] devClass,
            byte[] deviceName, bool connected)
        {
            EntryIsWidcommThread();
            WidcommUtils.Trace_WriteLine("HandleDeviceResponded");
            lock (lockInquiry) {
                WidcommUtils.Trace_WriteLine("HDR: {0} {1} {2} {3}",
                    ToStringQuotedOrNull(bdAddr), ToStringQuotedOrNull(devClass),
                    ToStringQuotedOrNull(deviceName), connected);
                if (m_inquiryDevices == null) {
                    Debug.Assert(TestUtilities.IsUnderTestHarness(), "HandleDeviceResponded without DD i.e. m_inquiryDevices == null.");
                    goto exit;
                }
                IBluetoothDeviceInfo bdi = WidcommBluetoothDeviceInfo.CreateFromHandleDeviceResponded(
                    bdAddr, deviceName, devClass, connected, m_factory);
                int idx = BluetoothDeviceInfo.ListIndexOf(m_inquiryDevices, bdi);
                AssertManualExistsIf(idx, m_inquiryDevices, bdi);
                if (idx == -1) {
                    m_inquiryDevices.Add(bdi);
                } else {
                    WidcommUtils.Trace_WriteLine("Replace.");
                    // Check the new info versus the previously discovered device.
                    IBluetoothDeviceInfo bdiOld = m_inquiryDevices[idx];
                    Debug.Assert(bdiOld.DeviceAddress.Equals(bdi.DeviceAddress));
                    Debug.Assert(deviceName != null);
                    Debug.Assert(deviceName.Length != 0);
                    //Debug.Assert(bdiOld.ClassOfDevice.Equals(bdi.ClassOfDevice));
                    // Replace
                    m_inquiryDevices[idx] = bdi;
                }
            }
        exit:
            WidcommUtils.Trace_WriteLine("exit HDR");
            ExitIsWidcommThread();
        }

        [Conditional("DEBUG")]
        private void AssertManualExistsIf(int index, List_IBluetoothDeviceInfo list, IBluetoothDeviceInfo item)
        {
            bool found = false;
            foreach (IBluetoothDeviceInfo cur in list) {
                if (cur.DeviceAddress == item.DeviceAddress)
                    found = true;
            }
            Debug.Assert(found == (index != -1), "manual found != list->object found");
        }

        private static string ToStringQuotedOrNull(byte[] array)
        {
            if (array == null)
                return "(null)";
            else
                return "\"" + BitConverter.ToString(array) + "\"";
        }

        internal void HandleInquiryComplete(bool success, UInt16 numResponses)
        {
            EntryIsWidcommThread();
            WidcommUtils.Trace_WriteLine("HandleInquiryComplete");
            HandleInquiryComplete_Internal(success, numResponses);
            WidcommUtils.Trace_WriteLine("exit HandleInquiryComplete");
            ExitIsWidcommThread();
        }

        internal void HandleInquiryComplete_Internal(bool success, UInt16 numResponses)
        {
            AR_Inquiry sacAr;
            List<AR_Inquiry> sacArFollowers = null;
            List_IBluetoothDeviceInfo sacResult;
            lock (lockInquiry) {
                m_btIf.StopInquiry();
                sacAr = m_arInquiry;
                sacResult = m_inquiryDevices;
                m_arInquiry = null;
                if (m_arInquiryFollowers != null) {
                    sacArFollowers = m_arInquiryFollowers;
                    m_arInquiryFollowers = null;
                }
            }//lock
            WaitCallback dlgt = delegate {
                RaiseInquiryComplete(sacAr, sacResult, sacArFollowers);
            };
            ThreadPool.QueueUserWorkItem(dlgt);
        }

        static void RaiseInquiryComplete(AR_Inquiry sacAr,
            List_IBluetoothDeviceInfo sacResult, List<AR_Inquiry> sacArFollowers)
        {
            if (sacAr != null) {
                sacAr.SetAsCompleted(sacResult, false);
                if (sacArFollowers != null) {
                    foreach (AR_Inquiry ar in sacArFollowers)
                        ar.SetAsCompleted(sacResult, false);
                }
            }
        }

        internal List_IBluetoothDeviceInfo EndInquiry(IAsyncResult ar)
        {
            // (Can't lock here as that would block the callback methods).
            // Check is one of queued ar.  However this function is only called from 
            // inside BluetoothClient.DiscoverDevices so we can be less careful/helpful!!
            AR_Inquiry ar2 = (AR_Inquiry)ar;
            return ar2.EndInvoke();
        }

        struct InquiryTimeoutParams
        {
            internal readonly IAsyncResult _ar;
            internal readonly TimeSpan _InquiryLength;

            public InquiryTimeoutParams(AR_Inquiry ar, TimeSpan inquiryLength)
            {
                _ar = ar;
                _InquiryLength = inquiryLength;
            }

            /// <summary>
            /// Get timeout value in Int32 milliseconds,
            /// as NETCF <c>WaitHandle.WaitOne</c> can't use TimeSpan.
            /// </summary>
            /// -
            /// <returns>An Int32 containing the timeout value in milliseconds.
            /// </returns>
            internal int InquiryLengthAsMiliseconds()
            {
                double ms0 = this._InquiryLength.TotalMilliseconds;
                int ms = checked((int)ms0);
                return ms;
            }
        }

        void _InquiryTimeoutRunner(object state)
        {
            InquiryTimeoutParams args = (InquiryTimeoutParams)state;
            bool completed = args._ar.AsyncWaitHandle.WaitOne(args.InquiryLengthAsMiliseconds(), false);
            if (completed)
                return;
            lock (lockInquiry) {
                if (args._ar.IsCompleted) // It won the race to enter the lock.
                    return;
                object arDD = m_arInquiry;
                // TO-DO What if its in the 'followers' list.
                if (arDD == null) // etc
                    return;
                if (arDD != args._ar)
                    return;
                HandleInquiryComplete_Internal(false, unchecked((ushort)-1));
                WidcommUtils.Trace_WriteLine("Cancelling Inquiry due to timeout.");
                Debug.Assert(m_arInquiry == null, "NOT m_arInquiry==null after (timed-out) completion.");
            }
        }

        //----------
        const int MaxNumberSdpRecords = 10;
        //
        object lockServiceDiscovery = new object();
        AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams> m_arServiceDiscovery;

        public IAsyncResult BeginServiceDiscovery(BluetoothAddress address, Guid serviceGuid, SdpSearchScope searchScope,
            AsyncCallback asyncCallback, Object state)
        {
            // Just in case the user modifies the original address!!!
            BluetoothAddress addr2 = (BluetoothAddress)address.Clone();
            AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams> ar
                = new AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams>(asyncCallback, state,
                    new ServiceDiscoveryParams(addr2, serviceGuid, searchScope));
            lock (lockServiceDiscovery) {
                if (m_arServiceDiscovery != null)
                    throw new NotSupportedException("Currently support only one concurrent Service Lookup operation.");
                bool success = false;
                try {
                    m_arServiceDiscovery = ar;
                    bool ret = m_btIf.StartDiscovery(addr2, serviceGuid);
                    if (!ret) {
                        WBtRc ee = GetExtendedError();
                        throw WidcommSocketExceptions.Create_StartDiscovery(ee);
                    }
                    success = true;
                } finally {
                    if (!success)
                        m_arServiceDiscovery = null;
                }
            }
            return ar;
        }

        public ISdpDiscoveryRecordsBuffer EndServiceDiscovery(IAsyncResult asyncResult)
        {
            AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams> checkTypeMatches = m_arServiceDiscovery;
            AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams> ar2
                = (AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams>)asyncResult;
            return ar2.EndInvoke();
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "will rethrow")]
        internal void HandleDiscoveryComplete()
        {
            EntryIsWidcommThread();
            WidcommUtils.Trace_WriteLine("HandleDiscoveryComplete");
            AsyncResult<ISdpDiscoveryRecordsBuffer, ServiceDiscoveryParams> sacAr = null;
            ISdpDiscoveryRecordsBuffer recBuf = null;
            Exception sacEx = null;
            try {
                lock (lockServiceDiscovery) {
                    Debug.Assert(m_arServiceDiscovery != null, "NOT m_arServiceDiscovery != null");
                    if (m_arServiceDiscovery == null) { return; } // Nothing we can do then!
                    sacAr = m_arServiceDiscovery;
                    m_arServiceDiscovery = null;
                    BluetoothAddress addr;
                    ushort numRecords0;
                    DISCOVERY_RESULT result = m_btIf.GetLastDiscoveryResult(out addr, out numRecords0);
                    if (result != DISCOVERY_RESULT.SUCCESS) {
                        sacEx = WidcommSocketExceptions.Create(result, "ServiceRecordsGetResult");
                        return;
                    }
                    if (!addr.Equals(sacAr.BeginParameters.address)) {
                        sacEx = new InvalidOperationException("Internal error -- different DiscoveryComplete address.");
                        return;
                    }
                    // Get the records
                    recBuf = m_btIf.ReadDiscoveryRecords(addr, MaxNumberSdpRecords,
                        sacAr.BeginParameters);
                }//lock
            } catch (Exception ex) {
                sacEx = ex;
            } finally {
                Debug.Assert(sacAr != null, "out: NOT sacAr != null");
                Debug.Assert(m_arServiceDiscovery == null, "out: NOT m_arServiceDiscovery == null");
                WaitCallback dlgt = delegate {
                    RaiseDiscoveryComplete(sacAr, recBuf, sacEx);
                };
                ThreadPool.QueueUserWorkItem(dlgt);
                ExitIsWidcommThread();
            }
        }

        static void RaiseDiscoveryComplete(
            AsyncResult<ISdpDiscoveryRecordsBuffer,ServiceDiscoveryParams> sacAr,
            ISdpDiscoveryRecordsBuffer recBuf, Exception sacEx)
        {
            if (sacAr != null) { // will always be true!
                if (sacEx != null) {
                    sacAr.SetAsCompleted(sacEx, false);
                } else {
                    sacAr.SetAsCompleted(recBuf, false);
                }
            }
        }

        //----------
        public List_IBluetoothDeviceInfo GetKnownRemoteDeviceEntries()
        {
            List<REM_DEV_INFO> list = new List<REM_DEV_INFO>();
            REM_DEV_INFO info = new REM_DEV_INFO();
            int cb = System.Runtime.InteropServices.Marshal.SizeOf(typeof(REM_DEV_INFO));
            IntPtr pBuf = System.Runtime.InteropServices.Marshal.AllocHGlobal(cb);
            try {
                REM_DEV_INFO_RETURN_CODE ret = m_btIf.GetRemoteDeviceInfo(ref info, pBuf, cb);
                WidcommUtils.Trace_WriteLine("GRDI: ret: {0}=0x{0:X}", ret);
                while (ret == REM_DEV_INFO_RETURN_CODE.SUCCESS) {
                    list.Add(info); // COPY it into the list
                    ret = m_btIf.GetNextRemoteDeviceInfo(ref info, pBuf, cb);
                    WidcommUtils.Trace_WriteLine("GnRDI: ret: {0}=0x{0:X}", ret);
                }//while
                if (ret != REM_DEV_INFO_RETURN_CODE.EOF)
                    throw WidcommSocketExceptions.Create(ret, "Get[Next]RemoteDeviceInfo");
                //
                List_IBluetoothDeviceInfo bdiList = new List_IBluetoothDeviceInfo(list.Count);
                foreach (REM_DEV_INFO cur in list) {
                    IBluetoothDeviceInfo bdi = WidcommBluetoothDeviceInfo.CreateFromStoredRemoteDeviceInfo(cur, m_factory);
                    bdiList.Add(bdi);
                }
                return bdiList;
            } finally {
                System.Runtime.InteropServices.Marshal.FreeHGlobal(pBuf);
            }
        }

        //----------
        const string DevicesRegPath = @"Software\WIDCOMM\BTConfig\Devices\"; // "HKEY_LOCAL_MACHINE\..."

        public List_IBluetoothDeviceInfo ReadKnownDevicesFromRegistry()
        {
            // Multiple keys, one per device, named with address e.g. 00:11:22:33:44:55
            // Each with values: BRCMStack DWORD, Code DWORD, DevClass DWORD, etc etc
            //
            List_IBluetoothDeviceInfo devices = new List_IBluetoothDeviceInfo();
            using (RegistryKey rkDevices = Registry.LocalMachine.OpenSubKey(DevicesRegPath)) {
                if (rkDevices == null) {
                    // The Registry key is created when the first device is stored, 
                    // so on a new device it doesn't exist. So return an empty list.
                    return devices;
                    // IOException is what GetValueKind throws.
                    //throw new System.IO.IOException("Widcomm 'Devices' key not found in the Registry.");
                }
                foreach (string itemName in rkDevices.GetSubKeyNames()) {
                    using (RegistryKey rkItem = rkDevices.OpenSubKey(itemName)) {
                        WidcommBluetoothDeviceInfo bdi = ReadDeviceFromRegistryAndCheckAndSetIfPaired_(
                            itemName, rkItem, m_factory);
                        devices.Add(bdi);
                    }
                }//for
            }
            return devices;
        }

        private WidcommBluetoothDeviceInfo ReadDeviceFromRegistryAndCheckAndSetIfPaired_(
            string itemName, RegistryKey rkItem, WidcommBluetoothFactoryBase factory)
        {
            BluetoothAddress address = BluetoothAddress.Parse(itemName);
            byte[] devName = Registry_ReadBinaryValue(rkItem, "Name");
            byte[] devClass = Registry_ReadBinaryValue(rkItem, "DevClass");
            Int32? trusted = Registry_ReadDwordValue_Optional(rkItem, "TrustedMask");
            WidcommBluetoothDeviceInfo bdi = CreateFromStoredRemoteDeviceInfo(address, devName, devClass, factory);
            WidcommBluetoothDeviceInfo.CheckAndSetIfPaired(bdi, factory);
            return bdi;
        }

        internal WidcommBluetoothDeviceInfo ReadDeviceFromRegistryAndCheckAndSetIfPaired(BluetoothAddress address,
            WidcommBluetoothFactoryBase factory)
        {
            using (RegistryKey rkDevices = Registry.LocalMachine.OpenSubKey(DevicesRegPath)) {
                if (rkDevices == null) {
                    // The Registry key is created when the first device is stored, 
                    // so on a new device it doesn't exist. So return an empty list.
                    return null;
                }
                string itemName = address.ToString("C");
                using (RegistryKey rkItem = rkDevices.OpenSubKey(itemName)) {
                    if (rkItem == null) {
                        return null;
                    }
                    WidcommBluetoothDeviceInfo bdi = ReadDeviceFromRegistryAndCheckAndSetIfPaired_(itemName, rkItem, factory);
                    return bdi;
                }
            }
        }

        private static WidcommBluetoothDeviceInfo CreateFromStoredRemoteDeviceInfo(
            BluetoothAddress devAddress, byte[] devName, byte[] devClass,
            WidcommBluetoothFactoryBase factory)
        {
            REM_DEV_INFO rdi = new REM_DEV_INFO();
            rdi.bda = WidcommUtils.FromBluetoothAddress(devAddress);
            rdi.bd_name = devName;
            rdi.dev_class = devClass;
            // rdi.b_connected = ...
            // rdi.b_paired = ...
            WidcommBluetoothDeviceInfo bdi = WidcommBluetoothDeviceInfo.CreateFromStoredRemoteDeviceInfo(rdi, factory);
            string nameStr = bdi.DeviceName;
            Debug.Assert(nameStr.Length == 0 || nameStr[nameStr.Length - 1] != 0, "null terminator!!");
            int idxDbg;
            Debug.Assert((idxDbg = nameStr.IndexOf((char)0)) == -1, "null terminator!! at: " + idxDbg);
            return bdi;
        }

        private static byte[] Registry_ReadBinaryValue(RegistryKey rkItem, string name)
        {
            Registry_CheckIsKind(rkItem, name, RegistryValueKind.Binary);
            byte[] raw = (byte[])rkItem.GetValue(name);
            return raw;
        }

        private static Int32? Registry_ReadDwordValue_Optional(RegistryKey rkItem, string name)
        {
            object val = rkItem.GetValue(name);
            if (val == null)
                return null;
            Registry_CheckIsKind(rkItem, name, RegistryValueKind.DWord);
            return (Int32)val;
        }

        private static void Registry_CheckIsKind(RegistryKey rkItem, string name, RegistryValueKind expectedKind)
        {
            if (PlatformVerification.IsMonoRuntime) {
                WidcommUtils.Trace_WriteLine("Skipping Registry_CheckIsKind check on Mono as it's not supported.");
                return;
            }
            RegistryValueKind kind = rkItem.GetValueKind(name);
            if (kind != expectedKind) {
                string msg = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                    "Expected '{0}':'{1}', to be '{2}' but was '{3}'.",
                    rkItem.Name, name, expectedKind, kind);
                throw new FormatException(msg);
            }
        }

        //----------
        internal bool GetLocalDeviceVersionInfo(ref DEV_VER_INFO m_dvi)
        {
            return m_btIf.GetLocalDeviceVersionInfo(ref m_dvi);
        }

        internal bool GetLocalDeviceInfoBdAddr(byte[] bdAddr)
        {
            return m_btIf.GetLocalDeviceInfoBdAddr(bdAddr);
        }

        internal bool GetLocalDeviceName(byte[] bdName)
        {
            return m_btIf.GetLocalDeviceName(bdName);
        }

        internal void IsStackUpAndRadioReady(out bool stackServerUp, out bool deviceReady)
        {
            m_btIf.IsStackUpAndRadioReady(out stackServerUp, out deviceReady);
        }

        internal void IsDeviceConnectableDiscoverable(out bool conno, out bool disco)
        {
            m_btIf.IsDeviceConnectableDiscoverable(out conno, out disco);
        }

        internal void SetDeviceConnectableDiscoverable(bool connectable, bool forPairedOnly, bool discoverable)
        {
            m_btIf.SetDeviceConnectableDiscoverable(connectable, forPairedOnly, discoverable);
        }

        internal int GetRssi(byte[] bd_addr)
        {
            return m_btIf.GetRssi(bd_addr);
        }

        internal bool BondQuery(byte[] bd_addr)
        {
            return m_btIf.BondQuery(bd_addr);
        }

        internal BOND_RETURN_CODE Bond(BluetoothAddress address, string passphrase)
        {
            return m_btIf.Bond(address, passphrase);
        }

        internal bool UnBond(BluetoothAddress address)
        {
            return m_btIf.UnBond(address);
        }

        //----------
        /// <summary>
        /// Call CBtIf::GetExtendedError.
        /// </summary>
        /// -
        /// <remarks>
        /// <para>Is not currently used anywhere...
        /// </para>
        /// <para>Not supported on Widcomm WCE WM/WinCE, we (natively) return -1.
        /// </para>
        /// </remarks>
        /// -
        /// <returns>A <see cref="T:InTheHand.Net.Bluetooth.Widcomm.WBtRc"/> value.</returns>
        private WBtRc GetExtendedError()
        {
            return m_btIf.GetExtendedError();
        }

        /// <summary>
        /// CBtIf::IsRemoteDevicePresent
        /// </summary>
        /// -
        /// <remarks>
        /// <note>"added BTW and SDK 5.0.1.1000"</note>
        /// <note>"added BTW-CE and SDK 1.7.1.2700"</note>
        /// </remarks>
        internal SDK_RETURN_CODE IsRemoteDevicePresent(byte[] bd_addr)
        {
            return m_btIf.IsRemoteDevicePresent(bd_addr);
        }

        /// <summary>
        /// CBtIf::IsRemoteDeviceConnected
        /// </summary>
        /// -
        /// <remarks>
        /// <note>"added BTW 5.0.1.300, SDK 5.0"</note>
        /// <note>"added BTW-CE and SDK 1.7.1.2700"</note>
        /// </remarks>
        internal bool IsRemoteDeviceConnected(byte[] bd_addr)
        {
            return m_btIf.IsRemoteDeviceConnected(bd_addr);
        }

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

        /// <summary>
        /// Mark that we're running on a thread provided from within the Widcomm API.
        /// </summary>
        /// -
        /// <remarks>
        /// <para>These annotations should be added at the concrete level of the
        /// stack and not at the swappable interface level, i.e. not at WidcommRfcommPort
        /// but at WidcommRfcommStream.  That's a bit further from the native callback
        /// method but it means that we can test this area in unit-tests where we
        /// use mock IRfcommPort etc.
        /// </para>
        /// </remarks>
        internal static void EntryIsWidcommThread()
        {
#if WIDCOMM_SINGLE_THREADING
            //if (IsWidcommThread) { // DEBUG
            //} else { // DEBUG
            //}
#if !NETCF
            checked { ++_InWidcommCallbackThreadCount; }
#else
            int v = GetStaticData<int>(_slotInWidcommCallbackThreadCount);
            checked { ++v; }
            Thread.SetData(_slotInWidcommCallbackThreadCount, v);
#endif
#endif
        }

        internal static void ExitIsWidcommThread()
        {
#if !NETCF
            checked { --_InWidcommCallbackThreadCount; }
            if (_InWidcommCallbackThreadCount < 0) {
                Debug.Fail("_InWidcommThreadCount exit became -ve: " + _InWidcommCallbackThreadCount);
                _InWidcommCallbackThreadCount = 0;
            }
#else
            int v = GetStaticData<int>(_slotInWidcommCallbackThreadCount);
            checked { --v; }
            if (v < 0) {
                Debug.Fail("_InWidcommThreadCount exit became -ve: " + v);
                v = 0;
            }
            Thread.SetData(_slotInWidcommCallbackThreadCount, v);
#endif
        }

        internal static bool IsWidcommCallbackThread
        {
            get
            {
#if !WIDCOMM_SINGLE_THREADING
                return false;
#else
#if !NETCF
                int c = _InWidcommCallbackThreadCount;
#endif
#if NETCF
                int c = GetStaticData<int>(_slotInWidcommCallbackThreadCount);
#endif
                bool flag = (c > 0);
                Debug.Assert(c >= 0, "NEG _InWidcommThreadCount!! is: " + c);
                if (flag) {
                    //WidcommUtils.Trace_WriteLine("(IsWidcommThread)");
                } else {
                    //WidcommUtils.Trace_WriteLine("(NOT IsWidcommThread)");
                }
                return flag;
#endif
            }
        }

        internal static void ReportIfWidcommThread(string name)
        {
#if WIDCOMM_SINGLE_THREADING
            if (!IsWidcommSingleThread) {
                WidcommUtils.Trace_WriteLine("NOT {0} on our Widcomm SINGLE thread!", name);
            }
            if (IsWidcommCallbackThread) {
                Debug.Assert(!IsWidcommSingleThread, "Does Widcomm use the main thread for callbacks!!??");
                WidcommUtils.Trace_WriteLine("{0} on Widcomm callback thread!", name);
            }
            if (IsWidcommSingleThread && IsWidcommCallbackThread) { // COVERAGE
            }
#endif
        }

#if WIDCOMM_SINGLE_THREADING
        public static bool IsWidcommSingleThread
        {
            get
            {
#if !NETCF
                return _IsWidcommSingleThread;
#else
                bool v = GetStaticData<bool>(_slotIsWidcommSingleThread);
                return v;
#endif
            }
            set
            {
#if !NETCF
                _IsWidcommSingleThread = value;
#else
                Thread.SetData(_slotIsWidcommSingleThread, value);
#endif
            }
        }

        static T GetStaticData<T>(LocalDataStoreSlot slot) where T : struct
        {
            object o = Thread.GetData(slot);
            T v = o == null ? default(T) : (T)o;
            return v;
        }
#endif

    }//class


    internal enum SdpSearchScope
    {
        Anywhere,
        ServiceClassOnly
    }


    sealed class ServiceDiscoveryParams
    {
        readonly internal BluetoothAddress address;
        readonly internal Guid serviceGuid;
        readonly internal SdpSearchScope searchScope;

        internal ServiceDiscoveryParams(BluetoothAddress address, Guid serviceGuid, SdpSearchScope searchScope)
        {
            this.address = address;
            this.serviceGuid = serviceGuid;
            if (searchScope != SdpSearchScope.Anywhere
                    && searchScope != SdpSearchScope.ServiceClassOnly)
                throw new ArgumentException("Unrecognized value for SdpSearchScope enum.", "searchScope");
            this.searchScope = searchScope;
        }
    }

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