2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
19 using System.Collections.Specialized;
20 using System.Threading.Tasks;
21 using System.Runtime.InteropServices;
23 namespace Tizen.Network.Bluetooth
25 internal class BluetoothLeImplAdapter : IDisposable
27 private static readonly BluetoothLeImplAdapter _instance = new BluetoothLeImplAdapter();
29 private bool disposed = false;
31 private event EventHandler<AdapterLeScanResultChangedEventArgs> _adapterLeScanResultChanged = null;
32 private Interop.Bluetooth.AdapterLeScanResultChangedCallBack _adapterLeScanResultChangedCallback;
34 private event EventHandler<AdvertisingStateChangedEventArgs> _advertisingStateChanged = null;
35 private Interop.Bluetooth.AdvertisingStateChangedCallBack _advertisingStateChangedCallback;
37 private int _serviceListCount = 0;
38 private bool _scanStarted;
40 internal static BluetoothLeImplAdapter Instance
48 private BluetoothLeImplAdapter()
52 ~BluetoothLeImplAdapter()
60 GC.SuppressFinalize(this);
63 private void Dispose(bool disposing)
70 // Free managed objects.
73 //stop scan operation in progress
79 internal event EventHandler<AdapterLeScanResultChangedEventArgs> AdapterLeScanResultChanged
83 _adapterLeScanResultChanged += value;
86 _adapterLeScanResultChanged -= value;
90 internal event EventHandler<AdvertisingStateChangedEventArgs> AdapterLeAdvertisingStateChanged
94 _advertisingStateChanged += value;
98 _advertisingStateChanged -= value;
102 internal int StartScan()
104 _adapterLeScanResultChangedCallback = (int result, ref BluetoothLeScanDataStruct scanData, IntPtr userData) =>
106 Log.Info(Globals.LogTag, "Inside Le scan callback " );
107 BluetoothLeScanData scanDataInfo = BluetoothUtils.ConvertStructToLeScanData(scanData);
109 BluetoothLeDevice device = new BluetoothLeDevice(scanDataInfo);
110 BluetoothError res = (BluetoothError)result;
112 AdapterLeScanResultChangedEventArgs e = new AdapterLeScanResultChangedEventArgs (res,
114 _adapterLeScanResultChanged (null, e);
117 IntPtr data = IntPtr.Zero;
118 int ret = Interop.Bluetooth.StartScan(_adapterLeScanResultChangedCallback, data);
119 if (ret != (int)BluetoothError.None)
121 Log.Error(Globals.LogTag, "Failed to start BLE scan - " + (BluetoothError)ret);
122 BluetoothErrorFactory.ThrowBluetoothException(ret);
128 internal int StopScan()
130 int ret = (int)BluetoothError.None;
134 ret = Interop.Bluetooth.StopScan ();
135 if (ret != (int)BluetoothError.None) {
136 Log.Error (Globals.LogTag, "Failed to stop BLE scan - " + (BluetoothError)ret);
137 BluetoothErrorFactory.ThrowBluetoothException (ret);
143 internal int SetScanMode(BluetoothLeScanMode mode)
145 int ret = (int)BluetoothError.None;
147 ret = Interop.Bluetooth.SetLeScanMode(mode);
148 if (ret != (int)BluetoothError.None) {
149 Log.Error (Globals.LogTag, "Failed to set LE scan mode - " + (BluetoothError)ret);
150 BluetoothErrorFactory.ThrowBluetoothException (ret);
155 internal IList<string> GetLeScanResultServiceUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
157 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
159 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
162 IntPtr uuidListArray = IntPtr.Zero;
164 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
166 int ret = Interop.Bluetooth.GetScanResultServiceUuid(ref scanDataStruct, packetType, ref uuidListArray, ref count);
167 if (ret == (int)BluetoothError.NoData)
169 Log.Info(Globals.LogTag, "No ServiceUuids in " + packetType);
170 Marshal.FreeHGlobal(scanDataStruct.AdvData);
171 Marshal.FreeHGlobal(scanDataStruct.ScanData);
174 else if (ret != (int)BluetoothError.None)
176 Log.Info(Globals.LogTag, "Failed to service uuids list- " + (BluetoothError)ret);
177 Marshal.FreeHGlobal(scanDataStruct.AdvData);
178 Marshal.FreeHGlobal(scanDataStruct.ScanData);
179 BluetoothErrorFactory.ThrowBluetoothException(ret);
182 Log.Info(Globals.LogTag, "Count of ServiceUuids: " + count);
184 IList<string> list = new List<string>();
185 IntPtr[] uuidList = new IntPtr[count];
186 Marshal.Copy(uuidListArray, uuidList, 0, count);
187 foreach (IntPtr uuids in uuidList)
189 list.Add(Marshal.PtrToStringAnsi(uuids));
190 Interop.Libc.Free(uuids);
193 Interop.Libc.Free(uuidListArray);
194 Marshal.FreeHGlobal(scanDataStruct.AdvData);
195 Marshal.FreeHGlobal(scanDataStruct.ScanData);
199 internal string GetLeScanResultDeviceName(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
201 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
203 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
207 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
209 int ret = Interop.Bluetooth.GetLeScanResultDeviceName(ref scanDataStruct, packetType, out deviceName);
210 if (ret == (int)BluetoothError.NoData)
212 Log.Info(Globals.LogTag, "No DeviceName in " + packetType);
213 Marshal.FreeHGlobal(scanDataStruct.AdvData);
214 Marshal.FreeHGlobal(scanDataStruct.ScanData);
217 else if (ret != (int)BluetoothError.None)
219 Log.Error(Globals.LogTag, "Failed to get Device name- " + (BluetoothError)ret);
220 Marshal.FreeHGlobal(scanDataStruct.AdvData);
221 Marshal.FreeHGlobal(scanDataStruct.ScanData);
222 BluetoothErrorFactory.ThrowBluetoothException(ret);
225 Log.Info(Globals.LogTag, "DeviceName: " + deviceName);
226 Marshal.FreeHGlobal(scanDataStruct.AdvData);
227 Marshal.FreeHGlobal(scanDataStruct.ScanData);
231 internal int GetScanResultTxPowerLevel(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
233 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
235 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
239 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
241 int ret = Interop.Bluetooth.GetScanResultTxPowerLevel(ref scanDataStruct, packetType, out powerLevel);
242 if (ret == (int)BluetoothError.NoData)
244 Log.Info(Globals.LogTag, "No TxPowerLevel data in " + packetType);
245 Marshal.FreeHGlobal(scanDataStruct.AdvData);
246 Marshal.FreeHGlobal(scanDataStruct.ScanData);
249 else if (ret != (int)BluetoothError.None)
251 Log.Error(Globals.LogTag, "Failed to get tx power level- " + (BluetoothError)ret);
252 Marshal.FreeHGlobal(scanDataStruct.AdvData);
253 Marshal.FreeHGlobal(scanDataStruct.ScanData);
254 BluetoothErrorFactory.ThrowBluetoothException(ret);
257 Log.Info (Globals.LogTag, "TxPowerLevel: " + powerLevel);
258 Marshal.FreeHGlobal(scanDataStruct.AdvData);
259 Marshal.FreeHGlobal(scanDataStruct.ScanData);
263 internal IList<string> GetScanResultSvcSolicitationUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
265 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
267 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
270 IntPtr uuidListArray;
272 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
274 int ret = Interop.Bluetooth.GetScanResultSvcSolicitationUuids(ref scanDataStruct, packetType, out uuidListArray, out count);
275 if (ret == (int)BluetoothError.NoData)
277 Log.Info(Globals.LogTag, "No ServiceSolicitationUuids in " + packetType);
278 Marshal.FreeHGlobal(scanDataStruct.AdvData);
279 Marshal.FreeHGlobal(scanDataStruct.ScanData);
282 else if (ret != (int)BluetoothError.None)
284 Log.Error(Globals.LogTag, "Failed to get service solicitation uuids " + (BluetoothError)ret);
285 Marshal.FreeHGlobal(scanDataStruct.AdvData);
286 Marshal.FreeHGlobal(scanDataStruct.ScanData);
287 BluetoothErrorFactory.ThrowBluetoothException(ret);
290 Log.Info(Globals.LogTag, "Count of ServiceSolicitationUuids: " + count);
292 IList<string> list = new List<string>();
293 IntPtr[] uuidList = new IntPtr[count];
294 Marshal.Copy(uuidListArray, uuidList, 0, count);
295 foreach (IntPtr uuids in uuidList)
297 list.Add(Marshal.PtrToStringAnsi(uuids));
298 Interop.Libc.Free(uuids);
301 Interop.Libc.Free(uuidListArray);
302 Marshal.FreeHGlobal(scanDataStruct.AdvData);
303 Marshal.FreeHGlobal(scanDataStruct.ScanData);
307 internal IList<BluetoothLeServiceData> GetScanResultServiceDataList(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
309 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
311 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
314 IntPtr serviceListArray;
315 _serviceListCount = 0;
316 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
318 int ret = Interop.Bluetooth.GetScanResultServiceDataList(ref scanDataStruct, packetType, out serviceListArray, out _serviceListCount);
319 if (ret == (int)BluetoothError.NoData)
321 Log.Info(Globals.LogTag, "No ServiceDataList in " + packetType);
322 Marshal.FreeHGlobal(scanDataStruct.AdvData);
323 Marshal.FreeHGlobal(scanDataStruct.ScanData);
326 else if (ret != (int)BluetoothError.None)
328 Log.Info(Globals.LogTag, "Failed to get Service Data List, Error - " + (BluetoothError)ret);
329 Marshal.FreeHGlobal(scanDataStruct.AdvData);
330 Marshal.FreeHGlobal(scanDataStruct.ScanData);
331 BluetoothErrorFactory.ThrowBluetoothException(ret);
334 Log.Info(Globals.LogTag, "Count of ServiceDataList: " + _serviceListCount);
336 IList<BluetoothLeServiceData> list = new List<BluetoothLeServiceData>();
337 int sizePointerToABC = Marshal.SizeOf(new BluetoothLeServiceDataStruct());
338 for (int i = 0; i < _serviceListCount; i++)
340 var svc = (BluetoothLeServiceDataStruct)Marshal.PtrToStructure(new IntPtr(serviceListArray.ToInt32() + (i * sizePointerToABC)), typeof(BluetoothLeServiceDataStruct));
341 list.Add(BluetoothUtils.ConvertStructToLeServiceData(svc));
344 Interop.Bluetooth.FreeServiceDataList(serviceListArray, _serviceListCount);
345 Marshal.FreeHGlobal(scanDataStruct.AdvData);
346 Marshal.FreeHGlobal(scanDataStruct.ScanData);
350 internal int GetScanResultAppearance(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
352 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
354 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
358 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
360 int ret = Interop.Bluetooth.GetScanResultAppearance(ref scanDataStruct, packetType, out appearance);
361 if (ret == (int)BluetoothError.NoData)
363 Log.Info(Globals.LogTag, "No Appearance in " + packetType);
364 Marshal.FreeHGlobal(scanDataStruct.AdvData);
365 Marshal.FreeHGlobal(scanDataStruct.ScanData);
368 else if (ret != (int)BluetoothError.None)
370 Log.Error(Globals.LogTag, "Failed to get Appearance value- " + (BluetoothError)ret);
371 Marshal.FreeHGlobal(scanDataStruct.AdvData);
372 Marshal.FreeHGlobal(scanDataStruct.ScanData);
373 BluetoothErrorFactory.ThrowBluetoothException(ret);
376 Marshal.FreeHGlobal(scanDataStruct.AdvData);
377 Marshal.FreeHGlobal(scanDataStruct.ScanData);
381 internal ManufacturerData GetScanResultManufacturerData(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
383 if (!BluetoothAdapter.IsBluetoothEnabled || !Globals.IsInitialize)
385 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotEnabled);
391 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
393 int ret = Interop.Bluetooth.GetScanResultManufacturerData(ref scanDataStruct, packetType, out dataId, out manufData, out dataLength);
394 if (ret == (int)BluetoothError.NoData)
396 Log.Info(Globals.LogTag, "No ManufacturerData in " + packetType);
397 Marshal.FreeHGlobal(scanDataStruct.AdvData);
398 Marshal.FreeHGlobal(scanDataStruct.ScanData);
401 else if (ret != (int)BluetoothError.None)
403 Log.Error(Globals.LogTag, "Failed to get Manufacturer data - " + (BluetoothError)ret);
404 Marshal.FreeHGlobal(scanDataStruct.AdvData);
405 Marshal.FreeHGlobal(scanDataStruct.ScanData);
406 BluetoothErrorFactory.ThrowBluetoothException(ret);
409 Log.Info(Globals.LogTag, "Count of ManufacturerData: " + dataLength);
411 ManufacturerData data = new ManufacturerData();
413 data.DataLength = dataLength;
414 if (data.DataLength > 0)
416 data.Data = new byte[data.DataLength];
417 Marshal.Copy(manufData, data.Data, 0, data.DataLength);
420 Interop.Libc.Free(manufData);
421 Marshal.FreeHGlobal(scanDataStruct.AdvData);
422 Marshal.FreeHGlobal(scanDataStruct.ScanData);
426 internal int GattConnect(string remoteAddress, bool autoConnect)
428 int ret = Interop.Bluetooth.GattConnect (remoteAddress, autoConnect);
429 if (ret != (int)BluetoothError.None)
431 Log.Error(Globals.LogTag, "Failed to establish GATT connection - " + (BluetoothError)ret);
432 BluetoothErrorFactory.ThrowBluetoothException(ret);
437 internal int GattDisconnect(string remoteAddress)
439 int ret = Interop.Bluetooth.GattDisconnect (remoteAddress);
440 if (ret != (int)BluetoothError.None)
442 Log.Error(Globals.LogTag, "Failed to disconnect GATT connection - " + (BluetoothError)ret);
443 BluetoothErrorFactory.ThrowBluetoothException(ret);
448 internal int CreateAdvertiser(out IntPtr advertiserHandle)
450 return Interop.Bluetooth.CreateAdvertiser (out advertiserHandle);
453 internal int DestroyAdvertiser(IntPtr advertiserHandle)
455 int ret = Interop.Bluetooth.DestroyAdvertiser (advertiserHandle);
456 if (ret != (int)BluetoothError.None) {
457 Log.Error(Globals.LogTag, "Failed to destroy the Advertiser- " + (BluetoothError)ret);
458 BluetoothErrorFactory.ThrowBluetoothException(ret);
463 internal int StartAdvertising(IntPtr advertisingHandle)
465 _advertisingStateChangedCallback = (int result, IntPtr advertiserHandle,
466 BluetoothLeAdvertisingState state, IntPtr userData) =>
468 Log.Info(Globals.LogTag, "Setting advertising state changed callback !! " );
469 AdvertisingStateChangedEventArgs e = new AdvertisingStateChangedEventArgs(result, advertiserHandle, state);
470 _advertisingStateChanged(null, e);
473 IntPtr uData = IntPtr.Zero;
474 int ret = Interop.Bluetooth.BluetoothLeStartAdvertising (advertisingHandle,
475 _advertisingStateChangedCallback, uData );
476 if (ret != (int)BluetoothError.None)
478 Log.Error(Globals.LogTag, "Failed to start BLE advertising - " + (BluetoothError)ret);
479 BluetoothErrorFactory.ThrowBluetoothException(ret);
485 internal int StopAdvertising(IntPtr advertisingHandle)
487 return Interop.Bluetooth.BluetoothLeStopAdvertising (advertisingHandle);