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