Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothLeAdapterImpl.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.Collections.Specialized;
20 using System.Threading.Tasks;
21 using System.Runtime.InteropServices;
22
23 namespace Tizen.Network.Bluetooth
24 {
25     internal class BluetoothLeImplAdapter : IDisposable
26     {
27         private static readonly BluetoothLeImplAdapter _instance = new BluetoothLeImplAdapter();
28
29         private bool disposed = false;
30
31         private event EventHandler<AdapterLeScanResultChangedEventArgs> _adapterLeScanResultChanged = null;
32         private Interop.Bluetooth.AdapterLeScanResultChangedCallBack _adapterLeScanResultChangedCallback;
33
34         private event EventHandler<AdvertisingStateChangedEventArgs> _advertisingStateChanged = null;
35         private Interop.Bluetooth.AdvertisingStateChangedCallBack _advertisingStateChangedCallback;
36
37         private event EventHandler<GattConnectionStateChangedEventArgs> _gattConnectionStateChanged = null;
38         private Interop.Bluetooth.GattConnectionStateChangedCallBack _gattConnectionStateChangedCallback;
39
40         private int _serviceListCount = 0;
41         private IList<BluetoothLeServiceData> _list = new List<BluetoothLeServiceData>();
42         private bool _scanStarted;
43
44         internal static BluetoothLeImplAdapter Instance
45         {
46             get
47             {
48                 return _instance;
49             }
50         }
51
52         private BluetoothLeImplAdapter()
53         {
54         }
55
56         ~BluetoothLeImplAdapter()
57         {
58             Dispose(false);
59         }
60
61         public void Dispose()
62         {
63             Dispose(true);
64             GC.SuppressFinalize(this);
65         }
66
67         private void Dispose(bool disposing)
68         {
69             if (disposed)
70                 return;
71
72             if (disposing)
73             {
74                 // Free managed objects.
75             }
76             //Free unmanaged objects
77             if (_gattConnectionStateChanged != null)
78             {
79                 UnRegisterGattConnectionStateChangedEvent();
80             }
81
82             //stop scan operation in progress
83             StopScan ();
84
85             disposed = true;
86         }
87
88         internal event EventHandler<AdapterLeScanResultChangedEventArgs> AdapterLeScanResultChanged
89         {
90             add
91             {
92                 _adapterLeScanResultChanged += value;
93             }
94             remove {
95                 _adapterLeScanResultChanged -= value;
96             }
97         }
98
99         internal event EventHandler<AdvertisingStateChangedEventArgs> AdapterLeAdvertisingStateChanged
100         {
101             add
102             {
103                 _advertisingStateChanged += value;
104             }
105             remove
106             {
107                 _advertisingStateChanged -= value;
108             }
109         }
110
111         internal event EventHandler<GattConnectionStateChangedEventArgs> LeGattConnectionStateChanged
112         {
113             add
114             {
115                 if (_gattConnectionStateChanged == null)
116                 {
117                     RegisterGattConnectionStateChangedEvent();
118                 }
119                 _gattConnectionStateChanged += value;
120             }
121             remove
122             {
123                 _gattConnectionStateChanged -= value;
124                 if (_gattConnectionStateChanged == null)
125                 {
126                     UnRegisterGattConnectionStateChangedEvent();
127                 }
128             }
129         }
130
131         internal void RegisterGattConnectionStateChangedEvent()
132         {
133             _gattConnectionStateChangedCallback = (int result, bool connected,
134                                     string remoteDeviceAddress, IntPtr userData) =>
135             {
136                 if (_gattConnectionStateChanged != null)
137                 {
138                     Log.Info(Globals.LogTag, "Setting gatt connection state changed callback" );
139                     GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs (result,
140                         connected, remoteDeviceAddress);
141
142                     _gattConnectionStateChanged(null, e);
143                 }
144             };
145
146             int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(
147                                     _gattConnectionStateChangedCallback, IntPtr.Zero);
148             if (ret != (int)BluetoothError.None)
149             {
150                 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
151             }
152         }
153
154         internal void UnRegisterGattConnectionStateChangedEvent()
155         {
156             int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
157             if (ret != (int)BluetoothError.None)
158             {
159                 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
160             }
161         }
162
163         internal int StartScan()
164         {
165             _adapterLeScanResultChangedCallback = (int result, ref BluetoothLeScanDataStruct scanData, IntPtr userData) =>
166             {
167                 Log.Info(Globals.LogTag, "Inside Le scan callback " );
168                 BluetoothLeScanData scanDataInfo = BluetoothUtils.ConvertStructToLeScanData(scanData);
169
170                 BluetoothLeDevice device = new BluetoothLeDevice(scanDataInfo);
171                 BluetoothError res = (BluetoothError)result;
172
173                 AdapterLeScanResultChangedEventArgs e = new AdapterLeScanResultChangedEventArgs (res,
174                                                                     device);
175                 _adapterLeScanResultChanged (null, e);
176             };
177
178             IntPtr data = IntPtr.Zero;
179             int ret = Interop.Bluetooth.StartScan(_adapterLeScanResultChangedCallback, data);
180             if (ret != (int)BluetoothError.None)
181             {
182                 Log.Error(Globals.LogTag, "Failed to start BLE scan - " + (BluetoothError)ret);
183                 BluetoothErrorFactory.ThrowBluetoothException(ret);
184             }
185             _scanStarted = true;
186             return ret;
187         }
188
189         internal int StopScan()
190         {
191             int ret = (int)BluetoothError.None;
192
193             if (_scanStarted)
194             {
195                 ret = Interop.Bluetooth.StopScan ();
196                 if (ret != (int)BluetoothError.None) {
197                     Log.Error (Globals.LogTag, "Failed to stop BLE scan - " + (BluetoothError)ret);
198                     BluetoothErrorFactory.ThrowBluetoothException (ret);
199                 }
200             }
201             return ret;
202         }
203
204         internal IList<string> GetLeScanResultServiceUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
205         {
206             IntPtr uuidListArray = IntPtr.Zero;
207             int count = -1;
208
209             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
210
211             int ret = Interop.Bluetooth.GetScanResultServiceUuid(ref scanDataStruct, packetType,
212                                                 ref uuidListArray, ref count);
213             if (ret != (int)BluetoothError.None)
214             {
215                 Log.Info(Globals.LogTag, "Failed to service uuids list- " + (BluetoothError)ret);
216                 return null;
217             }
218
219             Log.Info(Globals.LogTag, "count of uuids :  " + count);
220
221             IntPtr[] uuidList = new IntPtr[count];
222             Marshal.Copy(uuidListArray, uuidList, 0, count);
223             IList<string> list = new List<string>();
224             foreach(IntPtr uuids in uuidList)
225             {
226                 list.Add(Marshal.PtrToStringAnsi(uuids));
227                 Interop.Libc.Free(uuids);
228             }
229
230             Interop.Libc.Free(uuidListArray);
231             return list;
232         }
233
234         internal string GetLeScanResultDeviceName(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
235         {
236             string deviceName;
237
238             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
239
240             int ret = Interop.Bluetooth.GetLeScanResultDeviceName(ref scanDataStruct, packetType, out deviceName);
241             if (ret != (int)BluetoothError.None) {
242                 Log.Error(Globals.LogTag, "Failed to get Device name- " + (BluetoothError)ret);
243                 return null;
244             }
245             Log.Info (Globals.LogTag, "Device name " + deviceName);
246             return deviceName;
247         }
248
249         internal int GetScanResultTxPowerLevel(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
250         {
251             int powerLevel = -1;
252             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
253
254             int ret = Interop.Bluetooth.GetScanResultTxPowerLevel(ref scanDataStruct, packetType, out powerLevel);
255             if (ret != (int)BluetoothError.None) {
256                 Log.Error(Globals.LogTag, "Failed to get tx power level- " + (BluetoothError)ret);
257             }
258             Log.Info (Globals.LogTag, "TxPowerLevel is --- " + powerLevel);
259             return powerLevel;
260         }
261
262         internal IList<string> GetScanResultSvcSolicitationUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
263         {
264             IntPtr uuidListArray;
265             int count;
266
267             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
268
269             int ret = Interop.Bluetooth.GetScaResultSvcSolicitationUuids(ref scanDataStruct, packetType, out uuidListArray, out count);
270             if (ret != (int)BluetoothError.None) {
271                 Log.Error(Globals.LogTag, "Failed to get service solicitation uuids " + (BluetoothError)ret);
272                 return null;
273             }
274
275             IntPtr[] uuidList = new IntPtr[count];
276             Marshal.Copy(uuidListArray, uuidList, 0, count);
277             IList<string> list = new List<string>();
278             foreach(IntPtr uuids in uuidList)
279             {
280                 list.Add(Marshal.PtrToStringAnsi(uuids));
281                 Interop.Libc.Free(uuids);
282             }
283
284             Interop.Libc.Free(uuidListArray);
285             return list;
286         }
287
288         internal IList<BluetoothLeServiceData> GetScanResultServiceDataList(BluetoothLeScanData scanData,
289                             BluetoothLePacketType packetType, out int serviceCount)
290         {
291             int ret = 0;
292             IntPtr serviceListArray;
293             _serviceListCount = 0;
294
295             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
296
297             ret = Interop.Bluetooth.GetScanResultServiceDataList(ref scanDataStruct, packetType, out serviceListArray, out _serviceListCount);
298             Log.Info(Globals.LogTag, "ServiceListCount :  " + _serviceListCount + " PacketType : " + packetType + " Error: " + (BluetoothError)ret);
299             if (ret != (int)BluetoothError.None)
300             {
301                 Log.Info(Globals.LogTag, "Failed to get Service Data List, Error - " + (BluetoothError)ret);
302                 serviceCount = 0;
303                 Marshal.FreeHGlobal(serviceListArray);
304                 Marshal.FreeHGlobal(scanDataStruct.AdvData);
305                 Marshal.FreeHGlobal(scanDataStruct.ScanData);
306                 return null;
307             }
308
309             BluetoothLeServiceDataStruct[] svcList = new BluetoothLeServiceDataStruct[_serviceListCount];
310             int sizePointerToABC = Marshal.SizeOf(new BluetoothLeServiceDataStruct());
311             for (int i = 0; i < _serviceListCount; i++)
312             {
313                 svcList[i] = (BluetoothLeServiceDataStruct)Marshal.PtrToStructure(new IntPtr(serviceListArray.ToInt32() + (i * sizePointerToABC)), typeof(BluetoothLeServiceDataStruct));
314                 Log.Info(Globals.LogTag, " Uuid : " + svcList[i].ServiceUuid + "length :  " + svcList[i].ServiceDataLength);
315
316                 _list.Add(BluetoothUtils.ConvertStructToLeServiceData(svcList[i]));
317             }
318
319             serviceCount = _serviceListCount;
320
321             Interop.Libc.Free(serviceListArray);
322             Marshal.FreeHGlobal(scanDataStruct.AdvData);
323             Marshal.FreeHGlobal(scanDataStruct.ScanData);
324             return _list;
325         }
326
327         internal int FreeServiceDataList()
328         {
329             if (_list.Count > 0)
330             {
331                 int iServiceDataSize = Marshal.SizeOf(typeof(BluetoothLeServiceData));
332                 IntPtr structServiceData = Marshal.AllocHGlobal(iServiceDataSize);
333                 Marshal.StructureToPtr(_list, structServiceData, false);
334
335                 int ret = Interop.Bluetooth.FreeServiceDataList(structServiceData, _serviceListCount);
336                 if (ret != (int)BluetoothError.None)
337                 {
338                     Log.Error(Globals.LogTag, "Failed to free Service Data List, Error - " + (BluetoothError)ret);
339                     BluetoothErrorFactory.ThrowBluetoothException(ret);
340                 }
341
342                 Marshal.FreeHGlobal(structServiceData);
343             }
344             return 0;
345         }
346
347         internal int GetScanResultAppearance(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
348         {
349             int appearance;
350
351             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
352
353             int ret = Interop.Bluetooth.GetScanResultAppearance(ref scanDataStruct, packetType, out appearance);
354             if (ret != (int)BluetoothError.None) {
355                 Log.Error(Globals.LogTag, "Failed to get Appearance value- " + (BluetoothError)ret);
356             }
357             return appearance;
358         }
359
360         internal ManufacturerData GetScanResultManufacturerData(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
361         {
362             int dataId = 0;
363             int dataLength = 0;
364             IntPtr manufData;
365
366             BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
367             ManufacturerData data = new ManufacturerData();
368
369             int ret = Interop.Bluetooth.GetScanResultManufacturerData(ref scanDataStruct, packetType, out dataId,
370                 out manufData, out dataLength);
371             if (ret != (int)BluetoothError.None)
372             {
373                 Log.Error(Globals.LogTag, "Failed to get Manufacturer data - " + (BluetoothError)ret);
374                 return null;
375             }
376
377             data.Id = dataId;
378             data.DataLength = dataLength;
379             if (data.DataLength > 0)
380             {
381                 data.Data = new byte[data.DataLength];
382                 Marshal.Copy(manufData, data.Data, 0, data.DataLength);
383             }
384
385             return data;
386         }
387
388         internal int GattConnect(string remoteAddress, bool autoConnect)
389         {
390             int ret = Interop.Bluetooth.GattConnect (remoteAddress, autoConnect);
391             if (ret != (int)BluetoothError.None)
392             {
393                 Log.Error(Globals.LogTag, "Failed to establish GATT connection - " + (BluetoothError)ret);
394                 BluetoothErrorFactory.ThrowBluetoothException(ret);
395             }
396             return ret;
397         }
398
399         internal int GattDisconnect(string remoteAddress)
400         {
401             int ret = Interop.Bluetooth.GattDisconnect (remoteAddress);
402             if (ret != (int)BluetoothError.None)
403             {
404                 Log.Error(Globals.LogTag, "Failed to disconnect GATT connection - " + (BluetoothError)ret);
405                 BluetoothErrorFactory.ThrowBluetoothException(ret);
406             }
407             return ret;
408         }
409
410         internal int CreateAdvertiser(out IntPtr advertiserHandle)
411         {
412             return Interop.Bluetooth.CreateAdvertiser (out advertiserHandle);
413         }
414
415         internal int DestroyAdvertiser(IntPtr advertiserHandle)
416         {
417             int ret =  Interop.Bluetooth.DestroyAdvertiser (advertiserHandle);
418             if (ret != (int)BluetoothError.None) {
419                 Log.Error(Globals.LogTag, "Failed to destroy the Advertiser- " + (BluetoothError)ret);
420                 BluetoothErrorFactory.ThrowBluetoothException(ret);
421             }
422             return ret;
423         }
424
425         internal int StartAdvertising(IntPtr advertisingHandle)
426         {
427             _advertisingStateChangedCallback = (int result, IntPtr advertiserHandle,
428                             BluetoothLeAdvertisingState state, IntPtr userData) =>
429             {
430                 Log.Info(Globals.LogTag, "Setting advertising state changed callback !! " );
431                 AdvertisingStateChangedEventArgs e = new AdvertisingStateChangedEventArgs(result, advertiserHandle, state);
432                 _advertisingStateChanged(null, e);
433             };
434
435             IntPtr uData = IntPtr.Zero;
436             int ret = Interop.Bluetooth.BluetoothLeStartAdvertising (advertisingHandle,
437                                    _advertisingStateChangedCallback, uData );
438             if (ret != (int)BluetoothError.None)
439             {
440                 Log.Error(Globals.LogTag, "Failed to start BLE advertising - " + (BluetoothError)ret);
441                 BluetoothErrorFactory.ThrowBluetoothException(ret);
442             }
443             return ret;
444         }
445
446
447         internal int StopAdvertising(IntPtr advertisingHandle)
448         {
449             return Interop.Bluetooth.BluetoothLeStopAdvertising (advertisingHandle);
450         }
451     }
452 }