// 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.Runtime.InteropServices;
using System.Diagnostics;
namespace InTheHand.Net.Bluetooth.Widcomm{
internal sealed class WidcommRfcommPort : IRfcommPort
{
internal static class NativeMethods
{
#if NETCF
internal const string WidcommDll = "32feetWidcomm"; //"wm2";
#else
internal const string WidcommDll = "32feetWidcomm"; //"32feetWidcommWin32";
#endif
internal delegate void RfcommPort_DataReceivedCallbackDelegate(IntPtr data, UInt16 len);
internal delegate void RfcommPort_EventReceivedCallbackDelegate(UInt32 data);
[DllImport(WidcommDll)]
internal static extern IntPtr RfcommPort_Create(out IntPtr ppRfcommPort,
RfcommPort_DataReceivedCallbackDelegate handleDataReceived,
RfcommPort_EventReceivedCallbackDelegate handleEvent);
[DllImport(WidcommDll)]
internal static extern void RfcommPort_Destroy(IntPtr pRfcommPort);
[DllImport(WidcommDll)]
internal static extern PORT_RETURN_CODE RfcommPort_OpenClient(IntPtr pRfcommPort, int scn, byte[] address);
[DllImport(WidcommDll)]
internal static extern PORT_RETURN_CODE RfcommPort_OpenServer(IntPtr pRfcommPort, int scn);
[DllImport(WidcommDll)]
internal static extern PORT_RETURN_CODE RfcommPort_Write(IntPtr pRfcommPort, byte[] p_data, UInt16 len_to_write, out UInt16 p_len_written);
[DllImport(WidcommDll)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool RfcommPort_IsConnected(IntPtr pObj, [Out] byte[] p_remote_bdaddr, int bufLen);
[DllImport(WidcommDll)]
internal static extern PORT_RETURN_CODE RfcommPort_Close(IntPtr pRfcommPort);
}
IntPtr m_pRfcommPort;
WidcommRfcommStream m_parent;
//
// Stop the delegates being GC'd, as the native code is calling their thunks.
NativeMethods.RfcommPort_DataReceivedCallbackDelegate m_handleDataReceived;
NativeMethods.RfcommPort_EventReceivedCallbackDelegate m_handleEvent;
public void SetParentStream(WidcommRfcommStream parent)
{
if (m_parent != null)
throw new InvalidOperationException("Can only have one parent.");
m_parent = parent;
}
public void Create()
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_Create");
m_handleDataReceived = HandleDataReceived;
m_handleEvent = HandleEventReceived;
NativeMethods.RfcommPort_Create(out m_pRfcommPort, m_handleDataReceived, m_handleEvent);
WidcommUtils.Trace_WriteLine("WidcommRfcommPort.Create'd: " + DebugId);
if (m_pRfcommPort == IntPtr.Zero)
throw new InvalidOperationException("Native object creation failed.");
}
public string DebugId
{
get
{
if (m_pRfcommPort == IntPtr.Zero)
throw new InvalidOperationException("Can't call get_DebugId before initialised.");
return m_pRfcommPort.ToInt64().ToString("X");
}
}
void HandleDataReceived(IntPtr buffer, UInt16 len)
{
WidcommUtils.Trace_WriteLine("HandleReceive: len: {0}", len);
byte[] arr = WidcommUtils.GetByteArray(buffer, len);
m_parent.HandlePortReceive(arr, this);
}
void HandleEventReceived(UInt32 eventId)
{
WidcommUtils.Trace_WriteLine("HandleEvent: {0}=0x{0:X}={1}", eventId, (PORT_EV)eventId);
m_parent.HandlePortEvent((PORT_EV)eventId, this);
}
public PORT_RETURN_CODE OpenClient(byte scn, byte[] address)
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_OpenClient");
if (scn < BluetoothEndPoint.MinScn || scn == 0xFF || scn > BluetoothEndPoint.MaxScn)
throw new ArgumentOutOfRangeException("scn", "Should be >0 and <31, is: " + scn + ".");
if (address == null || address.Length != 6)
throw new ArgumentException("Parameter 'address' must be non-null and six-bytes long.");
PORT_RETURN_CODE ret = NativeMethods.RfcommPort_OpenClient(m_pRfcommPort, scn, address);
WidcommUtils.Trace_WriteLine("NativeMethods.RfcommPort_OpenClient ret: {0}=0x{0:X}", ret);
return ret;
}
public PORT_RETURN_CODE OpenServer(byte scn)
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_OpenServer");
if (scn < BluetoothEndPoint.MinScn || scn == 0xFF || scn > BluetoothEndPoint.MaxScn)
throw new ArgumentOutOfRangeException("scn", "Should be >0 and <31, is: " + scn + ".");
PORT_RETURN_CODE ret = NativeMethods.RfcommPort_OpenServer(m_pRfcommPort, scn);
WidcommUtils.Trace_WriteLine("NativeMethods.RfcommPort_OpenServer ret: {0}=0x{0:X}", ret);
return ret;
}
public PORT_RETURN_CODE Write(byte[] data, ushort lenToWrite, out ushort lenWritten)
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_Write");
return NativeMethods.RfcommPort_Write(m_pRfcommPort, data, lenToWrite, out lenWritten);
}
public bool IsConnected(out BluetoothAddress p_remote_bdaddr)
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_IsConnected");
byte[] bdaddr = new byte[WidcommStructs.BD_ADDR_LEN];
bool ret = NativeMethods.RfcommPort_IsConnected(m_pRfcommPort, bdaddr, bdaddr.Length);
p_remote_bdaddr = WidcommUtils.ToBluetoothAddress(bdaddr);
return ret;
}
public PORT_RETURN_CODE Close()
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_Close");
return NativeMethods.RfcommPort_Close(m_pRfcommPort);
}
public void Destroy()
{
WidcommBtInterface.ReportIfWidcommThread("RfcommPort_Destroy");
Debug.Assert(m_pRfcommPort != IntPtr.Zero, "WidcommRfcommPort Already Destroyed");
if (m_pRfcommPort != IntPtr.Zero) {
NativeMethods.RfcommPort_Destroy(m_pRfcommPort);
m_pRfcommPort = IntPtr.Zero;
}
}
}
}
|