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
28 event EventHandler<SocketDataReceivedEventArgs> DataReceived;
29 event EventHandler<SocketConnectionStateChangedEventArgs> ConnectionStateChanged;
30 int SendData(string data);
34 /// The IBluetoothClientSocket interface handles the client socket operations.
36 public interface IBluetoothClientSocket : IBluetoothServerSocket
42 internal class BluetoothSocket : IBluetoothClientSocket, IDisposable
44 private event EventHandler<SocketDataReceivedEventArgs> _dataReceived;
45 private event EventHandler<SocketConnectionStateChangedEventArgs> _connectionStateChanged;
46 private Interop.Bluetooth.DataReceivedCallback _dataReceivedCallback;
47 private Interop.Bluetooth.SocketConnectionStateChangedCallback _connectionStateChangedCallback;
48 private bool disposed = false;
49 internal int connectedSocket;
50 internal string remoteAddress;
51 internal string serviceUuid;
54 /// This event occurs when the socket server receives data from the client.
56 /// <exception cref="System.InvalidOperationException">Thrown when the Bluetooth is not enabled
57 /// or when the register data received callback fails.</exception>
58 public event EventHandler<SocketDataReceivedEventArgs> DataReceived
62 if (_dataReceived == null)
64 RegisterDataReceivedEvent();
66 _dataReceived += value;
70 _dataReceived -= value;
71 if (_dataReceived == null)
73 UnregisterDataReceivedEvent();
79 /// This event occurs when the connection state between two devices is changed.
81 /// <exception cref="System.InvalidOperationException">Thrown when the Bluetooth is not enabled
82 /// or when the register connection changed callback fails.</exception>
83 public event EventHandler<SocketConnectionStateChangedEventArgs> ConnectionStateChanged
87 if (_connectionStateChanged == null)
89 RegisterConnectionStateChangedEvent();
91 _connectionStateChanged += value;
95 _connectionStateChanged -= value;
96 if (_connectionStateChanged == null)
98 UnregisterConnectionStateChangedEvent();
103 private void RegisterDataReceivedEvent()
105 _dataReceivedCallback = (ref SocketDataStruct socketData, IntPtr userData) =>
107 Log.Info(Globals.LogTag, "DataReceivedCallback is called");
108 if (_dataReceived != null)
110 GCHandle handle2 = (GCHandle) userData;
111 _dataReceived(handle2.Target as IBluetoothServerSocket, new SocketDataReceivedEventArgs(BluetoothUtils.ConvertStructToSocketData(socketData)));
114 GCHandle handle1 = GCHandle.Alloc (this);
115 IntPtr uData = (IntPtr) handle1;
116 int ret = Interop.Bluetooth.SetDataReceivedCallback(_dataReceivedCallback, uData);
117 if (ret != (int)BluetoothError.None)
119 Log.Error(Globals.LogTag, "Failed to set data received callback, Error - " + (BluetoothError)ret);
120 BluetoothErrorFactory.ThrowBluetoothException(ret);
124 private void UnregisterDataReceivedEvent()
126 int ret = Interop.Bluetooth.UnsetDataReceivedCallback();
127 if (ret != (int)BluetoothError.None)
129 Log.Error(Globals.LogTag, "Failed to unset data received callback, Error - " + (BluetoothError)ret);
130 BluetoothErrorFactory.ThrowBluetoothException(ret);
134 private void RegisterConnectionStateChangedEvent()
136 _connectionStateChangedCallback = (int result, BluetoothSocketState connectionState, ref SocketConnectionStruct socketConnection, IntPtr userData) =>
138 Log.Info(Globals.LogTag, "ConnectionStateChangedCallback is called");
139 if (_connectionStateChanged != null)
141 connectedSocket = socketConnection.SocketFd;
142 GCHandle handle2 = (GCHandle) userData;
143 _connectionStateChanged(handle2.Target as IBluetoothServerSocket, new SocketConnectionStateChangedEventArgs((BluetoothError)result, connectionState, BluetoothUtils.ConvertStructToSocketConnection(socketConnection)));
146 GCHandle handle1 = GCHandle.Alloc(this);
147 IntPtr data = (IntPtr) handle1;
148 int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionStateChangedCallback, data);
149 if (ret != (int)BluetoothError.None)
151 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
152 BluetoothErrorFactory.ThrowBluetoothException(ret);
156 private void UnregisterConnectionStateChangedEvent()
158 int ret = Interop.Bluetooth.UnsetSocketConnectionStateChangedCallback();
159 if (ret != (int)BluetoothError.None)
161 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
162 BluetoothErrorFactory.ThrowBluetoothException(ret);
167 /// Connects to a specific RFCOMM based service on a remote Bluetooth device UUID.
170 /// 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.
172 /// <param name="address">The address of the remote Bluetooth device.</param>
173 /// <param name="serviceUuid">The UUID of the service provided by the remote Bluetooth device.</param>
174 /// <exception cref="System.InvalidOperationException">Thrown when the Bluetooth is not enabled
175 /// or when the connect socket attempt to remote device fails, or when the service UUID is not supported by the remote device.</exception>
176 void IBluetoothClientSocket.Connect()
178 int ret = Interop.Bluetooth.ConnectSocket(remoteAddress, serviceUuid);
179 if (ret != (int)BluetoothError.None)
181 Log.Error(Globals.LogTag, "Failed to connect to socket, Error - " + (BluetoothError)ret);
182 BluetoothErrorFactory.ThrowBluetoothException(ret);
187 /// Disconnects the RFCOMM connection with the given file descriptor of the conneted socket.
190 /// The connection must be established.
192 /// <param name="socketFd">The file descriptor of the socket to close.</param>
193 /// <exception cref="System.InvalidOperationException">Thrown when the Bluetooth is not enabled
194 /// or when the socket disconnect to remote device fails.</exception>
195 void IBluetoothClientSocket.Disconnect()
197 int ret = Interop.Bluetooth.DisconnectSocket(connectedSocket);
198 if (ret != (int)BluetoothError.None)
200 Log.Error(Globals.LogTag, "Failed to disconnect socket, Error - " + (BluetoothError)ret);
201 BluetoothErrorFactory.ThrowBluetoothException(ret);
206 /// Sends data to the connected device.
208 /// <returns>The number of bytes written (zero indicates nothing was written).</returns>
210 /// The connection must be established.
212 /// <param name="socketFd">The file descriptor of the connected socket.</param>
213 /// <param name="data">The data to be sent.</param>
214 /// <exception cref="System.InvalidOperationException">Thrown when the Bluetooth is not enabled
215 /// or when the remote device is not connected, or the send data procedure fails.</exception>
216 public int SendData(string data)
218 int ret = Interop.Bluetooth.SendData(connectedSocket, data, data.Length);
221 Log.Error(Globals.LogTag, "Failed to send data, Error - " + (BluetoothError)ret);
222 BluetoothErrorFactory.ThrowBluetoothException(ret);
232 public void Dispose()
235 GC.SuppressFinalize(this);
238 private void Dispose(bool disposing)
245 // Free managed objects.
247 //Free unmanaged objects
248 RemoveRegisteredEvents();
252 private void RemoveRegisteredEvents()
254 //unregister all remaining events when this object is released.
255 if (_dataReceived != null)
257 UnregisterDataReceivedEvent();
259 if (_connectionStateChanged != null)
261 UnregisterConnectionStateChangedEvent();