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