Merge remote-tracking branch 'origin/API8' into tizen_6.0
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothGatt.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.ComponentModel;
20 using System.Runtime.InteropServices;
21 using System.Text;
22 using System.Threading.Tasks;
23
24 namespace Tizen.Network.Bluetooth
25 {
26     /// <summary>
27     /// The Bluetooth GATT server.
28     /// </summary>
29     /// <since_tizen> 3 </since_tizen>
30     public class BluetoothGattServer : IDisposable
31     {
32         private static BluetoothGattServer _instance;
33         private BluetoothGattServerImpl _impl;
34
35         private BluetoothGattServer()
36         {
37             _impl = new BluetoothGattServerImpl();
38             _impl._notificationSent += (s, e) =>
39             {
40                 e.Server = this;
41                 NotificationSent?.Invoke(this, e);
42             };
43         }
44
45         /// <summary>
46         /// (event) This event is called when the indication acknowledgement is received for each notified client.
47         /// </summary>
48         /// <since_tizen> 3 </since_tizen>
49         public event EventHandler<NotificationSentEventArg> NotificationSent;
50
51         /// <summary>
52         /// Creates the Bluetooth GATT server.
53         /// </summary>
54         /// <returns>The BluetoothGattServer instance.</returns>
55         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
56         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
57         /// <exception cref="InvalidOperationException">Thrown when the create GATT server fails.</exception>
58         /// <since_tizen> 3 </since_tizen>
59         public static BluetoothGattServer CreateServer()
60         {
61             if (_instance == null)
62             {
63                 BluetoothGattServer server = new BluetoothGattServer();
64                 if (server.IsValid())
65                 {
66                     _instance = server;
67                 }
68             }
69             return _instance;
70         }
71
72         /// <summary>
73         /// Registers the server along with the GATT services of the application it is hosting.
74         /// </summary>
75         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
76         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
77         /// <exception cref="InvalidOperationException">Thrown when the register server application fails.</exception>
78         /// <since_tizen> 3 </since_tizen>
79         public void Start()
80         {
81             _impl.Start();
82         }
83
84         /// <summary>
85         /// Registers a specified service to this server.
86         /// </summary>
87         /// <param name="service">The service, which needs to be registered with this server.</param>
88         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
89         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
90         /// <exception cref="InvalidOperationException">Thrown when the register service fails.</exception>
91         /// <since_tizen> 3 </since_tizen>
92         public void RegisterGattService(BluetoothGattService service)
93         {
94             if (service.IsRegistered())
95             {
96                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
97             }
98             _impl.RegisterGattService(this, service);
99         }
100
101         /// <summary>
102         /// Unregisters a specified service from this server.
103         /// </summary>
104         /// <param name="service">The service, which needs to be unregistered from this server.</param>
105         /// <remarks>
106         /// Once unregistered, the service object will become invalid and should not be used to access sevices or any children attribute's methods/members.
107         /// </remarks>
108         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
109         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
110         /// <exception cref="InvalidOperationException">Thrown when the unregister service fails.</exception>
111         /// <since_tizen> 3 </since_tizen>
112         public void UnregisterGattService(BluetoothGattService service)
113         {
114             if (service.GetGattServer() != this)
115             {
116                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
117             }
118
119             _impl.UnregisterGattService(service);
120         }
121
122         /// <summary>
123         /// Unregisters all services from this server.
124         /// </summary>
125         /// <remarks>
126         /// Once unregistered, servicees will become invalid and should not be used to access sevices or any children attribute's methods/members.
127         /// </remarks>
128         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
129         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
130         /// <exception cref="InvalidOperationException">Thrown when the unregister all services fail.</exception>
131         /// <since_tizen> 3 </since_tizen>
132         public void UnregisterGattServices()
133         {
134             _impl.UnregisterAllGattServices(this);
135         }
136
137         /// <summary>
138         /// Gets service with given UUID that belongs to this server.
139         /// </summary>
140         /// <param name="uuid">The UUID for the service to get.</param>
141         /// <returns>The Service with the given UUID if it exists, null otherwise.</returns>
142         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
143         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
144         /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
145         /// <since_tizen> 3 </since_tizen>
146         public BluetoothGattService GetService(string uuid)
147         {
148             return _impl.GetService(this, uuid);
149         }
150
151         /// <summary>
152         /// Gets the list of services that belongs to this server.
153         /// </summary>
154         /// <returns>The list of services that belongs to this server.</returns>
155         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
156         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
157         /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
158         /// <since_tizen> 3 </since_tizen>
159         public IEnumerable<BluetoothGattService> GetServices()
160         {
161             return _impl.GetServices(this);
162         }
163
164         /// <summary>
165         /// Sends indication for the value change of the characteristic to the remote devices.
166         /// </summary>
167         /// <param name="characteristic">The characteristic whose the value is changed.</param>
168         /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
169         /// <returns>true on success, false otherwise.</returns>
170         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
171         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
172         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
173         /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
174         /// <since_tizen> 3 </since_tizen>
175         public async Task<bool> SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
176         {
177             return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
178         }
179
180         /// <summary>
181         /// Sends the notification for the value change of the characteristic to the remote devices.
182         /// </summary>
183         /// <param name="characteristic">The characteristic, which has a changed value.</param>
184         /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
185         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
186         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
187         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
188         /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
189         /// <since_tizen> 3 </since_tizen>
190         public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
191         {
192             _ = _impl.SendIndicationAsync(this, characteristic, clientAddress);
193         }
194
195         /// <summary>
196         /// Sends a response to the remote device as a result of a read/write request.
197         /// </summary>
198         /// <param name="requestId">The identification of a read/write request.</param>
199         /// <param name="type">The request type for read/write.</param>
200         /// <param name="status">The error value in case of failure, 0 for success.</param>
201         /// <param name="value">The value to be sent.</param>
202         /// <param name="offset">The offset from where the value is read.</param>
203         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
204         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
205         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
206         /// or when the remote device is disconnected, or the send response procedure fails.</exception>
207         /// <since_tizen> 3 </since_tizen>
208         public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
209         {
210             _impl.SendResponse(requestId, (int)type, status, value, offset);
211         }
212
213         internal bool IsValid()
214         {
215             return _impl.GetHandle().IsInvalid == false;
216         }
217
218         /// <summary>
219         /// Destroys the current object.
220         /// </summary>
221         ~BluetoothGattServer()
222         {
223             Dispose(false);
224         }
225
226         /// <summary>
227         /// Destroys the current object.
228         /// </summary>
229         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
230         /// <since_tizen> 6 </since_tizen>
231         public void Dispose()
232         {
233             Dispose(true);
234             GC.SuppressFinalize(this);
235         }
236
237         /// <summary>
238         /// Releases all the resources currently used by this instance.
239         /// </summary>
240         /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
241         /// <since_tizen> 6 </since_tizen>
242         protected virtual void Dispose(bool disposing)
243         {
244             if (disposing)
245             {
246                 _impl?.GetHandle()?.Dispose();
247                 _instance = null;
248             }
249         }
250     }
251
252     /// <summary>
253     /// The Bluetooth GATT client.
254     /// </summary>
255     /// <since_tizen> 3 </since_tizen>
256     public class BluetoothGattClient : IDisposable
257     {
258         private BluetoothGattClientImpl _impl;
259         private string _remoteAddress = string.Empty;
260         private TaskCompletionSource<bool> _taskForConnection;
261         private TaskCompletionSource<bool> _taskForDisconnection;
262         private static event EventHandler<GattConnectionStateChangedEventArgs> s_connectionStateChanged;
263         private static Interop.Bluetooth.GattConnectionStateChangedCallBack s_connectionStateChangeCallback;
264
265         internal BluetoothGattClient(string remoteAddress)
266         {
267             _impl = new BluetoothGattClientImpl(remoteAddress);
268             _remoteAddress = remoteAddress;
269             StaticConnectionStateChanged += OnConnectionStateChanged;
270             _impl.AttMtuChanged += OnAttMtuChanged;
271         }
272
273         private void OnAttMtuChanged(object s, AttMtuChangedEventArgs e)
274         {
275             AttMtuChanged?.Invoke(this, e);
276         }
277
278         /// <summary>
279         /// Creates the Bluetooth GATT client.
280         /// </summary>
281         /// <param name="remoteAddress">The remote device address.</param>
282         /// <returns>The BluetoothGattClient instance.</returns>
283         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
284         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
285         /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
286         /// <since_tizen> 6 </since_tizen>
287         public static BluetoothGattClient CreateClient(string remoteAddress)
288         {
289             BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
290             return client.Isvalid() ? client : null;
291         }
292
293         /// <summary>
294         /// The ConnectionStateChanged event is raised when the gatt connection state is changed.
295         /// </summary>
296         /// <since_tizen> 6 </since_tizen>
297         public event EventHandler<GattConnectionStateChangedEventArgs> ConnectionStateChanged;
298
299         private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
300         {
301             if (e.RemoteAddress == _remoteAddress)
302             {
303                 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
304                 {
305                     if (e.Result == (int)BluetoothError.None)
306                     {
307                         _taskForConnection.SetResult(true);
308                     }
309                     else
310                     {
311                         _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
312                     }
313                     _taskForConnection = null;
314                 }
315
316                 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
317                 {
318                     if (e.Result == (int)BluetoothError.None)
319                     {
320                         _taskForDisconnection.SetResult(true);
321                     }
322                     else
323                     {
324                         _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
325                     }
326                     _taskForDisconnection = null;
327                 }
328
329                 if (e.Result == (int)BluetoothError.None)
330                 {
331                     ConnectionStateChanged?.Invoke(this, e);
332                 }
333             }
334         }
335
336         internal static event EventHandler<GattConnectionStateChangedEventArgs> StaticConnectionStateChanged
337         {
338             add
339             {
340                 if (s_connectionStateChanged == null)
341                 {
342                     RegisterConnectionStateChangedEvent();
343                 }
344                 s_connectionStateChanged += value;
345             }
346             remove
347             {
348                 s_connectionStateChanged -= value;
349                 if (s_connectionStateChanged == null)
350                 {
351                     UnregisterConnectionStateChangedEvent();
352                 }
353             }
354         }
355
356         private static void RegisterConnectionStateChangedEvent()
357         {
358             s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
359             {
360                 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
361                 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
362                 s_connectionStateChanged?.Invoke(null, e);
363             };
364
365             int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
366             if (ret != (int)BluetoothError.None)
367             {
368                 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
369             }
370         }
371
372         private static void UnregisterConnectionStateChangedEvent()
373         {
374             int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
375             if (ret != (int)BluetoothError.None)
376             {
377                 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
378             }
379         }
380
381         /// <summary>
382         /// Connects to the remote GATT server asynchronously.
383         /// </summary>
384         /// <param name="autoConnect">The flag for reconnecting when the connection is disconnceted.</param>
385         /// <returns> A task indicating whether the method is done or not.</returns>
386         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
387         /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
388         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
389         /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
390         /// <since_tizen> 6 </since_tizen>
391         public Task ConnectAsync(bool autoConnect)
392         {
393             if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
394             {
395                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
396             }
397             _taskForConnection = new TaskCompletionSource<bool>();
398             _impl.Connect(_remoteAddress, autoConnect);
399             return _taskForConnection.Task;
400         }
401
402         /// <summary>
403         /// Disconnects to the remote GATT server asynchronously.
404         /// </summary>
405         /// <returns> A task indicating whether the method is done or not.</returns>
406         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
407         /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
408         /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
409         /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
410         /// <since_tizen> 6 </since_tizen>
411         public Task DisconnectAsync()
412         {
413             if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
414             {
415                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
416             }
417             _taskForDisconnection = new TaskCompletionSource<bool>();
418             _impl.Disconnect(_remoteAddress);
419             return _taskForDisconnection.Task;
420         }
421
422         /// <summary>
423         /// Destroy Bluetooth GATT client
424         /// </summary>
425         /// <since_tizen> 3 </since_tizen>
426         [Obsolete("Deprecated since API level 6. Please use Dispose() method on BluetoothGattClient.")]
427         public void DestroyClient()
428         {
429             _impl.GetHandle().Dispose();
430         }
431
432         /// <summary>
433         /// The address of the remote device.
434         /// </summary>
435         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
436         /// or when the remote device is disconnected.</exception>
437         /// <since_tizen> 3 </since_tizen>
438         public string RemoteAddress
439         {
440             get
441             {
442                 if (string.IsNullOrEmpty(_remoteAddress))
443                 {
444                     _remoteAddress = _impl.GetRemoteAddress();
445                 }
446                 return _remoteAddress;
447             }
448         }
449
450         /// <summary>
451         /// Gets the service with the given UUID that belongs to the remote device.
452         /// </summary>
453         /// <param name="uuid">The UUID for the service to get.</param>
454         /// <returns>The service with the given UUID if it exists, null otherwise.</returns>
455         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
456         /// or when the remote device is disconnected, or when the get service fails.</exception>
457         /// <since_tizen> 3 </since_tizen>
458         public BluetoothGattService GetService(string uuid)
459         {
460             return _impl.GetService(this, uuid);
461         }
462
463         /// <summary>
464         /// Gets list of services that belongs to the remote device.
465         /// </summary>
466         /// <returns>The list of services that belongs to the remote device.</returns>
467         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
468         /// or when the remote device is disconnected, or when the get service fails.</exception>
469         /// <since_tizen> 3 </since_tizen>
470         public IEnumerable<BluetoothGattService> GetServices()
471         {
472             return _impl.GetServices(this);
473         }
474
475         /// <summary>
476         /// Reads the value of a given characteristic from the remote device asynchronously.
477         /// </summary>
478         /// <param name="characteristic">The characteristic to be read.</param>
479         /// <returns>true on success, false otherwise.</returns>
480         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
481         /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
482         /// <since_tizen> 3 </since_tizen>
483         public async Task<bool> ReadValueAsync(BluetoothGattCharacteristic characteristic)
484         {
485             return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
486         }
487
488         /// <summary>
489         /// Reads the value of the given descriptor from the remote device asynchronously.
490         /// </summary>
491         /// <param name="descriptor">The descriptor to be read.</param>
492         /// <returns>true on success, false otherwise.</returns>
493         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
494         /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
495         /// <since_tizen> 3 </since_tizen>
496         public async Task<bool> ReadValueAsync(BluetoothGattDescriptor descriptor)
497         {
498             return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
499         }
500
501         /// <summary>
502         /// Writes the value of a given characteristic to the remote device asynchronously.
503         /// </summary>
504         /// <param name="characteristic">The characteristic to be written.</param>
505         /// <returns>true on success, false otherwise.</returns>
506         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
507         /// or when the remote device is disconnected or when the write attribute value fails.</exception>
508         /// <since_tizen> 3 </since_tizen>
509         public async Task<bool> WriteValueAsync(BluetoothGattCharacteristic characteristic)
510         {
511             return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
512         }
513
514         /// <summary>
515         /// Writes the value of the given descriptor to the remote device asynchronously.
516         /// </summary>
517         /// <param name="descriptor">The descriptor to be written.</param>
518         /// <returns>true on success, false otherwise.</returns>
519         /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
520         /// or when the remote device is disconnected, or when the write attribute value fails.</exception>
521         /// <since_tizen> 3 </since_tizen>
522         public async Task<bool> WriteValueAsync(BluetoothGattDescriptor descriptor)
523         {
524             return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
525         }
526
527         /// <summary>
528         /// Gets the value of the ATT MTU(Maximum Transmission Unit) for the connection.
529         /// </summary>
530         /// <returns>The MTU value</returns>
531         /// <exception cref="NotSupportedException">Thrown when the BT/BLE is not supported.</exception>
532         /// <exception cref="InvalidOperationException">Thrown when the BT/BLE is not enabled
533         /// or when the remote device is disconnected, or when other specific error occurs.</exception>
534         /// <since_tizen> 8 </since_tizen>
535         [EditorBrowsable(EditorBrowsableState.Never)]
536         public int GetAttMtu()
537         {
538             return _impl.GetAttMtu();
539         }
540
541         /// <summary>
542         /// Sets the value of the ATT MTU(Maximum Transmission Unit) for the connection.
543         /// </summary>
544         /// <param name="mtu">The MTU value</param>
545         /// <exception cref="NotSupportedException">Thrown when the BT/BLE is not supported.</exception>
546         /// <exception cref="InvalidOperationException">Thrown when the BT/BLE is not enabled
547         /// or when the remote device is disconnected, or when other specific error occurs.</exception>
548         /// <since_tizen> 8 </since_tizen>
549         [EditorBrowsable(EditorBrowsableState.Never)]
550         public void SetAttMtu(int mtu)
551         {
552             _impl.SetAttMtu(mtu);
553         }
554
555         /// <summary>
556         /// The AttMtuChanged event is raised when the MTU value changed.
557         /// </summary>
558         /// <since_tizen> 8 </since_tizen>
559         [EditorBrowsable(EditorBrowsableState.Never)]
560         public event EventHandler<AttMtuChangedEventArgs> AttMtuChanged;
561
562         internal bool Isvalid()
563         {
564             return _impl.GetHandle().IsInvalid == false;
565         }
566
567         /// <summary>
568         /// Destroys the current object.
569         /// </summary>
570         ~BluetoothGattClient()
571         {
572             Dispose(false);
573         }
574
575         /// <summary>
576         /// Destroys the current object.
577         /// </summary>
578         /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
579         /// <since_tizen> 6 </since_tizen>
580         public void Dispose()
581         {
582             Dispose(true);
583             GC.SuppressFinalize(this);
584         }
585
586         /// <summary>
587         /// Releases all the resources currently used by this instance.
588         /// </summary>
589         /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
590         /// <since_tizen> 6 </since_tizen>
591         protected virtual void Dispose(bool disposing)
592         {
593             if (disposing)
594             {
595                 _impl?.GetHandle()?.Dispose();
596                 _impl = null;
597                 StaticConnectionStateChanged -= OnConnectionStateChanged;
598             }
599         }
600     }
601
602     /// <summary>
603     /// The Bluetooth GATT service.
604     /// </summary>
605     /// <since_tizen> 3 </since_tizen>
606     public class BluetoothGattService
607     {
608         private BluetoothGattServiceImpl _impl;
609         private BluetoothGattClient _parentClient = null;
610         private BluetoothGattServer _parentServer = null;
611         private BluetoothGattService _parentService = null;
612
613         /// <summary>
614         /// The constructor.
615         /// </summary>
616         /// <param name="uuid">The UUID of the service.</param>
617         /// <param name="type">The type of service.</param>
618         /// <exception cref="InvalidOperationException">Thrown when the create GATT service procedure fails.</exception>
619         /// <since_tizen> 3 </since_tizen>
620         public BluetoothGattService(string uuid, BluetoothGattServiceType type)
621         {
622             Uuid = uuid;
623             _impl = new BluetoothGattServiceImpl(uuid, type);
624         }
625
626         internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
627         {
628             Uuid = uuid;
629             _impl = impl;
630         }
631
632         /// <summary>
633         /// Specification name from the UUID.
634         /// </summary>
635         /// <since_tizen> 3 </since_tizen>
636         public string Uuid { get; }
637
638         /// <summary>
639         /// Adds a characteristic to this service.
640         /// </summary>
641         /// <param name="characteristic">The characteristic to be added.</param>
642         /// <returns>true on success, false otherwise.</returns>
643         /// <exception cref="InvalidOperationException">Thrown when the add GATT characteristic procedure fails.</exception>
644         /// <since_tizen> 3 </since_tizen>
645         public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
646         {
647             if (GetGattClient() != null)
648             {
649                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
650             }
651
652             if (characteristic.GetService() != null)
653             {
654                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
655             }
656
657             _impl.AddCharacteristic(characteristic);
658             characteristic.SetParent(this);
659         }
660
661         /// <summary>
662         /// Gets the characteristic with the given UUID that belongs to this service.
663         /// </summary>
664         /// <param name="uuid">The UUID for the characteristic to get.</param>
665         /// <returns>The characteristic with a given UUID if it exists, null otherwise.</returns>
666         /// <since_tizen> 3 </since_tizen>
667         public BluetoothGattCharacteristic GetCharacteristic(string uuid)
668         {
669             return _impl.GetCharacteristic(this, uuid);
670         }
671
672         /// <summary>
673         /// Gets list of the characteristic that belongs to this service.
674         /// </summary>
675         /// <returns>The list of the characteristic that belongs to this service.</returns>
676         /// <since_tizen> 3 </since_tizen>
677         public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
678         {
679             return _impl.GetCharacteristics(this);
680         }
681
682         /// <summary>
683         /// Includes a service to this service.
684         /// </summary>
685         /// <param name="service">The service to be included.</param>
686         /// <returns>true on success, false otherwise</returns>
687         /// <exception cref="InvalidOperationException">Thrown when the add GATT service procedure fails.</exception>///
688         /// <since_tizen> 3 </since_tizen>
689         public void AddService(BluetoothGattService service)
690         {
691             if (GetGattClient() != null)
692             {
693                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
694             }
695
696             if (service.IsRegistered())
697             {
698                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
699             }
700
701             _impl.AddIncludeService(service);
702             service.SetParent(this);
703         }
704
705         /// <summary>
706         /// Gets the included service.
707         /// </summary>
708         /// <param name="uuid">The UUID for the service to get.</param>
709         /// <returns>The service with a given UUID if it exists, null otherwise.</returns>
710         /// <since_tizen> 3 </since_tizen>
711         public BluetoothGattService GetIncludeService(string uuid)
712         {
713             return _impl.GetIncludeService(this, uuid);
714         }
715
716         /// <summary>
717         /// Gets the included service list of this service.
718         /// </summary>
719         /// <returns>The included service list of this service.</returns>
720         /// <since_tizen> 3 </since_tizen>
721         public IEnumerable<BluetoothGattService> GetIncludeServices()
722         {
723             return _impl.GetIncludeServices(this);
724         }
725
726         /// <summary>
727         /// Gets the server instance which the specified service belongs to.
728         /// </summary>
729         /// <returns>The server instance which the specified service belongs to.</returns>
730         /// <since_tizen> 3 </since_tizen>
731         public BluetoothGattServer GetGattServer()
732         {
733             return _parentServer;
734         }
735
736         /// <summary>
737         /// Gets the client instance which the specified service belongs to.
738         /// </summary>
739         /// <returns>The client instance which the specified service belongs to.</returns>
740         /// <since_tizen> 3 </since_tizen>
741         public BluetoothGattClient GetGattClient()
742         {
743             return _parentClient;
744         }
745
746         internal BluetoothGattAttributeHandle GetHandle()
747         {
748             return _impl.GetHandle();
749         }
750
751         internal void SetParent(BluetoothGattService parent)
752         {
753             if (!IsRegistered())
754             {
755                 _parentService = parent;
756                 _impl.ReleaseHandleOwnership();
757             }
758         }
759
760         internal void SetParent(BluetoothGattClient parent)
761         {
762             if (!IsRegistered())
763             {
764                 _parentClient = parent;
765                 _impl.ReleaseHandleOwnership();
766             }
767         }
768
769         internal void SetParent(BluetoothGattServer parent)
770         {
771             if (!IsRegistered())
772             {
773                 _parentServer = parent;
774                 _impl.ReleaseHandleOwnership();
775             }
776         }
777
778         internal void UnregisterService()
779         {
780             _parentServer = null;
781             _parentClient = null;
782             _parentService = null;
783         }
784
785         internal bool IsRegistered()
786         {
787             return _parentClient != null || _parentServer != null || _parentService != null;
788         }
789     }
790
791     /// <summary>
792     /// The Bluetooth GATT characteristic.
793     /// </summary>
794     /// <since_tizen> 3 </since_tizen>
795     public class BluetoothGattCharacteristic : BluetoothGattAttribute
796     {
797         private BluetoothGattCharacteristicImpl _impl;
798         private BluetoothGattService _parent = null;
799
800         private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
801         private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
802
803         private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
804         internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
805
806         /// <summary>
807         /// The constructor.
808         /// </summary>
809         /// <param name="uuid">The UUID of the characterstic.</param>
810         /// <param name="permissions">Permissions for the characterstic.</param>
811         /// <param name="properties">Properties set for the characterstic.</param>
812         /// <param name="value">The value associated with the characterstic.</param>
813         /// <remarks>throws in case of internal error.</remarks>
814         /// <exception cref="InvalidOperationException">Thrown when the create GATT characteristics procedure fails.</exception>
815         /// <since_tizen> 3 </since_tizen>
816         public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
817         {
818             _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
819         }
820
821         internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
822         {
823             _impl = impl;
824         }
825
826         /// <summary>
827         /// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
828         /// </summary>
829         /// <remarks>
830         /// Adding the event handle on characteristic on the server side will not have any effect.
831         /// </remarks>
832         /// <since_tizen> 3 </since_tizen>
833         public event EventHandler<ValueChangedEventArgs> ValueChanged
834         {
835             add
836             {
837                 if (Client != null)
838                 {
839                     if (_characteristicValueChanged == null)
840                     {
841                         _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
842                         {
843                             _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
844                         };
845
846                         _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
847                     }
848                     _characteristicValueChanged = value;
849                 }
850             }
851             remove
852             {
853                 if (Client != null)
854                 {
855                     _characteristicValueChanged = null;
856                     if (_characteristicValueChanged == null)
857                     {
858                         _impl.UnsetCharacteristicValueChangedEvent();
859                     }
860
861                 }
862             }
863         }
864
865         /// <summary>
866         /// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
867         /// </summary>
868         /// <remarks>
869         /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
870         /// Adding event handle on the characteristic on the client side will not have any effect.
871         /// </remarks>
872         /// <since_tizen> 3 </since_tizen>
873         public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
874         {
875             add
876             {
877                 if (Server != null)
878                 {
879                     if (_notificationStateChangedCallback == null)
880                     {
881                         _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
882                         {
883                             _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
884                         };
885
886                         _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
887                     }
888
889                     _notificationStateChanged = value;
890                 }
891             }
892             remove
893             {
894                 if (Server != null)
895                 {
896                     _notificationStateChanged = null;
897                     // CAPI does not allow unsetting ReadValueRequestedEventCallback.
898                 }
899             }
900         }
901
902         /// <summary>
903         /// The property for this characteristic.
904         /// </summary>
905         /// <since_tizen> 3 </since_tizen>
906         public BluetoothGattProperty Properties
907         {
908             get
909             {
910                 return _impl.GetProperties();
911             }
912             set
913             {
914                 if (Server != null)
915                 {
916                     _impl.SetProperties(value);
917                 }
918             }
919         }
920
921         /// <summary>
922         /// The write type to be used for write operations.
923         /// </summary>
924         /// <since_tizen> 3 </since_tizen>
925         public BluetoothGattWriteType WriteType
926         {
927             get
928             {
929                 return _impl.GetWriteType();
930             }
931             set
932             {
933                 _impl.SetWriteType(value);
934             }
935         }
936
937         internal override BluetoothGattClient Client
938         {
939             get
940             {
941                 return _parent?.GetGattClient();
942             }
943         }
944
945         internal override BluetoothGattServer Server
946         {
947             get
948             {
949                 return _parent?.GetGattServer();
950             }
951         }
952
953         internal override BluetoothGattAttributeImpl Impl
954         {
955             get
956             {
957                 return _impl;
958             }
959         }
960
961         /// <summary>
962         /// Adds a descriptor to this characteristic.
963         /// </summary>
964         /// <param name="descriptor">The descriptor to be added.</param>
965         /// <returns>true on success, false otherwise.</returns>
966         /// <exception cref="InvalidOperationException">Thrown when the add GATT descriptor procedure fails.</exception>
967         /// <since_tizen> 3 </since_tizen>
968         public void AddDescriptor(BluetoothGattDescriptor descriptor)
969         {
970             if (Client != null)
971             {
972                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
973             }
974
975             if (descriptor.GetCharacteristic() != null)
976             {
977                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
978             }
979
980             _impl.AddDescriptor(descriptor);
981             descriptor.SetParent(this);
982         }
983
984         /// <summary>
985         /// Gets the descriptor with the given UUID that belongs to this characteristic.
986         /// </summary>
987         /// <param name="uuid">The UUID for the descriptor to get.</param>
988         /// <returns>The descriptor with a given UUID if it exists, null otherwise.</returns>
989         /// <since_tizen> 3 </since_tizen>
990         public BluetoothGattDescriptor GetDescriptor(string uuid)
991         {
992             return _impl.GetDescriptor(this, uuid);
993         }
994
995         /// <summary>
996         /// Gets the list of descriptors that belongs to this characteristic.
997         /// </summary>
998         /// <returns>The list of descriptors that belongs to this characteristic.</returns>
999         /// <since_tizen> 3 </since_tizen>
1000         public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
1001         {
1002             return _impl.GetDescriptors(this);
1003         }
1004
1005         /// <summary>
1006         /// Gets the service instance, which the specified characterstic belongs to.
1007         /// </summary>
1008         /// <returns>The characteristic instance, the specified characterstic belongs to.</returns>
1009         /// <since_tizen> 3 </since_tizen>
1010         public BluetoothGattService GetService()
1011         {
1012             return _parent;
1013         }
1014
1015         internal void SetParent(BluetoothGattService parent)
1016         {
1017             if (_parent == null)
1018             {
1019                 _parent = parent;
1020                 ReleaseHandleOwnership();
1021             }
1022          }
1023     }
1024
1025     /// <summary>
1026     /// The Bluetooth GATT descriptor.
1027     /// </summary>
1028     /// <since_tizen> 3 </since_tizen>
1029     public class BluetoothGattDescriptor : BluetoothGattAttribute
1030     {
1031         private BluetoothGattCharacteristic _parent = null;
1032         private BluetoothGattDescriptorImpl _impl;
1033
1034         /// <summary>
1035         /// The constructor.
1036         /// </summary>
1037         /// <param name="uuid">The UUID of the descriptor.</param>
1038         /// <param name="permisions">Permissions for the descriptor.</param>
1039         /// <param name="value">The value associated with the descriptor.</param>
1040         /// <remarks>throws in case of internal error.</remarks>
1041         /// <exception cref="InvalidOperationException">Thrown when the create GATT descriptor procedure fails.</exception>
1042         /// <since_tizen> 3 </since_tizen>
1043         public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
1044         {
1045             _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
1046         }
1047
1048         internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
1049         {
1050             _impl = impl;
1051         }
1052
1053         internal override BluetoothGattClient Client
1054         {
1055             get
1056             {
1057                 return _parent?.Client;
1058             }
1059         }
1060
1061         internal override BluetoothGattServer Server
1062         {
1063             get
1064             {
1065                 return _parent?.Server;
1066             }
1067         }
1068
1069         internal override BluetoothGattAttributeImpl Impl
1070         {
1071             get
1072             {
1073                 return _impl;
1074             }
1075         }
1076
1077         /// <summary>
1078         /// Gets the characteristic instance, which the specified descriptor belongs to.
1079         /// </summary>
1080         /// <returns>The characteristic instance, the specified descriptor belongs to.</returns>
1081         /// <since_tizen> 3 </since_tizen>
1082         public BluetoothGattCharacteristic GetCharacteristic()
1083         {
1084             return _parent;
1085         }
1086
1087         internal void SetParent(BluetoothGattCharacteristic parent)
1088         {
1089             if (_parent == null)
1090             {
1091                 _parent = parent;
1092                 ReleaseHandleOwnership();
1093             }
1094         }
1095     }
1096
1097     /// <summary>
1098     /// The Bluetooth GATT attribute.
1099     /// </summary>
1100     /// <since_tizen> 3 </since_tizen>
1101     public abstract class BluetoothGattAttribute
1102     {
1103         private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
1104         private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
1105
1106         private EventHandler<ReadRequestedEventArgs> _readValueRequested;
1107         private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
1108
1109         /// <summary>
1110         /// The constructor.
1111         /// </summary>
1112         /// <param name="uuid">The UUID of the GATT attribute.</param>
1113         /// <param name="permission">Permission for the GATT attribute.</param>
1114         /// <since_tizen> 3 </since_tizen>
1115         public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
1116         {
1117             Uuid = uuid;
1118             Permissions = permission;
1119         }
1120
1121         // Events
1122
1123         /// <summary>
1124         /// This event is called when the client request to read the value of a characteristic or a descriptor.
1125         /// </summary>
1126         /// <remarks>
1127         /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
1128         /// </remarks>
1129         /// <exception cref="InvalidOperationException">Thrown when the set read value requested callback procedure fails.</exception>
1130         /// <since_tizen> 3 </since_tizen>
1131         public event EventHandler<ReadRequestedEventArgs> ReadRequested
1132         {
1133             add
1134             {
1135                 if (Server == null) return;
1136                 if (_readValueRequestedCallback == null)
1137                 {
1138                     _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
1139                     {
1140                         _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
1141                     };
1142                     Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
1143                 }
1144                 _readValueRequested = value;
1145             }
1146             remove
1147             {
1148                 if (Server == null) return;
1149                 _readValueRequested = null;
1150                 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1151             }
1152         }
1153
1154         /// <summary>
1155         /// This event is called when a value of a characteristic or a descriptor has been changed by a client.
1156         /// </summary>
1157         /// <remarks>
1158         /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
1159         /// </remarks>
1160         /// <exception cref="InvalidOperationException">Thrown when the set write value requested callback procedure fails.</exception>
1161         /// <since_tizen> 3 </since_tizen>
1162         public event EventHandler<WriteRequestedEventArgs> WriteRequested
1163         {
1164             add
1165             {
1166                 if (Server == null) return;
1167                 if (_writeValueRequested == null)
1168                 {
1169                     _writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, response_needed, offset, valueToWrite, len, userData) =>
1170                     {
1171                         byte[] writeValue = new byte[len];
1172                         Marshal.Copy(valueToWrite, writeValue, 0, len);
1173                         _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, writeValue, offset, response_needed));
1174                     };
1175                     Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
1176                 }
1177                 _writeValueRequested = value;
1178             }
1179             remove
1180             {
1181                 if (Server == null) return;
1182                 _writeValueRequested = null;
1183                 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1184             }
1185         }
1186
1187         /// <summary>
1188         /// The attribute's UUID.
1189         /// </summary>
1190         /// <since_tizen> 3 </since_tizen>
1191         public string Uuid { get; }
1192
1193         /// <summary>
1194         /// Permissions for this attribute.
1195         /// </summary>
1196         /// <since_tizen> 3 </since_tizen>
1197         public BluetoothGattPermission Permissions { get; }
1198
1199         /// <summary>
1200         /// The value of this descriptor.
1201         /// </summary>
1202         /// <since_tizen> 3 </since_tizen>
1203         public byte[] Value
1204         {
1205             get
1206             {
1207                 return Impl.GetValue();
1208             }
1209             set
1210             {
1211                 Impl.SetValue(value);
1212             }
1213         }
1214
1215         internal abstract BluetoothGattClient Client { get; }
1216         internal abstract BluetoothGattServer Server { get; }
1217         internal abstract BluetoothGattAttributeImpl Impl { get; }
1218
1219         /// <summary>
1220         /// Returns a string value at the specified offset.
1221         /// </summary>
1222         /// <param name="offset">An offset in the attribute value buffer.</param>
1223         /// <returns>The string value at specified offset.</returns>
1224         /// <since_tizen> 3 </since_tizen>
1225         public string GetValue(int offset)
1226         {
1227             return Impl.GetValue(offset);
1228         }
1229
1230         /// <summary>
1231         /// Sets the string value as a specified offset.
1232         /// </summary>
1233         /// <param name="value">value to set</param>
1234         /// <exception cref="InvalidOperationException">Throws exception if the value is null.</exception>
1235         /// <since_tizen> 3 </since_tizen>
1236         public void SetValue(string value)
1237         {
1238             if (string.IsNullOrEmpty(value))
1239                 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
1240
1241             byte[] val = Encoding.UTF8.GetBytes(value);
1242             Impl.SetValue(val);
1243         }
1244
1245         /// <summary>
1246         /// Returns a value at specified offset as the int value of the specified type.
1247         /// </summary>
1248         /// <param name="type">The type of the int value.</param>
1249         /// <param name="offset">An offset in the attribute value buffer.</param>
1250         /// <returns>The int value at given offset.</returns>
1251         /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1252         /// <since_tizen> 3 </since_tizen>
1253         public int GetValue(IntDataType type, int offset)
1254         {
1255             return Impl.GetValue(type, offset);
1256         }
1257
1258         /// <summary>
1259         /// Updates a value at the specified offset by the int value of the specified type.
1260         /// </summary>
1261         /// <param name="type">The type of the int value.</param>
1262         /// <param name="value">The value to set.</param>
1263         /// <param name="offset">An offset in the attribute value buffer.</param>
1264         /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1265         /// <since_tizen> 3 </since_tizen>
1266         public void SetValue(IntDataType type, int value, int offset)
1267         {
1268             Impl.SetValue(type, value, offset);
1269         }
1270
1271         /// <summary>
1272         /// Returns a value at the specified offset as the float value of the specified type.
1273         /// </summary>
1274         /// <param name="type">The type of the float value.</param>
1275         /// <param name="offset">An offset in the attribute value buffer.</param>
1276         /// <returns>The float value at given offset.</returns>
1277         /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1278         /// <since_tizen> 3 </since_tizen>
1279         public float GetValue(FloatDataType type, int offset)
1280         {
1281             return Impl.GetValue(type, offset);
1282         }
1283
1284         /// <summary>
1285         /// Updates the value at the specified offset by the float value of the specified type.
1286         /// </summary>
1287         /// <param name="type">The type of the float value.</param>
1288         /// <param name="mantissa">The mantissa of the float value.</param>
1289         /// <param name="exponent">An exponent of the float value.</param>
1290         /// <param name="offset">An offset in the attribute value buffer.</param>
1291         /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1292         /// <since_tizen> 3 </since_tizen>
1293         public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
1294         {
1295             Impl.SetValue(type, mantissa, exponent, offset);
1296         }
1297
1298         internal void ReleaseHandleOwnership()
1299         {
1300             Impl.ReleaseHandleOwnership();
1301         }
1302
1303         internal BluetoothGattAttributeHandle GetHandle()
1304         {
1305             return Impl.GetHandle();
1306         }
1307     }
1308 }