Merge "[C# Bluetooth]: Add response_needed parameter in eventargs" into tizen
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothDevice.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
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;
23
24 namespace Tizen.Network.Bluetooth
25 {
26     /// <summary>
27     /// A class which 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.
29     /// </summary>
30     /// <privilege> http://tizen.org/privilege/bluetooth </privilege>
31     public class BluetoothDevice
32     {
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;
38
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;
44
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;
57
58         internal BluetoothDevice()
59         {
60         }
61
62         /// <summary>
63         /// Address of device.
64         /// </summary>
65         public string Address
66         {
67             get
68             {
69                 return RemoteDeviceAddress;
70             }
71         }
72         /// <summary>
73         /// Name of device.
74         /// </summary>
75         public string Name
76         {
77             get
78             {
79                 return RemoteDeviceName;
80             }
81         }
82         /// <summary>
83         /// Strength indicator of received signal of device.
84         /// </summary>
85         public int Rssi
86         {
87             get
88             {
89                 return RemoteDeviceRssi;
90             }
91         }
92         /// <summary>
93         /// Class of device.
94         /// </summary>
95         public BluetoothClass Class
96         {
97             get
98             {
99                 return RemoteDeviceClass;
100             }
101         }
102         /// <summary>
103         /// Service UUID list of device.
104         /// </summary>
105         public IEnumerable<string> ServiceUuidList
106         {
107             get
108             {
109                 return RemoteDeviceService;
110             }
111         }
112         /// <summary>
113         /// The number of services.
114         /// </summary>
115         public int ServiceCount
116         {
117             get
118             {
119                 return RemoteDeviceCount;
120             }
121         }
122         /// <summary>
123         /// The paired state of device.
124         /// </summary>
125         public bool IsPaired
126         {
127             get
128             {
129                 return RemotePaired;
130             }
131         }
132         /// <summary>
133         /// The connection state of device.
134         /// </summary>
135         public bool IsConnected
136         {
137             get
138             {
139                 return RemoteConnected;
140             }
141         }
142         /// <summary>
143         /// The authorization state of device.
144         /// </summary>
145         public bool IsAuthorized
146         {
147             get
148             {
149                 return RemoteAuthorized;
150             }
151         }
152         /// <summary>
153         /// Bluetooth Appearance.
154         /// </summary>
155         public BluetoothAppearanceType AppearanceType
156         {
157             get
158             {
159                 return RemoteAppearance;
160             }
161         }
162
163         /// <summary>
164         /// The length of manufacturer data.
165         /// </summary>
166         public int ManufacturerDataLength
167         {
168             get
169             {
170                 return RemoteManufLength;
171             }
172         }
173         /// <summary>
174         /// The manufacturer data.
175         /// </summary>
176         public string ManufacturerData
177         {
178             get
179             {
180                 return RemoteManufData;
181             }
182         }
183
184         /// <summary>
185         /// (event) BondCreated is raised when process of creating bond is finished.
186         /// </summary>
187         public event EventHandler<BondCreatedEventArgs> BondCreated
188         {
189             add
190             {
191                 if (_bondCreated == null)
192                 {
193                     RegisterBondCreatedEvent();
194                 }
195                 _bondCreated += value;
196             }
197             remove
198             {
199                 _bondCreated -= value;
200                 if (_bondCreated == null)
201                 {
202                     UnregisterBondCreatedEvent();
203                 }
204             }
205         }
206
207         /// <summary>
208         /// (event) BondDestroyed is raised when the bond is destroyed.
209         /// </summary>
210         public event EventHandler<BondDestroyedEventArgs> BondDestroyed
211         {
212             add
213             {
214                 if (_bondDestroyed == null)
215                 {
216                     RegisterBondDestroyedEvent();
217                 }
218                 _bondDestroyed += value;
219             }
220             remove
221             {
222                 _bondDestroyed -= value;
223                 if (_bondDestroyed == null)
224                 {
225                     UnregisterBondDestroyedEvent();
226                 }
227             }
228         }
229
230         /// <summary>
231         /// (event) AuthorizationChanged is raised when the authorization of device is changed.
232         /// </summary>
233         public event EventHandler<AuthorizationChangedEventArgs> AuthorizationChanged
234         {
235             add
236             {
237                 if (_authorizationChanged == null)
238                 {
239                     RegisterAuthorizationChangedEvent();
240                 }
241                 _authorizationChanged += value;
242             }
243             remove
244             {
245                 _authorizationChanged -= value;
246                 if (_authorizationChanged == null)
247                 {
248                     UnregisterAuthorizationChangedEvent();
249                 }
250             }
251         }
252
253         /// <summary>
254         /// (event) ServiceSearched is raised when the process of service searched is finished.
255         /// </summary>
256         public event EventHandler<ServiceSearchedEventArgs> ServiceSearched
257         {
258             add
259             {
260                 if (_serviceSearched == null)
261                 {
262                     RegisterServiceSearchedEvent();
263                 }
264                 _serviceSearched += value;
265             }
266             remove
267             {
268                 _serviceSearched -= value;
269                 if (_serviceSearched == null)
270                 {
271                     UnregisterServiceSearchedEvent();
272                 }
273             }
274         }
275
276         /// <summary>
277         /// (event) ConnectionStateChanged is raised when the connection state is changed.
278         /// </summary>
279         public event EventHandler<DeviceConnectionStateChangedEventArgs> ConnectionStateChanged
280         {
281             add
282             {
283                 if (_connectionChanged == null)
284                 {
285                     RegisterConnectionChangedEvent();
286                 }
287                 _connectionChanged += value;
288             }
289             remove
290             {
291                 _connectionChanged -= value;
292                 if (_connectionChanged == null)
293                 {
294                     UnregisterConnectionChangedEvent();
295                 }
296             }
297         }
298
299         private void RegisterBondCreatedEvent()
300         {
301             _bondCreatedCallback = (int result, ref BluetoothDeviceStruct device, IntPtr userData) =>
302             {
303                 if (_bondCreated != null)
304                 {
305                     BluetoothError res = (BluetoothError)result;
306                     _bondCreated(null, new BondCreatedEventArgs(res, BluetoothUtils.ConvertStructToDeviceClass(device)));
307                 }
308             };
309             int ret = Interop.Bluetooth.SetBondCreatedCallback(_bondCreatedCallback, IntPtr.Zero);
310             if (ret != (int)BluetoothError.None)
311             {
312                 Log.Error(Globals.LogTag, "Failed to set bond created callback, Error - " + (BluetoothError)ret);
313             }
314         }
315
316         private void UnregisterBondCreatedEvent()
317         {
318             int ret = Interop.Bluetooth.UnsetBondCreatedCallback();
319             if (ret != (int)BluetoothError.None)
320             {
321                 Log.Error(Globals.LogTag, "Failed to unset bond created callback, Error - " + (BluetoothError)ret);
322             }
323         }
324
325         private void RegisterBondDestroyedEvent()
326         {
327             _bondDestroyedCallback = (int result, string deviceAddress, IntPtr userData) =>
328             {
329                 if (_bondDestroyed != null)
330                 {
331                     BluetoothError res = (BluetoothError)result;
332                     _bondDestroyed(null, new BondDestroyedEventArgs(res, deviceAddress));
333                 }
334             };
335             int ret = Interop.Bluetooth.SetBondDestroyedCallback(_bondDestroyedCallback, IntPtr.Zero);
336             if (ret != (int)BluetoothError.None)
337             {
338                 Log.Error(Globals.LogTag, "Failed to set bond destroyed callback, Error - " + (BluetoothError)ret);
339             }
340         }
341
342         private void UnregisterBondDestroyedEvent()
343         {
344             int ret = Interop.Bluetooth.UnsetBondDestroyedCallback();
345             if (ret != (int)BluetoothError.None)
346             {
347                 Log.Error(Globals.LogTag, "Failed to unset bond destroyed callback, Error - " + (BluetoothError)ret);
348             }
349         }
350
351         private void RegisterServiceSearchedEvent()
352         {
353             _serviceSearchedCallback = (int result, ref BluetoothDeviceSdpStruct sdp, IntPtr userData) =>
354             {
355                 Log.Info(Globals.LogTag, "Servicesearched cb is called");
356                 if (_serviceSearched != null)
357                 {
358                     BluetoothError res = (BluetoothError)result;
359                     _serviceSearched(null, new ServiceSearchedEventArgs(res, BluetoothUtils.ConvertStructToSdpData(sdp)));
360                 }
361             };
362             int ret = Interop.Bluetooth.SetServiceSearchedCallback(_serviceSearchedCallback, IntPtr.Zero);
363             if (ret != (int)BluetoothError.None)
364             {
365                 Log.Error(Globals.LogTag, "Failed to set service searched callback, Error - " + (BluetoothError)ret);
366             }
367         }
368
369         private void UnregisterServiceSearchedEvent()
370         {
371             int ret = Interop.Bluetooth.UnsetServiceSearchedCallback();
372             if (ret != (int)BluetoothError.None)
373             {
374                 Log.Error(Globals.LogTag, "Failed to unset service searched callback, Error - " + (BluetoothError)ret);
375             }
376         }
377
378         private void RegisterAuthorizationChangedEvent()
379         {
380             _authorizationChangedCallback = (int authorization, string deviceAddress, IntPtr userData) =>
381             {
382                 Log.Info(Globals.LogTag, "Authorization changed cb is called");
383                 if (_authorizationChanged != null)
384                 {
385                     BluetoothAuthorizationType auth = (BluetoothAuthorizationType)authorization;
386                     _authorizationChanged(null, new AuthorizationChangedEventArgs(auth, deviceAddress));
387                 }
388             };
389             int ret = Interop.Bluetooth.SetAuthorizationChangedCallback(_authorizationChangedCallback, IntPtr.Zero);
390             if (ret != (int)BluetoothError.None)
391             {
392                 Log.Error(Globals.LogTag, "Failed to set authroization changed callback, Error - " + (BluetoothError)ret);
393             }
394         }
395
396         private void UnregisterAuthorizationChangedEvent()
397         {
398             int ret = Interop.Bluetooth.UnsetAuthorizationChangedCallback();
399             if (ret != (int)BluetoothError.None)
400             {
401                 Log.Error(Globals.LogTag, "Failed to unset authroization changed callback, Error - " + (BluetoothError)ret);
402             }
403         }
404
405         private void RegisterConnectionChangedEvent()
406         {
407             _connectionChangedCallback = (bool connected, ref BluetoothDeviceConnectionStruct device, IntPtr userData) =>
408             {
409                 Log.Info(Globals.LogTag, "Connection state changed cb is called");
410                 if (_connectionChanged != null)
411                 {
412                     _connectionChanged(null, new DeviceConnectionStateChangedEventArgs(connected, BluetoothUtils.ConvertStructToConnectionData(device)));
413                 }
414             };
415
416             int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionChangedCallback, IntPtr.Zero);
417             if (ret != (int)BluetoothError.None)
418             {
419                 Log.Error(Globals.LogTag, "Failed to set connection state changed callback, Error - " + (BluetoothError)ret);
420             }
421         }
422
423         private void UnregisterConnectionChangedEvent()
424         {
425             int ret = Interop.Bluetooth.UnsetConnectionStateChangedCallback();
426             if (ret != (int)BluetoothError.None)
427             {
428                 Log.Error(Globals.LogTag, "Failed to unset connection state changed callback, Error - " + (BluetoothError)ret);
429             }
430         }
431
432         /// <summary>
433         /// Creates a bond with remote Bluetooth device.
434         /// </summary>
435         /// <remarks>
436         /// The Bluetooth must be enabled and 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, BondCreated event will be invoked.
438         /// </remarks>
439         public void CreateBond()
440         {
441             if (BluetoothAdapter.IsBluetoothEnabled)
442             {
443                 int ret = Interop.Bluetooth.CreateBond(RemoteDeviceAddress);
444                 if (ret != (int)BluetoothError.None)
445                 {
446                     Log.Error(Globals.LogTag, "Failed to create bond, Error - " + (BluetoothError)ret);
447                     BluetoothErrorFactory.ThrowBluetoothException(ret);
448                 }
449             }
450         }
451
452         /// <summary>
453         /// Cancels the bonding process.
454         /// </summary>
455         /// <remarks>
456         /// Bonding must be in progress by CreateBond().
457         /// </remarks>
458         public void CancelBonding()
459         {
460             int ret = Interop.Bluetooth.CancelBonding();
461             if (ret != (int)BluetoothError.None)
462             {
463                 Log.Error(Globals.LogTag, "Failed to cancel bonding process, Error - " + (BluetoothError)ret);
464                 BluetoothErrorFactory.ThrowBluetoothException(ret);
465             }
466         }
467
468         /// <summary>
469         /// Destroys the bond.
470         /// </summary>
471         /// <remarks>
472         /// The Bluetooth must be enabled and the bond must be created by CreateBond().
473         /// If this succeeds, BondDestroyed event will be invoked.
474         /// </remarks>
475         public void DestroyBond()
476         {
477             if (BluetoothAdapter.IsBluetoothEnabled)
478             {
479                 int ret = Interop.Bluetooth.DestroyBond(RemoteDeviceAddress);
480                 if (ret != (int)BluetoothError.None)
481                 {
482                     Log.Error(Globals.LogTag, "Failed to destroy bond, Error - " + (BluetoothError)ret);
483                     BluetoothErrorFactory.ThrowBluetoothException(ret);
484                 }
485             }
486         }
487
488         /// <summary>
489         /// Sets an alias for the bonded device.
490         /// </summary>
491         /// <remarks>
492         /// The Bluetooth must be enabled and the bond must be created by CreateBond().
493         /// </remarks>
494         /// <param name="aliasName">Alias name of remote device.</param>
495         public void SetAlias(string aliasName)
496         {
497             if (BluetoothAdapter.IsBluetoothEnabled)
498             {
499                 int ret = Interop.Bluetooth.SetAlias(RemoteDeviceAddress, aliasName);
500                 if (ret != (int)BluetoothError.None)
501                 {
502                     Log.Error(Globals.LogTag, "Failed to set alias name, Error - " + (BluetoothError)ret);
503                     BluetoothErrorFactory.ThrowBluetoothException(ret);
504                 }
505             }
506         }
507
508         /// <summary>
509         /// Sets the authorization of a bonded device.
510         /// </summary>
511         /// <remarks>
512         /// The Bluetooth must be enabled and the bond must be created by CreateBond().
513         /// If this succeeds, AuthorizationChanged event will be invoked.
514         /// </remarks>
515         /// <param name="authorizationState">Authorization state.</param>
516         public void SetAuthorization(BluetoothAuthorizationType authorizationState)
517         {
518             if (BluetoothAdapter.IsBluetoothEnabled)
519             {
520                 int ret = Interop.Bluetooth.SetAuthorization(RemoteDeviceAddress, (int)authorizationState);
521                 if (ret != (int)BluetoothError.None)
522                 {
523                     Log.Error(Globals.LogTag, "Failed to set authroization state, Error - " + (BluetoothError)ret);
524                     BluetoothErrorFactory.ThrowBluetoothException(ret);
525                 }
526             }
527         }
528
529         /// <summary>
530         /// Gets the mask from UUID.
531         /// </summary>
532         /// <returns>The service mask list converted from the given UUID list.</returns>
533         /// <param name="uuids">Uuid list of the device.</param>
534         public BluetoothServiceClassType GetMaskFromUuid(string[] uuids)
535         {
536             BluetoothServiceClassType serviceMask;
537
538             int ret = Interop.Bluetooth.GetMaskFromUuid(uuids, uuids.Length, out serviceMask);
539             if (ret != (int)BluetoothError.None)
540             {
541                 Log.Error(Globals.LogTag, "Failed to get service mask, Error - " + (BluetoothError)ret);
542                 BluetoothErrorFactory.ThrowBluetoothException(ret);
543             }
544             return serviceMask;
545         }
546
547         /// <summary>
548         /// Starts the search for services supported by the specified device.
549         /// </summary>
550         /// <remarks>
551         /// The Bluetooth must be enabled and remote device must be discoverable by StartDiscovery().The bond must be created by CreateBond().
552         /// If this succeeds, ServiceSearched will be invoked.
553         /// </remarks>
554         public void StartServiceSearch()
555         {
556             Log.Info(Globals.LogTag, "startservicesearch entry");
557             if (BluetoothAdapter.IsBluetoothEnabled)
558             {
559                 int ret = Interop.Bluetooth.StartServiceSearch(RemoteDeviceAddress);
560                 if (ret != (int)BluetoothError.None)
561                 {
562                     Log.Error(Globals.LogTag, "Failed to start service search, Error - " + (BluetoothError)ret);
563                     BluetoothErrorFactory.ThrowBluetoothException(ret);
564                 }
565             }
566         }
567
568         /// <summary>
569         /// Gets the connected profiles.
570         /// </summary>
571         /// <remarks>
572         /// The Bluetooth must be enabled.
573         /// </remarks>
574         /// <returns>The connected Bluetooth profiles.</returns>
575         public IEnumerable<BluetoothProfileType> GetConnectedProfiles()
576         {
577             if (BluetoothAdapter.IsBluetoothEnabled)
578             {
579                 List<BluetoothProfileType> profileList = new List<BluetoothProfileType>();
580                 Interop.Bluetooth.ConnectedProfileCallback callback = (int profile, IntPtr userData) =>
581                 {
582                     if (!profile.Equals(null))
583                     {
584                         profileList.Add((BluetoothProfileType)profile);
585                     }
586                     return true;
587                 };
588                 int ret = Interop.Bluetooth.GetConnectedProfiles(RemoteDeviceAddress, callback, IntPtr.Zero);
589                 if (ret != (int)BluetoothError.None)
590                 {
591                     Log.Error(Globals.LogTag, "Failed to get connected profiles, Error - " + (BluetoothError)ret);
592                     BluetoothErrorFactory.ThrowBluetoothException(ret);
593                 }
594                 return profileList;
595             }
596             else
597             {
598                 return null;
599             }
600         }
601
602         /// <summary>
603         /// Determines if profile is connected to the specified remote device.
604         /// </summary>
605         /// <remarks>
606         /// The Bluetooth must be enabled.
607         /// </remarks>
608         /// <returns><c>true</c> if profile is connected; otherwise, <c>false</c>.</returns>
609         /// <param name="profileType">Bluetooth Profile type.</param>
610         public bool IsProfileConnected(BluetoothProfileType profileType)
611         {
612             if (BluetoothAdapter.IsBluetoothEnabled)
613             {
614                 bool isConnected;
615                 int ret = Interop.Bluetooth.IsProfileConnected(RemoteDeviceAddress, (int)profileType, out isConnected);
616                 if (ret != (int)BluetoothError.None)
617                 {
618                     Log.Error(Globals.LogTag, "Failed to get profile connected state, Error - " + (BluetoothError)ret);
619                 }
620                 return isConnected;
621             }
622             else
623             {
624                 return false;
625             }
626         }
627
628         /// <summary>
629         /// Returns the instance of Bluetooth profile type.
630         /// </summary>
631         /// <remarks>
632         /// The Bluetooth must be enabled.
633         /// </remarks>
634         public T GetProfile<T>() where T : BluetoothProfile
635         {
636             /*
637              * FIXME: Find a proper way for dynamic allocation.
638              */
639             T profile = null;
640             String type = typeof(T).ToString();
641             if (type.Equals("Tizen.Network.Bluetooth.BluetoothAudio"))
642             {
643                 BluetoothAudio audio = new BluetoothAudio();
644                 profile = (audio as T);
645             }
646             else if (type.Equals("Tizen.Network.Bluetooth.BluetoothAvrcp"))
647             {
648                 BluetoothAvrcp avrcp = new BluetoothAvrcp();
649                 profile = (avrcp as T);
650             }
651             else if (type.Equals("Tizen.Network.Bluetooth.BluetoothHid"))
652             {
653                 BluetoothHid hid = new BluetoothHid();
654                 profile = (hid as T);
655             }
656
657             if (profile != null)
658             {
659                 profile.RemoteAddress = RemoteDeviceAddress;
660             }
661             return profile;
662         }
663
664         /// <summary>
665         /// Creates the client socket.
666         /// </summary>
667         /// <returns>The IBluetoothClientSocket instance.</returns>
668         /// <param name="serviceUuid">The UUID of service.</param>
669         public IBluetoothClientSocket CreateSocket(string serviceUuid)
670         {
671             BluetoothSocket clientSocket = new BluetoothSocket();
672             clientSocket.remoteAddress = this.Address;
673             clientSocket.serviceUuid = serviceUuid;
674             return (IBluetoothClientSocket)clientSocket;
675         }
676     }
677 }