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 event EventHandler<GattConnectionStateChangedEventArgs> _gattConnectionStateChanged = null;
38 private Interop.Bluetooth.GattConnectionStateChangedCallBack _gattConnectionStateChangedCallback;
40 private int _serviceListCount = 0;
41 private IList<BluetoothLeServiceData> _list = new List<BluetoothLeServiceData>();
42 private bool _scanStarted;
44 internal static BluetoothLeImplAdapter Instance
52 private BluetoothLeImplAdapter()
56 ~BluetoothLeImplAdapter()
64 GC.SuppressFinalize(this);
67 private void Dispose(bool disposing)
74 // Free managed objects.
76 //Free unmanaged objects
77 if (_gattConnectionStateChanged != null)
79 UnRegisterGattConnectionStateChangedEvent();
82 //stop scan operation in progress
88 internal event EventHandler<AdapterLeScanResultChangedEventArgs> AdapterLeScanResultChanged
92 _adapterLeScanResultChanged += value;
95 _adapterLeScanResultChanged -= value;
99 internal event EventHandler<AdvertisingStateChangedEventArgs> AdapterLeAdvertisingStateChanged
103 _advertisingStateChanged += value;
107 _advertisingStateChanged -= value;
111 internal event EventHandler<GattConnectionStateChangedEventArgs> LeGattConnectionStateChanged
115 if (_gattConnectionStateChanged == null)
117 RegisterGattConnectionStateChangedEvent();
119 _gattConnectionStateChanged += value;
123 _gattConnectionStateChanged -= value;
124 if (_gattConnectionStateChanged == null)
126 UnRegisterGattConnectionStateChangedEvent();
131 internal void RegisterGattConnectionStateChangedEvent()
133 _gattConnectionStateChangedCallback = (int result, bool connected,
134 string remoteDeviceAddress, IntPtr userData) =>
136 if (_gattConnectionStateChanged != null)
138 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback" );
139 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs (result,
140 connected, remoteDeviceAddress);
142 _gattConnectionStateChanged(null, e);
146 int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(
147 _gattConnectionStateChangedCallback, IntPtr.Zero);
148 if (ret != (int)BluetoothError.None)
150 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
154 internal void UnRegisterGattConnectionStateChangedEvent()
156 int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
157 if (ret != (int)BluetoothError.None)
159 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
163 internal int StartScan()
165 _adapterLeScanResultChangedCallback = (int result, ref BluetoothLeScanDataStruct scanData, IntPtr userData) =>
167 Log.Info(Globals.LogTag, "Inside Le scan callback " );
168 BluetoothLeScanData scanDataInfo = BluetoothUtils.ConvertStructToLeScanData(scanData);
170 BluetoothLeDevice device = new BluetoothLeDevice(scanDataInfo);
171 BluetoothError res = (BluetoothError)result;
173 AdapterLeScanResultChangedEventArgs e = new AdapterLeScanResultChangedEventArgs (res,
175 _adapterLeScanResultChanged (null, e);
178 IntPtr data = IntPtr.Zero;
179 int ret = Interop.Bluetooth.StartScan(_adapterLeScanResultChangedCallback, data);
180 if (ret != (int)BluetoothError.None)
182 Log.Error(Globals.LogTag, "Failed to start BLE scan - " + (BluetoothError)ret);
183 BluetoothErrorFactory.ThrowBluetoothException(ret);
189 internal int StopScan()
191 int ret = (int)BluetoothError.None;
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);
204 internal IList<string> GetLeScanResultServiceUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
206 IntPtr uuidListArray = IntPtr.Zero;
209 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
211 int ret = Interop.Bluetooth.GetScanResultServiceUuid(ref scanDataStruct, packetType,
212 ref uuidListArray, ref count);
213 if (ret != (int)BluetoothError.None)
215 Log.Info(Globals.LogTag, "Failed to service uuids list- " + (BluetoothError)ret);
219 Log.Info(Globals.LogTag, "count of uuids : " + count);
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)
226 list.Add(Marshal.PtrToStringAnsi(uuids));
227 Interop.Libc.Free(uuids);
230 Interop.Libc.Free(uuidListArray);
234 internal string GetLeScanResultDeviceName(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
238 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
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);
245 Log.Info (Globals.LogTag, "Device name " + deviceName);
249 internal int GetScanResultTxPowerLevel(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
252 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
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);
258 Log.Info (Globals.LogTag, "TxPowerLevel is --- " + powerLevel);
262 internal IList<string> GetScanResultSvcSolicitationUuids(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
264 IntPtr uuidListArray;
267 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct(scanData);
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);
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)
280 list.Add(Marshal.PtrToStringAnsi(uuids));
281 Interop.Libc.Free(uuids);
284 Interop.Libc.Free(uuidListArray);
288 internal IList<BluetoothLeServiceData> GetScanResultServiceDataList(BluetoothLeScanData scanData,
289 BluetoothLePacketType packetType, out int serviceCount)
292 IntPtr serviceListArray;
293 _serviceListCount = 0;
295 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
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)
301 Log.Info(Globals.LogTag, "Failed to get Service Data List, Error - " + (BluetoothError)ret);
303 Marshal.FreeHGlobal(serviceListArray);
304 Marshal.FreeHGlobal(scanDataStruct.AdvData);
305 Marshal.FreeHGlobal(scanDataStruct.ScanData);
309 BluetoothLeServiceDataStruct[] svcList = new BluetoothLeServiceDataStruct[_serviceListCount];
310 int sizePointerToABC = Marshal.SizeOf(new BluetoothLeServiceDataStruct());
311 for (int i = 0; i < _serviceListCount; i++)
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);
316 _list.Add(BluetoothUtils.ConvertStructToLeServiceData(svcList[i]));
319 serviceCount = _serviceListCount;
321 Interop.Libc.Free(serviceListArray);
322 Marshal.FreeHGlobal(scanDataStruct.AdvData);
323 Marshal.FreeHGlobal(scanDataStruct.ScanData);
327 internal int FreeServiceDataList()
331 int iServiceDataSize = Marshal.SizeOf(typeof(BluetoothLeServiceData));
332 IntPtr structServiceData = Marshal.AllocHGlobal(iServiceDataSize);
333 Marshal.StructureToPtr(_list, structServiceData, false);
335 int ret = Interop.Bluetooth.FreeServiceDataList(structServiceData, _serviceListCount);
336 if (ret != (int)BluetoothError.None)
338 Log.Error(Globals.LogTag, "Failed to free Service Data List, Error - " + (BluetoothError)ret);
339 BluetoothErrorFactory.ThrowBluetoothException(ret);
342 Marshal.FreeHGlobal(structServiceData);
347 internal int GetScanResultAppearance(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
351 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
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);
360 internal ManufacturerData GetScanResultManufacturerData(BluetoothLeScanData scanData, BluetoothLePacketType packetType)
366 BluetoothLeScanDataStruct scanDataStruct = BluetoothUtils.ConvertLeScanDataToStruct (scanData);
367 ManufacturerData data = new ManufacturerData();
369 int ret = Interop.Bluetooth.GetScanResultManufacturerData(ref scanDataStruct, packetType, out dataId,
370 out manufData, out dataLength);
371 if (ret != (int)BluetoothError.None)
373 Log.Error(Globals.LogTag, "Failed to get Manufacturer data - " + (BluetoothError)ret);
378 data.DataLength = dataLength;
379 if (data.DataLength > 0)
381 data.Data = new byte[data.DataLength];
382 Marshal.Copy(manufData, data.Data, 0, data.DataLength);
388 internal int GattConnect(string remoteAddress, bool autoConnect)
390 int ret = Interop.Bluetooth.GattConnect (remoteAddress, autoConnect);
391 if (ret != (int)BluetoothError.None)
393 Log.Error(Globals.LogTag, "Failed to establish GATT connection - " + (BluetoothError)ret);
394 BluetoothErrorFactory.ThrowBluetoothException(ret);
399 internal int GattDisconnect(string remoteAddress)
401 int ret = Interop.Bluetooth.GattDisconnect (remoteAddress);
402 if (ret != (int)BluetoothError.None)
404 Log.Error(Globals.LogTag, "Failed to disconnect GATT connection - " + (BluetoothError)ret);
405 BluetoothErrorFactory.ThrowBluetoothException(ret);
410 internal int CreateAdvertiser(out IntPtr advertiserHandle)
412 return Interop.Bluetooth.CreateAdvertiser (out advertiserHandle);
415 internal int DestroyAdvertiser(IntPtr advertiserHandle)
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);
425 internal int StartAdvertising(IntPtr advertisingHandle)
427 _advertisingStateChangedCallback = (int result, IntPtr advertiserHandle,
428 BluetoothLeAdvertisingState state, IntPtr userData) =>
430 Log.Info(Globals.LogTag, "Setting advertising state changed callback !! " );
431 AdvertisingStateChangedEventArgs e = new AdvertisingStateChangedEventArgs(result, advertiserHandle, state);
432 _advertisingStateChanged(null, e);
435 IntPtr uData = IntPtr.Zero;
436 int ret = Interop.Bluetooth.BluetoothLeStartAdvertising (advertisingHandle,
437 _advertisingStateChangedCallback, uData );
438 if (ret != (int)BluetoothError.None)
440 Log.Error(Globals.LogTag, "Failed to start BLE advertising - " + (BluetoothError)ret);
441 BluetoothErrorFactory.ThrowBluetoothException(ret);
447 internal int StopAdvertising(IntPtr advertisingHandle)
449 return Interop.Bluetooth.BluetoothLeStopAdvertising (advertisingHandle);