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 status, byte[] value, int offset)
106 int err = Interop.Bluetooth.BtGattServerSendResponse(requestId, 0, 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) =>
203 int err = Interop.Bluetooth.BtGattClientReadValue(handle, cb, IntPtr.Zero);
206 GattUtil.Error(err, "Failed to read value from remote device");
207 tcs.SetResult(false);
208 BluetoothErrorFactory.ThrowBluetoothException(err);
213 internal Task<bool> WriteValueAsyncTask(BluetoothGattAttributeHandle handle)
215 TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
216 Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
221 int err = Interop.Bluetooth.BtGattClientWriteValue(handle, cb, IntPtr.Zero);
224 GattUtil.Error(err, "Failed to write value to remote device");
225 tcs.SetResult(false);
226 BluetoothErrorFactory.ThrowBluetoothException(err);
231 internal BluetoothGattClientHandle GetHandle()
237 internal class BluetoothGattServiceImpl : BluetoothGattAttributeImpl
239 internal BluetoothGattServiceImpl(string uuid, BluetoothGattServiceType type)
241 int err = Interop.Bluetooth.BtGattServiceCreate(uuid, (int)type, out _handle);
242 GattUtil.ThrowForError(err, "Failed to get native service handle");
245 internal BluetoothGattServiceImpl(BluetoothGattAttributeHandle handle)
250 internal static BluetoothGattService CreateBluetoothGattService(BluetoothGattAttributeHandle handle, string uuid)
254 int err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
255 GattUtil.ThrowForError(err, "Failed to get UUID");
258 BluetoothGattServiceImpl impl = new BluetoothGattServiceImpl(handle);
259 return new BluetoothGattService(impl, uuid);
262 internal void AddCharacteristic(BluetoothGattCharacteristic characteristic)
264 int err = Interop.Bluetooth.BtGattServiceAddCharacteristic(_handle, characteristic.GetHandle());
265 GattUtil.ThrowForError(err, string.Format("Failed to add characteristic with UUID ({0})", characteristic.Uuid));
268 internal BluetoothGattCharacteristic GetCharacteristic(BluetoothGattService service, string uuid)
270 BluetoothGattAttributeHandle attributeHandle;
271 int err = Interop.Bluetooth.BtGattServiceGetCharacteristic(_handle, uuid, out attributeHandle);
274 GattUtil.Error(err, string.Format("Failed to get Characteristic with UUID ({0})", uuid));
278 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(attributeHandle, uuid);
279 Characteristic.SetParent(service);
280 return Characteristic;
283 internal IEnumerable<BluetoothGattCharacteristic> GetCharacteristics(BluetoothGattService service)
285 List<BluetoothGattCharacteristic> attribututeList = new List<BluetoothGattCharacteristic>();
286 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
288 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
289 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(handle, "");
290 if (Characteristic != null)
292 Characteristic.SetParent(service);
293 attribututeList.Add(Characteristic);
298 int err = Interop.Bluetooth.BtGattServiceForeachCharacteristics(service.GetHandle(), cb, IntPtr.Zero);
299 GattUtil.Error(err, "Failed to get all Characteristic");
301 return attribututeList;
304 internal void AddIncludeService(BluetoothGattService includedService)
306 int err = Interop.Bluetooth.BtGattServiceAddIncludedService(_handle, includedService.GetHandle());
307 GattUtil.ThrowForError(err, string.Format("Failed to add service with UUID ({0})", includedService.Uuid));
310 internal BluetoothGattService GetIncludeService(BluetoothGattService parentService, string uuid)
312 BluetoothGattAttributeHandle attributeHandle;
313 int err = Interop.Bluetooth.BtGattServiceGetIncludedService(_handle, uuid, out attributeHandle);
316 GattUtil.Error(err, string.Format("Failed to get included service with UUID ({0})", uuid));
320 BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(attributeHandle), uuid);
321 service.SetParent(parentService);
325 internal IEnumerable<BluetoothGattService> GetIncludeServices(BluetoothGattService parentService)
327 List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
328 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
330 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
331 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
334 service.SetParent(parentService);
335 attribututeList.Add(service);
340 int err = Interop.Bluetooth.BtGattServiceForeachIncludedServices(parentService.GetHandle(), cb, IntPtr.Zero);
341 GattUtil.Error(err, "Failed to get all services");
343 return attribututeList;
347 internal class BluetoothGattCharacteristicImpl : BluetoothGattAttributeImpl
349 internal BluetoothGattCharacteristicImpl(string uuid, BluetoothGattPermission permission, BluetoothGattProperty property, byte[] value)
351 int err = Interop.Bluetooth.BtGattCharacteristicCreate(uuid, (int)permission, (int)property, value, value.Length, out _handle);
352 GattUtil.ThrowForError(err, "Failed to get native characteristic handle");
355 internal BluetoothGattCharacteristicImpl(BluetoothGattAttributeHandle handle)
360 internal static BluetoothGattCharacteristic CreateBluetoothGattGattCharacteristic(BluetoothGattAttributeHandle handle, string uuid)
363 int err = Interop.Bluetooth.BtGattCharacteristicGetPermissions(handle, out permission);
364 GattUtil.ThrowForError(err, "Failed to get permissions");
368 err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
369 GattUtil.ThrowForError(err, "Failed to get UUID");
372 BluetoothGattCharacteristicImpl impl = new BluetoothGattCharacteristicImpl(handle);
373 return new BluetoothGattCharacteristic(impl, uuid, (BluetoothGattPermission)permission);
376 internal void SetCharacteristicValueChangedEvent(Interop.Bluetooth.BtClientCharacteristicValueChangedCallback callback)
378 int err = Interop.Bluetooth.BtGattClientSetCharacteristicValueChangedCallback(_handle, callback, IntPtr.Zero);
379 GattUtil.Error(err, "Failed to set client characteristic value changed callback");
382 internal void UnsetCharacteristicValueChangedEvent()
384 int err = Interop.Bluetooth.BtGattClientUnsetCharacteristicValueChangedCallback(_handle);
385 GattUtil.Error(err, "Failed to unset client characteristic value changed callback");
388 internal void SetNotificationStateChangedEvent(Interop.Bluetooth.BtGattServerNotificationStateChangeCallback callback)
390 int err = Interop.Bluetooth.BtGattServeSetNotificationStateChangeCallback(_handle, callback, IntPtr.Zero);
391 GattUtil.Error(err, "Failed to set characteristic notification state changed callback");
394 internal BluetoothGattProperty GetProperties()
397 int err = Interop.Bluetooth.BtGattCharacteristicGetProperties(_handle, out properties);
398 GattUtil.Error(err, "Failed to get characteristic properties");
399 return (BluetoothGattProperty)properties;
402 internal void SetProperties(BluetoothGattProperty perperties)
404 int err = Interop.Bluetooth.BtGattCharacteristicSetProperties(_handle, (int)perperties);
405 GattUtil.Error(err, "Failed to set characteristic properties");
408 internal BluetoothGattWriteType GetWriteType()
411 int err = Interop.Bluetooth.BtGattCharacteristicGetWriteType(_handle, out writeType);
412 GattUtil.Error(err, "Failed to get characteristic writetype");
413 return (BluetoothGattWriteType) writeType;
416 internal void SetWriteType(BluetoothGattWriteType writeType)
418 int err = Interop.Bluetooth.BtGattCharacteristicSetWriteType(_handle, (int)writeType);
419 GattUtil.Error(err, "Failed to get characteristic writetype");
422 internal void AddDescriptor(BluetoothGattDescriptor descriptor)
424 int err = Interop.Bluetooth.BtGattCharacteristicAddDescriptor(_handle, descriptor.GetHandle());
425 GattUtil.ThrowForError(err, string.Format("Failed to add descriptor with UUID ({0})", descriptor.Uuid));
428 internal BluetoothGattDescriptor GetDescriptor(BluetoothGattCharacteristic characteristic, string uuid)
430 BluetoothGattAttributeHandle handle;
431 int err = Interop.Bluetooth.BtGattCharacteristicGetDescriptor(_handle, uuid, out handle);
434 GattUtil.Error(err, string.Format("Failed to get descriptor with UUID ({0})", uuid));
437 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, uuid);
438 descriptor.SetParent(characteristic);
442 internal IEnumerable<BluetoothGattDescriptor> GetDescriptors(BluetoothGattCharacteristic characteristic)
444 List<BluetoothGattDescriptor> attribututeList = new List<BluetoothGattDescriptor>();
445 Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
447 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
448 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, "");
449 if (descriptor != null)
451 descriptor.SetParent(characteristic);
452 attribututeList.Add(descriptor);
457 int err = Interop.Bluetooth.BtGattCharacteristicForeachDescriptors(characteristic.GetHandle(), cb, IntPtr.Zero);
458 GattUtil.Error(err, "Failed to get all descriptor");
460 return attribututeList;
464 internal class BluetoothGattDescriptorImpl : BluetoothGattAttributeImpl
466 internal BluetoothGattDescriptorImpl(string uuid, BluetoothGattPermission permission, byte[] value)
468 int err = Interop.Bluetooth.BtGattDescriptorCreate(uuid, (int)permission, value, value.Length, out _handle);
469 GattUtil.ThrowForError(err, "Failed to get native descriptor handle");
472 internal BluetoothGattDescriptorImpl(BluetoothGattAttributeHandle handle)
477 internal static BluetoothGattDescriptor CreateBluetoothGattDescriptor(BluetoothGattAttributeHandle handle, string uuid)
480 int err = Interop.Bluetooth.BtGattDescriptorGetPermissions(handle, out permission);
481 GattUtil.ThrowForError(err, string.Format("Failed to get permissions with UUID ({0})", uuid));
485 int ret = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
486 GattUtil.ThrowForError(ret, "Failed to get UUID");
489 BluetoothGattDescriptorImpl impl = new BluetoothGattDescriptorImpl(handle);
490 return new BluetoothGattDescriptor(impl, uuid, (BluetoothGattPermission)permission);
494 internal abstract class BluetoothGattAttributeImpl
496 protected BluetoothGattAttributeHandle _handle;
498 internal string GetUuid()
501 int err = Interop.Bluetooth.BtGattGetUuid(_handle, out uuid);
502 GattUtil.Error(err, "Failed to get attribute uuid");
507 internal byte[] GetValue()
510 int nativeValueLength;
511 int err = Interop.Bluetooth.BtGattGetValue(_handle, out nativeValue, out nativeValueLength);
512 GattUtil.Error(err, "Failed to get attribute value");
514 return GattUtil.IntPtrToByteArray(nativeValue, nativeValueLength);
517 internal void SetValue(byte[] value)
519 int err = Interop.Bluetooth.BtGattSetValue(_handle, value, value.Length);
520 GattUtil.ThrowForError(err, "Failed to set attribute value");
523 internal string GetValue(int offset)
525 byte[] value = GetValue();
527 int nullPos = value.Length - offset;
528 for (int i = offset; i < value.Length; ++i)
530 if (value[i] == '\0')
537 string strValue = "";
538 strValue = Encoding.UTF8.GetString(value, offset, nullPos - offset);
542 internal void SetValue(string value, int offset)
544 byte[] byteValue = GetValue();
545 byte[] strValue = Encoding.UTF8.GetBytes(value);
546 int length = offset + strValue.Length;
547 if (length >= byteValue.Length)
549 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "Can not fit value to buffer");
552 Buffer.BlockCopy(strValue, 0, byteValue, offset, strValue.Length);
553 byteValue[length] = (byte)'\0';
557 internal int GetValue(IntDataType type, int offset)
560 int err = Interop.Bluetooth.BtGattGetIntValue(_handle, (int)type, offset, out value);
561 GattUtil.Error(err, "Failed to get attribute int value at offset");
565 internal void SetValue(IntDataType type, int value, int offset)
567 int err = Interop.Bluetooth.BtGattSetIntValue(_handle, (int)type, value, offset);
568 GattUtil.ThrowForError(err, "Failed to set attribute int value at offset");
571 internal float GetValue(FloatDataType type, int offset)
574 int err = Interop.Bluetooth.BtGattGetFloatValue(_handle, (int)type, offset, out value);
575 GattUtil.Error(err, "Failed to get attribute float value at offset");
579 internal void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
581 int err = Interop.Bluetooth.BtGattSetFloatValue(_handle, (int)type, mantissa, exponent, offset);
582 GattUtil.ThrowForError(err, "Failed to set attribute float value at offset");
585 internal void SetReadValueRequestedEventCallback(Interop.Bluetooth.BtGattServerReadValueRequestedCallback callback)
587 int err = Interop.Bluetooth.BtGattServerSetReadValueRequestedCallback(_handle, callback, IntPtr.Zero);
588 GattUtil.ThrowForError(err, "Failed to set attribute read value requested callback");
591 internal void SetWriteValueRequestedEventCallback(Interop.Bluetooth.BtGattServerWriteValueRequestedCallback callback)
593 int err = Interop.Bluetooth.BtGattServerSetWriteValueRequestedCallback(_handle, callback, IntPtr.Zero);
594 GattUtil.ThrowForError(err, "Failed to set attribute write value requested callback");
597 internal BluetoothGattAttributeHandle GetHandle()
602 internal void ReleaseHandleOwnership()
604 _handle.ReleaseOwnership();
609 internal class BluetoothGattAttributeHandle : BluetoothGattHandle
611 public BluetoothGattAttributeHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, hasOwnership)
615 public BluetoothGattAttributeHandle()
619 protected override bool ReleaseHandle()
621 if (_hasOwnership == true)
623 Interop.Bluetooth.BtGattDestroy(handle);
625 SetHandle(IntPtr.Zero);
630 internal class BluetoothGattClientHandle : BluetoothGattHandle
632 protected override bool ReleaseHandle()
634 if (_hasOwnership == true)
636 Interop.Bluetooth.BtGattClientDestroy(handle);
637 Interop.Bluetooth.BtGattServerDeinitialize();
639 SetHandle(IntPtr.Zero);
644 internal class BluetoothGattServerHandle : BluetoothGattHandle
646 protected override bool ReleaseHandle()
648 if (_hasOwnership == true)
650 Interop.Bluetooth.BtGattServerDestroy(handle);
652 SetHandle(IntPtr.Zero);
657 internal abstract class BluetoothGattHandle : SafeHandle
659 protected bool _hasOwnership;
661 public BluetoothGattHandle() : base(IntPtr.Zero, true)
663 _hasOwnership = true;
666 public BluetoothGattHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, true)
668 _hasOwnership = hasOwnership;
671 public override bool IsInvalid
673 get { return handle == IntPtr.Zero; }
676 public void ReleaseOwnership()
678 _hasOwnership = false;
682 internal static class GattUtil
684 internal static byte[] IntPtrToByteArray(IntPtr nativeValue, int lenght)
686 byte[] value = new byte[lenght];
687 if (nativeValue != IntPtr.Zero)
689 Marshal.Copy(nativeValue, value, 0, lenght);
694 internal static void Error(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
698 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
702 internal static void ThrowForError(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
706 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
707 BluetoothErrorFactory.ThrowBluetoothException(err);
711 internal static bool IsFailed(this int err)
713 return err != (int)BluetoothError.None;