From 96c3309bf93b2a828053654e75e933b65500b343 Mon Sep 17 00:00:00 2001 From: Wootak Date: Thu, 20 Dec 2018 13:32:40 +0900 Subject: [PATCH] [Bluetooth] Add Bluetooth Internal APIs (#598) * Add Bluetooth Internal APIs * Deprecated wrong AcceptStateChangedEventArgs class property and DestroyServerSocket API * Add new SocketConnection class property --- .../Interop/Interop.Bluetooth.cs | 51 +++-- .../Tizen.Network.Bluetooth/BluetoothAdapter.cs | 74 ++++++++ .../BluetoothAdapterImpl.cs | 52 ++++++ .../Tizen.Network.Bluetooth/BluetoothAudio.cs | 81 ++++++++ .../Tizen.Network.Bluetooth/BluetoothAudioImpl.cs | 109 +++++++++++ .../Tizen.Network.Bluetooth/BluetoothData.cs | 18 ++ .../Tizen.Network.Bluetooth/BluetoothDevice.cs | 1 + .../Tizen.Network.Bluetooth/BluetoothEventArgs.cs | 68 ++++++- .../Tizen.Network.Bluetooth/BluetoothGatt.cs | 5 +- .../Tizen.Network.Bluetooth/BluetoothOpp.cs | 2 + .../BluetoothServerSocket.cs | 208 ++++++++++++++++++--- .../Tizen.Network.Bluetooth/BluetoothSocket.cs | 1 - .../Tizen.Network.Bluetooth/BluetoothStructs.cs | 8 + 13 files changed, 624 insertions(+), 54 deletions(-) diff --git a/src/Tizen.Network.Bluetooth/Interop/Interop.Bluetooth.cs b/src/Tizen.Network.Bluetooth/Interop/Interop.Bluetooth.cs index 9d2e737..be77f93 100755 --- a/src/Tizen.Network.Bluetooth/Interop/Interop.Bluetooth.cs +++ b/src/Tizen.Network.Bluetooth/Interop/Interop.Bluetooth.cs @@ -103,65 +103,58 @@ internal static partial class Interop [DllImport(Libraries.Bluetooth, EntryPoint = "bt_deinitialize")] internal static extern int Deinitialize(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_enable")] + internal static extern int EnableAdapter(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_disable")] + internal static extern int DisableAdapter(); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_name")] internal static extern int GetName(out string name); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_name")] internal static extern int SetName(string name); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_state")] internal static extern int GetState(out BluetoothState isActivated); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_address")] internal static extern int GetAddress(out string address); - + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_visibility")] + internal static extern int SetVisibility(VisibilityMode visibilityMode, int duration); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_visibility")] internal static extern int GetVisibility(out int visibility, out int duration); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_is_discovering")] internal static extern int IsDiscovering(out bool isDiscovering); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_start_device_discovery")] internal static extern int StartDiscovery(); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_stop_device_discovery")] internal static extern int StopDiscovery(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_foreach_bonded_device")] internal static extern int GetBondedDevices(BondedDeviceCallback bondedDeviceCb, IntPtr userData); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_bonded_device_info")] internal static extern int GetBondedDeviceByAddress(string deviceAddress, out IntPtr deviceInfo); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_free_device_info")] - internal static extern int FreeDeviceInfo(BluetoothDeviceStruct deviceInfo); - + internal static extern int FreeDeviceInfo(IntPtr deviceInfo); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_is_service_used")] internal static extern int IsServiceUsed(string serviceUuid, out bool used); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_get_local_oob_data")] internal static extern int GetOobData(out IntPtr hash, out IntPtr randomizer, out int hashLen, out int randomizerLen); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_remote_oob_data")] internal static extern int SetOobData(string deviceAddress, IntPtr hash, IntPtr randomizer, int hashLen, int randomizerLen); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_remove_remote_oob_data")] internal static extern int RemoveOobData(string deviceAddress); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_state_changed_cb")] internal static extern int SetStateChangedCallback(StateChangedCallback stateChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_unset_state_changed_cb")] internal static extern int UnsetStateChangedCallback(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_name_changed_cb")] internal static extern int SetNameChangedCallback(NameChangedCallback nameChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_unset_name_changed_cb")] internal static extern int UnsetNameChangedCallback(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_visibility_mode_changed_cb")] internal static extern int SetVisibilityModeChangedCallback(VisibilityModeChangedCallback visibilityChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_unset_visibility_mode_changed_cb")] internal static extern int UnsetVisibilityModeChangedCallback(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_visibility_duration_changed_cb")] internal static extern int SetVisibilityDurationChangedCallback(VisibilityDurationChangedCallback durationChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_unset_visibility_duration_changed_cb")] internal static extern int UnsetVisibilityDurationChangedCallback(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_set_device_discovery_state_changed_cb")] internal static extern int SetDiscoveryStateChangedCallback(DiscoveryStateChangedCallback discoveryChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_adapter_unset_device_discovery_state_changed_cb")] @@ -336,12 +329,21 @@ internal static partial class Interop bool connectable); //Bluetooth Socket + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SocketConnectionRequestedCallback(int socket_fd, string remoteAddress, IntPtr userData); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_create_rfcomm")] internal static extern int CreateServerSocket(string serviceUuid, out int socketFd); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_destroy_rfcomm")] internal static extern int DestroyServerSocket(int socketFd); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_listen_and_accept_rfcomm")] internal static extern int Listen(int socketFd, int pendingConnections); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_listen")] + internal static extern int ListenWithoutAccept(int socketFd, int pendingConnections); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_accept")] + internal static extern int Accept(int socketFd); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_reject")] + internal static extern int Reject(int socketFd); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_connect_rfcomm")] internal static extern int ConnectSocket(string address, string serviceUuid); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_disconnect_rfcomm")] @@ -356,22 +358,39 @@ internal static partial class Interop internal static extern int SetConnectionStateChangedCallback(SocketConnectionStateChangedCallback callback, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_unset_connection_state_changed_cb")] internal static extern int UnsetSocketConnectionStateChangedCallback(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_set_connection_requested_cb")] + internal static extern int SetSocketConnectionRequestedCallback(SocketConnectionRequestedCallback socketConnectionRequestedCb, IntPtr userData); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_socket_unset_connection_requested_cb")] + internal static extern int UnsetSocketConnectionRequestedCallback(); // Bluetooth Audio + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AgScoStateChangedCallback(int result, bool opened, IntPtr userData); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_initialize")] internal static extern int InitializeAudio(); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_deinitialize")] internal static extern int DeinitializeAudio(); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_connect")] internal static extern int Connect(string deviceAddress, int profileType); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_disconnect")] internal static extern int Disconnect(string deviceAddress, int profileType); - [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_set_connection_state_changed_cb")] internal static extern int SetAudioConnectionStateChangedCallback(AudioConnectionStateChangedCallback audioStateChangedCb, IntPtr userData); [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_unset_connection_state_changed_cb")] internal static extern int UnsetAudioConnectionStateChangedCallback(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_open_sco")] + internal static extern int OpenAgSco(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_close_sco")] + internal static extern int CloseAgSco(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_is_sco_opened")] + internal static extern int IsAgScoOpened(out bool opened); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_set_sco_state_changed_cb")] + internal static extern int SetAgScoStateChangedCallback(AgScoStateChangedCallback scoStateChangedCb, IntPtr userData); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_unset_sco_state_changed_cb")] + internal static extern int UnsetAgScoStateChangedCallback(); + [DllImport(Libraries.Bluetooth, EntryPoint = "bt_ag_notify_voice_recognition_state")] + internal static extern int NotifyAgVoiceRecognitionState(bool enable); // Bluetooth Hid [UnmanagedFunctionPointer(CallingConvention.Cdecl)] diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapter.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapter.cs index e82c7b9..b23b03a 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapter.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapter.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; namespace Tizen.Network.Bluetooth { @@ -372,6 +373,77 @@ namespace Tizen.Network.Bluetooth } /// + /// Enables the local Bluetooth adapter, asynchronously. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void Enable() + { + BluetoothAdapterImpl.Instance.Enable(); + } + + /// + /// Disables the local Bluetooth adapter, asynchronously. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void Disable() + { + BluetoothAdapterImpl.Instance.Disable(); + } + + /// + /// Enables the discoverable mode. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void EnableDiscoverable() + { + BluetoothAdapterImpl.Instance.SetVisibility(VisibilityMode.Discoverable, 0); + } + + /// + /// Enables the discoverable mode. + /// + /// 6 + /// The duration until the discoverable mode is to be disabled(in seconds). + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void EnableDiscoverable(int duration) + { + BluetoothAdapterImpl.Instance.SetVisibility(VisibilityMode.TimeLimitedDiscoverable, duration); + } + + /// + /// Disables the discoverable mode. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void DisableDiscoverable() + { + BluetoothAdapterImpl.Instance.SetVisibility(VisibilityMode.NonDiscoverable, 0); + } + + /// /// Starts the device discovery process. /// /// @@ -439,6 +511,7 @@ namespace Tizen.Network.Bluetooth /// The Bluetooth must be enabled. /// /// Information of the bonded BluetoothDeviceInfo object. + /// The remote device address. /// Thrown when the Bluetooth is not supported. /// Thrown when the Bluetooth is not enabled /// or reading the bonded device information fails. @@ -639,6 +712,7 @@ namespace Tizen.Network.Bluetooth /// Thrown when the Bluetooth is not enabled /// or the socket destroy error occurs. /// 3 + [Obsolete("Deprecated since API level 6. Please use Dispose() on BluetoothServerSocket.")] static public void DestroyServerSocket(BluetoothServerSocket socket) { if (IsBluetoothEnabled && Globals.IsInitialize) diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapterImpl.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapterImpl.cs index 14e2981..c5aaee3 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapterImpl.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAdapterImpl.cs @@ -396,6 +396,57 @@ namespace Tizen.Network.Bluetooth } } + internal void Enable() + { + if (Globals.IsInitialize) + { + int ret = Interop.Bluetooth.EnableAdapter(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to enable adapter, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized); + } + } + + internal void Disable() + { + if (IsBluetoothEnabled) + { + int ret = Interop.Bluetooth.DisableAdapter(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to disable adapter, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled); + } + } + + internal void SetVisibility(VisibilityMode mode, int timeout) + { + if (IsBluetoothEnabled) + { + int ret = Interop.Bluetooth.SetVisibility(mode, timeout); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to set visibility, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled); + } + } + internal void StartDiscovery() { int ret = Interop.Bluetooth.StartDiscovery(); @@ -448,6 +499,7 @@ namespace Tizen.Network.Bluetooth } BluetoothDeviceStruct device = (BluetoothDeviceStruct)Marshal.PtrToStructure(deviceInfo, typeof(BluetoothDeviceStruct)); + Interop.Bluetooth.FreeDeviceInfo(deviceInfo); return BluetoothUtils.ConvertStructToDeviceClass(device); } diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudio.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudio.cs index 8ff829d..8a20ab2 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudio.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudio.cs @@ -15,6 +15,7 @@ */ using System; +using System.ComponentModel; namespace Tizen.Network.Bluetooth { @@ -105,5 +106,85 @@ namespace Tizen.Network.Bluetooth BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled); } } + + /// + /// Opens a AG(Audio Gateway) SCO(Synchronous Connection Oriented link) to connected remote device, asynchronously. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/feature/network.bluetooth.audio.call + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void OpenAgSco() + { + BluetoothAudioImpl.Instance.OpenAgSco(); + } + + /// + /// Closes a AG(Audio Gateway) SCO(Synchronous Connection Oriented link) to connected remote device, asynchronously. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/feature/network.bluetooth.audio.call + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void CloseAgSco() + { + BluetoothAudioImpl.Instance.CloseAgSco(); + } + + /// + /// A property to check whether an opened AG(Audio Gateway) SCO(Synchronous Connection Oriented link) exists or not. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/feature/network.bluetooth.audio.call + [EditorBrowsable(EditorBrowsableState.Never)] + public static bool IsAgScoOpened + { + get + { + return BluetoothAudioImpl.Instance.IsAgScoOpened; + } + } + + /// + /// This event is called when the AG(Audio Gateway) SCO(Synchronous Connection Oriented link) state is changed. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/feature/network.bluetooth.audio.call + [EditorBrowsable(EditorBrowsableState.Never)] + public static event EventHandler AgScoStateChanged + { + add + { + BluetoothAudioImpl.Instance.AgScoStateChanged += value; + } + remove + { + BluetoothAudioImpl.Instance.AgScoStateChanged -= value; + } + } + + /// + /// Notifies the state of AG(Audio Gateway) voice recognition to connected remote device. + /// + /// The state of voice recognition. It is true if voice recognition state is enabled. + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/feature/network.bluetooth.audio.call + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public static void NotifyAgVoiceRecognitionState(bool enable) + { + BluetoothAudioImpl.Instance.NotifyAgVoiceRecognitionState(enable); + } } } diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudioImpl.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudioImpl.cs index 6570dc9..c536f90 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudioImpl.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothAudioImpl.cs @@ -21,6 +21,7 @@ namespace Tizen.Network.Bluetooth internal class BluetoothAudioImpl : IDisposable { private event EventHandler _audioConnectionChanged; + private event EventHandler _agScoStateChanged; private Interop.Bluetooth.AudioConnectionStateChangedCallback _audioConnectionChangedCallback; private static readonly BluetoothAudioImpl _instance = new BluetoothAudioImpl(); @@ -91,6 +92,114 @@ namespace Tizen.Network.Bluetooth return ret; } + internal void OpenAgSco() + { + if (Globals.IsAudioInitialize) + { + int ret = Interop.Bluetooth.OpenAgSco(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to open ag sco to remote device, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized); + } + } + + internal void CloseAgSco() + { + if (Globals.IsAudioInitialize) + { + int ret = Interop.Bluetooth.CloseAgSco(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to close ag sco to remote device, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized); + } + } + + internal bool IsAgScoOpened + { + get + { + bool isOpened; + int ret = Interop.Bluetooth.IsAgScoOpened(out isOpened); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to check whether an opened SCO exists or not., Error - " + (BluetoothError)ret); + } + return isOpened; + } + } + + internal event EventHandler AgScoStateChanged + { + add + { + if (_agScoStateChanged == null) + { + RegisterAgScoStateChangedEvent(); + } + _agScoStateChanged += value; + } + remove + { + _agScoStateChanged -= value; + if (_agScoStateChanged == null) + { + UnregisterAgScoStateChangedEvent(); + } + } + } + + private void RegisterAgScoStateChangedEvent() + { + Interop.Bluetooth.AgScoStateChangedCallback _agScoStateChangedCallback = (int result, bool opened, IntPtr userData) => + { + _agScoStateChanged?.Invoke(null, new AgScoStateChangedEventArgs(opened)); + }; + + int ret = Interop.Bluetooth.SetAgScoStateChangedCallback(_agScoStateChangedCallback, IntPtr.Zero); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to set ag sco state changed callback, Error - " + (BluetoothError)ret); + } + } + + private void UnregisterAgScoStateChangedEvent() + { + int ret = Interop.Bluetooth.UnsetAgScoStateChangedCallback(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to unset ag sco state changed callback, Error - " + (BluetoothError)ret); + } + } + + internal void NotifyAgVoiceRecognitionState(bool enable) + { + if (Globals.IsAudioInitialize) + { + int ret = Interop.Bluetooth.NotifyAgVoiceRecognitionState(enable); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to notify sco voice recognition state, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + else + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized); + } + } + internal static BluetoothAudioImpl Instance { get diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothData.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothData.cs index 6bf97b5..2c132b52 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothData.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothData.cs @@ -504,6 +504,7 @@ namespace Tizen.Network.Bluetooth internal string Uuid; internal string RemoteAddress; internal int Fd; + internal IBluetoothServerSocket ClientSocket; internal SocketConnection() { @@ -542,6 +543,23 @@ namespace Tizen.Network.Bluetooth return Uuid; } } + + internal int ServerFd + { + get; + set; + } + /// + /// The client socket. + /// + /// 6 + public IBluetoothServerSocket Client + { + get + { + return ClientSocket; + } + } } /// diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothDevice.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothDevice.cs index 34894a0..f40c7c8 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothDevice.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothDevice.cs @@ -676,6 +676,7 @@ namespace Tizen.Network.Bluetooth /// /// The Bluetooth must be enabled. /// + /// The profile instance. /// 3 public T GetProfile() where T : BluetoothProfile { diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEventArgs.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEventArgs.cs index d3288e8..ebfa544 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEventArgs.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEventArgs.cs @@ -552,6 +552,7 @@ namespace Tizen.Network.Bluetooth /// The server socket instance. /// /// 3 + [Obsolete("Deprecated since API level 6. Please use the 'Client' in the SocketConnection.")] public IBluetoothServerSocket Server { get @@ -562,6 +563,40 @@ namespace Tizen.Network.Bluetooth } /// + /// An extended EventArgs class contains the socket connection requested. + /// + /// 6 + [EditorBrowsable(EditorBrowsableState.Never)] + public class SocketConnectionRequestedEventArgs : EventArgs + { + internal SocketConnectionRequestedEventArgs(int socketFd, string remoteAddress) + { + SocketFd = socketFd; + RemoteAddress = remoteAddress; + } + + /// + /// The socket fd. + /// + /// 6 + internal int SocketFd + { + get; + private set; + } + + /// + /// The remote address. + /// + /// 6 + public string RemoteAddress + { + get; + private set; + } + } + + /// /// An extended EventArgs class contains the connection state, remote address, and the type of audio profile. /// /// 3 @@ -632,6 +667,29 @@ namespace Tizen.Network.Bluetooth /// /// An extended EventArgs class contains the connection state and the address of the remote Bluetooth device. /// + /// 6 + [EditorBrowsable(EditorBrowsableState.Never)] + public class AgScoStateChangedEventArgs : EventArgs + { + internal AgScoStateChangedEventArgs(bool isOpened) + { + IsOpened = isOpened; + } + + /// + /// A value indicating whether the state is connected. + /// + /// 6 + public bool IsOpened + { + get; + private set; + } + } + + /// + /// An extended EventArgs class contains the connection state and the address of the remote Bluetooth device. + /// /// 3 public class HidConnectionStateChangedEventArgs : EventArgs { @@ -1350,11 +1408,10 @@ namespace Tizen.Network.Bluetooth } } - /// + /// /// An extended EventArgs class which contains the Push Request respond state - /// + /// /// 4 - public class PushRespondedEventArgs : EventArgs { int _result; @@ -1445,11 +1502,10 @@ namespace Tizen.Network.Bluetooth } } - /// + /// /// An extended EventArgs class which contains the Push Request respond state - /// + /// /// 4 - public class PushFinishedEventArgs : EventArgs { int _result; diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothGatt.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothGatt.cs index 4d6f2d5..36e0314 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothGatt.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothGatt.cs @@ -54,7 +54,7 @@ namespace Tizen.Network.Bluetooth /// /// Creates the Bluetooth GATT server. /// - /// + /// The BluetoothGattServer instance. /// Thrown when the BT/BTLE is not supported. /// Thrown when the create GATT server fails. /// 3 @@ -158,6 +158,7 @@ namespace Tizen.Network.Bluetooth /// /// The characteristic whose the value is changed. /// The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled. + /// true on success, false otherwise. /// Thrown when the BT/BTLE is not enabled /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled. /// 3 @@ -943,7 +944,7 @@ namespace Tizen.Network.Bluetooth /// /// Returns a string value at the specified offset. /// - /// + /// An offset in the attribute value buffer. /// The string value at specified offset. /// 3 public string GetValue(int offset) diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothOpp.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothOpp.cs index 5a4a379..d3b76a0 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothOpp.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothOpp.cs @@ -92,6 +92,7 @@ namespace Tizen.Network.Bluetooth /// The device must be bonded with remote device by CreateBond(). /// If connection request is received from OPP Client, ConnectionRequested event will be invoked. /// + /// The BluetoothOppServer instance. /// Path to store the files. /// http://tizen.org/feature/network.bluetooth.opp /// Thrown when the required feature is not Supported. @@ -156,6 +157,7 @@ namespace Tizen.Network.Bluetooth /// /// Accept File Push request. /// + /// The id of transfer. /// File name to accept. /// http://tizen.org/feature/network.bluetooth.opp /// Thrown when the required feature is not Supported. diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothServerSocket.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothServerSocket.cs index 8601ac9..22aadec 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothServerSocket.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothServerSocket.cs @@ -17,6 +17,8 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Threading.Tasks; namespace Tizen.Network.Bluetooth { @@ -26,18 +28,58 @@ namespace Tizen.Network.Bluetooth /// 3 public class BluetoothServerSocket : IDisposable { - private event EventHandler _acceptStateChanged; - private Interop.Bluetooth.SocketConnectionStateChangedCallback _connectionStateChangedCallback; + private static event EventHandler _acceptStateChanged; + private static event EventHandler _connectionRequested; + private static Interop.Bluetooth.SocketConnectionStateChangedCallback _connectionStateChangedCallback; + private static Interop.Bluetooth.SocketConnectionRequestedCallback _connectionRequestedCallback; + private TaskCompletionSource _taskForAccept; internal int socketFd; private bool disposed = false; + internal BluetoothServerSocket() + { + StaticAcceptStateChanged += OnAcceptStateChanged; + StaticConnectionRequested += OnConnectionRequested; + } + + private void OnConnectionRequested(Object s, SocketConnectionRequestedEventArgs e) + { + if (e.SocketFd == socketFd) + { + ConnectionRequested?.Invoke(this, e); + } + } + + private void OnAcceptStateChanged(Object s, AcceptStateChangedEventArgs e) + { + if (e.Connection.ServerFd == socketFd) + { + if (_taskForAccept != null && !_taskForAccept.Task.IsCompleted) + { + if (e.State == BluetoothSocketState.Connected) + { + _taskForAccept.SetResult(e.Connection); + } + else + { + _taskForAccept.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result)); + } + _taskForAccept = null; + } + + AcceptStateChanged?.Invoke(this, e); + } + } + /// /// The AcceptStateChanged event is raised when the socket connection state is changed. /// /// Thrown when the Bluetooth is not enabled /// or when the register accpet state changed callback fails. /// 3 - public event EventHandler AcceptStateChanged + public event EventHandler AcceptStateChanged; + + private static event EventHandler StaticAcceptStateChanged { add { @@ -57,22 +99,19 @@ namespace Tizen.Network.Bluetooth } } - private void RegisterAcceptStateChangedEvent() + private static void RegisterAcceptStateChangedEvent() { _connectionStateChangedCallback = (int result, BluetoothSocketState connectionState, ref SocketConnectionStruct socketConnection, IntPtr userData) => { Log.Info(Globals.LogTag, "AcceptStateChanged cb is called"); - if (_acceptStateChanged != null) - { - BluetoothSocket socket = new BluetoothSocket(); - socket.connectedSocket = socketConnection.SocketFd; - GCHandle handle2 = (GCHandle) userData; - _acceptStateChanged(handle2.Target as BluetoothServerSocket, new AcceptStateChangedEventArgs((BluetoothError)result, connectionState, BluetoothUtils.ConvertStructToSocketConnection(socketConnection), socket)); - } + BluetoothSocket socket = new BluetoothSocket(); + socket.connectedSocket = socketConnection.SocketFd; + socket.remoteAddress = socketConnection.Address; + socket.serviceUuid = socketConnection.ServiceUuid; + _acceptStateChanged?.Invoke(null, new AcceptStateChangedEventArgs((BluetoothError)result, connectionState, BluetoothUtils.ConvertStructToSocketConnection(socketConnection), socket)); }; - GCHandle handle1 = GCHandle.Alloc(this); - IntPtr data = (IntPtr) handle1; - int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionStateChangedCallback, data); + + int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionStateChangedCallback, IntPtr.Zero); if (ret != (int)BluetoothError.None) { Log.Error(Globals.LogTag, "Failed to set accept state changed callback, Error - " + (BluetoothError)ret); @@ -80,7 +119,7 @@ namespace Tizen.Network.Bluetooth } } - private void UnregisterAcceptStateChangedEvent() + private static void UnregisterAcceptStateChangedEvent() { int ret = Interop.Bluetooth.UnsetSocketConnectionStateChangedCallback(); if (ret != (int)BluetoothError.None) @@ -116,7 +155,126 @@ namespace Tizen.Network.Bluetooth } /// - /// BluetoothServerSocket distructor. + /// Starts listening on the passed RFCOMM socket without accepting connection requests. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public void ListenWithoutAccept() + { + int ret = Interop.Bluetooth.ListenWithoutAccept(socketFd, 1); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to ListenWithoutAccept, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + + /// + /// Accepts a connection request asynchronously. + /// + /// 6 + /// A task indicating whether the method is done or not. + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public Task AcceptAsync() + { + if (_taskForAccept != null && !_taskForAccept.Task.IsCompleted) + { + BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress); + } + _taskForAccept = new TaskCompletionSource(); + + int ret = Interop.Bluetooth.Accept(socketFd); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to accept connection, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + return _taskForAccept.Task; + } + + /// + /// Rejects a connection request. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + /// http://tizen.org/privilege/bluetooth.admin + /// Thrown when the Bluetooth is not supported. + /// Thrown when the method is failed with message. + [EditorBrowsable(EditorBrowsableState.Never)] + public void Reject() + { + int ret = Interop.Bluetooth.Reject(socketFd); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to reject connection, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + + /// + /// Registers a callback function that will be invoked when a RFCOMM connection is requested. + /// + /// 6 + /// http://tizen.org/feature/network.bluetooth + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler ConnectionRequested; + + private static event EventHandler StaticConnectionRequested + { + add + { + if (_connectionRequested == null) + { + RegisterConnectionRequestedEvent(); + } + _connectionRequested += value; + } + remove + { + _connectionRequested -= value; + if (_connectionRequested == null) + { + UnregisterConnectionRequestedEvent(); + } + } + } + + private static void RegisterConnectionRequestedEvent() + { + _connectionRequestedCallback = (int socketFd, string remoteAddress, IntPtr userData) => + { + Log.Info(Globals.LogTag, "SocketConnectionRequestedCallback is called"); + _connectionRequested?.Invoke(null, new SocketConnectionRequestedEventArgs(socketFd, remoteAddress)); + }; + + int ret = Interop.Bluetooth.SetSocketConnectionRequestedCallback(_connectionRequestedCallback, IntPtr.Zero); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to set connection requested callback, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + + private static void UnregisterConnectionRequestedEvent() + { + int ret = Interop.Bluetooth.UnsetSocketConnectionRequestedCallback(); + if (ret != (int)BluetoothError.None) + { + Log.Error(Globals.LogTag, "Failed to unset connection requested callback, Error - " + (BluetoothError)ret); + BluetoothErrorFactory.ThrowBluetoothException(ret); + } + } + + /// + /// BluetoothServerSocket destructor. /// ~BluetoothServerSocket() { @@ -138,22 +296,14 @@ namespace Tizen.Network.Bluetooth if (disposed) return; - if (disposing) + int ret = Interop.Bluetooth.DestroyServerSocket(socketFd); + if (ret != (int)BluetoothError.None) { - // Free managed objects. + Log.Error(Globals.LogTag, "Failed to destroy socket, Error - " + (BluetoothError)ret); } - //Free unmanaged objects - RemoveRegisteredEvents(); + StaticAcceptStateChanged -= OnAcceptStateChanged; + StaticConnectionRequested -= OnConnectionRequested; disposed = true; } - - private void RemoveRegisteredEvents() - { - //unregister all remaining events when this object is released. - if (_acceptStateChanged != null) - { - UnregisterAcceptStateChangedEvent(); - } - } } } diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothSocket.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothSocket.cs index 35b8ba1..fc3ceb8 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothSocket.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothSocket.cs @@ -48,7 +48,6 @@ namespace Tizen.Network.Bluetooth /// The connection must be established. /// /// The data to be sent. - /// /// 3 int SendData(string data); } diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothStructs.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothStructs.cs index 55cb1d1..454d675 100644 --- a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothStructs.cs +++ b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothStructs.cs @@ -397,6 +397,14 @@ namespace Tizen.Network.Bluetooth connectionInfo.Fd = structInfo.SocketFd; connectionInfo.RemoteAddress = structInfo.Address; connectionInfo.Uuid = structInfo.ServiceUuid; + connectionInfo.ServerFd = structInfo.ServerFd; + + BluetoothSocket clientSocket = new BluetoothSocket(); + clientSocket.connectedSocket = structInfo.SocketFd; + clientSocket.remoteAddress = structInfo.Address; + clientSocket.serviceUuid = structInfo.ServiceUuid; + connectionInfo.ClientSocket = (IBluetoothServerSocket)clientSocket; + return connectionInfo; } } -- 2.7.4