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 public class BluetoothDevice
33 private event EventHandler<BondCreatedEventArgs> _bondCreated;
34 private event EventHandler<BondDestroyedEventArgs> _bondDestroyed;
35 private event EventHandler<AuthorizationChangedEventArgs> _authorizationChanged;
36 private event EventHandler<ServiceSearchedEventArgs> _serviceSearched;
37 private event EventHandler<DeviceConnectionStateChangedEventArgs> _connectionChanged;
39 private Interop.Bluetooth.BondCreatedCallback _bondCreatedCallback;
40 private Interop.Bluetooth.BondDestroyedCallback _bondDestroyedCallback;
41 private Interop.Bluetooth.AuthorizationChangedCallback _authorizationChangedCallback;
42 private Interop.Bluetooth.ServiceSearchedCallback _serviceSearchedCallback;
43 private Interop.Bluetooth.DeviceConnectionStateChangedCallback _connectionChangedCallback;
45 internal string RemoteDeviceAddress;
46 internal string RemoteDeviceName;
47 internal int RemoteDeviceRssi;
48 internal BluetoothClass RemoteDeviceClass;
49 internal Collection<string> RemoteDeviceService;
50 internal int RemoteDeviceCount;
51 internal bool RemotePaired;
52 internal bool RemoteAuthorized;
53 internal bool RemoteConnected;
54 internal BluetoothAppearanceType RemoteAppearance;
55 internal int RemoteManufLength;
56 internal string RemoteManufData;
58 internal BluetoothDevice()
63 /// The address of the device.
69 return RemoteDeviceAddress;
73 /// The name of the device.
79 return RemoteDeviceName;
83 /// The strength indicator of received signal of the device.
89 return RemoteDeviceRssi;
93 /// The class of the device.
95 public BluetoothClass Class
99 return RemoteDeviceClass;
103 /// The service UUID list of the device.
105 public IEnumerable<string> ServiceUuidList
109 return RemoteDeviceService;
113 /// The number of services.
115 public int ServiceCount
119 return RemoteDeviceCount;
123 /// The paired state of the device.
133 /// The connection state of the device.
135 public bool IsConnected
139 return RemoteConnected;
143 /// The authorization state of the device.
145 public bool IsAuthorized
149 return RemoteAuthorized;
153 /// The Bluetooth appearance.
155 public BluetoothAppearanceType AppearanceType
159 return RemoteAppearance;
164 /// The length of the manufacturer data.
166 public int ManufacturerDataLength
170 return RemoteManufLength;
174 /// The manufacturer data.
176 public string ManufacturerData
180 return RemoteManufData;
185 /// The BondCreated event is raised when the process of creating the bond is finished.
187 public event EventHandler<BondCreatedEventArgs> BondCreated
191 if (_bondCreated == null)
193 RegisterBondCreatedEvent();
195 _bondCreated += value;
199 _bondCreated -= value;
200 if (_bondCreated == null)
202 UnregisterBondCreatedEvent();
208 /// The BondDestroyed event is raised when the bond is destroyed.
210 public event EventHandler<BondDestroyedEventArgs> BondDestroyed
214 if (_bondDestroyed == null)
216 RegisterBondDestroyedEvent();
218 _bondDestroyed += value;
222 _bondDestroyed -= value;
223 if (_bondDestroyed == null)
225 UnregisterBondDestroyedEvent();
231 /// The AuthorizationChanged event is raised when the authorization of the device is changed.
233 public event EventHandler<AuthorizationChangedEventArgs> AuthorizationChanged
237 if (_authorizationChanged == null)
239 RegisterAuthorizationChangedEvent();
241 _authorizationChanged += value;
245 _authorizationChanged -= value;
246 if (_authorizationChanged == null)
248 UnregisterAuthorizationChangedEvent();
254 /// The ServiceSearched event is raised when the process of service searched is finished.
256 public event EventHandler<ServiceSearchedEventArgs> ServiceSearched
260 if (_serviceSearched == null)
262 RegisterServiceSearchedEvent();
264 _serviceSearched += value;
268 _serviceSearched -= value;
269 if (_serviceSearched == null)
271 UnregisterServiceSearchedEvent();
277 /// The ConnectionStateChanged event is raised when the connection state is changed.
279 public event EventHandler<DeviceConnectionStateChangedEventArgs> ConnectionStateChanged
283 if (_connectionChanged == null)
285 RegisterConnectionChangedEvent();
287 _connectionChanged += value;
291 _connectionChanged -= value;
292 if (_connectionChanged == null)
294 UnregisterConnectionChangedEvent();
299 private void RegisterBondCreatedEvent()
301 _bondCreatedCallback = (int result, ref BluetoothDeviceStruct device, IntPtr userData) =>
303 if (_bondCreated != null)
305 BluetoothError res = (BluetoothError)result;
306 _bondCreated(null, new BondCreatedEventArgs(res, BluetoothUtils.ConvertStructToDeviceClass(device)));
309 int ret = Interop.Bluetooth.SetBondCreatedCallback(_bondCreatedCallback, IntPtr.Zero);
310 if (ret != (int)BluetoothError.None)
312 Log.Error(Globals.LogTag, "Failed to set bond created callback, Error - " + (BluetoothError)ret);
316 private void UnregisterBondCreatedEvent()
318 int ret = Interop.Bluetooth.UnsetBondCreatedCallback();
319 if (ret != (int)BluetoothError.None)
321 Log.Error(Globals.LogTag, "Failed to unset bond created callback, Error - " + (BluetoothError)ret);
325 private void RegisterBondDestroyedEvent()
327 _bondDestroyedCallback = (int result, string deviceAddress, IntPtr userData) =>
329 if (_bondDestroyed != null)
331 BluetoothError res = (BluetoothError)result;
332 _bondDestroyed(null, new BondDestroyedEventArgs(res, deviceAddress));
335 int ret = Interop.Bluetooth.SetBondDestroyedCallback(_bondDestroyedCallback, IntPtr.Zero);
336 if (ret != (int)BluetoothError.None)
338 Log.Error(Globals.LogTag, "Failed to set bond destroyed callback, Error - " + (BluetoothError)ret);
342 private void UnregisterBondDestroyedEvent()
344 int ret = Interop.Bluetooth.UnsetBondDestroyedCallback();
345 if (ret != (int)BluetoothError.None)
347 Log.Error(Globals.LogTag, "Failed to unset bond destroyed callback, Error - " + (BluetoothError)ret);
351 private void RegisterServiceSearchedEvent()
353 _serviceSearchedCallback = (int result, ref BluetoothDeviceSdpStruct sdp, IntPtr userData) =>
355 Log.Info(Globals.LogTag, "Servicesearched cb is called");
356 if (_serviceSearched != null)
358 BluetoothError res = (BluetoothError)result;
359 _serviceSearched(null, new ServiceSearchedEventArgs(res, BluetoothUtils.ConvertStructToSdpData(sdp)));
362 int ret = Interop.Bluetooth.SetServiceSearchedCallback(_serviceSearchedCallback, IntPtr.Zero);
363 if (ret != (int)BluetoothError.None)
365 Log.Error(Globals.LogTag, "Failed to set service searched callback, Error - " + (BluetoothError)ret);
369 private void UnregisterServiceSearchedEvent()
371 int ret = Interop.Bluetooth.UnsetServiceSearchedCallback();
372 if (ret != (int)BluetoothError.None)
374 Log.Error(Globals.LogTag, "Failed to unset service searched callback, Error - " + (BluetoothError)ret);
378 private void RegisterAuthorizationChangedEvent()
380 _authorizationChangedCallback = (int authorization, string deviceAddress, IntPtr userData) =>
382 Log.Info(Globals.LogTag, "Authorization changed cb is called");
383 if (_authorizationChanged != null)
385 BluetoothAuthorizationType auth = (BluetoothAuthorizationType)authorization;
386 _authorizationChanged(null, new AuthorizationChangedEventArgs(auth, deviceAddress));
389 int ret = Interop.Bluetooth.SetAuthorizationChangedCallback(_authorizationChangedCallback, IntPtr.Zero);
390 if (ret != (int)BluetoothError.None)
392 Log.Error(Globals.LogTag, "Failed to set authroization changed callback, Error - " + (BluetoothError)ret);
396 private void UnregisterAuthorizationChangedEvent()
398 int ret = Interop.Bluetooth.UnsetAuthorizationChangedCallback();
399 if (ret != (int)BluetoothError.None)
401 Log.Error(Globals.LogTag, "Failed to unset authroization changed callback, Error - " + (BluetoothError)ret);
405 private void RegisterConnectionChangedEvent()
407 _connectionChangedCallback = (bool connected, ref BluetoothDeviceConnectionStruct device, IntPtr userData) =>
409 Log.Info(Globals.LogTag, "Connection state changed cb is called");
410 if (_connectionChanged != null)
412 _connectionChanged(null, new DeviceConnectionStateChangedEventArgs(connected, BluetoothUtils.ConvertStructToConnectionData(device)));
416 int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionChangedCallback, IntPtr.Zero);
417 if (ret != (int)BluetoothError.None)
419 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
423 private void UnregisterConnectionChangedEvent()
425 int ret = Interop.Bluetooth.UnsetConnectionStateChangedCallback();
426 if (ret != (int)BluetoothError.None)
428 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
433 /// Creates a bond with the remote Bluetooth device.
436 /// The Bluetooth must be enabled and the remote device must be discoverable by StartDiscovery(). The bond can be destroyed by DestroyBond().
437 /// The bonding request can be cancelled by CancelBonding(). If this succeeds, the BondCreated event will be invoked.
439 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
440 /// or when the create bonding process to the remote device fails.</exception>
441 public void CreateBond()
443 if (BluetoothAdapter.IsBluetoothEnabled)
445 int ret = Interop.Bluetooth.CreateBond(RemoteDeviceAddress);
446 if (ret != (int)BluetoothError.None)
448 Log.Error(Globals.LogTag, "Failed to create bond, Error - " + (BluetoothError)ret);
449 BluetoothErrorFactory.ThrowBluetoothException(ret);
455 /// Cancels the bonding process.
458 /// Bonding must be in progress by CreateBond().
460 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
461 /// or when the cancel bonding procedure to remote device fails.</exception>
462 public void CancelBonding()
464 int ret = Interop.Bluetooth.CancelBonding();
465 if (ret != (int)BluetoothError.None)
467 Log.Error(Globals.LogTag, "Failed to cancel bonding process, Error - " + (BluetoothError)ret);
468 BluetoothErrorFactory.ThrowBluetoothException(ret);
473 /// Destroys the bond.
476 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
477 /// If this succeeds, the BondDestroyed event will be invoked.
479 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
480 /// or when the destroy bonding procedure fails.</exception>
481 public void DestroyBond()
483 if (BluetoothAdapter.IsBluetoothEnabled)
485 int ret = Interop.Bluetooth.DestroyBond(RemoteDeviceAddress);
486 if (ret != (int)BluetoothError.None)
488 Log.Error(Globals.LogTag, "Failed to destroy bond, Error - " + (BluetoothError)ret);
489 BluetoothErrorFactory.ThrowBluetoothException(ret);
495 /// Sets an alias for the bonded device.
498 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
500 /// <param name="aliasName">The alias name of the remote device.</param>
501 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
502 /// or when the set alias name to remote device fails.</exception>
503 public void SetAlias(string aliasName)
505 if (BluetoothAdapter.IsBluetoothEnabled)
507 int ret = Interop.Bluetooth.SetAlias(RemoteDeviceAddress, aliasName);
508 if (ret != (int)BluetoothError.None)
510 Log.Error(Globals.LogTag, "Failed to set alias name, Error - " + (BluetoothError)ret);
511 BluetoothErrorFactory.ThrowBluetoothException(ret);
517 /// Sets the authorization of a bonded device.
520 /// The Bluetooth must be enabled and the bond must be created by CreateBond().
521 /// If this succeeds, the AuthorizationChanged event will be invoked.
523 /// <param name="authorizationState">The authorization state.</param>
524 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
525 /// or when the set authorization to remote device fails.</exception>
526 public void SetAuthorization(BluetoothAuthorizationType authorizationState)
528 if (BluetoothAdapter.IsBluetoothEnabled)
530 int ret = Interop.Bluetooth.SetAuthorization(RemoteDeviceAddress, (int)authorizationState);
531 if (ret != (int)BluetoothError.None)
533 Log.Error(Globals.LogTag, "Failed to set authroization state, Error - " + (BluetoothError)ret);
534 BluetoothErrorFactory.ThrowBluetoothException(ret);
540 /// Gets the mask from the UUID.
542 /// <returns>The service mask list converted from the given UUID list.</returns>
543 /// <param name="uuids">The UUID list of the device.</param>
544 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
545 /// or when the get Mask from UUID fails.</exception>
546 public BluetoothServiceClassType GetMaskFromUuid(string[] uuids)
548 BluetoothServiceClassType serviceMask;
550 int ret = Interop.Bluetooth.GetMaskFromUuid(uuids, uuids.Length, out serviceMask);
551 if (ret != (int)BluetoothError.None)
553 Log.Error(Globals.LogTag, "Failed to get service mask, Error - " + (BluetoothError)ret);
554 BluetoothErrorFactory.ThrowBluetoothException(ret);
560 /// Starts the search for services supported by the specified device.
563 /// The Bluetooth must be enabled and remote device must be discoverable by StartDiscovery(). The bond must be created by CreateBond().
564 /// If this succeeds, the ServiceSearched event will be invoked.
566 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
567 /// or when the remote device service search fails.</exception>
568 public void StartServiceSearch()
570 Log.Info(Globals.LogTag, "startservicesearch entry");
571 if (BluetoothAdapter.IsBluetoothEnabled)
573 int ret = Interop.Bluetooth.StartServiceSearch(RemoteDeviceAddress);
574 if (ret != (int)BluetoothError.None)
576 Log.Error(Globals.LogTag, "Failed to start service search, Error - " + (BluetoothError)ret);
577 BluetoothErrorFactory.ThrowBluetoothException(ret);
583 /// Gets the connected profiles.
586 /// The Bluetooth must be enabled.
588 /// <returns>The connected Bluetooth profiles.</returns>
589 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
590 /// or when there is no BT connection.</exception>
591 public IEnumerable<BluetoothProfileType> GetConnectedProfiles()
593 if (BluetoothAdapter.IsBluetoothEnabled)
595 List<BluetoothProfileType> profileList = new List<BluetoothProfileType>();
596 Interop.Bluetooth.ConnectedProfileCallback callback = (int profile, IntPtr userData) =>
598 if (!profile.Equals(null))
600 profileList.Add((BluetoothProfileType)profile);
604 int ret = Interop.Bluetooth.GetConnectedProfiles(RemoteDeviceAddress, callback, IntPtr.Zero);
605 if (ret != (int)BluetoothError.None)
607 Log.Error(Globals.LogTag, "Failed to get connected profiles, Error - " + (BluetoothError)ret);
608 BluetoothErrorFactory.ThrowBluetoothException(ret);
619 /// Determines if profile is connected to the specified remote device.
622 /// The Bluetooth must be enabled.
624 /// <returns><c>true</c> if profile is connected, otherwise <c>false</c>.</returns>
625 /// <param name="profileType">The Bluetooth profile type.</param>
626 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
627 /// or when there is no BT connection.</exception>
628 public bool IsProfileConnected(BluetoothProfileType profileType)
630 if (BluetoothAdapter.IsBluetoothEnabled)
633 int ret = Interop.Bluetooth.IsProfileConnected(RemoteDeviceAddress, (int)profileType, out isConnected);
634 if (ret != (int)BluetoothError.None)
636 Log.Error(Globals.LogTag, "Failed to get profile connected state, Error - " + (BluetoothError)ret);
647 /// Returns the instance of the Bluetooth profile type.
650 /// The Bluetooth must be enabled.
652 public T GetProfile<T>() where T : BluetoothProfile
655 * FIXME: Find a proper way for dynamic allocation.
658 String type = typeof(T).ToString();
659 if (type.Equals("Tizen.Network.Bluetooth.BluetoothAudio"))
661 BluetoothAudio audio = new BluetoothAudio();
662 profile = (audio as T);
664 else if (type.Equals("Tizen.Network.Bluetooth.BluetoothAvrcp"))
666 BluetoothAvrcp avrcp = new BluetoothAvrcp();
667 profile = (avrcp as T);
669 else if (type.Equals("Tizen.Network.Bluetooth.BluetoothHid"))
671 BluetoothHid hid = new BluetoothHid();
672 profile = (hid as T);
675 else if (type.Equals("Tizen.Network.Bluetooth.BluetoothOppClient"))
677 BluetoothOppClient oppClient = new BluetoothOppClient();
678 profile = (oppClient as T);
683 profile.RemoteAddress = RemoteDeviceAddress;
689 /// Creates the client socket.
691 /// <returns>The IBluetoothClientSocket instance.</returns>
692 /// <param name="serviceUuid">The UUID of the service.</param>
693 public IBluetoothClientSocket CreateSocket(string serviceUuid)
695 BluetoothSocket clientSocket = new BluetoothSocket();
696 clientSocket.remoteAddress = this.Address;
697 clientSocket.serviceUuid = serviceUuid;
698 return (IBluetoothClientSocket)clientSocket;