[Bluetooth][Non-ACR] Define Interop callback to global variable (#2005)
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothAdapterImpl.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
21 namespace Tizen.Network.Bluetooth
22 {
23     static internal class Globals
24     {
25         internal const string LogTag = "Tizen.Network.Bluetooth";
26         internal static bool IsInitialize = false;
27         internal static bool IsAudioInitialize = false;
28         internal static bool IsHidInitialize = false;
29         internal static bool IsOppServerInitialized = false;
30         internal static bool IsOppClientInitialized = false;
31     }
32
33     internal partial class BluetoothAdapterImpl : IDisposable
34     {
35         private event EventHandler<StateChangedEventArgs> _stateChanged;
36         private event EventHandler<NameChangedEventArgs> _nameChanged;
37         private event EventHandler<VisibilityModeChangedEventArgs> _visibilityModeChanged;
38         private event EventHandler<VisibilityDurationChangedEventArgs> _visibilityDurationChanged;
39         private event EventHandler<DiscoveryStateChangedEventArgs> _discoveryStateChanged;
40
41         private Interop.Bluetooth.StateChangedCallback _stateChangedCallback;
42         private Interop.Bluetooth.NameChangedCallback _nameChangedCallback;
43         private Interop.Bluetooth.VisibilityModeChangedCallback _visibilityChangedCallback;
44         private Interop.Bluetooth.VisibilityDurationChangedCallback _visibilitydurationChangedCallback;
45         private Interop.Bluetooth.DiscoveryStateChangedCallback _discoveryStateChangedCallback;
46         private Interop.Bluetooth.BondedDeviceCallback _bondedDeviceCallback;
47
48         private static readonly BluetoothAdapterImpl _instance = new BluetoothAdapterImpl();
49         private bool disposed = false;
50
51         internal event EventHandler<StateChangedEventArgs> StateChanged
52         {
53             add
54             {
55                 if (_stateChanged == null)
56                 {
57                     RegisterStateChangedEvent();
58                 }
59                 _stateChanged += value;
60             }
61             remove
62             {
63                 _stateChanged -= value;
64                 if (_stateChanged == null)
65                 {
66                     UnregisterStateChangedEvent();
67                 }
68             }
69         }
70
71         internal event EventHandler<NameChangedEventArgs> NameChanged
72         {
73             add
74             {
75                 if (_nameChanged == null)
76                 {
77                     RegisterNameChangedEvent();
78                 }
79                 _nameChanged += value;
80             }
81             remove
82             {
83                 _nameChanged -= value;
84                 if (_nameChanged == null)
85                 {
86                     UnregisterNameChangedEvent();
87                 }
88             }
89         }
90
91         internal event EventHandler<VisibilityModeChangedEventArgs> VisibilityModeChanged
92         {
93             add
94             {
95                 if (_visibilityModeChanged == null)
96                 {
97                     RegisterVisibilityChangedEvent();
98                 }
99                 _visibilityModeChanged += value;
100             }
101             remove
102             {
103                 _visibilityModeChanged -= value;
104                 if (_visibilityModeChanged == null)
105                 {
106                     UnregisterVisibilityChangedEvent();
107                 }
108             }
109         }
110
111         internal event EventHandler<VisibilityDurationChangedEventArgs> VisibilityDurationChanged
112         {
113             add
114             {
115                 if (_visibilityDurationChanged == null)
116                 {
117                     RegisterVisibilityDurationChangedEvent();
118                 }
119                 _visibilityDurationChanged += value;
120             }
121             remove
122             {
123                 _visibilityDurationChanged -= value;
124                 if (_visibilityDurationChanged == null)
125                 {
126                     UnregisterVisibilityDurationChangedEvent();
127                 }
128             }
129         }
130
131         internal event EventHandler<DiscoveryStateChangedEventArgs> DiscoveryStateChanged
132         {
133             add
134             {
135                 if (_discoveryStateChanged == null)
136                 {
137                     RegisterDiscoveryStateChangedEvent();
138                 }
139                 _discoveryStateChanged+= value;
140             }
141             remove
142             {
143                 _discoveryStateChanged -= value;
144                 if (_discoveryStateChanged == null)
145                 {
146                     UnregisterDiscoveryStateChangedEvent();
147                 }
148             }
149         }
150
151         private void RegisterStateChangedEvent()
152         {
153             _stateChangedCallback = (int result, int state, IntPtr userData) =>
154             {
155                 if (_stateChanged != null)
156                 {
157                     BluetoothState st = (BluetoothState)state;
158                     BluetoothError res = (BluetoothError)result;
159                     _stateChanged(null, new StateChangedEventArgs(res,st));
160                 }
161             };
162             int ret = Interop.Bluetooth.SetStateChangedCallback(_stateChangedCallback, IntPtr.Zero);
163             if (ret != (int)BluetoothError.None)
164             {
165                 Log.Error(Globals.LogTag, "Failed to set state changed callback, Error - " + (BluetoothError)ret);
166             }
167         }
168
169         private void UnregisterStateChangedEvent()
170         {
171             int ret = Interop.Bluetooth.UnsetStateChangedCallback();
172             if (ret != (int)BluetoothError.None)
173             {
174                 Log.Error(Globals.LogTag, "Failed to unset state changed callback, Error - " + (BluetoothError)ret);
175             }
176         }
177
178         private void RegisterNameChangedEvent()
179         {
180             _nameChangedCallback = (string deviceName, IntPtr userData) =>
181             {
182                 if (_nameChanged != null)
183                 {
184                     _nameChanged(null, new NameChangedEventArgs(deviceName));
185                 }
186             };
187             int ret = Interop.Bluetooth.SetNameChangedCallback(_nameChangedCallback, IntPtr.Zero);
188             if (ret != (int)BluetoothError.None)
189             {
190                 Log.Error(Globals.LogTag, "Failed to set name changed callback, Error - " + (BluetoothError)ret);
191             }
192         }
193
194         private void UnregisterNameChangedEvent()
195         {
196             int ret = Interop.Bluetooth.UnsetNameChangedCallback();
197             if (ret != (int)BluetoothError.None)
198             {
199                 Log.Error(Globals.LogTag, "Failed to unset name changed callback, Error - " + (BluetoothError)ret);
200             }
201         }
202
203         private void RegisterVisibilityChangedEvent()
204         {
205             _visibilityChangedCallback = (int result, int mode, IntPtr userData) =>
206             {
207                 if (_visibilityModeChanged != null)
208                 {
209                     VisibilityMode visibility = (VisibilityMode)mode;
210                     BluetoothError res = (BluetoothError)result;
211                     _visibilityModeChanged(null, new VisibilityModeChangedEventArgs(res,visibility));
212                 }
213             };
214             int ret = Interop.Bluetooth.SetVisibilityModeChangedCallback(_visibilityChangedCallback, IntPtr.Zero);
215             if (ret != (int)BluetoothError.None)
216             {
217                 Log.Error(Globals.LogTag, "Failed to set visibility mode changed callback, Error - " + (BluetoothError)ret);
218             }
219         }
220
221         private void UnregisterVisibilityChangedEvent()
222         {
223             int ret = Interop.Bluetooth.UnsetVisibilityModeChangedCallback();
224             if (ret != (int)BluetoothError.None)
225             {
226                 Log.Error(Globals.LogTag, "Failed to unset visibility mode changed callback, Error - " + (BluetoothError)ret);
227             }
228         }
229
230         private void RegisterVisibilityDurationChangedEvent()
231         {
232             _visibilitydurationChangedCallback = (int duration, IntPtr userData) =>
233             {
234                 if (_visibilityDurationChanged != null)
235                 {
236                     _visibilityDurationChanged(null, new VisibilityDurationChangedEventArgs(duration));
237                 }
238             };
239             int ret = Interop.Bluetooth.SetVisibilityDurationChangedCallback(_visibilitydurationChangedCallback, IntPtr.Zero);
240             if (ret != (int)BluetoothError.None)
241             {
242                 Log.Error(Globals.LogTag, "Failed to set visibility duration changed callback, Error - " + (BluetoothError)ret);
243             }
244         }
245
246         private void UnregisterVisibilityDurationChangedEvent()
247         {
248             int ret = Interop.Bluetooth.UnsetVisibilityDurationChangedCallback();
249             if (ret != (int)BluetoothError.None)
250             {
251                 Log.Error(Globals.LogTag, "Failed to unset visiiblity duration changed callback, Error - " + (BluetoothError)ret);
252             }
253         }
254
255         private void RegisterDiscoveryStateChangedEvent()
256         {
257             _discoveryStateChangedCallback = (int result, BluetoothDeviceDiscoveryState state, IntPtr deviceInfo, IntPtr userData) =>
258             {
259                 Log.Info(Globals.LogTag, "Discovery state changed callback is called");
260                 if (_discoveryStateChanged != null)
261                 {
262                     BluetoothError res = (BluetoothError)result;
263                     switch(state)
264                     {
265                     case BluetoothDeviceDiscoveryState.Started:
266                         _discoveryStateChanged(null, new DiscoveryStateChangedEventArgs(res,state));
267                         break;
268                     case BluetoothDeviceDiscoveryState.Finished:
269                         {
270                             _discoveryStateChanged(null, new DiscoveryStateChangedEventArgs(res,state));
271                             break;
272                         }
273                     case BluetoothDeviceDiscoveryState.Found:
274                         {
275                             BluetoothDiscoveredDeviceStruct info = (BluetoothDiscoveredDeviceStruct)Marshal.PtrToStructure(deviceInfo, typeof(BluetoothDiscoveredDeviceStruct));
276                             _discoveryStateChanged(null, new DiscoveryStateChangedEventArgs(res,state,BluetoothUtils.ConvertStructToDiscoveredDevice(info)));
277                             break;
278                         }
279                     default:
280                         break;
281                     }
282                 }
283             };
284             int ret = Interop.Bluetooth.SetDiscoveryStateChangedCallback(_discoveryStateChangedCallback, IntPtr.Zero);
285             if (ret != (int)BluetoothError.None)
286             {
287                 Log.Error(Globals.LogTag, "Failed to set discovery state changed callback, Error - " + (BluetoothError)ret);
288             }
289         }
290
291         private void UnregisterDiscoveryStateChangedEvent()
292         {
293             int ret = Interop.Bluetooth.UnsetDiscoveryStateChangedCallback();
294             if (ret != (int)BluetoothError.None)
295             {
296                 Log.Error(Globals.LogTag, "Failed to unset discovery state changed callback, Error - " + (BluetoothError)ret);
297             }
298         }
299
300         internal bool IsBluetoothEnabled
301         {
302             get
303             {
304                 BluetoothState active;
305                 int ret = Interop.Bluetooth.GetState(out active);
306                 if (ret != (int)BluetoothError.None)
307                 {
308                     Log.Error(Globals.LogTag, "Failed to get state, Error - " + (BluetoothError)ret);
309                 }
310                 if (active == BluetoothState.Enabled)
311                     return true;
312                 else
313                     return false;
314             }
315         }
316         internal string Address
317         {
318             get
319             {
320                 string address;
321                 int ret = Interop.Bluetooth.GetAddress(out address);
322                 if (ret != (int)BluetoothError.None)
323                 {
324                     Log.Error(Globals.LogTag, "Failed to get address, Error - " + (BluetoothError)ret);
325                     return "";
326                 }
327                 return address;
328             }
329         }
330
331         internal VisibilityMode Visibility
332         {
333             get
334             {
335                 int visibilityMode;
336                 int time;
337                 int ret = Interop.Bluetooth.GetVisibility(out visibilityMode, out time);
338                 if(ret != (int)BluetoothError.None)
339                 {
340                     Log.Error(Globals.LogTag, "Failed to get visibility mode, Error - " + (BluetoothError)ret);
341                     return VisibilityMode.NonDiscoverable;
342                 }
343                 return (VisibilityMode)visibilityMode;
344             }
345         }
346
347         internal bool IsDiscoveryInProgress
348         {
349             get
350             {
351                 bool isDiscovering;
352                 int ret = Interop.Bluetooth.IsDiscovering(out isDiscovering);
353                 if(ret != (int)BluetoothError.None)
354                 {
355                     Log.Error(Globals.LogTag, "Failed to get discovery progress state, Error - " + (BluetoothError)ret);
356                 }
357                 return isDiscovering;
358             }
359         }
360
361         internal int RemainingTimeAsVisible
362         {
363             get
364             {
365                 int duration = 0;
366                 int visibilityMode;
367                 int ret = Interop.Bluetooth.GetVisibility(out visibilityMode, out duration);
368                 if ((ret != (int)BluetoothError.None) || ((VisibilityMode)visibilityMode != VisibilityMode.TimeLimitedDiscoverable))
369                 {
370                     Log.Error(Globals.LogTag, "Failed to get remaining visible time, Error - " + (BluetoothError)ret);
371                 }
372                 return duration;
373             }
374         }
375
376         internal string Name
377         {
378             get
379             {
380                 string name;
381                 int ret = Interop.Bluetooth.GetName(out name);
382                 if (ret != (int)BluetoothError.None)
383                 {
384                     Log.Error(Globals.LogTag, "Failed to get adapter name, Error - " + (BluetoothError)ret);
385                     return "";
386                 }
387                 return name;
388             }
389             set
390             {
391                 int ret = Interop.Bluetooth.SetName(value.ToString());
392                 if (ret != (int)BluetoothError.None)
393                 {
394                     Log.Error(Globals.LogTag, "Failed to set adapter name, Error - " + (BluetoothError)ret);
395                     BluetoothErrorFactory.ThrowBluetoothException(ret);
396                 }
397             }
398         }
399
400         internal void Enable()
401         {
402             if (Globals.IsInitialize)
403             {
404                 int ret = Interop.Bluetooth.EnableAdapter();
405                 if (ret != (int)BluetoothError.None)
406                 {
407                     Log.Error(Globals.LogTag, "Failed to enable adapter, Error - " + (BluetoothError)ret);
408                     BluetoothErrorFactory.ThrowBluetoothException(ret);
409                 }
410             }
411             else
412             {
413                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
414             }
415         }
416
417         internal void Disable()
418         {
419             if (IsBluetoothEnabled)
420             {
421                 int ret = Interop.Bluetooth.DisableAdapter();
422                 if (ret != (int)BluetoothError.None)
423                 {
424                     Log.Error(Globals.LogTag, "Failed to disable adapter, Error - " + (BluetoothError)ret);
425                     BluetoothErrorFactory.ThrowBluetoothException(ret);
426                 }
427             }
428             else
429             {
430                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
431             }
432         }
433
434         internal void SetVisibility(VisibilityMode mode, int timeout)
435         {
436             if (IsBluetoothEnabled)
437             {
438                 int ret = Interop.Bluetooth.SetVisibility(mode, timeout);
439                 if (ret != (int)BluetoothError.None)
440                 {
441                     Log.Error(Globals.LogTag, "Failed to set visibility, Error - " + (BluetoothError)ret);
442                     BluetoothErrorFactory.ThrowBluetoothException(ret);
443                 }
444             }
445             else
446             {
447                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
448             }
449         }
450
451         internal void StartDiscovery()
452         {
453             int ret = Interop.Bluetooth.StartDiscovery();
454             if (ret != (int)BluetoothError.None)
455             {
456                 Log.Error(Globals.LogTag, "Failed to start discovery, Error - " + (BluetoothError)ret);
457                 BluetoothErrorFactory.ThrowBluetoothException(ret);
458             }
459         }
460
461         internal void StopDiscovery()
462         {
463             int ret = Interop.Bluetooth.StopDiscovery();
464             if(ret != (int)BluetoothError.None)
465             {
466                 Log.Error(Globals.LogTag, "Failed to stop discovery, Error - " + (BluetoothError)ret);
467                 BluetoothErrorFactory.ThrowBluetoothException(ret);
468             }
469         }
470
471         internal IEnumerable<BluetoothDevice> GetBondedDevices()
472         {
473             List<BluetoothDevice> deviceList = new List<BluetoothDevice>();
474             _bondedDeviceCallback = (ref BluetoothDeviceStruct deviceInfo, IntPtr userData) =>
475             {
476                 Log.Info(Globals.LogTag, "Bonded devices cb is called");
477                 if(!deviceInfo.Equals(null))
478                 {
479                     deviceList.Add(BluetoothUtils.ConvertStructToDeviceClass(deviceInfo));
480                 }
481                 return true;
482             };
483             int ret = Interop.Bluetooth.GetBondedDevices(_bondedDeviceCallback, IntPtr.Zero);
484             if(ret != (int)BluetoothError.None)
485             {
486                 Log.Error(Globals.LogTag, "Failed to get bonded devices, Error - " + (BluetoothError)ret);
487                 BluetoothErrorFactory.ThrowBluetoothException(ret);
488             }
489             return deviceList;
490         }
491
492         internal BluetoothDevice GetBondedDevice(string address)
493         {
494             IntPtr deviceInfo;
495             int ret = Interop.Bluetooth.GetBondedDeviceByAddress(address, out deviceInfo);
496             if(ret != (int)BluetoothError.None)
497             {
498                 Log.Error(Globals.LogTag, "Failed to get bonded device by address, Error - " + (BluetoothError)ret);
499                 BluetoothErrorFactory.ThrowBluetoothException(ret);
500             }
501             BluetoothDeviceStruct device = (BluetoothDeviceStruct)Marshal.PtrToStructure(deviceInfo, typeof(BluetoothDeviceStruct));
502
503             Interop.Bluetooth.FreeDeviceInfo(deviceInfo);
504             return BluetoothUtils.ConvertStructToDeviceClass(device);
505         }
506
507         internal bool IsServiceUsed(string serviceUuid)
508         {
509             bool isUsed;
510             int ret = Interop.Bluetooth.IsServiceUsed(serviceUuid, out isUsed);
511             if(ret != (int)BluetoothError.None)
512             {
513                 Log.Error(Globals.LogTag, "Failed to check the usage of service, Error - " + (BluetoothError)ret);
514             }
515             return isUsed;
516         }
517
518         internal BluetoothOobData GetLocalOobData()
519         {
520             BluetoothOobData oobData = new BluetoothOobData();
521             IntPtr hash;
522             IntPtr randomizer;
523             int hashLength;
524             int randomizerLength;
525             int ret = Interop.Bluetooth.GetOobData(out hash, out randomizer, out hashLength, out randomizerLength);
526             if(ret != (int)BluetoothError.None)
527             {
528                 Log.Error(Globals.LogTag, "Failed to get the local oob data, Error - " + (BluetoothError)ret);
529                 BluetoothErrorFactory.ThrowBluetoothException(ret);
530             }
531
532             byte[] hashArr = new byte[hashLength];
533             Marshal.Copy(hash, hashArr, 0, hashLength);
534             byte[] randomizerArr = new byte[randomizerLength];
535             Marshal.Copy(randomizer, randomizerArr, 0, randomizerLength);
536
537             oobData.HashValue = hashArr;
538             oobData.RandomizerValue = randomizerArr;
539             return oobData;
540         }
541
542         internal void SetRemoteOobData(string deviceAddress, BluetoothOobData oobData)
543         {
544             byte[] hash = oobData.HashValue;
545             byte[] randomizer = oobData.RandomizerValue;
546             int hashLength = hash.Length;
547             int randomizerLength = randomizer.Length;
548
549             IntPtr hashPtr = Marshal.AllocHGlobal(hashLength);
550             Marshal.Copy(hash, 0, hashPtr, hashLength);
551             IntPtr randomizerPtr = Marshal.AllocHGlobal(randomizerLength);
552             Marshal.Copy(randomizer, 0, randomizerPtr, randomizerLength);
553
554             int ret = Interop.Bluetooth.SetOobData(deviceAddress, hashPtr, randomizerPtr, hashLength, randomizerLength);
555             if(ret != (int)BluetoothError.None)
556             {
557                 Log.Error(Globals.LogTag, "Failed to set the remote oob data, Error - " + (BluetoothError)ret);
558                 BluetoothErrorFactory.ThrowBluetoothException(ret);
559             }
560         }
561
562         internal void RemoveRemoteOobData(string deviceAddress)
563         {
564             int ret = Interop.Bluetooth.RemoveOobData(deviceAddress);
565             if(ret != (int)BluetoothError.None)
566             {
567                 Log.Error(Globals.LogTag, "Failed to remove the remote oob data, Error - " + (BluetoothError)ret);
568                 BluetoothErrorFactory.ThrowBluetoothException(ret);
569             }
570         }
571
572         internal BluetoothServerSocket CreateServerSocket(string serviceUuid)
573         {
574             int socketFd;
575             int ret = Interop.Bluetooth.CreateServerSocket(serviceUuid, out socketFd);
576             if(ret != (int)BluetoothError.None)
577             {
578                 Log.Error(Globals.LogTag, "Failed to create server socket, Error - " + (BluetoothError)ret);
579                 BluetoothErrorFactory.ThrowBluetoothException(ret);
580             }
581             Log.Info (Globals.LogTag, "Created socketfd: "+ socketFd);
582             return new BluetoothServerSocket(socketFd);
583         }
584
585         internal void DestroyServerSocket(BluetoothServerSocket socket)
586         {
587             int ret = Interop.Bluetooth.DestroyServerSocket(socket.socketFd);
588             if (ret != (int)BluetoothError.None)
589             {
590                 Log.Error(Globals.LogTag, "Failed to destroy socket, Error - " + (BluetoothError)ret);
591                 BluetoothErrorFactory.ThrowBluetoothException(ret);
592             }
593         }
594
595         internal static BluetoothAdapterImpl Instance
596         {
597             get
598             {
599                 return _instance;
600             }
601         }
602
603         private BluetoothAdapterImpl()
604         {
605             initialize();
606         }
607
608         ~BluetoothAdapterImpl()
609         {
610             Dispose(false);
611         }
612
613         public void Dispose()
614         {
615             Dispose(true);
616             GC.SuppressFinalize(this);
617         }
618
619         private void Dispose(bool disposing)
620         {
621             if (disposed)
622                 return;
623
624             if (disposing)
625             {
626                 // Free managed objects.
627             }
628             //Free unmanaged objects
629             RemoveAllRegisteredEvent();
630             deinitialize();
631             disposed = true;
632         }
633
634         private void initialize()
635         {
636             int ret = Interop.Bluetooth.Initialize();
637             if (ret != (int)BluetoothError.None)
638             {
639                 Log.Error (Globals.LogTag, "Failed to initialize bluetooth, Error - " + (BluetoothError)ret);
640                 BluetoothErrorFactory.ThrowBluetoothException (ret);
641             }
642             else
643             {
644                 Globals.IsInitialize = true;
645             }
646         }
647
648         private void deinitialize()
649         {
650             int ret = Interop.Bluetooth.Deinitialize();
651             if (ret != (int)BluetoothError.None)
652             {
653                 Log.Error (Globals.LogTag, "Failed to deinitialize bluetooth, Error - " + (BluetoothError)ret);
654             }
655             else
656             {
657                 Globals.IsInitialize = false;
658             }
659         }
660
661         private void RemoveAllRegisteredEvent()
662         {
663             //unregister all remaining events when this object is released.
664             if (_stateChanged != null)
665             {
666                 UnregisterStateChangedEvent();
667             }
668
669             if (_nameChanged != null)
670             {
671                 UnregisterNameChangedEvent();
672             }
673
674             if (_visibilityDurationChanged != null)
675             {
676                 UnregisterVisibilityDurationChangedEvent();
677             }
678
679             if (_visibilityModeChanged != null)
680             {
681                 UnregisterVisibilityChangedEvent();
682             }
683
684             if (_discoveryStateChanged != null)
685             {
686                 UnregisterDiscoveryStateChangedEvent();
687             }
688         }
689     }
690 }