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