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