2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
21 namespace Tizen.Network.Bluetooth
24 /// The IBluetoothServerSocket interface handles the server socket operations.
26 public interface IBluetoothServerSocket
29 /// Event handler to receive data over bluetooth socket.
30 /// This event occurs when the socket server receives data from the client.
32 event EventHandler<SocketDataReceivedEventArgs> DataReceived;
35 /// Event handler method to receive bluetooth socket connection state changed events.
36 /// This event occurs when the connection state between two devices is changed.
38 event EventHandler<SocketConnectionStateChangedEventArgs> ConnectionStateChanged;
41 /// Method to send data over bluetooth socket
43 /// <returns>The number of bytes written (zero indicates nothing was written).</returns>
45 /// The connection must be established.
47 /// <param name="data">The data to be sent.</param>
48 /// <returns></returns>
49 int SendData(string data);
53 /// The IBluetoothClientSocket interface handles the client socket operations.
55 public interface IBluetoothClientSocket : IBluetoothServerSocket
58 /// Connect client socket to server socket on remote device.
63 /// Disconnect client socket from server socket.
68 internal class BluetoothSocket : IBluetoothClientSocket, IDisposable
70 private event EventHandler<SocketDataReceivedEventArgs> _dataReceived;
71 private event EventHandler<SocketConnectionStateChangedEventArgs> _connectionStateChanged;
72 private Interop.Bluetooth.DataReceivedCallback _dataReceivedCallback;
73 private Interop.Bluetooth.SocketConnectionStateChangedCallback _connectionStateChangedCallback;
74 private bool disposed = false;
75 internal int connectedSocket;
76 internal string remoteAddress;
77 internal string serviceUuid;
80 /// This event occurs when the socket server receives data from the client.
82 /// <exception cref="InvalidOperationException">Thrown when the Bluetooth is not enabled
83 /// or when the register data received callback fails.</exception>
84 public event EventHandler<SocketDataReceivedEventArgs> DataReceived
88 if (_dataReceived == null)
90 RegisterDataReceivedEvent();
92 _dataReceived += value;
96 _dataReceived -= value;
97 if (_dataReceived == null)
99 UnregisterDataReceivedEvent();
105 /// This event occurs when the connection state between two devices is changed.
107 /// <exception cref="InvalidOperationException">Thrown when the Bluetooth is not enabled
108 /// or when the register connection changed callback fails.</exception>
109 public event EventHandler<SocketConnectionStateChangedEventArgs> ConnectionStateChanged
113 if (_connectionStateChanged == null)
115 RegisterConnectionStateChangedEvent();
117 _connectionStateChanged += value;
121 _connectionStateChanged -= value;
122 if (_connectionStateChanged == null)
124 UnregisterConnectionStateChangedEvent();
129 private void RegisterDataReceivedEvent()
131 _dataReceivedCallback = (ref SocketDataStruct socketData, IntPtr userData) =>
133 Log.Info(Globals.LogTag, "DataReceivedCallback is called");
134 if (_dataReceived != null)
136 GCHandle handle2 = (GCHandle) userData;
137 _dataReceived(handle2.Target as IBluetoothServerSocket, new SocketDataReceivedEventArgs(BluetoothUtils.ConvertStructToSocketData(socketData)));
140 GCHandle handle1 = GCHandle.Alloc (this);
141 IntPtr uData = (IntPtr) handle1;
142 int ret = Interop.Bluetooth.SetDataReceivedCallback(_dataReceivedCallback, uData);
143 if (ret != (int)BluetoothError.None)
145 Log.Error(Globals.LogTag, "Failed to set data received callback, Error - " + (BluetoothError)ret);
146 BluetoothErrorFactory.ThrowBluetoothException(ret);
150 private void UnregisterDataReceivedEvent()
152 int ret = Interop.Bluetooth.UnsetDataReceivedCallback();
153 if (ret != (int)BluetoothError.None)
155 Log.Error(Globals.LogTag, "Failed to unset data received callback, Error - " + (BluetoothError)ret);
156 BluetoothErrorFactory.ThrowBluetoothException(ret);
160 private void RegisterConnectionStateChangedEvent()
162 _connectionStateChangedCallback = (int result, BluetoothSocketState connectionState, ref SocketConnectionStruct socketConnection, IntPtr userData) =>
164 Log.Info(Globals.LogTag, "ConnectionStateChangedCallback is called");
165 if (_connectionStateChanged != null)
167 connectedSocket = socketConnection.SocketFd;
168 GCHandle handle2 = (GCHandle) userData;
169 _connectionStateChanged(handle2.Target as IBluetoothServerSocket, new SocketConnectionStateChangedEventArgs((BluetoothError)result, connectionState, BluetoothUtils.ConvertStructToSocketConnection(socketConnection)));
172 GCHandle handle1 = GCHandle.Alloc(this);
173 IntPtr data = (IntPtr) handle1;
174 int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionStateChangedCallback, data);
175 if (ret != (int)BluetoothError.None)
177 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
178 BluetoothErrorFactory.ThrowBluetoothException(ret);
182 private void UnregisterConnectionStateChangedEvent()
184 int ret = Interop.Bluetooth.UnsetSocketConnectionStateChangedCallback();
185 if (ret != (int)BluetoothError.None)
187 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
188 BluetoothErrorFactory.ThrowBluetoothException(ret);
193 /// Connects to a specific RFCOMM based service on a remote Bluetooth device UUID.
196 /// The bluetooth must be enabled, discoverable with StartDiscovery(), and bonded with the remote device using CreateBond(). The ConnectionStateChanged event is raised once this API is called.
198 /// <exception cref="InvalidOperationException">Thrown when the Bluetooth is not enabled
199 /// or when the connect socket attempt to remote device fails, or when the service UUID is not supported by the remote device.</exception>
200 void IBluetoothClientSocket.Connect()
202 int ret = Interop.Bluetooth.ConnectSocket(remoteAddress, serviceUuid);
203 if (ret != (int)BluetoothError.None)
205 Log.Error(Globals.LogTag, "Failed to connect to socket, Error - " + (BluetoothError)ret);
206 BluetoothErrorFactory.ThrowBluetoothException(ret);
211 /// Disconnects the RFCOMM connection with the given file descriptor of the conneted socket.
214 /// The connection must be established.
216 /// <exception cref="InvalidOperationException">Thrown when the Bluetooth is not enabled
217 /// or when the socket disconnect to remote device fails.</exception>
218 void IBluetoothClientSocket.Disconnect()
220 int ret = Interop.Bluetooth.DisconnectSocket(connectedSocket);
221 if (ret != (int)BluetoothError.None)
223 Log.Error(Globals.LogTag, "Failed to disconnect socket, Error - " + (BluetoothError)ret);
224 BluetoothErrorFactory.ThrowBluetoothException(ret);
229 /// Sends data to the connected device.
231 /// <returns>The number of bytes written (zero indicates nothing was written).</returns>
233 /// The connection must be established.
235 /// <param name="data">The data to be sent.</param>
236 /// <exception cref="InvalidOperationException">Thrown when the Bluetooth is not enabled
237 /// or when the remote device is not connected, or the send data procedure fails.</exception>
238 public int SendData(string data)
240 int ret = Interop.Bluetooth.SendData(connectedSocket, data, data.Length);
243 Log.Error(Globals.LogTag, "Failed to send data, Error - " + (BluetoothError)ret);
244 BluetoothErrorFactory.ThrowBluetoothException(ret);
254 public void Dispose()
257 GC.SuppressFinalize(this);
260 private void Dispose(bool disposing)
267 // Free managed objects.
269 //Free unmanaged objects
270 RemoveRegisteredEvents();
274 private void RemoveRegisteredEvents()
276 //unregister all remaining events when this object is released.
277 if (_dataReceived != null)
279 UnregisterDataReceivedEvent();
281 if (_connectionStateChanged != null)
283 UnregisterConnectionStateChangedEvent();