[C# Bluetooth]: Rename Tizen.Bluetooth to Tizen.Network.Bluetooth
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothGattImpl.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.Runtime.CompilerServices;
20 using System.Runtime.InteropServices;
21 using System.Text;
22 using System.Threading.Tasks;
23
24 namespace Tizen.Network.Bluetooth
25 {
26     internal class BluetoothGattServerImpl
27     {
28         private BluetoothGattServerHandle _handle;
29         internal event EventHandler<NotificationSentEventArg> _notificationSent;
30
31         internal BluetoothGattServerImpl()
32         {
33             int err = Interop.Bluetooth.BtGattServerInitialize();
34             GattUtil.ThrowForError(err, "Failed to initialize server");
35
36             err = Interop.Bluetooth.BtGattServerCreate(out _handle);
37             GattUtil.ThrowForError(err, "Failed to create server");
38         }
39
40         internal void Start()
41         {
42             int err = Interop.Bluetooth.BtGattServerStart();
43             GattUtil.ThrowForError(err, "Failed to start server");
44         }
45
46         internal void RegisterGattService(BluetoothGattServer server, BluetoothGattService service)
47         {
48             int err = Interop.Bluetooth.BtGattServerRegisterService(_handle, service.GetHandle());
49             GattUtil.ThrowForError(err, "Failed to Register service");
50
51             service.SetParent(server);
52         }
53
54         internal void UnregisterGattService(BluetoothGattService service)
55         {
56             int err = Interop.Bluetooth.BtGattServerUnregisterService(_handle, service.GetHandle());
57             GattUtil.ThrowForError(err, "Failed to Unregister service");
58
59             service.UnregisterService();
60         }
61
62         internal void UnregisterAllGattServices(BluetoothGattServer server)
63         {
64             int err = Interop.Bluetooth.BtGattServerUnregisterAllServices(_handle);
65             GattUtil.ThrowForError(err, "Failed to Unregister all services");
66         }
67
68         internal BluetoothGattService GetService(BluetoothGattServer server, string uuid)
69         {
70             BluetoothGattAttributeHandle serviceHandle;
71             int err = Interop.Bluetooth.BtGattServerGetService(_handle, uuid, out serviceHandle);
72             if (err.IsFailed())
73             {
74                 GattUtil.Error(err, string.Format("Failed to get service with UUID ({0})", uuid));
75                 return null;
76             }
77
78             BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(serviceHandle), uuid); ;
79             service.SetParent(server);
80             return service;
81         }
82
83         internal IEnumerable<BluetoothGattService> GetServices(BluetoothGattServer server)
84         {
85             List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
86             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
87             {
88                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
89                 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, ""); ;
90                 if (service != null)
91                 {
92                     service.SetParent(server);
93                     attribututeList.Add(service);
94                 }
95                 return true;
96             };
97
98             int err = Interop.Bluetooth.BtGattServerForeachServices(_handle, cb, IntPtr.Zero);
99             GattUtil.Error(err, "Failed to get all services");
100
101             return attribututeList;
102         }
103
104         internal void SendResponse(int requestId, int status, byte[] value, int offset)
105         {
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));
108         }
109
110         internal void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
111         {
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));
114         }
115
116         internal Task<bool> SendIndicationAsync(BluetoothGattServer server, BluetoothGattCharacteristic characteristic, string clientAddress)
117         {
118             TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
119             Interop.Bluetooth.BtGattServerNotificationSentCallback cb = (result, address, serverHandle, characteristicHandle, completed, userData) =>
120             {
121                 _notificationSent?.Invoke(characteristic, new NotificationSentEventArg(server, address, result, completed));
122                 if (completed)
123                 {
124                     tcs.SetResult(true);
125                 }
126             };
127
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));
130
131             return tcs.Task;
132         }
133
134         internal BluetoothGattServerHandle GetHandle()
135         {
136             return _handle;
137         }
138     }
139
140     internal class BluetoothGattClientImpl
141     {
142         private BluetoothGattClientHandle _handle;
143
144         internal BluetoothGattClientImpl(string remoteAddress)
145         {
146             int err = Interop.Bluetooth.BtGattClientCreate(remoteAddress, out _handle);
147             GattUtil.ThrowForError(err, "Failed to get native client handle");
148         }
149
150         internal string GetRemoteAddress()
151         {
152             string remoteAddress;
153             int err = Interop.Bluetooth.BtGattClientGetRemoteAddress(_handle, out remoteAddress);
154             GattUtil.ThrowForError(err, "Failed to get remote address for this client");
155
156             return remoteAddress;
157         }
158
159         internal BluetoothGattService GetService(BluetoothGattClient client, string uuid)
160         {
161             BluetoothGattAttributeHandle serviceHandle;
162             int err = Interop.Bluetooth.BtGattClientGetService(_handle, uuid, out serviceHandle);
163             if (err.IsFailed())
164             {
165                 GattUtil.Error(err, string.Format("Failed to get service with UUID ({0})", uuid));
166                 return null;
167             }
168
169             BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(serviceHandle), uuid); ;
170             service.SetParent(client);
171             return service;
172         }
173
174         internal IEnumerable<BluetoothGattService> GetServices(BluetoothGattClient client)
175         {
176             List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
177             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
178             {
179                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
180                 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
181                 if (service != null)
182                 {
183                     service.SetParent(client);
184                     attribututeList.Add(service);
185                 }
186                 return true;
187             };
188
189             int err = Interop.Bluetooth.BtGattClientForeachServices(_handle, cb, IntPtr.Zero);
190             GattUtil.Error(err, "Failed to get all services");
191
192             return attribututeList;
193         }
194
195         internal Task<bool> ReadValueAsyncTask(BluetoothGattAttributeHandle handle)
196         {
197             TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
198             Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
199             {
200                 tcs.SetResult(true);
201             };
202
203             int err = Interop.Bluetooth.BtGattClientReadValue(handle, cb, IntPtr.Zero);
204             if (err.IsFailed())
205             {
206                 GattUtil.Error(err, "Failed to read value from remote device");
207                 tcs.SetResult(false);
208                 BluetoothErrorFactory.ThrowBluetoothException(err);
209             }
210             return tcs.Task;
211         }
212
213         internal Task<bool> WriteValueAsyncTask(BluetoothGattAttributeHandle handle)
214         {
215             TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
216             Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
217             {
218                 tcs.SetResult(true);
219             };
220
221             int err = Interop.Bluetooth.BtGattClientWriteValue(handle, cb, IntPtr.Zero);
222             if (err.IsFailed())
223             {
224                 GattUtil.Error(err, "Failed to write value to remote device");
225                 tcs.SetResult(false);
226                 BluetoothErrorFactory.ThrowBluetoothException(err);
227             }
228             return tcs.Task;
229         }
230
231         internal BluetoothGattClientHandle GetHandle()
232         {
233             return _handle;
234         }
235     }
236
237     internal class BluetoothGattServiceImpl : BluetoothGattAttributeImpl
238     {
239         internal BluetoothGattServiceImpl(string uuid, BluetoothGattServiceType type)
240         {
241             int err = Interop.Bluetooth.BtGattServiceCreate(uuid, (int)type, out _handle);
242             GattUtil.ThrowForError(err, "Failed to get native service handle");
243         }
244
245         internal BluetoothGattServiceImpl(BluetoothGattAttributeHandle handle)
246         {
247             _handle = handle;
248         }
249
250         internal static BluetoothGattService CreateBluetoothGattService(BluetoothGattAttributeHandle handle, string uuid)
251         {
252             if (uuid == "")
253             {
254                 int err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
255                 GattUtil.ThrowForError(err, "Failed to get UUID");
256             }
257
258             BluetoothGattServiceImpl impl = new BluetoothGattServiceImpl(handle);
259             return new BluetoothGattService(impl, uuid);
260         }
261
262         internal void AddCharacteristic(BluetoothGattCharacteristic characteristic)
263         {
264             int err = Interop.Bluetooth.BtGattServiceAddCharacteristic(_handle, characteristic.GetHandle());
265             GattUtil.ThrowForError(err, string.Format("Failed to add characteristic with UUID ({0})", characteristic.Uuid));
266         }
267
268         internal BluetoothGattCharacteristic GetCharacteristic(BluetoothGattService service, string uuid)
269         {
270             BluetoothGattAttributeHandle attributeHandle;
271             int err = Interop.Bluetooth.BtGattServiceGetCharacteristic(_handle, uuid, out attributeHandle);
272             if (err.IsFailed())
273             {
274                 GattUtil.Error(err, string.Format("Failed to get Characteristic with UUID ({0})", uuid));
275                 return null;
276             }
277
278             BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(attributeHandle, uuid);
279             Characteristic.SetParent(service);
280             return Characteristic;
281         }
282
283         internal IEnumerable<BluetoothGattCharacteristic> GetCharacteristics(BluetoothGattService service)
284         {
285             List<BluetoothGattCharacteristic> attribututeList = new List<BluetoothGattCharacteristic>();
286             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
287             {
288                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
289                 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(handle, "");
290                 if (Characteristic != null)
291                 {
292                     Characteristic.SetParent(service);
293                     attribututeList.Add(Characteristic);
294                 }
295                 return true;
296             };
297
298             int err = Interop.Bluetooth.BtGattServiceForeachCharacteristics(service.GetHandle(), cb, IntPtr.Zero);
299             GattUtil.Error(err, "Failed to get all Characteristic");
300
301             return attribututeList;
302         }
303
304         internal void AddIncludeService(BluetoothGattService includedService)
305         {
306             int err = Interop.Bluetooth.BtGattServiceAddIncludedService(_handle, includedService.GetHandle());
307             GattUtil.ThrowForError(err, string.Format("Failed to add service with UUID ({0})", includedService.Uuid));
308         }
309
310         internal BluetoothGattService GetIncludeService(BluetoothGattService parentService, string uuid)
311         {
312             BluetoothGattAttributeHandle attributeHandle;
313             int err = Interop.Bluetooth.BtGattServiceGetIncludedService(_handle, uuid, out attributeHandle);
314             if (err.IsFailed())
315             {
316                 GattUtil.Error(err, string.Format("Failed to get included service with UUID ({0})", uuid));
317                 return null;
318             }
319
320             BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(attributeHandle), uuid);
321             service.SetParent(parentService);
322             return service;
323         }
324
325         internal IEnumerable<BluetoothGattService> GetIncludeServices(BluetoothGattService parentService)
326         {
327             List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
328             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
329             {
330                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
331                 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
332                 if (service != null)
333                 {
334                     service.SetParent(parentService);
335                     attribututeList.Add(service);
336                 }
337                 return true;
338             };
339
340             int err = Interop.Bluetooth.BtGattServiceForeachIncludedServices(parentService.GetHandle(), cb, IntPtr.Zero);
341             GattUtil.Error(err, "Failed to get all services");
342
343             return attribututeList;
344         }
345     }
346
347     internal class BluetoothGattCharacteristicImpl : BluetoothGattAttributeImpl
348     {
349         internal BluetoothGattCharacteristicImpl(string uuid, BluetoothGattPermission permission, BluetoothGattProperty property, byte[] value)
350         {
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");
353         }
354
355         internal BluetoothGattCharacteristicImpl(BluetoothGattAttributeHandle handle)
356         {
357             _handle = handle;
358         }
359
360         internal static BluetoothGattCharacteristic CreateBluetoothGattGattCharacteristic(BluetoothGattAttributeHandle handle, string uuid)
361         {
362             int permission;
363             int err = Interop.Bluetooth.BtGattCharacteristicGetPermissions(handle, out permission);
364             GattUtil.ThrowForError(err, "Failed to get permissions");
365
366             if (uuid == "")
367             {
368                 err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
369                 GattUtil.ThrowForError(err, "Failed to get UUID");
370             }
371
372             BluetoothGattCharacteristicImpl impl = new BluetoothGattCharacteristicImpl(handle);
373             return new BluetoothGattCharacteristic(impl, uuid, (BluetoothGattPermission)permission);
374         }
375
376         internal void SetCharacteristicValueChangedEvent(Interop.Bluetooth.BtClientCharacteristicValueChangedCallback callback)
377         {
378             int err = Interop.Bluetooth.BtGattClientSetCharacteristicValueChangedCallback(_handle, callback, IntPtr.Zero);
379             GattUtil.Error(err, "Failed to set client characteristic value changed callback");
380         }
381
382         internal void UnsetCharacteristicValueChangedEvent()
383         {
384             int err = Interop.Bluetooth.BtGattClientUnsetCharacteristicValueChangedCallback(_handle);
385             GattUtil.Error(err, "Failed to unset client characteristic value changed callback");
386         }
387
388         internal void SetNotificationStateChangedEvent(Interop.Bluetooth.BtGattServerNotificationStateChangeCallback callback)
389         {
390             int err = Interop.Bluetooth.BtGattServeSetNotificationStateChangeCallback(_handle, callback, IntPtr.Zero);
391             GattUtil.Error(err, "Failed to set characteristic notification state changed callback");
392         }
393
394         internal BluetoothGattProperty GetProperties()
395         {
396             int properties = 0 ;
397             int err = Interop.Bluetooth.BtGattCharacteristicGetProperties(_handle, out properties);
398             GattUtil.Error(err, "Failed to get characteristic properties");
399             return (BluetoothGattProperty)properties;
400         }
401
402         internal void SetProperties(BluetoothGattProperty perperties)
403         {
404             int err = Interop.Bluetooth.BtGattCharacteristicSetProperties(_handle, (int)perperties);
405             GattUtil.Error(err, "Failed to set characteristic properties");
406         }
407
408         internal BluetoothGattWriteType GetWriteType()
409         {
410             int writeType;
411             int err = Interop.Bluetooth.BtGattCharacteristicGetWriteType(_handle, out writeType);
412             GattUtil.Error(err, "Failed to get characteristic writetype");
413             return (BluetoothGattWriteType) writeType;
414         }
415
416         internal void SetWriteType(BluetoothGattWriteType writeType)
417         {
418             int err = Interop.Bluetooth.BtGattCharacteristicSetWriteType(_handle, (int)writeType);
419             GattUtil.Error(err, "Failed to get characteristic writetype");
420         }
421
422         internal void AddDescriptor(BluetoothGattDescriptor descriptor)
423         {
424             int err = Interop.Bluetooth.BtGattCharacteristicAddDescriptor(_handle, descriptor.GetHandle());
425             GattUtil.ThrowForError(err, string.Format("Failed to add descriptor with UUID ({0})", descriptor.Uuid));
426         }
427
428         internal BluetoothGattDescriptor GetDescriptor(BluetoothGattCharacteristic characteristic, string uuid)
429         {
430             BluetoothGattAttributeHandle handle;
431             int err = Interop.Bluetooth.BtGattCharacteristicGetDescriptor(_handle, uuid, out handle);
432             if (err.IsFailed())
433             {
434                 GattUtil.Error(err, string.Format("Failed to get descriptor with UUID ({0})", uuid));
435                 return null;
436             }
437             BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, uuid);
438             descriptor.SetParent(characteristic);
439             return descriptor;
440         }
441
442         internal IEnumerable<BluetoothGattDescriptor> GetDescriptors(BluetoothGattCharacteristic characteristic)
443         {
444             List<BluetoothGattDescriptor> attribututeList = new List<BluetoothGattDescriptor>();
445             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
446             {
447                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
448                 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, "");
449                 if (descriptor != null)
450                 {
451                     descriptor.SetParent(characteristic);
452                     attribututeList.Add(descriptor);
453                 }
454                 return true;
455             };
456
457             int err = Interop.Bluetooth.BtGattCharacteristicForeachDescriptors(characteristic.GetHandle(), cb, IntPtr.Zero);
458             GattUtil.Error(err, "Failed to get all descriptor");
459
460             return attribututeList;
461         }
462     }
463
464     internal class BluetoothGattDescriptorImpl : BluetoothGattAttributeImpl
465     {
466         internal BluetoothGattDescriptorImpl(string uuid, BluetoothGattPermission permission, byte[] value)
467         {
468             int err = Interop.Bluetooth.BtGattDescriptorCreate(uuid, (int)permission, value, value.Length, out _handle);
469             GattUtil.ThrowForError(err, "Failed to get native descriptor handle");
470         }
471
472         internal BluetoothGattDescriptorImpl(BluetoothGattAttributeHandle handle)
473         {
474             _handle = handle;
475         }
476
477         internal static BluetoothGattDescriptor CreateBluetoothGattDescriptor(BluetoothGattAttributeHandle handle, string uuid)
478         {
479             int permission;
480             int err = Interop.Bluetooth.BtGattDescriptorGetPermissions(handle, out permission);
481             GattUtil.ThrowForError(err, string.Format("Failed to get permissions with UUID ({0})", uuid));
482
483             if (uuid == "")
484             {
485                 int ret = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
486                 GattUtil.ThrowForError(ret, "Failed to get UUID");
487             }
488
489             BluetoothGattDescriptorImpl impl = new BluetoothGattDescriptorImpl(handle);
490             return new BluetoothGattDescriptor(impl, uuid, (BluetoothGattPermission)permission);
491         }
492     }
493
494     internal abstract class BluetoothGattAttributeImpl
495     {
496         protected BluetoothGattAttributeHandle _handle;
497
498         internal string GetUuid()
499         {
500             string uuid;
501             int err = Interop.Bluetooth.BtGattGetUuid(_handle, out uuid);
502             GattUtil.Error(err, "Failed to get attribute uuid");
503
504             return uuid;
505         }
506
507         internal byte[] GetValue()
508         {
509             IntPtr nativeValue;
510             int nativeValueLength;
511             int err = Interop.Bluetooth.BtGattGetValue(_handle, out nativeValue, out nativeValueLength);
512             GattUtil.Error(err, "Failed to get attribute value");
513
514             return GattUtil.IntPtrToByteArray(nativeValue, nativeValueLength);
515         }
516
517         internal void SetValue(byte[] value)
518         {
519             int err = Interop.Bluetooth.BtGattSetValue(_handle, value, value.Length);
520             GattUtil.ThrowForError(err, "Failed to set attribute value");
521         }
522
523         internal string GetValue(int offset)
524         {
525             byte[] value = GetValue();
526
527             int nullPos = value.Length - offset;
528             for (int i = offset; i < value.Length; ++i)
529             {
530                 if (value[i] == '\0')
531                 {
532                     nullPos = i;
533                     break;
534                 }
535             }
536
537             string strValue = "";
538             strValue = Encoding.UTF8.GetString(value, offset, nullPos - offset);
539             return strValue;
540         }
541
542         internal void SetValue(string value, int offset)
543         {
544             byte[] byteValue = GetValue();
545             byte[] strValue = Encoding.UTF8.GetBytes(value);
546             int length = offset + strValue.Length;
547             if (length >= byteValue.Length)
548             {
549                 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "Can not fit value to buffer");
550             }
551
552             Buffer.BlockCopy(strValue, 0, byteValue, offset, strValue.Length);
553             byteValue[length] = (byte)'\0';
554             SetValue(byteValue);
555         }
556
557         internal int GetValue(IntDataType type, int offset)
558         {
559             int value;
560             int err = Interop.Bluetooth.BtGattGetIntValue(_handle, (int)type, offset, out value);
561             GattUtil.Error(err, "Failed to get attribute int value at offset");
562             return value;
563         }
564
565         internal void SetValue(IntDataType type, int value, int offset)
566         {
567             int err = Interop.Bluetooth.BtGattSetIntValue(_handle, (int)type, value, offset);
568             GattUtil.ThrowForError(err, "Failed to set attribute int value at offset");
569         }
570
571         internal float GetValue(FloatDataType type, int offset)
572         {
573             float value;
574             int err = Interop.Bluetooth.BtGattGetFloatValue(_handle, (int)type, offset, out value);
575             GattUtil.Error(err, "Failed to get attribute float value at offset");
576             return value;
577         }
578
579         internal void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
580         {
581             int err = Interop.Bluetooth.BtGattSetFloatValue(_handle, (int)type, mantissa, exponent, offset);
582             GattUtil.ThrowForError(err, "Failed to set attribute float value at offset");
583         }
584
585         internal void SetReadValueRequestedEventCallback(Interop.Bluetooth.BtGattServerReadValueRequestedCallback callback)
586         {
587             int err = Interop.Bluetooth.BtGattServerSetReadValueRequestedCallback(_handle, callback, IntPtr.Zero);
588             GattUtil.ThrowForError(err, "Failed to set attribute read value requested callback");
589         }
590
591         internal void SetWriteValueRequestedEventCallback(Interop.Bluetooth.BtGattServerWriteValueRequestedCallback callback)
592         {
593             int err = Interop.Bluetooth.BtGattServerSetWriteValueRequestedCallback(_handle, callback, IntPtr.Zero);
594             GattUtil.ThrowForError(err, "Failed to set attribute write value requested callback");
595         }
596
597         internal BluetoothGattAttributeHandle GetHandle()
598         {
599             return _handle;
600         }
601
602         internal void ReleaseHandleOwnership()
603         {
604             _handle.ReleaseOwnership();
605         }
606     }
607
608
609     internal class BluetoothGattAttributeHandle : BluetoothGattHandle
610     {
611         public BluetoothGattAttributeHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, hasOwnership)
612         {
613         }
614
615         public BluetoothGattAttributeHandle()
616         {
617         }
618
619         protected override bool ReleaseHandle()
620         {
621             if (_hasOwnership == true)
622             {
623                 Interop.Bluetooth.BtGattDestroy(handle);
624             }
625             SetHandle(IntPtr.Zero);
626             return true;
627         }
628     }
629
630     internal class BluetoothGattClientHandle : BluetoothGattHandle
631     {
632         protected override bool ReleaseHandle()
633         {
634             if (_hasOwnership == true)
635             {
636                 Interop.Bluetooth.BtGattClientDestroy(handle);
637                 Interop.Bluetooth.BtGattServerDeinitialize();
638             }
639             SetHandle(IntPtr.Zero);
640             return true;
641         }
642     }
643
644     internal class BluetoothGattServerHandle : BluetoothGattHandle
645     {
646         protected override bool ReleaseHandle()
647         {
648             if (_hasOwnership == true)
649             {
650                 Interop.Bluetooth.BtGattServerDestroy(handle);
651             }
652             SetHandle(IntPtr.Zero);
653             return true;
654         }
655     }
656
657     internal abstract class BluetoothGattHandle : SafeHandle
658     {
659         protected bool _hasOwnership;
660
661         public BluetoothGattHandle() : base(IntPtr.Zero, true)
662         {
663             _hasOwnership = true;
664         }
665
666         public BluetoothGattHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, true)
667         {
668             _hasOwnership = hasOwnership;
669         }
670
671         public override bool IsInvalid
672         {
673             get { return handle == IntPtr.Zero; }
674         }
675
676         public void ReleaseOwnership()
677         {
678             _hasOwnership = false;
679         }
680     }
681
682     internal static class GattUtil
683     {
684         internal static byte[] IntPtrToByteArray(IntPtr nativeValue, int lenght)
685         {
686             byte[] value = new byte[lenght];
687             if (nativeValue != IntPtr.Zero)
688             {
689                 Marshal.Copy(nativeValue, value, 0, lenght);
690             }
691             return value;
692         }
693
694         internal static void Error(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
695         {
696             if (err.IsFailed())
697             {
698                 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
699             }
700         }
701
702         internal static void ThrowForError(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
703         {
704             if (err.IsFailed())
705             {
706                 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
707                 BluetoothErrorFactory.ThrowBluetoothException(err);
708             }
709         }
710
711         internal static bool IsFailed(this int err)
712         {
713             return err != (int)BluetoothError.None;
714         }
715     }
716 }