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;
20 using System.Collections.Concurrent;
21 using System.Collections.ObjectModel;
22 using System.Collections.Specialized;
24 namespace Tizen.Network.Bluetooth
27 /// This class is used to handle the connection with other devices and set authorization of other devices.<br/>
28 /// The BluetoothDevice class is used to search for services available on remote devices.
30 /// <privilege> http://tizen.org/privilege/bluetooth </privilege>
31 /// <since_tizen> 3 </since_tizen>
32 public class BluetoothDevice
34 private event EventHandler<BondCreatedEventArgs> _bondCreated;
35 private event EventHandler<BondDestroyedEventArgs> _bondDestroyed;
36 private event EventHandler<AuthorizationChangedEventArgs> _authorizationChanged;
37 private event EventHandler<ServiceSearchedEventArgs> _serviceSearched;
38 private event EventHandler<DeviceConnectionStateChangedEventArgs> _connectionChanged;
40 private Interop.Bluetooth.BondCreatedCallback _bondCreatedCallback;
41 private Interop.Bluetooth.BondDestroyedCallback _bondDestroyedCallback;
42 private Interop.Bluetooth.AuthorizationChangedCallback _authorizationChangedCallback;
43 private Interop.Bluetooth.ServiceSearchedCallback _serviceSearchedCallback;
44 private Interop.Bluetooth.DeviceConnectionStateChangedCallback _connectionChangedCallback;
45 private Interop.Bluetooth.ConnectedProfileCallback _connectedProfileCallback;
47 internal string RemoteDeviceAddress;
48 internal string RemoteDeviceName;
49 internal int RemoteDeviceRssi;
50 internal BluetoothClass RemoteDeviceClass;
51 internal Collection<string> RemoteDeviceService;
52 internal int RemoteDeviceCount;
53 internal bool RemotePaired;
54 internal bool RemoteAuthorized;
55 internal bool RemoteConnected;
56 internal BluetoothAppearanceType RemoteAppearance;
57 internal int RemoteManufLength;
58 internal string RemoteManufData;
60 internal BluetoothDevice()
65 /// The address of the device.
67 /// <since_tizen> 3 </since_tizen>
72 return RemoteDeviceAddress;
76 /// The name of the device.
78 /// <since_tizen> 3 </since_tizen>
83 return RemoteDeviceName;
87 /// The strength indicator of received signal of the device.
89 /// <since_tizen> 3 </since_tizen>
94 return RemoteDeviceRssi;
98 /// The class of the device.
100 /// <since_tizen> 3 </since_tizen>
101 public BluetoothClass Class
105 return RemoteDeviceClass;
109 /// The service UUID list of the device.
111 /// <since_tizen> 3 </since_tizen>
112 public IEnumerable<string> ServiceUuidList
116 return RemoteDeviceService;
120 /// The number of services.
122 /// <since_tizen> 3 </since_tizen>
123 public int ServiceCount
127 return RemoteDeviceCount;
131 /// The paired state of the device.
133 /// <since_tizen> 3 </since_tizen>
142 /// The connection state of the device.
144 /// <since_tizen> 3 </since_tizen>
145 public bool IsConnected
149 return RemoteConnected;
153 /// The authorization state of the device.
155 /// <since_tizen> 3 </since_tizen>
156 public bool IsAuthorized
160 return RemoteAuthorized;
164 /// The Bluetooth appearance.
166 /// <since_tizen> 3 </since_tizen>
167 public BluetoothAppearanceType AppearanceType
171 return RemoteAppearance;
176 /// The length of the manufacturer data.
178 /// <since_tizen> 3 </since_tizen>
179 public int ManufacturerDataLength
183 return RemoteManufLength;
187 /// The manufacturer data.
189 /// <since_tizen> 3 </since_tizen>
190 public string ManufacturerData
194 return RemoteManufData;
199 /// The BondCreated event is raised when the process of creating the bond is finished.
201 /// <since_tizen> 3 </since_tizen>
202 public event EventHandler<BondCreatedEventArgs> BondCreated
206 if (_bondCreated == null)
208 RegisterBondCreatedEvent();
210 _bondCreated += value;
214 _bondCreated -= value;
215 if (_bondCreated == null)
217 UnregisterBondCreatedEvent();
223 /// The BondDestroyed event is raised when the bond is destroyed.
225 /// <since_tizen> 3 </since_tizen>
226 public event EventHandler<BondDestroyedEventArgs> BondDestroyed
230 if (_bondDestroyed == null)
232 RegisterBondDestroyedEvent();
234 _bondDestroyed += value;
238 _bondDestroyed -= value;
239 if (_bondDestroyed == null)
241 UnregisterBondDestroyedEvent();
247 /// The AuthorizationChanged event is raised when the authorization of the device is changed.
249 /// <since_tizen> 3 </since_tizen>
250 public event EventHandler<AuthorizationChangedEventArgs> AuthorizationChanged
254 if (_authorizationChanged == null)
256 RegisterAuthorizationChangedEvent();
258 _authorizationChanged += value;
262 _authorizationChanged -= value;
263 if (_authorizationChanged == null)
265 UnregisterAuthorizationChangedEvent();
271 /// The ServiceSearched event is raised when the process of service searched is finished.
273 /// <since_tizen> 3 </since_tizen>
274 public event EventHandler<ServiceSearchedEventArgs> ServiceSearched
278 if (_serviceSearched == null)
280 RegisterServiceSearchedEvent();
282 _serviceSearched += value;
286 _serviceSearched -= value;
287 if (_serviceSearched == null)
289 UnregisterServiceSearchedEvent();
295 /// The ConnectionStateChanged event is raised when the connection state is changed.
297 /// <since_tizen> 3 </since_tizen>
298 public event EventHandler<DeviceConnectionStateChangedEventArgs> ConnectionStateChanged
302 if (_connectionChanged == null)
304 RegisterConnectionChangedEvent();
306 _connectionChanged += value;
310 _connectionChanged -= value;
311 if (_connectionChanged == null)
313 UnregisterConnectionChangedEvent();
318 private void RegisterBondCreatedEvent()
320 _bondCreatedCallback = (int result, ref BluetoothDeviceStruct device, IntPtr userData) =>
322 if (_bondCreated != null)
324 BluetoothError res = (BluetoothError)result;
325 _bondCreated(null, new BondCreatedEventArgs(res, BluetoothUtils.ConvertStructToDeviceClass(device)));
328 int ret = Interop.Bluetooth.SetBondCreatedCallback(_bondCreatedCallback, IntPtr.Zero);
329 if (ret != (int)BluetoothError.None)
331 Log.Error(Globals.LogTag, "Failed to set bond created callback, Error - " + (BluetoothError)ret);
335 private void UnregisterBondCreatedEvent()
337 int ret = Interop.Bluetooth.UnsetBondCreatedCallback();
338 if (ret != (int)BluetoothError.None)
340 Log.Error(Globals.LogTag, "Failed to unset bond created callback, Error - " + (BluetoothError)ret);
344 private void RegisterBondDestroyedEvent()
346 _bondDestroyedCallback = (int result, string deviceAddress, IntPtr userData) =>
348 if (_bondDestroyed != null)
350 BluetoothError res = (BluetoothError)result;
351 _bondDestroyed(null, new BondDestroyedEventArgs(res, deviceAddress));
354 int ret = Interop.Bluetooth.SetBondDestroyedCallback(_bondDestroyedCallback, IntPtr.Zero);
355 if (ret != (int)BluetoothError.None)
357 Log.Error(Globals.LogTag, "Failed to set bond destroyed callback, Error - " + (BluetoothError)ret);
361 private void UnregisterBondDestroyedEvent()
363 int ret = Interop.Bluetooth.UnsetBondDestroyedCallback();
364 if (ret != (int)BluetoothError.None)
366 Log.Error(Globals.LogTag, "Failed to unset bond destroyed callback, Error - " + (BluetoothError)ret);
370 private void RegisterServiceSearchedEvent()
372 _serviceSearchedCallback = (int result, ref BluetoothDeviceSdpStruct sdp, IntPtr userData) =>
374 Log.Info(Globals.LogTag, "Servicesearched cb is called");
375 if (_serviceSearched != null)
377 BluetoothError res = (BluetoothError)result;
378 _serviceSearched(null, new ServiceSearchedEventArgs(res, BluetoothUtils.ConvertStructToSdpData(sdp)));
381 int ret = Interop.Bluetooth.SetServiceSearchedCallback(_serviceSearchedCallback, IntPtr.Zero);
382 if (ret != (int)BluetoothError.None)
384 Log.Error(Globals.LogTag, "Failed to set service searched callback, Error - " + (BluetoothError)ret);
388 private void UnregisterServiceSearchedEvent()
390 int ret = Interop.Bluetooth.UnsetServiceSearchedCallback();
391 if (ret != (int)BluetoothError.None)
393 Log.Error(Globals.LogTag, "Failed to unset service searched callback, Error - " + (BluetoothError)ret);
397 private void RegisterAuthorizationChangedEvent()
399 _authorizationChangedCallback = (int authorization, string deviceAddress, IntPtr userData) =>
401 Log.Info(Globals.LogTag, "Authorization changed cb is called");
402 if (_authorizationChanged != null)
404 BluetoothAuthorizationType auth = (BluetoothAuthorizationType)authorization;
405 _authorizationChanged(null, new AuthorizationChangedEventArgs(auth, deviceAddress));
408 int ret = Interop.Bluetooth.SetAuthorizationChangedCallback(_authorizationChangedCallback, IntPtr.Zero);
409 if (ret != (int)BluetoothError.None)
411 Log.Error(Globals.LogTag, "Failed to set authroization changed callback, Error - " + (BluetoothError)ret);
415 private void UnregisterAuthorizationChangedEvent()
417 int ret = Interop.Bluetooth.UnsetAuthorizationChangedCallback();
418 if (ret != (int)BluetoothError.None)
420 Log.Error(Globals.LogTag, "Failed to unset authroization changed callback, Error - " + (BluetoothError)ret);
424 private void RegisterConnectionChangedEvent()
426 _connectionChangedCallback = (bool connected, ref BluetoothDeviceConnectionStruct device, IntPtr userData) =>
428 Log.Info(Globals.LogTag, "Connection state changed cb is called");
429 if (_connectionChanged != null)
431 _connectionChanged(null, new DeviceConnectionStateChangedEventArgs(connected, BluetoothUtils.ConvertStructToConnectionData(device)));
435 int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionChangedCallback, IntPtr.Zero);
436 if (ret != (int)BluetoothError.None)
438 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
442 private void UnregisterConnectionChangedEvent()
444 int ret = Interop.Bluetooth.UnsetConnectionStateChangedCallback();
445 if (ret != (int)BluetoothError.None)
447 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
452 /// Creates a bond with the remote Bluetooth device.
455 /// The Bluetooth must be enabled and the remote device must be discoverable by StartDiscovery(). The bond can be destroyed by DestroyBond().
456 /// The bonding request can be cancelled by CancelBonding(). If this succeeds, the BondCreated event will be invoked.
458 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
459 /// or when the create bonding process to the remote device fails.</exception>
460 /// <since_tizen> 3 </since_tizen>
461 public void CreateBond()
463 if (BluetoothAdapter.IsBluetoothEnabled)
465 int ret = Interop.Bluetooth.CreateBond(RemoteDeviceAddress);
466 if (ret != (int)BluetoothError.None)
468 Log.Error(Globals.LogTag, "Failed to create bond, Error - " + (BluetoothError)ret);
469 BluetoothErrorFactory.ThrowBluetoothException(ret);
475 /// Cancels the bonding process.
478 /// Bonding must be in progress by CreateBond().
480 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
481 /// or when the cancel bonding procedure to remote device fails.</exception>
482 /// <since_tizen> 3 </since_tizen>
483 public void CancelBonding()
485 int ret = Interop.Bluetooth.CancelBonding();
486 if (ret != (int)BluetoothError.None)
488 Log.Error(Globals.LogTag, "Failed to cancel bonding process, Error - " + (BluetoothError)ret);
489 BluetoothErrorFactory.ThrowBluetoothException(ret);
494 /// Destroys the bond.
497 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
498 /// If this succeeds, the BondDestroyed event will be invoked.
500 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
501 /// or when the destroy bonding procedure fails.</exception>
502 /// <since_tizen> 3 </since_tizen>
503 public void DestroyBond()
505 if (BluetoothAdapter.IsBluetoothEnabled)
507 int ret = Interop.Bluetooth.DestroyBond(RemoteDeviceAddress);
508 if (ret != (int)BluetoothError.None)
510 Log.Error(Globals.LogTag, "Failed to destroy bond, Error - " + (BluetoothError)ret);
511 BluetoothErrorFactory.ThrowBluetoothException(ret);
517 /// Sets an alias for the bonded device.
520 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
522 /// <param name="aliasName">The alias name of the remote device.</param>
523 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
524 /// or when the set alias name to remote device fails.</exception>
525 /// <since_tizen> 3 </since_tizen>
526 public void SetAlias(string aliasName)
528 if (BluetoothAdapter.IsBluetoothEnabled)
530 int ret = Interop.Bluetooth.SetAlias(RemoteDeviceAddress, aliasName);
531 if (ret != (int)BluetoothError.None)
533 Log.Error(Globals.LogTag, "Failed to set alias name, Error - " + (BluetoothError)ret);
534 BluetoothErrorFactory.ThrowBluetoothException(ret);
540 /// Sets the authorization of a bonded device.
543 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
544 /// If this succeeds, the AuthorizationChanged event will be invoked.
546 /// <param name="authorizationState">The authorization state.</param>
547 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
548 /// or when the set authorization to remote device fails.</exception>
549 /// <since_tizen> 3 </since_tizen>
550 public void SetAuthorization(BluetoothAuthorizationType authorizationState)
552 if (BluetoothAdapter.IsBluetoothEnabled)
554 int ret = Interop.Bluetooth.SetAuthorization(RemoteDeviceAddress, (int)authorizationState);
555 if (ret != (int)BluetoothError.None)
557 Log.Error(Globals.LogTag, "Failed to set authroization state, Error - " + (BluetoothError)ret);
558 BluetoothErrorFactory.ThrowBluetoothException(ret);
564 /// Gets the mask from the UUID.
566 /// <returns>The service mask list converted from the given UUID list.</returns>
567 /// <param name="uuids">The UUID list of the device.</param>
568 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
569 /// or when the get Mask from UUID fails.</exception>
570 /// <since_tizen> 3 </since_tizen>
571 public BluetoothServiceClassType GetMaskFromUuid(string[] uuids)
573 BluetoothServiceClassType serviceMask;
575 int ret = Interop.Bluetooth.GetMaskFromUuid(uuids, uuids.Length, out serviceMask);
576 if (ret != (int)BluetoothError.None)
578 Log.Error(Globals.LogTag, "Failed to get service mask, Error - " + (BluetoothError)ret);
579 BluetoothErrorFactory.ThrowBluetoothException(ret);
585 /// Starts the search for services supported by the specified device.
588 /// The Bluetooth must be enabled and remote device must be discoverable by StartDiscovery(). The bond must be created by CreateBond().
589 /// If this succeeds, the ServiceSearched event will be invoked.
591 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
592 /// or when the remote device service search fails.</exception>
593 /// <since_tizen> 3 </since_tizen>
594 public void StartServiceSearch()
596 Log.Info(Globals.LogTag, "startservicesearch entry");
597 if (BluetoothAdapter.IsBluetoothEnabled)
599 int ret = Interop.Bluetooth.StartServiceSearch(RemoteDeviceAddress);
600 if (ret != (int)BluetoothError.None)
602 Log.Error(Globals.LogTag, "Failed to start service search, Error - " + (BluetoothError)ret);
603 BluetoothErrorFactory.ThrowBluetoothException(ret);
609 /// Gets the connected profiles.
612 /// The Bluetooth must be enabled.
614 /// <returns>The connected Bluetooth profiles.</returns>
615 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
616 /// or when there is no BT connection.</exception>
617 /// <since_tizen> 3 </since_tizen>
618 public IEnumerable<BluetoothProfileType> GetConnectedProfiles()
620 if (BluetoothAdapter.IsBluetoothEnabled)
622 List<BluetoothProfileType> profileList = new List<BluetoothProfileType>();
623 _connectedProfileCallback = (int profile, IntPtr userData) =>
625 if (!profile.Equals(null))
627 profileList.Add((BluetoothProfileType)profile);
631 int ret = Interop.Bluetooth.GetConnectedProfiles(RemoteDeviceAddress, _connectedProfileCallback, IntPtr.Zero);
632 if (ret != (int)BluetoothError.None)
634 Log.Error(Globals.LogTag, "Failed to get connected profiles, Error - " + (BluetoothError)ret);
635 BluetoothErrorFactory.ThrowBluetoothException(ret);
646 /// Determines if profile is connected to the specified remote device.
649 /// The Bluetooth must be enabled.
651 /// <returns><c>true</c> if profile is connected, otherwise <c>false</c>.</returns>
652 /// <param name="profileType">The Bluetooth profile type.</param>
653 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
654 /// or when there is no BT connection.</exception>
655 /// <since_tizen> 3 </since_tizen>
656 public bool IsProfileConnected(BluetoothProfileType profileType)
658 if (BluetoothAdapter.IsBluetoothEnabled)
661 int ret = Interop.Bluetooth.IsProfileConnected(RemoteDeviceAddress, (int)profileType, out isConnected);
662 if (ret != (int)BluetoothError.None)
664 Log.Error(Globals.LogTag, "Failed to get profile connected state, Error - " + (BluetoothError)ret);
675 /// Returns the instance of the Bluetooth profile type.
678 /// The Bluetooth must be enabled.
680 /// <returns>The profile instance.</returns>
681 /// <since_tizen> 3 </since_tizen>
682 public T GetProfile<T>() where T : BluetoothProfile
684 // TODO : Need to check capability of supporting profiles
685 var profile = (T)Activator.CreateInstance(typeof(T), true);
686 profile.RemoteAddress = RemoteDeviceAddress;
691 /// Creates the client socket.
693 /// <returns>The IBluetoothClientSocket instance.</returns>
694 /// <param name="serviceUuid">The UUID of the service.</param>
695 /// <since_tizen> 3 </since_tizen>
696 public IBluetoothClientSocket CreateSocket(string serviceUuid)
698 BluetoothSocket clientSocket = new BluetoothSocket();
699 clientSocket.remoteAddress = this.Address;
700 clientSocket.serviceUuid = serviceUuid;
701 return (IBluetoothClientSocket)clientSocket;