Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ void DidDiscoverPeripheral(CBCentralManager central, CBPeripheral peripheral, in
void DidUpdateState(CBCentralManager central);
}

internal interface INativeCentralManagerDelegate
{
void DidConnect(string peripheralId) { }
void DidDisconnectPeripheral(string peripheralId, CBError error) { }
void DidFailToConnect(string peripheralId, CBError error) { }
void DidDiscoverPeripheral(SafeNativePeripheralHandle peripheral, int rssi) { }
void DidUpdateState(CBManagerState state) { }
}

/// <summary>
/// An object that scans for, discovers, connects to, and manages peripherals.
/// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager
Expand Down Expand Up @@ -189,6 +198,7 @@ public void Dispose()
{
if (_disposed) return;

_nativeCentralManagerProxy?.Dispose();
_handle?.Dispose();
foreach (var peripheral in _peripherals.Values)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ void DidUpdateName(CBPeripheral peripheral) { }
void DidModifyServices(CBPeripheral peripheral, CBService[] services) { }
}

internal interface INativePeripheralDelegate
{
void DidDiscoverServices(string[] serviceUUIDs, CBError error) { }
void DidDiscoverCharacteristics(string serviceUUID, string[] characteristicUUIDs, CBError error) { }
void DidUpdateValueForCharacteristic(string serviceUUID, string characteristicUUID, byte[] data, CBError error) { }
void DidWriteValueForCharacteristic(string serviceUUID, string characteristicUUID, CBError error) { }
void IsReadyToSendWriteWithoutResponse() { }
void DidUpdateNotificationStateForCharacteristic(string serviceUUID, string characteristicUUID, bool enabled, CBError error) { }
void DidReadRSSI(int rssi, CBError error) { }
void DidUpdateName() { }
void DidModifyServices(string[] invalidatedServiceUUIDs) { }
}

/// <summary>
/// A remote peripheral device.
/// https://developer.apple.com/documentation/corebluetooth/cbperipheral
Expand Down Expand Up @@ -315,6 +328,7 @@ public void Dispose()
{
if (_disposed) return;

_nativePeripheral?.Dispose();
Handle?.Dispose();

_disposed = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ void DidReceiveReadRequest(CBPeripheralManager peripheral, CBATTRequest request)
void DidReceiveWriteRequests(CBPeripheralManager peripheral, CBATTRequest[] requests) { }
}

internal interface INativePeripheralManagerDelegate
{
void DidUpdateState(CBManagerState state) { }
void DidAddService(string serviceUUID, CBError error) { }
void DidStartAdvertising(CBError error) { }
void DidSubscribeToCharacteristic(SafeNativeCentralHandle central, string serviceUUID, string characteristicUUID) { }
void DidUnsubscribeFromCharacteristic(SafeNativeCentralHandle central, string serviceUUID, string characteristicUUID) { }
void IsReadyToUpdateSubscribers() { }
void DidReceiveReadRequest(SafeNativeATTRequestHandle request) { }
void DidReceiveWriteRequests(SafeNativeATTRequestsHandle requests) { }
}

internal interface IPeripheralManagerData
{
void AddCentral(CBCentral central);
Expand Down Expand Up @@ -283,6 +295,7 @@ public void Dispose()
{
if (_disposed) return;

_nativePeripheralManagerProxy.Dispose();
_handle?.Dispose();
foreach (var central in _centrals.Values)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;

namespace CoreBluetooth
{
internal class NativeCentralManagerProxy
internal class NativeCentralManagerProxy : IDisposable
{
readonly static Dictionary<IntPtr, INativeCentralManagerDelegate> s_centralManagerDelegateMap = new Dictionary<IntPtr, INativeCentralManagerDelegate>();

readonly SafeNativeCentralManagerHandle _handle;

public NativeCentralManagerProxy(SafeNativeCentralManagerHandle handle, INativeCentralManagerDelegate centralManagerDelegate)
{
_handle = handle;
_handle.SetDelegate(centralManagerDelegate);
if (centralManagerDelegate != null)
{
s_centralManagerDelegateMap[handle.DangerousGetHandle()] = centralManagerDelegate;
}
RegisterHandlers();
}

public void Connect(CBPeripheral peripheral)
Expand Down Expand Up @@ -52,5 +61,66 @@ public bool IsScanning()
{
return NativeMethods.cb4u_central_manager_is_scanning(_handle);
}

void RegisterHandlers()
{
NativeMethods.cb4u_central_manager_register_handlers(
_handle,
DidConnect,
DidDisconnectPeripheral,
DidFailToConnect,
DidDiscoverPeripheral,
DidUpdateState
);
}

public void Dispose()
{
s_centralManagerDelegateMap.Remove(_handle.DangerousGetHandle());
}

static INativeCentralManagerDelegate GetDelegate(IntPtr centralPtr)
{
return s_centralManagerDelegateMap.GetValueOrDefault(centralPtr);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UCentralManagerDidConnectHandler))]
internal static void DidConnect(IntPtr centralPtr, IntPtr peripheralIdPtr)
{
GetDelegate(centralPtr)?.DidConnect(Marshal.PtrToStringUTF8(peripheralIdPtr));
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UCentralManagerDidDisconnectPeripheralHandler))]
public static void DidDisconnectPeripheral(IntPtr centralPtr, IntPtr peripheralIdPtr, int errorCode)
{
GetDelegate(centralPtr)?.DidDisconnectPeripheral(
Marshal.PtrToStringUTF8(peripheralIdPtr),
CBError.CreateOrNullFromCode(errorCode)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UCentralManagerDidFailToConnectHandler))]
public static void DidFailToConnect(IntPtr centralPtr, IntPtr peripheralIdPtr, int errorCode)
{
GetDelegate(centralPtr)?.DidFailToConnect(
Marshal.PtrToStringUTF8(peripheralIdPtr),
CBError.CreateOrNullFromCode(errorCode)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UCentralManagerDidDiscoverPeripheralHandler))]
public static void DidDiscoverPeripheral(IntPtr centralPtr, IntPtr peripheralPtr, int rssi)
{
GetDelegate(centralPtr)?.DidDiscoverPeripheral(
new SafeNativePeripheralHandle(peripheralPtr),
rssi
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UCentralManagerDidUpdateStateHandler))]
public static void DidUpdateState(IntPtr centralPtr, CBManagerState state)
{
GetDelegate(centralPtr)?.DidUpdateState(state);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace CoreBluetooth
{
internal class NativePeripheralManagerProxy
internal class NativePeripheralManagerProxy : IDisposable
{
static Dictionary<IntPtr, INativePeripheralManagerDelegate> s_peripheralManagerDelegateMap = new Dictionary<IntPtr, INativePeripheralManagerDelegate>();

readonly SafeNativePeripheralManagerHandle _handle;

internal NativePeripheralManagerProxy(SafeNativePeripheralManagerHandle handle, INativePeripheralManagerDelegate peripheralManagerDelegate)
{
_handle = handle;
_handle.SetDelegate(peripheralManagerDelegate);
if (peripheralManagerDelegate != null)
{
s_peripheralManagerDelegateMap[handle.DangerousGetHandle()] = peripheralManagerDelegate;
}

RegisterHandlers();
}

internal void AddService(SafeNativeMutableServiceHandle service)
Expand Down Expand Up @@ -90,5 +99,93 @@ internal void RespondToRequest(CBATTRequest request, CBATTError result)
{
NativeMethods.cb4u_peripheral_manager_respond_to_request(_handle, request.Handle, (int)result);
}

void RegisterHandlers()
{
NativeMethods.cb4u_peripheral_manager_register_handlers(
_handle,
DidUpdateState,
DidAddService,
DidStartAdvertising,
DidSubscribeToCharacteristic,
DidUnsubscribeFromCharacteristic,
IsReadyToUpdateSubscribers,
DidReceiveReadRequest,
DidReceiveWriteRequests
);
}

public void Dispose()
{
s_peripheralManagerDelegateMap.Remove(_handle.DangerousGetHandle());
}

static INativePeripheralManagerDelegate GetDelegate(IntPtr peripheralPtr)
{
return s_peripheralManagerDelegateMap.GetValueOrDefault(peripheralPtr);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidUpdateStateHandler))]
public static void DidUpdateState(IntPtr peripheralPtr, CBManagerState state)
{
GetDelegate(peripheralPtr)?.DidUpdateState(state);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidAddServiceHandler))]
public static void DidAddService(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, int errorCode)
{
GetDelegate(peripheralPtr)?.DidAddService(
Marshal.PtrToStringUTF8(serviceUUIDPtr),
CBError.CreateOrNullFromCode(errorCode)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidStartAdvertisingHandler))]
public static void DidStartAdvertising(IntPtr peripheralPtr, int errorCode)
{
GetDelegate(peripheralPtr)?.DidStartAdvertising(CBError.CreateOrNullFromCode(errorCode));
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidSubscribeToCharacteristicHandler))]
public static void DidSubscribeToCharacteristic(IntPtr peripheralPtr, IntPtr centralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr)
{
GetDelegate(peripheralPtr)?.DidSubscribeToCharacteristic(
new SafeNativeCentralHandle(centralPtr),
Marshal.PtrToStringUTF8(serviceUUIDPtr),
Marshal.PtrToStringUTF8(characteristicUUIDPtr)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidUnsubscribeFromCharacteristicHandler))]
public static void DidUnsubscribeFromCharacteristic(IntPtr peripheralPtr, IntPtr centralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr)
{
GetDelegate(peripheralPtr)?.DidUnsubscribeFromCharacteristic(
new SafeNativeCentralHandle(centralPtr),
Marshal.PtrToStringUTF8(serviceUUIDPtr),
Marshal.PtrToStringUTF8(characteristicUUIDPtr)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerIsReadyToUpdateSubscribersHandler))]
public static void IsReadyToUpdateSubscribers(IntPtr peripheralPtr)
{
GetDelegate(peripheralPtr)?.IsReadyToUpdateSubscribers();
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidReceiveReadRequestHandler))]
public static void DidReceiveReadRequest(IntPtr peripheralPtr, IntPtr requestPtr)
{
GetDelegate(peripheralPtr)?.DidReceiveReadRequest(
new SafeNativeATTRequestHandle(requestPtr)
);
}

[AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralManagerDidReceiveWriteRequestsHandler))]
public static void DidReceiveWriteRequests(IntPtr peripheralPtr, IntPtr requestsPtr)
{
GetDelegate(peripheralPtr)?.DidReceiveWriteRequests(
new SafeNativeATTRequestsHandle(requestsPtr)
);
}
}
}
Loading