added network monitoring logic in CAUtil
[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_leServerThreadPoolMutex);
142     if (NULL == g_leServerThreadPool)
143     {
144         OIC_LOG(ERROR, TAG, "g_leServerThreadPool is NULL");
145         ca_mutex_unlock(g_leServerThreadPoolMutex);
146         return CA_STATUS_FAILED;
147     }
148
149     CAResult_t ret = ca_thread_pool_add_task(g_leServerThreadPool, CAStartLEGattServerThread,
150                                              NULL);
151     if (CA_STATUS_OK != ret)
152     {
153         OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
154         ca_mutex_unlock(g_leServerThreadPoolMutex);
155         return CA_STATUS_FAILED;
156     }
157
158     ca_mutex_unlock(g_leServerThreadPoolMutex);
159     OIC_LOG(DEBUG, TAG, "OUT");
160     return CA_STATUS_OK;
161 }
162
163 void CALENotificationCb(bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle,
164                         void *user_data)
165 {
166     OIC_LOG(DEBUG, TAG, "IN");
167     if(notify)
168     {
169         OIC_LOG(DEBUG, TAG, "Notification is subscribed by the client");
170     }
171     OIC_LOG(DEBUG, TAG, "OUT");
172 }
173
174 CAResult_t CALEStartAdvertise(const char *serviceUUID)
175 {
176     OIC_LOG(DEBUG, TAG, "IN");
177
178     int res = bt_adapter_le_create_advertiser(&g_hAdvertiser);
179     if (NULL == g_hAdvertiser || BT_ERROR_NONE != res)
180     {
181         OIC_LOG_V(ERROR, TAG, "g_hAdvertiser is NULL/ Result is %d", res);
182         return CA_STATUS_FAILED;
183     }
184
185     res = bt_adapter_le_add_advertising_service_uuid(g_hAdvertiser,
186                                                      BT_ADAPTER_LE_PACKET_ADVERTISING,
187                                                      serviceUUID);
188     if (BT_ERROR_NONE != res)
189     {
190         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_add_advertising_service_uuid failed with ret[%s]",
191                   CALEGetErrorMsg(res));
192         return CA_STATUS_FAILED;
193     }
194
195     res = bt_adapter_le_set_advertising_device_name(g_hAdvertiser,
196                                                     BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true);
197     if (BT_ERROR_NONE != res)
198     {
199         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_set_advertising_device_name failed with ret[%s]",
200                   CALEGetErrorMsg(res));
201         return CA_STATUS_FAILED;
202     }
203
204     res = bt_adapter_le_start_advertising_new(g_hAdvertiser, NULL, NULL);
205     if (BT_ERROR_NONE != res)
206     {
207         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_advertising_new failed with ret[%s]",
208                   CALEGetErrorMsg(res));
209         return CA_STATUS_FAILED;
210     }
211
212     OIC_LOG(DEBUG, TAG, "OUT");
213     return CA_STATUS_OK;
214 }
215
216 CAResult_t CALEStopAdvertise()
217 {
218     OIC_LOG(DEBUG, TAG, "IN");
219     if (NULL != g_hAdvertiser)
220     {
221         int ret  = bt_adapter_le_stop_advertising(g_hAdvertiser);
222         if (0 != ret)
223         {
224             OIC_LOG_V(ERROR, TAG,
225                       "bt_adapter_le_stop_advertising failed with ret[%s]", CALEGetErrorMsg(ret));
226         }
227
228         ret = bt_adapter_le_destroy_advertiser(g_hAdvertiser);
229         if (0 != ret)
230         {
231             OIC_LOG_V(ERROR, TAG,
232                       "bt_adapter_le_destroy_advertiser failed with ret[%s]", CALEGetErrorMsg(ret));
233         }
234         g_hAdvertiser = NULL;
235     }
236     else
237     {
238         OIC_LOG(ERROR, TAG, "Advertising is not running");
239         return CA_STATUS_FAILED;
240     }
241
242     OIC_LOG(DEBUG, TAG, "OUT");
243     return CA_STATUS_OK;
244 }
245
246 void CAStartLEGattServerThread(void *data)
247 {
248     OIC_LOG(DEBUG, TAG, "IN");
249     ca_mutex_lock(g_leServerStateMutex);
250     if (true == g_isLEGattServerStarted)
251     {
252         OIC_LOG(ERROR, TAG, "Gatt Server is already running");
253         ca_mutex_unlock(g_leServerStateMutex);
254         CATerminateLEGattServer();
255         return;
256     }
257
258     CAResult_t ret  =  CAInitLEGattServer();
259     if (CA_STATUS_OK != ret)
260     {
261         OIC_LOG_V(ERROR, TAG, "CAInitLEGattService failed[%d]", ret);
262         ca_mutex_unlock(g_leServerStateMutex);
263         CATerminateLEGattServer();
264         return;
265     }
266
267     char *serviceUUID = CA_GATT_SERVICE_UUID;
268
269     ret  = CAAddNewLEServiceInGattServer(serviceUUID);
270     if (CA_STATUS_OK != ret)
271     {
272         OIC_LOG_V(ERROR, TAG, "CAAddNewLEServiceInGattServer failed[%d]", ret);
273         ca_mutex_unlock(g_leServerStateMutex);
274         CATerminateLEGattServer();
275         return;
276     }
277
278     static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID;
279     char charReadValue[] = {33, 44, 55, 66}; // These are initial random values
280
281     // For Read Characteristics.
282     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue,
283                                               CA_LE_INITIAL_BUF_SIZE, true);
284     if (CA_STATUS_OK != ret)
285     {
286         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
287         ca_mutex_unlock(g_leServerStateMutex);
288         CATerminateLEGattServer();
289         return;
290     }
291
292     static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID;
293     char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
294
295
296     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue,
297             CA_LE_INITIAL_BUF_SIZE, false); // For Write Characteristics.
298     if (CA_STATUS_OK != ret )
299     {
300         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
301         ca_mutex_unlock(g_leServerStateMutex);
302         CATerminateLEGattServer();
303         return;
304     }
305
306     ret = CARegisterLEServicewithGattServer(g_gattSvcPath);
307     if (CA_STATUS_OK != ret )
308     {
309         OIC_LOG_V(ERROR, TAG, "CARegisterLEServicewithGattServer failed[%d]", ret);
310         ca_mutex_unlock(g_leServerStateMutex);
311         CATerminateLEGattServer();
312         return;
313     }
314
315     ret = CALEStartAdvertise(serviceUUID);
316     if (CA_STATUS_OK != ret)
317     {
318         OIC_LOG_V(ERROR, TAG, "CALEStartAdvertise failed[%d]", ret);
319         ca_mutex_unlock(g_leServerStateMutex);
320         CATerminateLEGattServer();
321         return;
322     }
323
324     g_isLEGattServerStarted = true;
325
326     ca_mutex_unlock(g_leServerStateMutex);
327
328     OIC_LOG(DEBUG, TAG, "LE Server initialization complete.");
329
330     GMainContext *thread_context = NULL;
331
332     thread_context = g_main_context_new();
333
334     g_eventLoop = g_main_loop_new(thread_context, FALSE);
335
336     g_main_context_push_thread_default(thread_context);
337
338     g_main_loop_run(g_eventLoop);
339
340     OIC_LOG(DEBUG, TAG, "OUT");
341 }
342
343 CAResult_t CAStopLEGattServer()
344 {
345     OIC_LOG(DEBUG, TAG, "IN");
346
347     ca_mutex_lock(g_leServerStateMutex);
348
349     if (false == g_isLEGattServerStarted)
350     {
351         OIC_LOG(ERROR, TAG, "Gatt Server is not running to stop");
352         ca_mutex_unlock(g_leServerStateMutex);
353         return CA_STATUS_OK;
354     }
355
356     g_isLEGattServerStarted = false;
357
358     CAResult_t res = CALEStopAdvertise();
359     {
360         OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res);
361     }
362
363     res = CADeInitLEGattServer();
364     if (CA_STATUS_OK != res)
365     {
366         OIC_LOG_V(ERROR, TAG, "CADeInitLEGattService failed with ret[%d]", res);
367     }
368
369     GMainContext  *context_event_loop = NULL;
370     // Required for waking up the thread which is running in gmain loop
371     if (NULL != g_eventLoop)
372     {
373         context_event_loop = g_main_loop_get_context(g_eventLoop);
374
375         if (context_event_loop)
376         {
377             OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %x", context_event_loop);
378             g_main_context_wakeup(context_event_loop);
379
380             // Kill g main loops and kill threads
381             g_main_loop_quit(g_eventLoop);
382         }
383     }
384     else
385     {
386         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
387     }
388
389     ca_mutex_unlock(g_leServerStateMutex);
390
391     OIC_LOG(DEBUG, TAG, "OUT");
392     return CA_STATUS_OK;
393 }
394
395 CAResult_t CAInitializeLEGattServer()
396 {
397     OIC_LOG(DEBUG, TAG, "IN");
398
399     CAResult_t ret = CAInitGattServerMutexVariables();
400     if (CA_STATUS_OK != ret )
401     {
402         OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!");
403         CATerminateGattServerMutexVariables();
404         return CA_SERVER_NOT_STARTED;
405     }
406     OIC_LOG(DEBUG, TAG, "OUT");
407     return ret;
408 }
409
410 void CATerminateLEGattServer()
411 {
412     OIC_LOG(DEBUG, TAG, "IN");
413
414     // Service and characteristics path will be freed by the platform.
415     ca_mutex_lock(g_leServiceMutex);
416     g_gattSvcPath = NULL;
417     ca_mutex_unlock(g_leServiceMutex);
418
419     ca_mutex_lock(g_leCharacteristicMutex);
420     g_gattReadCharPath = NULL;
421     g_gattWriteCharPath = NULL;
422     ca_mutex_unlock(g_leCharacteristicMutex);
423
424     ca_mutex_lock(g_leServerThreadPoolMutex);
425     g_leServerThreadPool = NULL;
426     ca_mutex_unlock(g_leServerThreadPoolMutex);
427
428     // Terminating all mutex variables.
429     CATerminateGattServerMutexVariables();
430     OIC_LOG(DEBUG, TAG, "OUT");
431 }
432
433 CAResult_t CAInitGattServerMutexVariables()
434 {
435     OIC_LOG(DEBUG, TAG, "IN");
436     if (NULL == g_leServerStateMutex)
437     {
438         g_leServerStateMutex = ca_mutex_new();
439         if (NULL == g_leServerStateMutex)
440         {
441             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
442             return CA_STATUS_FAILED;
443         }
444     }
445
446     if (NULL == g_leServiceMutex)
447     {
448         g_leServiceMutex = ca_mutex_new();
449         if (NULL == g_leServiceMutex)
450         {
451             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
452             return CA_STATUS_FAILED;
453         }
454     }
455
456     if (NULL == g_leCharacteristicMutex)
457     {
458         g_leCharacteristicMutex = ca_mutex_new();
459         if (NULL == g_leCharacteristicMutex)
460         {
461             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
462             return CA_STATUS_FAILED;
463         }
464     }
465
466     if (NULL == g_leReqRespCbMutex)
467     {
468         g_leReqRespCbMutex = ca_mutex_new();
469         if (NULL == g_leReqRespCbMutex)
470         {
471             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
472             return CA_STATUS_FAILED;
473         }
474     }
475     OIC_LOG(DEBUG, TAG, "OUT");
476     return CA_STATUS_OK;
477 }
478
479 void CATerminateGattServerMutexVariables()
480 {
481     OIC_LOG(DEBUG, TAG, "IN");
482     ca_mutex_free(g_leServerStateMutex);
483     g_leServerStateMutex = NULL;
484
485     ca_mutex_free(g_leServiceMutex);
486     g_leServiceMutex = NULL;
487
488     ca_mutex_free(g_leCharacteristicMutex);
489     g_leCharacteristicMutex = NULL;
490
491     ca_mutex_free(g_leReqRespCbMutex);
492     g_leReqRespCbMutex = NULL;
493
494     OIC_LOG(DEBUG, TAG, "OUT");
495 }
496
497 CAResult_t CAInitLEGattServer()
498 {
499     OIC_LOG(DEBUG, TAG, "IN");
500
501     int ret =  bt_gatt_server_initialize();
502     if (0 != ret)
503     {
504         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]",
505                   CALEGetErrorMsg(ret));
506         return CA_STATUS_FAILED;
507     }
508
509     bt_gatt_server_h server;
510
511     ret = bt_gatt_server_create(&server);
512     if (0 != ret)
513     {
514         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]",
515                   CALEGetErrorMsg(ret));
516         return CA_STATUS_FAILED;
517     }
518
519     if (NULL != g_gattServer)
520     {
521         OICFree(g_gattServer);
522         g_gattServer = NULL;
523     }
524     g_gattServer = server;
525
526     OIC_LOG(DEBUG, TAG, "OUT");
527     return CA_STATUS_OK;
528 }
529
530 CAResult_t CADeInitLEGattServer()
531 {
532     OIC_LOG(DEBUG, TAG, "IN");
533
534     int ret = bt_gatt_server_unregister_all_services(g_gattServer);
535     if (0 != ret)
536     {
537         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]",
538                   CALEGetErrorMsg(ret));
539         return CA_STATUS_FAILED;
540     }
541
542     ret = bt_gatt_server_destroy(g_gattServer);
543     if (0 != ret)
544     {
545         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]",
546                   CALEGetErrorMsg(ret));
547         return CA_STATUS_FAILED;
548     }
549
550     ret =  bt_gatt_server_deinitialize();
551     if (0 != ret)
552     {
553         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]",
554                   CALEGetErrorMsg(ret));
555         return CA_STATUS_FAILED;
556     }
557
558     OIC_LOG(DEBUG, TAG, "OUT");
559     return CA_STATUS_OK;
560 }
561
562 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
563 {
564     OIC_LOG(DEBUG, TAG, "IN");
565     ca_mutex_lock(g_leServerThreadPoolMutex);
566     g_leServerThreadPool = handle;
567     ca_mutex_unlock(g_leServerThreadPoolMutex);
568     OIC_LOG(DEBUG, TAG, "OUT");
569 }
570
571 CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID)
572 {
573     OIC_LOG(DEBUG, TAG, "IN");
574
575     VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID");
576
577     OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID);
578
579     bt_gatt_h service = NULL;
580     bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY;
581
582     int ret = bt_gatt_service_create(serviceUUID, type, &service);
583     if (0 != ret)
584     {
585         OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]",
586                   CALEGetErrorMsg(ret));
587         return CA_STATUS_FAILED;
588     }
589
590     if (NULL != service)
591     {
592         OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)service);
593
594         ca_mutex_lock(g_leServiceMutex);
595
596         if (NULL != g_gattSvcPath)
597         {
598             OICFree(g_gattSvcPath);
599             g_gattSvcPath = NULL;
600         }
601         g_gattSvcPath = service;
602
603         ca_mutex_unlock(g_leServiceMutex);
604     }
605
606     OIC_LOG(DEBUG, TAG, "OUT");
607     return CA_STATUS_OK;
608 }
609
610 void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server,
611                                          bt_gatt_h charPath, int offset, char *charValue,
612                                          int charValueLen, void *userData)
613 {
614     OIC_LOG(DEBUG, TAG, "IN");
615
616     if (NULL == charValue || NULL == remoteAddress)
617     {
618         OIC_LOG(ERROR, TAG, "Param callback values are NULL");
619         return;
620     }
621
622     OIC_LOG_V(DEBUG, TAG, "charPath = [%s] charValue = [%s] len [%d]", (char *)charPath,
623               charValue, charValueLen);
624
625     uint8_t *data = OICMalloc(charValueLen);
626     if (NULL == data)
627     {
628         OIC_LOG(ERROR, TAG, "Malloc failed!");
629         return;
630     }
631
632     memcpy(data, charValue, charValueLen);
633
634     ca_mutex_lock(g_leReqRespCbMutex);
635     if (NULL == g_leServerDataReceivedCallback)
636     {
637         OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!");
638         ca_mutex_unlock(g_leReqRespCbMutex);
639         OICFree(data);
640         return;
641     }
642
643     OIC_LOG(DEBUG, TAG, "Sending data up !");
644     uint32_t sentLength = 0;
645     g_leServerDataReceivedCallback(remoteAddress, data, charValueLen,
646                                     &sentLength);
647     ca_mutex_unlock(g_leReqRespCbMutex);
648     OICFree(data);
649     OIC_LOG(DEBUG, TAG, "OUT");
650 }
651
652 CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath)
653 {
654     OIC_LOG(DEBUG, TAG, "IN");
655
656     VERIFY_NON_NULL(svcPath, TAG, "svcPath");
657
658     OIC_LOG_V(DEBUG, TAG, "svcPath:%s", svcPath);
659
660     int ret = bt_gatt_server_register_service(g_gattServer, svcPath);
661     if (0 != ret)
662     {
663         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]",
664                   CALEGetErrorMsg(ret));
665         return CA_STATUS_FAILED;
666     }
667
668     ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath,
669                                               CALEGattRemoteCharacteristicWriteCb, NULL);
670
671     if (0 != ret)
672     {
673         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]",
674                   CALEGetErrorMsg(ret));
675         return CA_STATUS_FAILED;
676     }
677
678     OIC_LOG(DEBUG, TAG, "OUT");
679     return CA_STATUS_OK;
680 }
681
682 CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID,
683                                                const char *charValue, int charValueLen, bool read)
684 {
685
686     OIC_LOG(DEBUG, TAG, "IN");
687
688     int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
689     int properties;
690     if(read)
691     {
692         properties = BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_READ;
693     }
694     else
695     {
696         properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ;
697     }
698
699     bt_gatt_h charPath;
700
701     int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue,
702                                             charValueLen, &charPath);
703
704     if (0 != ret || NULL == charPath)
705     {
706         OIC_LOG_V(ERROR, TAG,
707                   "bt_gatt_add_characteristic  failed with ret [%s]", CALEGetErrorMsg(ret));
708         return CA_STATUS_FAILED;
709     }
710
711     OIC_LOG_V(DEBUG, TAG,
712               "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath);
713
714     if (read)
715     {
716         ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL);
717         if (0 != ret)
718         {
719             OIC_LOG_V(ERROR, TAG,
720                       "bt_gatt_server_set_notification_state_change_cb  failed with ret[%s]",
721                       CALEGetErrorMsg(ret));
722             return CA_STATUS_FAILED;
723         }
724     }
725
726     ret =  bt_gatt_service_add_characteristic(svcPath, charPath);
727     if (0 != ret)
728     {
729         OIC_LOG_V(ERROR, TAG,
730                   "bt_gatt_service_add_characteristic  failed with ret[%s]",
731                   CALEGetErrorMsg(ret));
732         return CA_STATUS_FAILED;
733     }
734
735     ca_mutex_lock(g_leCharacteristicMutex);
736
737     if (read)
738     {
739         char desc_value[2] = {1, 0};  // Notification enabled.
740         bt_gatt_h descriptor = NULL;
741         permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
742         ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, permissions,
743                                         desc_value, sizeof(desc_value),
744                                         &descriptor);
745         if (0 != ret)
746         {
747             OIC_LOG_V(ERROR, TAG,
748                       "bt_gatt_descriptor_create  failed with ret[%s]",
749                       CALEGetErrorMsg(ret));
750             return CA_STATUS_FAILED;
751         }
752
753         ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor);
754         if (0 != ret)
755         {
756             OIC_LOG_V(ERROR, TAG,
757                       "bt_gatt_characteristic_add_descriptor  failed with ret[%s]",
758                       CALEGetErrorMsg(ret));
759             return CA_STATUS_FAILED;
760         }
761
762         if (NULL != g_gattReadCharPath)
763         {
764             OICFree(g_gattReadCharPath);
765             g_gattReadCharPath = NULL;
766         }
767         g_gattReadCharPath = charPath;
768
769     }
770     else
771     {
772         if (NULL != g_gattWriteCharPath)
773         {
774             OICFree(g_gattWriteCharPath);
775             g_gattWriteCharPath = NULL;
776         }
777         g_gattWriteCharPath = charPath;
778     }
779
780     ca_mutex_unlock(g_leCharacteristicMutex);
781
782     OIC_LOG(DEBUG, TAG, "OUT");
783     return CA_STATUS_OK;
784 }
785
786 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue,
787                                                uint32_t charValueLen)
788 {
789     OIC_LOG(DEBUG, TAG, "IN");
790
791     VERIFY_NON_NULL(charValue, TAG, "charValue");
792     VERIFY_NON_NULL(address, TAG, "address");
793
794     OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address);
795
796     ca_mutex_lock(g_leCharacteristicMutex);
797
798     if (NULL  == g_gattReadCharPath)
799     {
800         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
801         ca_mutex_unlock(g_leCharacteristicMutex);
802         return CA_STATUS_FAILED;
803     }
804
805     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
806     if (0 != ret)
807     {
808         OIC_LOG_V(ERROR, TAG,
809                   "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret));
810         ca_mutex_unlock(g_leCharacteristicMutex);
811         return CA_STATUS_FAILED;
812     }
813
814     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
815                                 address, NULL);
816     if (0 != ret)
817     {
818         OIC_LOG_V(ERROR, TAG,
819                   "bt_gatt_server_notify failed with return [%s]", CALEGetErrorMsg(ret));
820         ca_mutex_unlock(g_leCharacteristicMutex);
821         return CA_STATUS_FAILED;
822     }
823
824     ca_mutex_unlock(g_leCharacteristicMutex);
825
826     OIC_LOG(DEBUG, TAG, "OUT");
827     return CA_STATUS_OK;
828 }
829
830 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
831 {
832     OIC_LOG(DEBUG, TAG, "IN");
833
834     VERIFY_NON_NULL(charValue, TAG, "charValue");
835
836     ca_mutex_lock(g_leCharacteristicMutex);
837
838     if (NULL  == g_gattReadCharPath)
839     {
840         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
841         ca_mutex_unlock(g_leCharacteristicMutex);
842         return CA_STATUS_FAILED;
843     }
844
845     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
846     if (0 != ret)
847     {
848         OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret));
849         ca_mutex_unlock(g_leCharacteristicMutex);
850         return CA_STATUS_FAILED;
851     }
852
853     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
854                                 NULL, NULL);
855     if (0 != ret)
856     {
857         OIC_LOG_V(ERROR, TAG,
858                   "bt_gatt_server_notify failed with return[%s]", CALEGetErrorMsg(ret));
859         ca_mutex_unlock(g_leCharacteristicMutex);
860         return CA_STATUS_FAILED;
861     }
862
863     ca_mutex_unlock(g_leCharacteristicMutex);
864
865     OIC_LOG(DEBUG, TAG, "OUT");
866     return CA_STATUS_OK;
867 }
868
869 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
870 {
871     OIC_LOG(DEBUG, TAG, "IN");
872
873     ca_mutex_lock(g_leReqRespCbMutex);
874     g_leServerDataReceivedCallback = callback;
875     ca_mutex_unlock(g_leReqRespCbMutex);
876
877     OIC_LOG(DEBUG, TAG, "OUT");
878 }
879
880 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
881 {
882     g_serverErrorCallback = callback;
883 }