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;
46 internal string RemoteDeviceAddress;
47 internal string RemoteDeviceName;
48 internal int RemoteDeviceRssi;
49 internal BluetoothClass RemoteDeviceClass;
50 internal Collection<string> RemoteDeviceService;
51 internal int RemoteDeviceCount;
52 internal bool RemotePaired;
53 internal bool RemoteAuthorized;
54 internal bool RemoteConnected;
55 internal BluetoothAppearanceType RemoteAppearance;
56 internal int RemoteManufLength;
57 internal string RemoteManufData;
59 internal BluetoothDevice()
64 /// The address of the device.
66 /// <since_tizen> 3 </since_tizen>
71 return RemoteDeviceAddress;
75 /// The name of the device.
77 /// <since_tizen> 3 </since_tizen>
82 return RemoteDeviceName;
86 /// The strength indicator of received signal of the device.
88 /// <since_tizen> 3 </since_tizen>
93 return RemoteDeviceRssi;
97 /// The class of the device.
99 /// <since_tizen> 3 </since_tizen>
100 public BluetoothClass Class
104 return RemoteDeviceClass;
108 /// The service UUID list of the device.
110 /// <since_tizen> 3 </since_tizen>
111 public IEnumerable<string> ServiceUuidList
115 return RemoteDeviceService;
119 /// The number of services.
121 /// <since_tizen> 3 </since_tizen>
122 public int ServiceCount
126 return RemoteDeviceCount;
130 /// The paired state of the device.
132 /// <since_tizen> 3 </since_tizen>
141 /// The connection state of the device.
143 /// <since_tizen> 3 </since_tizen>
144 public bool IsConnected
148 return RemoteConnected;
152 /// The authorization state of the device.
154 /// <since_tizen> 3 </since_tizen>
155 public bool IsAuthorized
159 return RemoteAuthorized;
163 /// The Bluetooth appearance.
165 /// <since_tizen> 3 </since_tizen>
166 public BluetoothAppearanceType AppearanceType
170 return RemoteAppearance;
175 /// The length of the manufacturer data.
177 /// <since_tizen> 3 </since_tizen>
178 public int ManufacturerDataLength
182 return RemoteManufLength;
186 /// The manufacturer data.
188 /// <since_tizen> 3 </since_tizen>
189 public string ManufacturerData
193 return RemoteManufData;
198 /// The BondCreated event is raised when the process of creating the bond is finished.
200 /// <since_tizen> 3 </since_tizen>
201 public event EventHandler<BondCreatedEventArgs> BondCreated
205 if (_bondCreated == null)
207 RegisterBondCreatedEvent();
209 _bondCreated += value;
213 _bondCreated -= value;
214 if (_bondCreated == null)
216 UnregisterBondCreatedEvent();
222 /// The BondDestroyed event is raised when the bond is destroyed.
224 /// <since_tizen> 3 </since_tizen>
225 public event EventHandler<BondDestroyedEventArgs> BondDestroyed
229 if (_bondDestroyed == null)
231 RegisterBondDestroyedEvent();
233 _bondDestroyed += value;
237 _bondDestroyed -= value;
238 if (_bondDestroyed == null)
240 UnregisterBondDestroyedEvent();
246 /// The AuthorizationChanged event is raised when the authorization of the device is changed.
248 /// <since_tizen> 3 </since_tizen>
249 public event EventHandler<AuthorizationChangedEventArgs> AuthorizationChanged
253 if (_authorizationChanged == null)
255 RegisterAuthorizationChangedEvent();
257 _authorizationChanged += value;
261 _authorizationChanged -= value;
262 if (_authorizationChanged == null)
264 UnregisterAuthorizationChangedEvent();
270 /// The ServiceSearched event is raised when the process of service searched is finished.
272 /// <since_tizen> 3 </since_tizen>
273 public event EventHandler<ServiceSearchedEventArgs> ServiceSearched
277 if (_serviceSearched == null)
279 RegisterServiceSearchedEvent();
281 _serviceSearched += value;
285 _serviceSearched -= value;
286 if (_serviceSearched == null)
288 UnregisterServiceSearchedEvent();
294 /// The ConnectionStateChanged event is raised when the connection state is changed.
296 /// <since_tizen> 3 </since_tizen>
297 public event EventHandler<DeviceConnectionStateChangedEventArgs> ConnectionStateChanged
301 if (_connectionChanged == null)
303 RegisterConnectionChangedEvent();
305 _connectionChanged += value;
309 _connectionChanged -= value;
310 if (_connectionChanged == null)
312 UnregisterConnectionChangedEvent();
317 private void RegisterBondCreatedEvent()
319 _bondCreatedCallback = (int result, ref BluetoothDeviceStruct device, IntPtr userData) =>
321 if (_bondCreated != null)
323 BluetoothError res = (BluetoothError)result;
324 _bondCreated(null, new BondCreatedEventArgs(res, BluetoothUtils.ConvertStructToDeviceClass(device)));
327 int ret = Interop.Bluetooth.SetBondCreatedCallback(_bondCreatedCallback, IntPtr.Zero);
328 if (ret != (int)BluetoothError.None)
330 Log.Error(Globals.LogTag, "Failed to set bond created callback, Error - " + (BluetoothError)ret);
334 private void UnregisterBondCreatedEvent()
336 int ret = Interop.Bluetooth.UnsetBondCreatedCallback();
337 if (ret != (int)BluetoothError.None)
339 Log.Error(Globals.LogTag, "Failed to unset bond created callback, Error - " + (BluetoothError)ret);
343 private void RegisterBondDestroyedEvent()
345 _bondDestroyedCallback = (int result, string deviceAddress, IntPtr userData) =>
347 if (_bondDestroyed != null)
349 BluetoothError res = (BluetoothError)result;
350 _bondDestroyed(null, new BondDestroyedEventArgs(res, deviceAddress));
353 int ret = Interop.Bluetooth.SetBondDestroyedCallback(_bondDestroyedCallback, IntPtr.Zero);
354 if (ret != (int)BluetoothError.None)
356 Log.Error(Globals.LogTag, "Failed to set bond destroyed callback, Error - " + (BluetoothError)ret);
360 private void UnregisterBondDestroyedEvent()
362 int ret = Interop.Bluetooth.UnsetBondDestroyedCallback();
363 if (ret != (int)BluetoothError.None)
365 Log.Error(Globals.LogTag, "Failed to unset bond destroyed callback, Error - " + (BluetoothError)ret);
369 private void RegisterServiceSearchedEvent()
371 _serviceSearchedCallback = (int result, ref BluetoothDeviceSdpStruct sdp, IntPtr userData) =>
373 Log.Info(Globals.LogTag, "Servicesearched cb is called");
374 if (_serviceSearched != null)
376 BluetoothError res = (BluetoothError)result;
377 _serviceSearched(null, new ServiceSearchedEventArgs(res, BluetoothUtils.ConvertStructToSdpData(sdp)));
380 int ret = Interop.Bluetooth.SetServiceSearchedCallback(_serviceSearchedCallback, IntPtr.Zero);
381 if (ret != (int)BluetoothError.None)
383 Log.Error(Globals.LogTag, "Failed to set service searched callback, Error - " + (BluetoothError)ret);
387 private void UnregisterServiceSearchedEvent()
389 int ret = Interop.Bluetooth.UnsetServiceSearchedCallback();
390 if (ret != (int)BluetoothError.None)
392 Log.Error(Globals.LogTag, "Failed to unset service searched callback, Error - " + (BluetoothError)ret);
396 private void RegisterAuthorizationChangedEvent()
398 _authorizationChangedCallback = (int authorization, string deviceAddress, IntPtr userData) =>
400 Log.Info(Globals.LogTag, "Authorization changed cb is called");
401 if (_authorizationChanged != null)
403 BluetoothAuthorizationType auth = (BluetoothAuthorizationType)authorization;
404 _authorizationChanged(null, new AuthorizationChangedEventArgs(auth, deviceAddress));
407 int ret = Interop.Bluetooth.SetAuthorizationChangedCallback(_authorizationChangedCallback, IntPtr.Zero);
408 if (ret != (int)BluetoothError.None)
410 Log.Error(Globals.LogTag, "Failed to set authroization changed callback, Error - " + (BluetoothError)ret);
414 private void UnregisterAuthorizationChangedEvent()
416 int ret = Interop.Bluetooth.UnsetAuthorizationChangedCallback();
417 if (ret != (int)BluetoothError.None)
419 Log.Error(Globals.LogTag, "Failed to unset authroization changed callback, Error - " + (BluetoothError)ret);
423 private void RegisterConnectionChangedEvent()
425 _connectionChangedCallback = (bool connected, ref BluetoothDeviceConnectionStruct device, IntPtr userData) =>
427 Log.Info(Globals.LogTag, "Connection state changed cb is called");
428 if (_connectionChanged != null)
430 _connectionChanged(null, new DeviceConnectionStateChangedEventArgs(connected, BluetoothUtils.ConvertStructToConnectionData(device)));
434 int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionChangedCallback, IntPtr.Zero);
435 if (ret != (int)BluetoothError.None)
437 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
441 private void UnregisterConnectionChangedEvent()
443 int ret = Interop.Bluetooth.UnsetConnectionStateChangedCallback();
444 if (ret != (int)BluetoothError.None)
446 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
451 /// Creates a bond with the remote Bluetooth device.
454 /// The Bluetooth must be enabled and the remote device must be discoverable by StartDiscovery(). The bond can be destroyed by DestroyBond().
455 /// The bonding request can be cancelled by CancelBonding(). If this succeeds, the BondCreated event will be invoked.
457 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
458 /// or when the create bonding process to the remote device fails.</exception>
459 /// <since_tizen> 3 </since_tizen>
460 public void CreateBond()
462 if (BluetoothAdapter.IsBluetoothEnabled)
464 int ret = Interop.Bluetooth.CreateBond(RemoteDeviceAddress);
465 if (ret != (int)BluetoothError.None)
467 Log.Error(Globals.LogTag, "Failed to create bond, Error - " + (BluetoothError)ret);
468 BluetoothErrorFactory.ThrowBluetoothException(ret);
474 /// Cancels the bonding process.
477 /// Bonding must be in progress by CreateBond().
479 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
480 /// or when the cancel bonding procedure to remote device fails.</exception>
481 /// <since_tizen> 3 </since_tizen>
482 public void CancelBonding()
484 int ret = Interop.Bluetooth.CancelBonding();
485 if (ret != (int)BluetoothError.None)
487 Log.Error(Globals.LogTag, "Failed to cancel bonding process, Error - " + (BluetoothError)ret);
488 BluetoothErrorFactory.ThrowBluetoothException(ret);
493 /// Destroys the bond.
496 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
497 /// If this succeeds, the BondDestroyed event will be invoked.
499 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
500 /// or when the destroy bonding procedure fails.</exception>
501 /// <since_tizen> 3 </since_tizen>
502 public void DestroyBond()
504 if (BluetoothAdapter.IsBluetoothEnabled)
506 int ret = Interop.Bluetooth.DestroyBond(RemoteDeviceAddress);
507 if (ret != (int)BluetoothError.None)
509 Log.Error(Globals.LogTag, "Failed to destroy bond, Error - " + (BluetoothError)ret);
510 BluetoothErrorFactory.ThrowBluetoothException(ret);
516 /// Sets an alias for the bonded device.
519 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
521 /// <param name="aliasName">The alias name of the remote device.</param>
522 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
523 /// or when the set alias name to remote device fails.</exception>
524 /// <since_tizen> 3 </since_tizen>
525 public void SetAlias(string aliasName)
527 if (BluetoothAdapter.IsBluetoothEnabled)
529 int ret = Interop.Bluetooth.SetAlias(RemoteDeviceAddress, aliasName);
530 if (ret != (int)BluetoothError.None)
532 Log.Error(Globals.LogTag, "Failed to set alias name, Error - " + (BluetoothError)ret);
533 BluetoothErrorFactory.ThrowBluetoothException(ret);
539 /// Sets the authorization of a bonded device.
542 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
543 /// If this succeeds, the AuthorizationChanged event will be invoked.
545 /// <param name="authorizationState">The authorization state.</param>
546 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
547 /// or when the set authorization to remote device fails.</exception>
548 /// <since_tizen> 3 </since_tizen>
549 public void SetAuthorization(BluetoothAuthorizationType authorizationState)
551 if (BluetoothAdapter.IsBluetoothEnabled)
553 int ret = Interop.Bluetooth.SetAuthorization(RemoteDeviceAddress, (int)authorizationState);
554 if (ret != (int)BluetoothError.None)
556 Log.Error(Globals.LogTag, "Failed to set authroization state, Error - " + (BluetoothError)ret);
557 BluetoothErrorFactory.ThrowBluetoothException(ret);
563 /// Gets the mask from the UUID.
565 /// <returns>The service mask list converted from the given UUID list.</returns>
566 /// <param name="uuids">The UUID list of the device.</param>
567 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
568 /// or when the get Mask from UUID fails.</exception>
569 /// <since_tizen> 3 </since_tizen>
570 public BluetoothServiceClassType GetMaskFromUuid(string[] uuids)
572 BluetoothServiceClassType serviceMask;
574 int ret = Interop.Bluetooth.GetMaskFromUuid(uuids, uuids.Length, out serviceMask);
575 if (ret != (int)BluetoothError.None)
577 Log.Error(Globals.LogTag, "Failed to get service mask, Error - " + (BluetoothError)ret);
578 BluetoothErrorFactory.ThrowBluetoothException(ret);
584 /// Starts the search for services supported by the specified device.
587 /// The Bluetooth must be enabled and remote device must be discoverable by StartDiscovery(). The bond must be created by CreateBond().
588 /// If this succeeds, the ServiceSearched event will be invoked.
590 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
591 /// or when the remote device service search fails.</exception>
592 /// <since_tizen> 3 </since_tizen>
593 public void StartServiceSearch()
595 Log.Info(Globals.LogTag, "startservicesearch entry");
596 if (BluetoothAdapter.IsBluetoothEnabled)
598 int ret = Interop.Bluetooth.StartServiceSearch(RemoteDeviceAddress);
599 if (ret != (int)BluetoothError.None)
601 Log.Error(Globals.LogTag, "Failed to start service search, Error - " + (BluetoothError)ret);
602 BluetoothErrorFactory.ThrowBluetoothException(ret);
608 /// Gets the connected profiles.
611 /// The Bluetooth must be enabled.
613 /// <returns>The connected Bluetooth profiles.</returns>
614 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
615 /// or when there is no BT connection.</exception>
616 /// <since_tizen> 3 </since_tizen>
617 public IEnumerable<BluetoothProfileType> GetConnectedProfiles()
619 if (BluetoothAdapter.IsBluetoothEnabled)
621 List<BluetoothProfileType> profileList = new List<BluetoothProfileType>();
622 Interop.Bluetooth.ConnectedProfileCallback callback = (int profile, IntPtr userData) =>
624 if (!profile.Equals(null))
626 profileList.Add((BluetoothProfileType)profile);
630 int ret = Interop.Bluetooth.GetConnectedProfiles(RemoteDeviceAddress, callback, IntPtr.Zero);
631 if (ret != (int)BluetoothError.None)
633 Log.Error(Globals.LogTag, "Failed to get connected profiles, Error - " + (BluetoothError)ret);
634 BluetoothErrorFactory.ThrowBluetoothException(ret);
645 /// Determines if profile is connected to the specified remote device.
648 /// The Bluetooth must be enabled.
650 /// <returns><c>true</c> if profile is connected, otherwise <c>false</c>.</returns>
651 /// <param name="profileType">The Bluetooth profile type.</param>
652 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
653 /// or when there is no BT connection.</exception>
654 /// <since_tizen> 3 </since_tizen>
655 public bool IsProfileConnected(BluetoothProfileType profileType)
657 if (BluetoothAdapter.IsBluetoothEnabled)
660 int ret = Interop.Bluetooth.IsProfileConnected(RemoteDeviceAddress, (int)profileType, out isConnected);
661 if (ret != (int)BluetoothError.None)
663 Log.Error(Globals.LogTag, "Failed to get profile connected state, Error - " + (BluetoothError)ret);
674 /// Returns the instance of the Bluetooth profile type.
677 /// The Bluetooth must be enabled.
679 /// <returns>The profile instance.</returns>
680 /// <since_tizen> 3 </since_tizen>
681 public T GetProfile<T>() where T : BluetoothProfile
683 // TODO : Need to check capability of supporting profiles
684 var profile = (T)Activator.CreateInstance(typeof(T), true);
685 profile.RemoteAddress = RemoteDeviceAddress;
690 /// Creates the client socket.
692 /// <returns>The IBluetoothClientSocket instance.</returns>
693 /// <param name="serviceUuid">The UUID of the service.</param>
694 /// <since_tizen> 3 </since_tizen>
695 public IBluetoothClientSocket CreateSocket(string serviceUuid)
697 BluetoothSocket clientSocket = new BluetoothSocket();
698 clientSocket.remoteAddress = this.Address;
699 clientSocket.serviceUuid = serviceUuid;
700 return (IBluetoothClientSocket)clientSocket;