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