Release 4.0.0-preview1-00051
[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 request_type, int status, byte[] value, int offset)
105         {
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));
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                 if (result == (int)BluetoothError.None)
201                     tcs.SetResult(true);
202                 else
203                     tcs.SetResult(false);
204             };
205
206             int err = Interop.Bluetooth.BtGattClientReadValue(handle, cb, IntPtr.Zero);
207             if (err.IsFailed())
208             {
209                 GattUtil.Error(err, "Failed to read value from remote device");
210                 tcs.SetResult(false);
211                 BluetoothErrorFactory.ThrowBluetoothException(err);
212             }
213             return tcs.Task;
214         }
215
216         internal Task<bool> WriteValueAsyncTask(BluetoothGattAttributeHandle handle)
217         {
218             TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
219             Interop.Bluetooth.BtGattClientRequestCompletedCallback cb = (result, requestHandle, userData) =>
220             {
221                 if (result == (int)BluetoothError.None)
222                     tcs.SetResult(true);
223                 else
224                     tcs.SetResult(false);
225             };
226
227             int err = Interop.Bluetooth.BtGattClientWriteValue(handle, cb, IntPtr.Zero);
228             if (err.IsFailed())
229             {
230                 GattUtil.Error(err, "Failed to write value to remote device");
231                 tcs.SetResult(false);
232                 BluetoothErrorFactory.ThrowBluetoothException(err);
233             }
234             return tcs.Task;
235         }
236
237         internal BluetoothGattClientHandle GetHandle()
238         {
239             return _handle;
240         }
241     }
242
243     internal class BluetoothGattServiceImpl : BluetoothGattAttributeImpl
244     {
245         internal BluetoothGattServiceImpl(string uuid, BluetoothGattServiceType type)
246         {
247             int err = Interop.Bluetooth.BtGattServiceCreate(uuid, (int)type, out _handle);
248             GattUtil.ThrowForError(err, "Failed to get native service handle");
249         }
250
251         internal BluetoothGattServiceImpl(BluetoothGattAttributeHandle handle)
252         {
253             _handle = handle;
254         }
255
256         internal static BluetoothGattService CreateBluetoothGattService(BluetoothGattAttributeHandle handle, string uuid)
257         {
258             if (uuid == "")
259             {
260                 int err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
261                 GattUtil.ThrowForError(err, "Failed to get UUID");
262             }
263
264             BluetoothGattServiceImpl impl = new BluetoothGattServiceImpl(handle);
265             return new BluetoothGattService(impl, uuid);
266         }
267
268         internal void AddCharacteristic(BluetoothGattCharacteristic characteristic)
269         {
270             int err = Interop.Bluetooth.BtGattServiceAddCharacteristic(_handle, characteristic.GetHandle());
271             GattUtil.ThrowForError(err, string.Format("Failed to add characteristic with UUID ({0})", characteristic.Uuid));
272         }
273
274         internal BluetoothGattCharacteristic GetCharacteristic(BluetoothGattService service, string uuid)
275         {
276             BluetoothGattAttributeHandle attributeHandle;
277             int err = Interop.Bluetooth.BtGattServiceGetCharacteristic(_handle, uuid, out attributeHandle);
278             if (err.IsFailed())
279             {
280                 GattUtil.Error(err, string.Format("Failed to get Characteristic with UUID ({0})", uuid));
281                 return null;
282             }
283
284             BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(attributeHandle, uuid);
285             Characteristic.SetParent(service);
286             return Characteristic;
287         }
288
289         internal IEnumerable<BluetoothGattCharacteristic> GetCharacteristics(BluetoothGattService service)
290         {
291             List<BluetoothGattCharacteristic> attribututeList = new List<BluetoothGattCharacteristic>();
292             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
293             {
294                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
295                 BluetoothGattCharacteristic Characteristic = BluetoothGattCharacteristicImpl.CreateBluetoothGattGattCharacteristic(handle, "");
296                 if (Characteristic != null)
297                 {
298                     Characteristic.SetParent(service);
299                     attribututeList.Add(Characteristic);
300                 }
301                 return true;
302             };
303
304             int err = Interop.Bluetooth.BtGattServiceForeachCharacteristics(service.GetHandle(), cb, IntPtr.Zero);
305             GattUtil.Error(err, "Failed to get all Characteristic");
306
307             return attribututeList;
308         }
309
310         internal void AddIncludeService(BluetoothGattService includedService)
311         {
312             int err = Interop.Bluetooth.BtGattServiceAddIncludedService(_handle, includedService.GetHandle());
313             GattUtil.ThrowForError(err, string.Format("Failed to add service with UUID ({0})", includedService.Uuid));
314         }
315
316         internal BluetoothGattService GetIncludeService(BluetoothGattService parentService, string uuid)
317         {
318             BluetoothGattAttributeHandle attributeHandle;
319             int err = Interop.Bluetooth.BtGattServiceGetIncludedService(_handle, uuid, out attributeHandle);
320             if (err.IsFailed())
321             {
322                 GattUtil.Error(err, string.Format("Failed to get included service with UUID ({0})", uuid));
323                 return null;
324             }
325
326             BluetoothGattService service = new BluetoothGattService(new BluetoothGattServiceImpl(attributeHandle), uuid);
327             service.SetParent(parentService);
328             return service;
329         }
330
331         internal IEnumerable<BluetoothGattService> GetIncludeServices(BluetoothGattService parentService)
332         {
333             List<BluetoothGattService> attribututeList = new List<BluetoothGattService>();
334             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
335             {
336                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
337                 BluetoothGattService service = BluetoothGattServiceImpl.CreateBluetoothGattService(handle, "");
338                 if (service != null)
339                 {
340                     service.SetParent(parentService);
341                     attribututeList.Add(service);
342                 }
343                 return true;
344             };
345
346             int err = Interop.Bluetooth.BtGattServiceForeachIncludedServices(parentService.GetHandle(), cb, IntPtr.Zero);
347             GattUtil.Error(err, "Failed to get all services");
348
349             return attribututeList;
350         }
351     }
352
353     internal class BluetoothGattCharacteristicImpl : BluetoothGattAttributeImpl
354     {
355         internal BluetoothGattCharacteristicImpl(string uuid, BluetoothGattPermission permission, BluetoothGattProperty property, byte[] value)
356         {
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");
359         }
360
361         internal BluetoothGattCharacteristicImpl(BluetoothGattAttributeHandle handle)
362         {
363             _handle = handle;
364         }
365
366         internal static BluetoothGattCharacteristic CreateBluetoothGattGattCharacteristic(BluetoothGattAttributeHandle handle, string uuid)
367         {
368             int permission;
369             int err = Interop.Bluetooth.BtGattCharacteristicGetPermissions(handle, out permission);
370             GattUtil.ThrowForError(err, "Failed to get permissions");
371
372             if (uuid == "")
373             {
374                 err = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
375                 GattUtil.ThrowForError(err, "Failed to get UUID");
376             }
377
378             BluetoothGattCharacteristicImpl impl = new BluetoothGattCharacteristicImpl(handle);
379             return new BluetoothGattCharacteristic(impl, uuid, (BluetoothGattPermission)permission);
380         }
381
382         internal void SetCharacteristicValueChangedEvent(Interop.Bluetooth.BtClientCharacteristicValueChangedCallback callback)
383         {
384             int err = Interop.Bluetooth.BtGattClientSetCharacteristicValueChangedCallback(_handle, callback, IntPtr.Zero);
385             GattUtil.Error(err, "Failed to set client characteristic value changed callback");
386         }
387
388         internal void UnsetCharacteristicValueChangedEvent()
389         {
390             int err = Interop.Bluetooth.BtGattClientUnsetCharacteristicValueChangedCallback(_handle);
391             GattUtil.Error(err, "Failed to unset client characteristic value changed callback");
392         }
393
394         internal void SetNotificationStateChangedEvent(Interop.Bluetooth.BtGattServerNotificationStateChangeCallback callback)
395         {
396             int err = Interop.Bluetooth.BtGattServeSetNotificationStateChangeCallback(_handle, callback, IntPtr.Zero);
397             GattUtil.Error(err, "Failed to set characteristic notification state changed callback");
398         }
399
400         internal BluetoothGattProperty GetProperties()
401         {
402             int properties = 0 ;
403             int err = Interop.Bluetooth.BtGattCharacteristicGetProperties(_handle, out properties);
404             GattUtil.Error(err, "Failed to get characteristic properties");
405             return (BluetoothGattProperty)properties;
406         }
407
408         internal void SetProperties(BluetoothGattProperty perperties)
409         {
410             int err = Interop.Bluetooth.BtGattCharacteristicSetProperties(_handle, (int)perperties);
411             GattUtil.Error(err, "Failed to set characteristic properties");
412         }
413
414         internal BluetoothGattWriteType GetWriteType()
415         {
416             int writeType;
417             int err = Interop.Bluetooth.BtGattCharacteristicGetWriteType(_handle, out writeType);
418             GattUtil.Error(err, "Failed to get characteristic writetype");
419             return (BluetoothGattWriteType) writeType;
420         }
421
422         internal void SetWriteType(BluetoothGattWriteType writeType)
423         {
424             int err = Interop.Bluetooth.BtGattCharacteristicSetWriteType(_handle, (int)writeType);
425             GattUtil.Error(err, "Failed to get characteristic writetype");
426         }
427
428         internal void AddDescriptor(BluetoothGattDescriptor descriptor)
429         {
430             int err = Interop.Bluetooth.BtGattCharacteristicAddDescriptor(_handle, descriptor.GetHandle());
431             GattUtil.ThrowForError(err, string.Format("Failed to add descriptor with UUID ({0})", descriptor.Uuid));
432         }
433
434         internal BluetoothGattDescriptor GetDescriptor(BluetoothGattCharacteristic characteristic, string uuid)
435         {
436             BluetoothGattAttributeHandle handle;
437             int err = Interop.Bluetooth.BtGattCharacteristicGetDescriptor(_handle, uuid, out handle);
438             if (err.IsFailed())
439             {
440                 GattUtil.Error(err, string.Format("Failed to get descriptor with UUID ({0})", uuid));
441                 return null;
442             }
443             BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, uuid);
444             descriptor.SetParent(characteristic);
445             return descriptor;
446         }
447
448         internal IEnumerable<BluetoothGattDescriptor> GetDescriptors(BluetoothGattCharacteristic characteristic)
449         {
450             List<BluetoothGattDescriptor> attribututeList = new List<BluetoothGattDescriptor>();
451             Interop.Bluetooth.BtGattForeachCallback cb = (total, index, attributeHandle, userData) =>
452             {
453                 BluetoothGattAttributeHandle handle = new BluetoothGattAttributeHandle(attributeHandle, false);
454                 BluetoothGattDescriptor descriptor = BluetoothGattDescriptorImpl.CreateBluetoothGattDescriptor(handle, "");
455                 if (descriptor != null)
456                 {
457                     descriptor.SetParent(characteristic);
458                     attribututeList.Add(descriptor);
459                 }
460                 return true;
461             };
462
463             int err = Interop.Bluetooth.BtGattCharacteristicForeachDescriptors(characteristic.GetHandle(), cb, IntPtr.Zero);
464             GattUtil.Error(err, "Failed to get all descriptor");
465
466             return attribututeList;
467         }
468     }
469
470     internal class BluetoothGattDescriptorImpl : BluetoothGattAttributeImpl
471     {
472         internal BluetoothGattDescriptorImpl(string uuid, BluetoothGattPermission permission, byte[] value)
473         {
474             int err = Interop.Bluetooth.BtGattDescriptorCreate(uuid, (int)permission, value, value.Length, out _handle);
475             GattUtil.ThrowForError(err, "Failed to get native descriptor handle");
476         }
477
478         internal BluetoothGattDescriptorImpl(BluetoothGattAttributeHandle handle)
479         {
480             _handle = handle;
481         }
482
483         internal static BluetoothGattDescriptor CreateBluetoothGattDescriptor(BluetoothGattAttributeHandle handle, string uuid)
484         {
485             int permission;
486             int err = Interop.Bluetooth.BtGattDescriptorGetPermissions(handle, out permission);
487             GattUtil.ThrowForError(err, string.Format("Failed to get permissions with UUID ({0})", uuid));
488
489             if (uuid == "")
490             {
491                 int ret = Interop.Bluetooth.BtGattGetUuid(handle, out uuid);
492                 GattUtil.ThrowForError(ret, "Failed to get UUID");
493             }
494
495             BluetoothGattDescriptorImpl impl = new BluetoothGattDescriptorImpl(handle);
496             return new BluetoothGattDescriptor(impl, uuid, (BluetoothGattPermission)permission);
497         }
498     }
499
500     internal abstract class BluetoothGattAttributeImpl
501     {
502         protected BluetoothGattAttributeHandle _handle;
503
504         internal string GetUuid()
505         {
506             string uuid;
507             int err = Interop.Bluetooth.BtGattGetUuid(_handle, out uuid);
508             GattUtil.Error(err, "Failed to get attribute uuid");
509
510             return uuid;
511         }
512
513         internal byte[] GetValue()
514         {
515             IntPtr nativeValue;
516             int nativeValueLength;
517             int err = Interop.Bluetooth.BtGattGetValue(_handle, out nativeValue, out nativeValueLength);
518             GattUtil.Error(err, "Failed to get attribute value");
519
520             return GattUtil.IntPtrToByteArray(nativeValue, nativeValueLength);
521         }
522
523         internal void SetValue(byte[] value)
524         {
525             int err = Interop.Bluetooth.BtGattSetValue(_handle, value, value.Length);
526             GattUtil.ThrowForError(err, "Failed to set attribute value");
527         }
528
529         internal string GetValue(int offset)
530         {
531             byte[] value = GetValue();
532
533             int nullPos = value.Length - offset;
534             for (int i = offset; i < value.Length; ++i)
535             {
536                 if (value[i] == '\0')
537                 {
538                     nullPos = i;
539                     break;
540                 }
541             }
542
543             string strValue = "";
544             strValue = Encoding.UTF8.GetString(value, offset, nullPos - offset);
545             return strValue;
546         }
547
548         internal int GetValue(IntDataType type, int offset)
549         {
550             int value;
551             int err = Interop.Bluetooth.BtGattGetIntValue(_handle, (int)type, offset, out value);
552             GattUtil.Error(err, "Failed to get attribute int value at offset");
553             return value;
554         }
555
556         internal void SetValue(IntDataType type, int value, int offset)
557         {
558             int err = Interop.Bluetooth.BtGattSetIntValue(_handle, (int)type, value, offset);
559             GattUtil.ThrowForError(err, "Failed to set attribute int value at offset");
560         }
561
562         internal float GetValue(FloatDataType type, int offset)
563         {
564             float value;
565             int err = Interop.Bluetooth.BtGattGetFloatValue(_handle, (int)type, offset, out value);
566             GattUtil.Error(err, "Failed to get attribute float value at offset");
567             return value;
568         }
569
570         internal void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
571         {
572             int err = Interop.Bluetooth.BtGattSetFloatValue(_handle, (int)type, mantissa, exponent, offset);
573             GattUtil.ThrowForError(err, "Failed to set attribute float value at offset");
574         }
575
576         internal void SetReadValueRequestedEventCallback(Interop.Bluetooth.BtGattServerReadValueRequestedCallback callback)
577         {
578             int err = Interop.Bluetooth.BtGattServerSetReadValueRequestedCallback(_handle, callback, IntPtr.Zero);
579             GattUtil.ThrowForError(err, "Failed to set attribute read value requested callback");
580         }
581
582         internal void SetWriteValueRequestedEventCallback(Interop.Bluetooth.BtGattServerWriteValueRequestedCallback callback)
583         {
584             int err = Interop.Bluetooth.BtGattServerSetWriteValueRequestedCallback(_handle, callback, IntPtr.Zero);
585             GattUtil.ThrowForError(err, "Failed to set attribute write value requested callback");
586         }
587
588         internal BluetoothGattAttributeHandle GetHandle()
589         {
590             return _handle;
591         }
592
593         internal void ReleaseHandleOwnership()
594         {
595             _handle.ReleaseOwnership();
596         }
597     }
598
599
600     internal class BluetoothGattAttributeHandle : BluetoothGattHandle
601     {
602         public BluetoothGattAttributeHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, hasOwnership)
603         {
604         }
605
606         public BluetoothGattAttributeHandle()
607         {
608         }
609
610         protected override bool ReleaseHandle()
611         {
612             if (_hasOwnership == true)
613             {
614                 Interop.Bluetooth.BtGattDestroy(handle);
615             }
616             SetHandle(IntPtr.Zero);
617             return true;
618         }
619     }
620
621     internal class BluetoothGattClientHandle : BluetoothGattHandle
622     {
623         protected override bool ReleaseHandle()
624         {
625             if (_hasOwnership == true)
626             {
627                 Interop.Bluetooth.BtGattClientDestroy(handle);
628             }
629             SetHandle(IntPtr.Zero);
630             return true;
631         }
632     }
633
634     internal class BluetoothGattServerHandle : BluetoothGattHandle
635     {
636         protected override bool ReleaseHandle()
637         {
638             if (_hasOwnership == true)
639             {
640                 Interop.Bluetooth.BtGattServerDeinitialize();
641                 Interop.Bluetooth.BtGattServerDestroy(handle);
642             }
643             SetHandle(IntPtr.Zero);
644             return true;
645         }
646     }
647
648     internal abstract class BluetoothGattHandle : SafeHandle
649     {
650         protected bool _hasOwnership;
651
652         public BluetoothGattHandle() : base(IntPtr.Zero, true)
653         {
654             _hasOwnership = true;
655         }
656
657         public BluetoothGattHandle(IntPtr nativeHandle, bool hasOwnership) : base(nativeHandle, true)
658         {
659             _hasOwnership = hasOwnership;
660         }
661
662         public override bool IsInvalid
663         {
664             get { return handle == IntPtr.Zero; }
665         }
666
667         public void ReleaseOwnership()
668         {
669             _hasOwnership = false;
670         }
671     }
672
673     internal static class GattUtil
674     {
675         internal static byte[] IntPtrToByteArray(IntPtr nativeValue, int lenght)
676         {
677             byte[] value = new byte[lenght];
678             if (nativeValue != IntPtr.Zero)
679             {
680                 Marshal.Copy(nativeValue, value, 0, lenght);
681             }
682             return value;
683         }
684
685         internal static void Error(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
686         {
687             if (err.IsFailed())
688             {
689                 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
690             }
691         }
692
693         internal static void ThrowForError(int err, string message, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
694         {
695             if (err.IsFailed())
696             {
697                 Log.Error(Globals.LogTag, string.Format("{0}, err: {1}", message, (BluetoothError)err), file, func, line);
698                 BluetoothErrorFactory.ThrowBluetoothException(err);
699             }
700         }
701
702         internal static bool IsFailed(this int err)
703         {
704             return err != (int)BluetoothError.None;
705         }
706     }
707 }