[TIZEN]Moved GMainloop to CSDK sample from network monitor[LE/EDR].
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / caleserver.c
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20
21 #include "caleserver.h"
22 #include "cacommon.h"
23 #include "cacommonutil.h"
24 #include "camutex.h"
25 #include "caqueueingthread.h"
26 #include "cagattservice.h"
27 #include "oic_malloc.h"
28 #include "caleutil.h"
29
30 /**
31  * Logging tag for module name
32  */
33 #define TAG "OIC_CA_LE_SERVER"
34
35 /**
36  * Initial buffer size for Gatt Server.
37  */
38 #define CA_LE_INITIAL_BUF_SIZE 512
39
40 /**
41  * The handle of the OIC server.
42  */
43 static bt_gatt_server_h g_gattServer = NULL;
44
45 /**
46  * The handle of the OIC service.
47  */
48 static bt_gatt_h g_gattSvcPath = NULL;
49
50 /**
51  * The handle of the OIC read characteristics.
52  */
53 static bt_gatt_h g_gattReadCharPath = NULL;
54
55 /**
56  * The handle of the OIC write characteristics.
57  */
58 static bt_gatt_h g_gattWriteCharPath = NULL;
59
60 /**
61  * The handle to control Bluetooth LE advertising.
62  */
63 static bt_advertiser_h g_hAdvertiser = NULL;
64
65 /**
66  * Callback register with LE adapter.  This callback is called on reception of any
67  * data from the remote device.
68  */
69 static CABLEDataReceivedCallback g_leServerDataReceivedCallback = NULL;
70
71 /**
72  * Callback to notify any error in LE adapter.
73  */
74 static CABLEErrorHandleCallback g_serverErrorCallback;
75
76 /**
77  * To keep the state of GATT server if started or not.
78  */
79 static bool g_isLEGattServerStarted = false;
80
81 /**
82  * Mutex to synchronize the calls to start and stop server.
83  */
84 static ca_mutex g_leServerStateMutex = NULL;
85
86 /**
87  * Mutex to synchronize writing operations on the characteristics.
88  */
89 static  ca_mutex g_leCharacteristicMutex = NULL;
90
91 /**
92  * Mutex to synchronize to creation of OIC service.
93  */
94 static  ca_mutex g_leServiceMutex = NULL;
95
96 /**
97  * Mutex to synchronize access to the requestResponse callback to be called
98  * when the data needs to be sent from GATTClient.
99  */
100 static  ca_mutex g_leReqRespCbMutex = NULL;
101
102 /**
103  * Mutex to synchronize the task to be pushed to thread pool.
104  */
105 static ca_mutex g_leServerThreadPoolMutex = NULL;
106
107 /**
108  * Reference to threadpool.
109  */
110 static ca_thread_pool_t g_leServerThreadPool = NULL;
111
112 /**
113  * GmainLoop to manage the threads to receive the callback from the platfrom.
114  */
115 static GMainLoop *g_eventLoop = NULL;
116
117 void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddress)
118 {
119     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address");
120
121     if (connected)
122     {
123         OIC_LOG_V(DEBUG, TAG, "Connected to [%s]", remoteAddress);
124     }
125     else
126     {
127         OIC_LOG_V(DEBUG, TAG, "Disconnected from [%s]", remoteAddress);
128     }
129 }
130
131 void CALEServerNotificationSentCB(int result, char *remote_address, bt_gatt_server_h server,
132                                   bt_gatt_h characteristic, bool completed, void *user_data)
133 {
134     OIC_LOG_V(DEBUG, TAG, "Notification to the device[%s] result[%d]", remote_address, result);
135 }
136
137 CAResult_t CAStartLEGattServer()
138 {
139     OIC_LOG(DEBUG, TAG, "IN");
140
141     ca_mutex_lock(g_leServerStateMutex);
142     if (true == g_isLEGattServerStarted)
143     {
144         OIC_LOG(ERROR, TAG, "Gatt Server is already running");
145         ca_mutex_unlock(g_leServerStateMutex);
146         return CA_STATUS_OK;
147     }
148
149     CAResult_t ret = CAInitLEGattServer();
150     if (CA_STATUS_OK != ret)
151     {
152         OIC_LOG_V(ERROR, TAG, "CAInitLEGattServer failed[%d]", ret);
153         ca_mutex_unlock(g_leServerStateMutex);
154         CATerminateLEGattServer();
155         return CA_STATUS_FAILED;
156     }
157
158     char *serviceUUID = CA_GATT_SERVICE_UUID;
159
160     ret  = CAAddNewLEServiceInGattServer(serviceUUID);
161     if (CA_STATUS_OK != ret)
162     {
163         OIC_LOG_V(ERROR, TAG, "CAAddNewLEServiceInGattServer failed[%d]", ret);
164         ca_mutex_unlock(g_leServerStateMutex);
165         CATerminateLEGattServer();
166         return CA_STATUS_FAILED;
167     }
168
169     static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID;
170     char charReadValue[] = {33, 44, 55, 66}; // These are initial random values
171
172     // For Read Characteristics.
173     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue,
174                                               CA_LE_INITIAL_BUF_SIZE, true);
175     if (CA_STATUS_OK != ret)
176     {
177         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
178         ca_mutex_unlock(g_leServerStateMutex);
179         CATerminateLEGattServer();
180         return CA_STATUS_FAILED;
181     }
182
183     static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID;
184     char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
185
186
187     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue,
188             CA_LE_INITIAL_BUF_SIZE, false); // For Write Characteristics.
189     if (CA_STATUS_OK != ret )
190     {
191         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
192         ca_mutex_unlock(g_leServerStateMutex);
193         CATerminateLEGattServer();
194         return CA_STATUS_FAILED;
195     }
196
197     ret = CARegisterLEServicewithGattServer(g_gattSvcPath);
198     if (CA_STATUS_OK != ret )
199     {
200         OIC_LOG_V(ERROR, TAG, "CARegisterLEServicewithGattServer failed[%d]", ret);
201         ca_mutex_unlock(g_leServerStateMutex);
202         CATerminateLEGattServer();
203         return CA_STATUS_FAILED;
204     }
205
206     ret = CALEStartAdvertise(serviceUUID);
207     if (CA_STATUS_OK != ret)
208     {
209         OIC_LOG_V(ERROR, TAG, "CALEStartAdvertise failed[%d]", ret);
210         ca_mutex_unlock(g_leServerStateMutex);
211         CATerminateLEGattServer();
212         return CA_STATUS_FAILED;
213     }
214
215     g_isLEGattServerStarted = true;
216
217     ca_mutex_unlock(g_leServerStateMutex);
218
219     OIC_LOG(DEBUG, TAG, "OUT");
220     return CA_STATUS_OK;
221 }
222
223 void CALENotificationCb(bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle,
224                         void *user_data)
225 {
226     OIC_LOG(DEBUG, TAG, "IN");
227     if(notify)
228     {
229         OIC_LOG(DEBUG, TAG, "Notification is subscribed by the client");
230     }
231     OIC_LOG(DEBUG, TAG, "OUT");
232 }
233
234 CAResult_t CALEStartAdvertise(const char *serviceUUID)
235 {
236     OIC_LOG(DEBUG, TAG, "IN");
237
238     int res = bt_adapter_le_create_advertiser(&g_hAdvertiser);
239     if (NULL == g_hAdvertiser || BT_ERROR_NONE != res)
240     {
241         OIC_LOG_V(ERROR, TAG, "g_hAdvertiser is NULL/ Result is %d", res);
242         return CA_STATUS_FAILED;
243     }
244
245     res = bt_adapter_le_add_advertising_service_uuid(g_hAdvertiser,
246                                                      BT_ADAPTER_LE_PACKET_ADVERTISING,
247                                                      serviceUUID);
248     if (BT_ERROR_NONE != res)
249     {
250         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_add_advertising_service_uuid failed with ret[%s]",
251                   CALEGetErrorMsg(res));
252         return CA_STATUS_FAILED;
253     }
254
255     res = bt_adapter_le_set_advertising_device_name(g_hAdvertiser,
256                                                     BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true);
257     if (BT_ERROR_NONE != res)
258     {
259         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_set_advertising_device_name failed with ret[%s]",
260                   CALEGetErrorMsg(res));
261         return CA_STATUS_FAILED;
262     }
263
264     res = bt_adapter_le_start_advertising_new(g_hAdvertiser, NULL, NULL);
265     if (BT_ERROR_NONE != res)
266     {
267         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_advertising_new failed with ret[%s]",
268                   CALEGetErrorMsg(res));
269         return CA_STATUS_FAILED;
270     }
271
272     OIC_LOG(DEBUG, TAG, "OUT");
273     return CA_STATUS_OK;
274 }
275
276 CAResult_t CALEStopAdvertise()
277 {
278     OIC_LOG(DEBUG, TAG, "IN");
279     if (NULL != g_hAdvertiser)
280     {
281         int ret  = bt_adapter_le_stop_advertising(g_hAdvertiser);
282         if (0 != ret)
283         {
284             OIC_LOG_V(ERROR, TAG,
285                       "bt_adapter_le_stop_advertising failed with ret[%s]", CALEGetErrorMsg(ret));
286         }
287
288         ret = bt_adapter_le_destroy_advertiser(g_hAdvertiser);
289         if (0 != ret)
290         {
291             OIC_LOG_V(ERROR, TAG,
292                       "bt_adapter_le_destroy_advertiser failed with ret[%s]", CALEGetErrorMsg(ret));
293         }
294         g_hAdvertiser = NULL;
295     }
296     else
297     {
298         OIC_LOG(ERROR, TAG, "Advertising is not running");
299         return CA_STATUS_FAILED;
300     }
301
302     OIC_LOG(DEBUG, TAG, "OUT");
303     return CA_STATUS_OK;
304 }
305
306 CAResult_t CAStopLEGattServer()
307 {
308     OIC_LOG(DEBUG, TAG, "IN");
309
310     ca_mutex_lock(g_leServerStateMutex);
311
312     if (false == g_isLEGattServerStarted)
313     {
314         OIC_LOG(ERROR, TAG, "Gatt Server is not running to stop");
315         ca_mutex_unlock(g_leServerStateMutex);
316         return CA_STATUS_OK;
317     }
318
319     g_isLEGattServerStarted = false;
320
321     CAResult_t res = CALEStopAdvertise();
322     {
323         OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res);
324     }
325
326     res = CADeInitLEGattServer();
327     if (CA_STATUS_OK != res)
328     {
329         OIC_LOG_V(ERROR, TAG, "CADeInitLEGattService failed with ret[%d]", res);
330     }
331
332     GMainContext  *context_event_loop = NULL;
333     // Required for waking up the thread which is running in gmain loop
334     if (NULL != g_eventLoop)
335     {
336         context_event_loop = g_main_loop_get_context(g_eventLoop);
337
338         if (context_event_loop)
339         {
340             OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %x", context_event_loop);
341             g_main_context_wakeup(context_event_loop);
342
343             // Kill g main loops and kill threads
344             g_main_loop_quit(g_eventLoop);
345         }
346     }
347     else
348     {
349         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
350     }
351
352     ca_mutex_unlock(g_leServerStateMutex);
353
354     OIC_LOG(DEBUG, TAG, "OUT");
355     return CA_STATUS_OK;
356 }
357
358 CAResult_t CAInitializeLEGattServer()
359 {
360     OIC_LOG(DEBUG, TAG, "IN");
361
362     CAResult_t ret = CAInitGattServerMutexVariables();
363     if (CA_STATUS_OK != ret )
364     {
365         OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!");
366         CATerminateGattServerMutexVariables();
367         return CA_SERVER_NOT_STARTED;
368     }
369     OIC_LOG(DEBUG, TAG, "OUT");
370     return ret;
371 }
372
373 void CATerminateLEGattServer()
374 {
375     OIC_LOG(DEBUG, TAG, "IN");
376
377     // Service and characteristics path will be freed by the platform.
378     ca_mutex_lock(g_leServiceMutex);
379     g_gattSvcPath = NULL;
380     ca_mutex_unlock(g_leServiceMutex);
381
382     ca_mutex_lock(g_leCharacteristicMutex);
383     g_gattReadCharPath = NULL;
384     g_gattWriteCharPath = NULL;
385     ca_mutex_unlock(g_leCharacteristicMutex);
386
387     ca_mutex_lock(g_leServerThreadPoolMutex);
388     g_leServerThreadPool = NULL;
389     ca_mutex_unlock(g_leServerThreadPoolMutex);
390
391     // Terminating all mutex variables.
392     CATerminateGattServerMutexVariables();
393     OIC_LOG(DEBUG, TAG, "OUT");
394 }
395
396 CAResult_t CAInitGattServerMutexVariables()
397 {
398     OIC_LOG(DEBUG, TAG, "IN");
399     if (NULL == g_leServerStateMutex)
400     {
401         g_leServerStateMutex = ca_mutex_new();
402         if (NULL == g_leServerStateMutex)
403         {
404             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
405             return CA_STATUS_FAILED;
406         }
407     }
408
409     if (NULL == g_leServiceMutex)
410     {
411         g_leServiceMutex = ca_mutex_new();
412         if (NULL == g_leServiceMutex)
413         {
414             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
415             return CA_STATUS_FAILED;
416         }
417     }
418
419     if (NULL == g_leCharacteristicMutex)
420     {
421         g_leCharacteristicMutex = ca_mutex_new();
422         if (NULL == g_leCharacteristicMutex)
423         {
424             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
425             return CA_STATUS_FAILED;
426         }
427     }
428
429     if (NULL == g_leReqRespCbMutex)
430     {
431         g_leReqRespCbMutex = ca_mutex_new();
432         if (NULL == g_leReqRespCbMutex)
433         {
434             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
435             return CA_STATUS_FAILED;
436         }
437     }
438
439     if (NULL == g_leServerThreadPoolMutex)
440     {
441         g_leServerThreadPoolMutex = ca_mutex_new();
442         if (NULL == g_leServerThreadPoolMutex)
443         {
444             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
445             return CA_STATUS_FAILED;
446         }
447     }
448
449     OIC_LOG(DEBUG, TAG, "OUT");
450     return CA_STATUS_OK;
451 }
452
453 void CATerminateGattServerMutexVariables()
454 {
455     OIC_LOG(DEBUG, TAG, "IN");
456     ca_mutex_free(g_leServerStateMutex);
457     g_leServerStateMutex = NULL;
458
459     ca_mutex_free(g_leServiceMutex);
460     g_leServiceMutex = NULL;
461
462     ca_mutex_free(g_leCharacteristicMutex);
463     g_leCharacteristicMutex = NULL;
464
465     ca_mutex_free(g_leReqRespCbMutex);
466     g_leReqRespCbMutex = NULL;
467
468     OIC_LOG(DEBUG, TAG, "OUT");
469 }
470
471 CAResult_t CAInitLEGattServer()
472 {
473     OIC_LOG(DEBUG, TAG, "IN");
474
475     int ret =  bt_gatt_server_initialize();
476     if (0 != ret)
477     {
478         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]",
479                   CALEGetErrorMsg(ret));
480         return CA_STATUS_FAILED;
481     }
482
483     bt_gatt_server_h server;
484
485     ret = bt_gatt_server_create(&server);
486     if (0 != ret)
487     {
488         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]",
489                   CALEGetErrorMsg(ret));
490         return CA_STATUS_FAILED;
491     }
492
493     if (NULL != g_gattServer)
494     {
495         OICFree(g_gattServer);
496         g_gattServer = NULL;
497     }
498     g_gattServer = server;
499
500     OIC_LOG(DEBUG, TAG, "OUT");
501     return CA_STATUS_OK;
502 }
503
504 CAResult_t CADeInitLEGattServer()
505 {
506     OIC_LOG(DEBUG, TAG, "IN");
507
508     int ret = bt_gatt_server_unregister_all_services(g_gattServer);
509     if (0 != ret)
510     {
511         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]",
512                   CALEGetErrorMsg(ret));
513         return CA_STATUS_FAILED;
514     }
515
516     ret = bt_gatt_server_destroy(g_gattServer);
517     if (0 != ret)
518     {
519         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]",
520                   CALEGetErrorMsg(ret));
521         return CA_STATUS_FAILED;
522     }
523
524     ret =  bt_gatt_server_deinitialize();
525     if (0 != ret)
526     {
527         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]",
528                   CALEGetErrorMsg(ret));
529         return CA_STATUS_FAILED;
530     }
531
532     OIC_LOG(DEBUG, TAG, "OUT");
533     return CA_STATUS_OK;
534 }
535
536 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
537 {
538     OIC_LOG(DEBUG, TAG, "IN");
539     ca_mutex_lock(g_leServerThreadPoolMutex);
540     g_leServerThreadPool = handle;
541     ca_mutex_unlock(g_leServerThreadPoolMutex);
542     OIC_LOG(DEBUG, TAG, "OUT");
543 }
544
545 CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID)
546 {
547     OIC_LOG(DEBUG, TAG, "IN");
548
549     VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID");
550
551     OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID);
552
553     bt_gatt_h service = NULL;
554     bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY;
555
556     int ret = bt_gatt_service_create(serviceUUID, type, &service);
557     if (0 != ret)
558     {
559         OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]",
560                   CALEGetErrorMsg(ret));
561         return CA_STATUS_FAILED;
562     }
563
564     if (NULL != service)
565     {
566         OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)service);
567
568         ca_mutex_lock(g_leServiceMutex);
569
570         if (NULL != g_gattSvcPath)
571         {
572             OICFree(g_gattSvcPath);
573             g_gattSvcPath = NULL;
574         }
575         g_gattSvcPath = service;
576
577         ca_mutex_unlock(g_leServiceMutex);
578     }
579
580     OIC_LOG(DEBUG, TAG, "OUT");
581     return CA_STATUS_OK;
582 }
583
584 void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server,
585                                          bt_gatt_h charPath, int offset, char *charValue,
586                                          int charValueLen, void *userData)
587 {
588     OIC_LOG(DEBUG, TAG, "IN");
589
590     if (NULL == charValue || NULL == remoteAddress)
591     {
592         OIC_LOG(ERROR, TAG, "Param callback values are NULL");
593         return;
594     }
595
596     OIC_LOG_V(DEBUG, TAG, "charPath = [%s] charValue = [%s] len [%d]", (char *)charPath,
597               charValue, charValueLen);
598
599     uint8_t *data = OICMalloc(charValueLen);
600     if (NULL == data)
601     {
602         OIC_LOG(ERROR, TAG, "Malloc failed!");
603         return;
604     }
605
606     memcpy(data, charValue, charValueLen);
607
608     ca_mutex_lock(g_leReqRespCbMutex);
609     if (NULL == g_leServerDataReceivedCallback)
610     {
611         OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!");
612         ca_mutex_unlock(g_leReqRespCbMutex);
613         OICFree(data);
614         return;
615     }
616
617     OIC_LOG(DEBUG, TAG, "Sending data up !");
618     uint32_t sentLength = 0;
619     g_leServerDataReceivedCallback(remoteAddress, data, charValueLen,
620                                     &sentLength);
621     ca_mutex_unlock(g_leReqRespCbMutex);
622     OICFree(data);
623     OIC_LOG(DEBUG, TAG, "OUT");
624 }
625
626 CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath)
627 {
628     OIC_LOG(DEBUG, TAG, "IN");
629
630     VERIFY_NON_NULL(svcPath, TAG, "svcPath");
631
632     OIC_LOG_V(DEBUG, TAG, "svcPath:%s", svcPath);
633
634     int ret = bt_gatt_server_register_service(g_gattServer, svcPath);
635     if (0 != ret)
636     {
637         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]",
638                   CALEGetErrorMsg(ret));
639         return CA_STATUS_FAILED;
640     }
641
642     ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath,
643                                               CALEGattRemoteCharacteristicWriteCb, NULL);
644
645     if (0 != ret)
646     {
647         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]",
648                   CALEGetErrorMsg(ret));
649         return CA_STATUS_FAILED;
650     }
651
652     OIC_LOG(DEBUG, TAG, "OUT");
653     return CA_STATUS_OK;
654 }
655
656 CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID,
657                                                const char *charValue, int charValueLen, bool read)
658 {
659
660     OIC_LOG(DEBUG, TAG, "IN");
661
662     int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
663     int properties;
664     if(read)
665     {
666         properties = BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_READ;
667     }
668     else
669     {
670         properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ;
671     }
672
673     bt_gatt_h charPath;
674
675     int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue,
676                                             charValueLen, &charPath);
677
678     if (0 != ret || NULL == charPath)
679     {
680         OIC_LOG_V(ERROR, TAG,
681                   "bt_gatt_add_characteristic  failed with ret [%s]", CALEGetErrorMsg(ret));
682         return CA_STATUS_FAILED;
683     }
684
685     OIC_LOG_V(DEBUG, TAG,
686               "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath);
687
688     if (read)
689     {
690         ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL);
691         if (0 != ret)
692         {
693             OIC_LOG_V(ERROR, TAG,
694                       "bt_gatt_server_set_notification_state_change_cb  failed with ret[%s]",
695                       CALEGetErrorMsg(ret));
696             return CA_STATUS_FAILED;
697         }
698     }
699
700     ret =  bt_gatt_service_add_characteristic(svcPath, charPath);
701     if (0 != ret)
702     {
703         OIC_LOG_V(ERROR, TAG,
704                   "bt_gatt_service_add_characteristic  failed with ret[%s]",
705                   CALEGetErrorMsg(ret));
706         return CA_STATUS_FAILED;
707     }
708
709     ca_mutex_lock(g_leCharacteristicMutex);
710
711     if (read)
712     {
713         char desc_value[2] = {1, 0};  // Notification enabled.
714         bt_gatt_h descriptor = NULL;
715         permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
716         ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, permissions,
717                                         desc_value, sizeof(desc_value),
718                                         &descriptor);
719         if (0 != ret)
720         {
721             OIC_LOG_V(ERROR, TAG,
722                       "bt_gatt_descriptor_create  failed with ret[%s]",
723                       CALEGetErrorMsg(ret));
724             return CA_STATUS_FAILED;
725         }
726
727         ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor);
728         if (0 != ret)
729         {
730             OIC_LOG_V(ERROR, TAG,
731                       "bt_gatt_characteristic_add_descriptor  failed with ret[%s]",
732                       CALEGetErrorMsg(ret));
733             return CA_STATUS_FAILED;
734         }
735
736         if (NULL != g_gattReadCharPath)
737         {
738             OICFree(g_gattReadCharPath);
739             g_gattReadCharPath = NULL;
740         }
741         g_gattReadCharPath = charPath;
742
743     }
744     else
745     {
746         if (NULL != g_gattWriteCharPath)
747         {
748             OICFree(g_gattWriteCharPath);
749             g_gattWriteCharPath = NULL;
750         }
751         g_gattWriteCharPath = charPath;
752     }
753
754     ca_mutex_unlock(g_leCharacteristicMutex);
755
756     OIC_LOG(DEBUG, TAG, "OUT");
757     return CA_STATUS_OK;
758 }
759
760 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue,
761                                                uint32_t charValueLen)
762 {
763     OIC_LOG(DEBUG, TAG, "IN");
764
765     VERIFY_NON_NULL(charValue, TAG, "charValue");
766     VERIFY_NON_NULL(address, TAG, "address");
767
768     OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address);
769
770     ca_mutex_lock(g_leCharacteristicMutex);
771
772     if (NULL  == g_gattReadCharPath)
773     {
774         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
775         ca_mutex_unlock(g_leCharacteristicMutex);
776         return CA_STATUS_FAILED;
777     }
778
779     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
780     if (0 != ret)
781     {
782         OIC_LOG_V(ERROR, TAG,
783                   "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret));
784         ca_mutex_unlock(g_leCharacteristicMutex);
785         return CA_STATUS_FAILED;
786     }
787
788     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
789                                 address, NULL);
790     if (0 != ret)
791     {
792         OIC_LOG_V(ERROR, TAG,
793                   "bt_gatt_server_notify failed with return [%s]", CALEGetErrorMsg(ret));
794         ca_mutex_unlock(g_leCharacteristicMutex);
795         return CA_STATUS_FAILED;
796     }
797
798     ca_mutex_unlock(g_leCharacteristicMutex);
799
800     OIC_LOG(DEBUG, TAG, "OUT");
801     return CA_STATUS_OK;
802 }
803
804 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
805 {
806     OIC_LOG(DEBUG, TAG, "IN");
807
808     VERIFY_NON_NULL(charValue, TAG, "charValue");
809
810     ca_mutex_lock(g_leCharacteristicMutex);
811
812     if (NULL  == g_gattReadCharPath)
813     {
814         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
815         ca_mutex_unlock(g_leCharacteristicMutex);
816         return CA_STATUS_FAILED;
817     }
818
819     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
820     if (0 != ret)
821     {
822         OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret));
823         ca_mutex_unlock(g_leCharacteristicMutex);
824         return CA_STATUS_FAILED;
825     }
826
827     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
828                                 NULL, NULL);
829     if (0 != ret)
830     {
831         OIC_LOG_V(ERROR, TAG,
832                   "bt_gatt_server_notify failed with return[%s]", CALEGetErrorMsg(ret));
833         ca_mutex_unlock(g_leCharacteristicMutex);
834         return CA_STATUS_FAILED;
835     }
836
837     ca_mutex_unlock(g_leCharacteristicMutex);
838
839     OIC_LOG(DEBUG, TAG, "OUT");
840     return CA_STATUS_OK;
841 }
842
843 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
844 {
845     OIC_LOG(DEBUG, TAG, "IN");
846
847     ca_mutex_lock(g_leReqRespCbMutex);
848     g_leServerDataReceivedCallback = callback;
849     ca_mutex_unlock(g_leReqRespCbMutex);
850
851     OIC_LOG(DEBUG, TAG, "OUT");
852 }
853
854 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
855 {
856     g_serverErrorCallback = callback;
857 }