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.Runtime.CompilerServices;
20 using System.Runtime.InteropServices;
22 using System.Threading.Tasks;
24 namespace Tizen.Network.Bluetooth
26 internal class BluetoothGattServerImpl
28 private BluetoothGattServerHandle _handle;
29 internal event EventHandler<NotificationSentEventArg> _notificationSent;
31 internal BluetoothGattServerImpl()
33 int err = Interop.Bluetooth.BtGattServerInitialize();
34 GattUtil.ThrowForError(err, "Failed to initialize server");
36 err = Interop.Bluetooth.BtGattServerCreate(out _handle);
37 GattUtil.ThrowForError(err, "Failed to create server");
42 int err = Interop.Bluetooth.BtGattServerStart();
43 GattUtil.ThrowForError(err, "Failed to start server");
46 internal void RegisterGattService(BluetoothGattServer server, BluetoothGattService service)
48 int err = Interop.Bluetooth.BtGattServerRegisterService(_handle, service.GetHandle());
49 GattUtil.ThrowForError(err, "Failed to Register service");
51 service.SetParent(server);
54 internal void UnregisterGattService(BluetoothGattService service)
56 int err = Interop.Bluetooth.BtGattServerUnregisterService(_handle, service.GetHandle());
57 GattUtil.ThrowForError(err, "Failed to Unregister service");
59 service.UnregisterService();
62 internal void UnregisterAllGattServices(BluetoothGattServer server)
64 int err = Interop.Bluetooth.BtGattServerUnregisterAllServices(_handle);
65 GattUtil.ThrowForError(err, "Failed to Unregister all services");
68 internal BluetoothGattService GetService(BluetoothGattServer server, string uuid)
70 BluetoothGattAttributeHandle serviceHandle;
71 int err = Interop.Bluetooth.BtGattServerGetService(_handle, uuid, out serviceHandle);
74 GattUtil.Error(err, string.Format("Failed to get service with UUID ({0})", uuid));
78 BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(serviceHandle), uuid); ;
79 service.SetParent(server);
83 internal IEnumerable<BluetoothGattService> GetServices(BluetoothGattServer server)
85 List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
86 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
88 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
89 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, ""); ;
92 service.SetParent(server);
93 attribututeList.Add(service);
98 int err = Interop.Bluetooth.BtGattServerForeachServices(_handle, cb, IntPtr.Zero);
99 GattUtil.Error(err, "Failed to get all services");
101 return attribututeList;
104 internal void SendResponse(int requestId, int request_type, int status, byte[] value, int offset)
106 int err = Interop.Bluetooth.BtGattServerSendResponse(requestId, request_type, offset, status, value, value.Length);
107 GattUtil.ThrowForError(err, string.Format("Failed to send response for request Id {0}", requestId));
110 internal void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
112 int err = Interop.Bluetooth.BtGattServerNotify(characteristic.GetHandle(), null, clientAddress, IntPtr.Zero);
113 GattUtil.ThrowForError(err, string.Format("Failed to send value changed notification for characteristic uuid {0}", characteristic.Uuid));
116 internal Task<bool> SendIndicationAsync(BluetoothGattServer server, BluetoothGattCharacteristic characteristic, string clientAddress)
118 TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
119 Interop.Bluetooth.BtGattServerNotificationSentCallback cb = (result, address, serverHandle, characteristicHandle, completed, userData) =>
121 _notificationSent?.Invoke(characteristic, new NotificationSentEventArg(server, address, result, completed));
128 int err = Interop.Bluetooth.BtGattServerNotify(characteristic.GetHandle(), cb, clientAddress, IntPtr.Zero);
129 GattUtil.ThrowForError(err, string.Format("Failed to send value changed indication for characteristic uuid {0}", characteristic.Uuid));
134 internal BluetoothGattServerHandle GetHandle()
140 internal class BluetoothGattClientImpl
142 private BluetoothGattClientHandle _handle;
144 internal BluetoothGattClientImpl(string remoteAddress)
146 int err = Interop.Bluetooth.BtGattClientCreate(remoteAddress, out _handle);
147 GattUtil.ThrowForError(err, "Failed to get native client handle");
150 internal string GetRemoteAddress()
152 string remoteAddress;
153 int err = Interop.Bluetooth.BtGattClientGetRemoteAddress(_handle, out remoteAddress);
154 GattUtil.ThrowForError(err, "Failed to get remote address for this client");
156 return remoteAddress;
159 internal BluetoothGattService GetService(BluetoothGattClient client, string uuid)
161 BluetoothGattAttributeHandle serviceHandle;
162 int err = Interop.Bluetooth.BtGattClientGetService(_handle, uuid, out serviceHandle);
165 GattUtil.Error(err, string.Format("Failed to get service with UUID ({0})", uuid));
169 BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(serviceHandle), uuid); ;
170 service.SetParent(client);
174 internal IEnumerable<BluetoothGattService> GetServices(BluetoothGattClient client)
176 List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
177 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
179 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
180 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
183 service.SetParent(client);
184 attribututeList.Add(service);
189 int err = Interop.Bluetooth.BtGattClientForeachServices(_handle, cb, IntPtr.Zero);
190 GattUtil.Error(err, "Failed to get all services");
192 return attribututeList;
195 internal Task<bool> ReadValueAsyncTask(BluetoothGattAttributeHandle handle)
197 TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
198 Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
200 if (result == (int)BluetoothError.None)
203 tcs.SetResult(false);
206 int err = Interop.Bluetooth.BtGattClientReadValue(handle, cb, IntPtr.Zero);
209 GattUtil.Error(err, "Failed to read value from remote device");
210 tcs.SetResult(false);
211 BluetoothErrorFactory.ThrowBluetoothException(err);
216 internal Task<bool> WriteValueAsyncTask(BluetoothGattAttributeHandle handle)
218 TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
219 Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
221 if (result == (int)BluetoothError.None)
224 tcs.SetResult(false);
227 int err = Interop.Bluetooth.BtGattClientWriteValue(handle, cb, IntPtr.Zero);
230 GattUtil.Error(err, "Failed to write value to remote device");
231 tcs.SetResult(false);
232 BluetoothErrorFactory.ThrowBluetoothException(err);
237 internal BluetoothGattClientHandle GetHandle()
243 internal class BluetoothGattServiceImpl : BluetoothGattAttributeImpl
245 internal BluetoothGattServiceImpl(string uuid, BluetoothGattServiceType type)
247 int err = Interop.Bluetooth.BtGattServiceCreate(uuid, (int)type, out _handle);
248 GattUtil.ThrowForError(err, "Failed to get native service handle");
251 internal BluetoothGattServiceImpl(BluetoothGattAttributeHandle handle)
256 internal static BluetoothGattService CreateBluetoothGattService(BluetoothGattAttributeHandle handle, string uuid)
260 int err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
261 GattUtil.ThrowForError(err, "Failed to get UUID");
264 BluetoothGattServiceImpl impl = new BluetoothGattServiceImpl(handle);
265 return new BluetoothGattService(impl, uuid);
268 internal void AddCharacteristic(BluetoothGattCharacteristic characteristic)
270 int err = Interop.Bluetooth.BtGattServiceAddCharacteristic(_handle, characteristic.GetHandle());
271 GattUtil.ThrowForError(err, string.Format("Failed to add characteristic with UUID ({0})", characteristic.Uuid));
274 internal BluetoothGattCharacteristic GetCharacteristic(BluetoothGattService service, string uuid)
276 BluetoothGattAttributeHandle attributeHandle;
277 int err = Interop.Bluetooth.BtGattServiceGetCharacteristic(_handle, uuid, out attributeHandle);
280 GattUtil.Error(err, string.Format("Failed to get Characteristic with UUID ({0})", uuid));
284 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(attributeHandle, uuid);
285 Characteristic.SetParent(service);
286 return Characteristic;
289 internal IEnumerable<BluetoothGattCharacteristic> GetCharacteristics(BluetoothGattService service)
291 List<BluetoothGattCharacteristic> attribututeList = new List<BluetoothGattCharacteristic>();
292 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
294 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
295 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(handle, "");
296 if (Characteristic != null)
298 Characteristic.SetParent(service);
299 attribututeList.Add(Characteristic);
304 int err = Interop.Bluetooth.BtGattServiceForeachCharacteristics(service.GetHandle(), cb, IntPtr.Zero);
305 GattUtil.Error(err, "Failed to get all Characteristic");
307 return attribututeList;
310 internal void AddIncludeService(BluetoothGattService includedService)
312 int err = Interop.Bluetooth.BtGattServiceAddIncludedService(_handle, includedService.GetHandle());
313 GattUtil.ThrowForError(err, string.Format("Failed to add service with UUID ({0})", includedService.Uuid));
316 internal BluetoothGattService GetIncludeService(BluetoothGattService parentService, string uuid)
318 BluetoothGattAttributeHandle attributeHandle;
319 int err = Interop.Bluetooth.BtGattServiceGetIncludedService(_handle, uuid, out attributeHandle);
322 GattUtil.Error(err, string.Format("Failed to get included service with UUID ({0})", uuid));
326 BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(attributeHandle), uuid);
327 service.SetParent(parentService);
331 internal IEnumerable<BluetoothGattService> GetIncludeServices(BluetoothGattService parentService)
333 List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
334 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
336 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
337 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
340 service.SetParent(parentService);
341 attribututeList.Add(service);
346 int err = Interop.Bluetooth.BtGattServiceForeachIncludedServices(parentService.GetHandle(), cb, IntPtr.Zero);
347 GattUtil.Error(err, "Failed to get all services");
349 return attribututeList;
353 internal class BluetoothGattCharacteristicImpl : BluetoothGattAttributeImpl
355 internal BluetoothGattCharacteristicImpl(string uuid, BluetoothGattPermission permission, BluetoothGattProperty property, byte[] value)
357 int err = Interop.Bluetooth.BtGattCharacteristicCreate(uuid, (int)permission, (int)property, value, value.Length, out _handle);
358 GattUtil.ThrowForError(err, "Failed to get native characteristic handle");
361 internal BluetoothGattCharacteristicImpl(BluetoothGattAttributeHandle handle)
366 internal static BluetoothGattCharacteristic CreateBluetoothGattGattCharacteristic(BluetoothGattAttributeHandle handle, string uuid)
369 int err = Interop.Bluetooth.BtGattCharacteristicGetPermissions(handle, out permission);
370 GattUtil.ThrowForError(err, "Failed to get permissions");
374 err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
375 GattUtil.ThrowForError(err, "Failed to get UUID");
378 BluetoothGattCharacteristicImpl impl = new BluetoothGattCharacteristicImpl(handle);
379 return new BluetoothGattCharacteristic(impl, uuid, (BluetoothGattPermission)permission);
382 internal void SetCharacteristicValueChangedEvent(Interop.Bluetooth.BtClientCharacteristicValueChangedCallback callback)
384 int err = Interop.Bluetooth.BtGattClientSetCharacteristicValueChangedCallback(_handle, callback, IntPtr.Zero);
385 GattUtil.Error(err, "Failed to set client characteristic value changed callback");
388 internal void UnsetCharacteristicValueChangedEvent()
390 int err = Interop.Bluetooth.BtGattClientUnsetCharacteristicValueChangedCallback(_handle);
391 GattUtil.Error(err, "Failed to unset client characteristic value changed callback");
394 internal void SetNotificationStateChangedEvent(Interop.Bluetooth.BtGattServerNotificationStateChangeCallback callback)
396 int err = Interop.Bluetooth.BtGattServeSetNotificationStateChangeCallback(_handle, callback, IntPtr.Zero);
397 GattUtil.Error(err, "Failed to set characteristic notification state changed callback");
400 internal BluetoothGattProperty GetProperties()
403 int err = Interop.Bluetooth.BtGattCharacteristicGetProperties(_handle, out properties);
404 GattUtil.Error(err, "Failed to get characteristic properties");
405 return (BluetoothGattProperty)properties;
408 internal void SetProperties(BluetoothGattProperty perperties)
410 int err = Interop.Bluetooth.BtGattCharacteristicSetProperties(_handle, (int)perperties);
411 GattUtil.Error(err, "Failed to set characteristic properties");
414 internal BluetoothGattWriteType GetWriteType()
417 int err = Interop.Bluetooth.BtGattCharacteristicGetWriteType(_handle, out writeType);
418 GattUtil.Error(err, "Failed to get characteristic writetype");
419 return (BluetoothGattWriteType) writeType;
422 internal void SetWriteType(BluetoothGattWriteType writeType)
424 int err = Interop.Bluetooth.BtGattCharacteristicSetWriteType(_handle, (int)writeType);
425 GattUtil.Error(err, "Failed to get characteristic writetype");
428 internal void AddDescriptor(BluetoothGattDescriptor descriptor)
430 int err = Interop.Bluetooth.BtGattCharacteristicAddDescriptor(_handle, descriptor.GetHandle());
431 GattUtil.ThrowForError(err, string.Format("Failed to add descriptor with UUID ({0})", descriptor.Uuid));
434 internal BluetoothGattDescriptor GetDescriptor(BluetoothGattCharacteristic characteristic, string uuid)
436 BluetoothGattAttributeHandle handle;
437 int err = Interop.Bluetooth.BtGattCharacteristicGetDescriptor(_handle, uuid, out handle);
440 GattUtil.Error(err, string.Format("Failed to get descriptor with UUID ({0})", uuid));
443 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, uuid);
444 descriptor.SetParent(characteristic);
448 internal IEnumerable<BluetoothGattDescriptor> GetDescriptors(BluetoothGattCharacteristic characteristic)
450 List<BluetoothGattDescriptor> attribututeList = new List<BluetoothGattDescriptor>();
451 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
453 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
454 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, "");
455 if (descriptor != null)
457 descriptor.SetParent(characteristic);
458 attribututeList.Add(descriptor);
463 int err = Interop.Bluetooth.BtGattCharacteristicForeachDescriptors(characteristic.GetHandle(), cb, IntPtr.Zero);
464 GattUtil.Error(err, "Failed to get all descriptor");
466 return attribututeList;
470 internal class BluetoothGattDescriptorImpl : BluetoothGattAttributeImpl
472 internal BluetoothGattDescriptorImpl(string uuid, BluetoothGattPermission permission, byte[] value)
474 int err = Interop.Bluetooth.BtGattDescriptorCreate(uuid, (int)permission, value, value.Length, out _handle);
475 GattUtil.ThrowForError(err, "Failed to get native descriptor handle");
478 internal BluetoothGattDescriptorImpl(BluetoothGattAttributeHandle handle)
483 internal static BluetoothGattDescriptor CreateBluetoothGattDescriptor(BluetoothGattAttributeHandle handle, string uuid)
486 int err = Interop.Bluetooth.BtGattDescriptorGetPermissions(handle, out permission);
487 GattUtil.ThrowForError(err, string.Format("Failed to get permissions with UUID ({0})", uuid));
491 int ret = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
492 GattUtil.ThrowForError(ret, "Failed to get UUID");
495 BluetoothGattDescriptorImpl impl = new BluetoothGattDescriptorImpl(handle);
496 return new BluetoothGattDescriptor(impl, uuid, (BluetoothGattPermission)permission);
500 internal abstract class BluetoothGattAttributeImpl
502 protected BluetoothGattAttributeHandle _handle;
504 internal string GetUuid()
507 int err = Interop.Bluetooth.BtGattGetUuid(_handle, out uuid);
508 GattUtil.Error(err, "Failed to get attribute uuid");
513 internal byte[] GetValue()
516 int nativeValueLength;
517 int err = Interop.Bluetooth.BtGattGetValue(_handle, out nativeValue, out nativeValueLength);
518 GattUtil.Error(err, "Failed to get attribute value");
520 return GattUtil.IntPtrToByteArray(nativeValue, nativeValueLength);
523 internal void SetValue(byte[] value)
525 int err = Interop.Bluetooth.BtGattSetValue(_handle, value, value.Length);
526 GattUtil.ThrowForError(err, "Failed to set attribute value");
529 internal string GetValue(int offset)
531 byte[] value = GetValue();
533 int nullPos = value.Length - offset;
534 for (int i = offset; i < value.Length; ++i)
536 if (value[i] == '\0')
543 string strValue = "";
544 strValue = Encoding.UTF8.GetString(value, offset, nullPos - offset);
548 internal int GetValue(IntDataType type, int offset)
551 int err = Interop.Bluetooth.BtGattGetIntValue(_handle, (int)type, offset, out value);
552 GattUtil.Error(err, "Failed to get attribute int value at offset");
556 internal void SetValue(IntDataType type, int value, int offset)
558 int err = Interop.Bluetooth.BtGattSetIntValue(_handle, (int)type, value, offset);
559 GattUtil.ThrowForError(err, "Failed to set attribute int value at offset");
562 internal float GetValue(FloatDataType type, int offset)
565 int err = Interop.Bluetooth.BtGattGetFloatValue(_handle, (int)type, offset, out value);
566 GattUtil.Error(err, "Failed to get attribute float value at offset");
570 internal void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
572 int err = Interop.Bluetooth.BtGattSetFloatValue(_handle, (int)type, mantissa, exponent, offset);
573 GattUtil.ThrowForError(err, "Failed to set attribute float value at offset");
576 internal void SetReadValueRequestedEventCallback(Interop.Bluetooth.BtGattServerReadValueRequestedCallback callback)
578 int err = Interop.Bluetooth.BtGattServerSetReadValueRequestedCallback(_handle, callback, IntPtr.Zero);
579 GattUtil.ThrowForError(err, "Failed to set attribute read value requested callback");
582 internal void SetWriteValueRequestedEventCallback(Interop.Bluetooth.BtGattServerWriteValueRequestedCallback callback)
584 int err = Interop.Bluetooth.BtGattServerSetWriteValueRequestedCallback(_handle, callback, IntPtr.Zero);
585 GattUtil.ThrowForError(err, "Failed to set attribute write value requested callback");
588 internal BluetoothGattAttributeHandle GetHandle()
593 internal void ReleaseHandleOwnership()
595 _handle.ReleaseOwnership();
600 internal class BluetoothGattAttributeHandle : BluetoothGattHandle
602 public BluetoothGattAttributeHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, hasOwnership)
606 public BluetoothGattAttributeHandle()
610 protected override bool ReleaseHandle()
612 if (_hasOwnership == true)
614 Interop.Bluetooth.BtGattDestroy(handle);
616 SetHandle(IntPtr.Zero);
621 internal class BluetoothGattClientHandle : BluetoothGattHandle
623 protected override bool ReleaseHandle()
625 if (_hasOwnership == true)
627 Interop.Bluetooth.BtGattClientDestroy(handle);
629 SetHandle(IntPtr.Zero);
634 internal class BluetoothGattServerHandle : BluetoothGattHandle
636 protected override bool ReleaseHandle()
638 if (_hasOwnership == true)
640 Interop.Bluetooth.BtGattServerDeinitialize();
641 Interop.Bluetooth.BtGattServerDestroy(handle);
643 SetHandle(IntPtr.Zero);
648 internal abstract class BluetoothGattHandle : SafeHandle
650 protected bool _hasOwnership;
652 public BluetoothGattHandle() : base(IntPtr.Zero, true)
654 _hasOwnership = true;
657 public BluetoothGattHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, true)
659 _hasOwnership = hasOwnership;
662 public override bool IsInvalid
664 get { return handle == IntPtr.Zero; }
667 public void ReleaseOwnership()
669 _hasOwnership = false;
673 internal static class GattUtil
675 internal static byte[] IntPtrToByteArray(IntPtr nativeValue, int lenght)
677 byte[] value = new byte[lenght];
678 if (nativeValue != IntPtr.Zero)
680 Marshal.Copy(nativeValue, value, 0, lenght);
685 internal static void Error(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
689 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
693 internal static void ThrowForError(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
697 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
698 BluetoothErrorFactory.ThrowBluetoothException(err);
702 internal static bool IsFailed(this int err)
704 return err != (int)BluetoothError.None;