// 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
};
}
|