Merge branch 'master' into windows-port
[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;
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     }
377     else
378     {
379         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
380     }
381
382     ca_mutex_unlock(g_leServerStateMutex);
383
384     OIC_LOG(DEBUG, TAG, "OUT");
385     return CA_STATUS_OK;
386 }
387
388 CAResult_t CAInitializeLEGattServer()
389 {
390     OIC_LOG(DEBUG, TAG, "IN");
391
392     CAResult_t ret = CAInitGattServerMutexVariables();
393     if (CA_STATUS_OK != ret )
394     {
395         OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!");
396         CATerminateGattServerMutexVariables();
397         return CA_SERVER_NOT_STARTED;
398     }
399     OIC_LOG(DEBUG, TAG, "OUT");
400     return ret;
401 }
402
403 void CATerminateLEGattServer()
404 {
405     OIC_LOG(DEBUG, TAG, "IN");
406
407     // Service and characteristics path will be freed by the platform.
408     ca_mutex_lock(g_leServiceMutex);
409     g_gattSvcPath = NULL;
410     ca_mutex_unlock(g_leServiceMutex);
411
412     ca_mutex_lock(g_leCharacteristicMutex);
413     g_gattReadCharPath = NULL;
414     g_gattWriteCharPath = NULL;
415     ca_mutex_unlock(g_leCharacteristicMutex);
416
417     ca_mutex_lock(g_leServerThreadPoolMutex);
418     g_leServerThreadPool = NULL;
419     ca_mutex_unlock(g_leServerThreadPoolMutex);
420
421     // Terminating all mutex variables.
422     CATerminateGattServerMutexVariables();
423     OIC_LOG(DEBUG, TAG, "OUT");
424 }
425
426 CAResult_t CAInitGattServerMutexVariables()
427 {
428     OIC_LOG(DEBUG, TAG, "IN");
429     if (NULL == g_leServerStateMutex)
430     {
431         g_leServerStateMutex = ca_mutex_new();
432         if (NULL == g_leServerStateMutex)
433         {
434             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
435             return CA_STATUS_FAILED;
436         }
437     }
438
439     if (NULL == g_leServiceMutex)
440     {
441         g_leServiceMutex = ca_mutex_new();
442         if (NULL == g_leServiceMutex)
443         {
444             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
445             return CA_STATUS_FAILED;
446         }
447     }
448
449     if (NULL == g_leCharacteristicMutex)
450     {
451         g_leCharacteristicMutex = ca_mutex_new();
452         if (NULL == g_leCharacteristicMutex)
453         {
454             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
455             return CA_STATUS_FAILED;
456         }
457     }
458
459     if (NULL == g_leReqRespCbMutex)
460     {
461         g_leReqRespCbMutex = ca_mutex_new();
462         if (NULL == g_leReqRespCbMutex)
463         {
464             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
465             return CA_STATUS_FAILED;
466         }
467     }
468
469     if (NULL == g_leServerThreadPoolMutex)
470     {
471         g_leServerThreadPoolMutex = ca_mutex_new();
472         if (NULL == g_leServerThreadPoolMutex)
473         {
474             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
475             return CA_STATUS_FAILED;
476         }
477     }
478
479     if (NULL == g_LEClientListMutex)
480     {
481         g_LEClientListMutex = ca_mutex_new();
482         if (NULL == g_LEClientListMutex)
483         {
484             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
485             return CA_STATUS_FAILED;
486         }
487     }
488
489     OIC_LOG(DEBUG, TAG, "OUT");
490     return CA_STATUS_OK;
491 }
492
493 void CATerminateGattServerMutexVariables()
494 {
495     OIC_LOG(DEBUG, TAG, "IN");
496     ca_mutex_free(g_leServerStateMutex);
497     g_leServerStateMutex = NULL;
498
499     ca_mutex_free(g_leServiceMutex);
500     g_leServiceMutex = NULL;
501
502     ca_mutex_free(g_leCharacteristicMutex);
503     g_leCharacteristicMutex = NULL;
504
505     ca_mutex_free(g_leReqRespCbMutex);
506     g_leReqRespCbMutex = NULL;
507
508     ca_mutex_free(g_leServerThreadPoolMutex);
509     g_leServerThreadPoolMutex = NULL;
510
511     ca_mutex_free(g_LEClientListMutex);
512     g_LEClientListMutex = NULL;
513
514     OIC_LOG(DEBUG, TAG, "OUT");
515 }
516
517 CAResult_t CAInitLEGattServer()
518 {
519     OIC_LOG(DEBUG, TAG, "IN");
520
521     int ret =  bt_gatt_server_initialize();
522     if (0 != ret)
523     {
524         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]",
525                   CALEGetErrorMsg(ret));
526         return CA_STATUS_FAILED;
527     }
528
529     bt_gatt_server_h server;
530
531     ret = bt_gatt_server_create(&server);
532     if (0 != ret)
533     {
534         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]",
535                   CALEGetErrorMsg(ret));
536         return CA_STATUS_FAILED;
537     }
538
539     if (NULL != g_gattServer)
540     {
541         OICFree(g_gattServer);
542         g_gattServer = NULL;
543     }
544     g_gattServer = server;
545
546     OIC_LOG(DEBUG, TAG, "OUT");
547     return CA_STATUS_OK;
548 }
549
550 CAResult_t CADeInitLEGattServer()
551 {
552     OIC_LOG(DEBUG, TAG, "IN");
553
554     int ret = bt_gatt_server_unregister_all_services(g_gattServer);
555     if (0 != ret)
556     {
557         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]",
558                   CALEGetErrorMsg(ret));
559         return CA_STATUS_FAILED;
560     }
561
562     ret = bt_gatt_server_destroy(g_gattServer);
563     if (0 != ret)
564     {
565         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]",
566                   CALEGetErrorMsg(ret));
567         return CA_STATUS_FAILED;
568     }
569
570     ret =  bt_gatt_server_deinitialize();
571     if (0 != ret)
572     {
573         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]",
574                   CALEGetErrorMsg(ret));
575         return CA_STATUS_FAILED;
576     }
577
578     OIC_LOG(DEBUG, TAG, "OUT");
579     return CA_STATUS_OK;
580 }
581
582 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
583 {
584     OIC_LOG(DEBUG, TAG, "IN");
585     ca_mutex_lock(g_leServerThreadPoolMutex);
586     g_leServerThreadPool = handle;
587     ca_mutex_unlock(g_leServerThreadPoolMutex);
588     OIC_LOG(DEBUG, TAG, "OUT");
589 }
590
591 CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID)
592 {
593     OIC_LOG(DEBUG, TAG, "IN");
594
595     VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID");
596
597     OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID);
598
599     bt_gatt_h service = NULL;
600     bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY;
601
602     int ret = bt_gatt_service_create(serviceUUID, type, &service);
603     if (0 != ret)
604     {
605         OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]",
606                   CALEGetErrorMsg(ret));
607         return CA_STATUS_FAILED;
608     }
609
610     if (NULL != service)
611     {
612         OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)service);
613
614         ca_mutex_lock(g_leServiceMutex);
615
616         if (NULL != g_gattSvcPath)
617         {
618             OICFree(g_gattSvcPath);
619             g_gattSvcPath = NULL;
620         }
621         g_gattSvcPath = service;
622
623         ca_mutex_unlock(g_leServiceMutex);
624     }
625
626     OIC_LOG(DEBUG, TAG, "OUT");
627     return CA_STATUS_OK;
628 }
629
630 void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server,
631                                          bt_gatt_h charPath, int offset, char *charValue,
632                                          int charValueLen, void *userData)
633 {
634     OIC_LOG(DEBUG, TAG, "IN");
635
636     if (NULL == charValue || NULL == remoteAddress)
637     {
638         OIC_LOG(ERROR, TAG, "Param callback values are NULL");
639         return;
640     }
641
642     OIC_LOG_V(DEBUG, TAG, "charPath = [%s] charValue = [%s] len [%d]", (char *)charPath,
643               charValue, charValueLen);
644
645     uint8_t *data = OICMalloc(charValueLen);
646     if (NULL == data)
647     {
648         OIC_LOG(ERROR, TAG, "Malloc failed!");
649         return;
650     }
651
652     memcpy(data, charValue, charValueLen);
653
654     ca_mutex_lock(g_leReqRespCbMutex);
655     if (NULL == g_leServerDataReceivedCallback)
656     {
657         OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!");
658         ca_mutex_unlock(g_leReqRespCbMutex);
659         OICFree(data);
660         return;
661     }
662
663     OIC_LOG(DEBUG, TAG, "Sending data up !");
664     uint32_t sentLength = 0;
665     g_leServerDataReceivedCallback(remoteAddress, data, charValueLen,
666                                     &sentLength);
667     ca_mutex_unlock(g_leReqRespCbMutex);
668     OICFree(data);
669     OIC_LOG(DEBUG, TAG, "OUT");
670 }
671
672 CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath)
673 {
674     OIC_LOG(DEBUG, TAG, "IN");
675
676     VERIFY_NON_NULL(svcPath, TAG, "svcPath");
677
678     OIC_LOG_V(DEBUG, TAG, "svcPath:%s", svcPath);
679
680     int ret = bt_gatt_server_register_service(g_gattServer, svcPath);
681     if (0 != ret)
682     {
683         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]",
684                   CALEGetErrorMsg(ret));
685         return CA_STATUS_FAILED;
686     }
687
688     ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath,
689                                               CALEGattRemoteCharacteristicWriteCb, NULL);
690
691     if (0 != ret)
692     {
693         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]",
694                   CALEGetErrorMsg(ret));
695         return CA_STATUS_FAILED;
696     }
697
698     OIC_LOG(DEBUG, TAG, "OUT");
699     return CA_STATUS_OK;
700 }
701
702 CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID,
703                                                const char *charValue, int charValueLen, bool read)
704 {
705
706     OIC_LOG(DEBUG, TAG, "IN");
707
708     int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
709     int properties;
710     if(read)
711     {
712         properties = BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_READ;
713     }
714     else
715     {
716         properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ;
717     }
718
719     bt_gatt_h charPath;
720
721     int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue,
722                                             charValueLen, &charPath);
723
724     if (0 != ret || NULL == charPath)
725     {
726         OIC_LOG_V(ERROR, TAG,
727                   "bt_gatt_add_characteristic  failed with ret [%s]", CALEGetErrorMsg(ret));
728         return CA_STATUS_FAILED;
729     }
730
731     OIC_LOG_V(DEBUG, TAG,
732               "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath);
733
734     if (read)
735     {
736         ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL);
737         if (0 != ret)
738         {
739             OIC_LOG_V(ERROR, TAG,
740                       "bt_gatt_server_set_notification_state_change_cb  failed with ret[%s]",
741                       CALEGetErrorMsg(ret));
742             return CA_STATUS_FAILED;
743         }
744     }
745
746     ret =  bt_gatt_service_add_characteristic(svcPath, charPath);
747     if (0 != ret)
748     {
749         OIC_LOG_V(ERROR, TAG,
750                   "bt_gatt_service_add_characteristic  failed with ret[%s]",
751                   CALEGetErrorMsg(ret));
752         return CA_STATUS_FAILED;
753     }
754
755     ca_mutex_lock(g_leCharacteristicMutex);
756
757     if (read)
758     {
759         char desc_value[2] = {1, 0};  // Notification enabled.
760         bt_gatt_h descriptor = NULL;
761         permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
762         ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, permissions,
763                                         desc_value, sizeof(desc_value),
764                                         &descriptor);
765         if (0 != ret)
766         {
767             OIC_LOG_V(ERROR, TAG,
768                       "bt_gatt_descriptor_create  failed with ret[%s]",
769                       CALEGetErrorMsg(ret));
770             return CA_STATUS_FAILED;
771         }
772
773         ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor);
774         if (0 != ret)
775         {
776             OIC_LOG_V(ERROR, TAG,
777                       "bt_gatt_characteristic_add_descriptor  failed with ret[%s]",
778                       CALEGetErrorMsg(ret));
779             return CA_STATUS_FAILED;
780         }
781
782         if (NULL != g_gattReadCharPath)
783         {
784             OICFree(g_gattReadCharPath);
785             g_gattReadCharPath = NULL;
786         }
787         g_gattReadCharPath = charPath;
788
789     }
790     else
791     {
792         if (NULL != g_gattWriteCharPath)
793         {
794             OICFree(g_gattWriteCharPath);
795             g_gattWriteCharPath = NULL;
796         }
797         g_gattWriteCharPath = charPath;
798     }
799
800     ca_mutex_unlock(g_leCharacteristicMutex);
801
802     OIC_LOG(DEBUG, TAG, "OUT");
803     return CA_STATUS_OK;
804 }
805
806 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue,
807                                                uint32_t charValueLen)
808 {
809     OIC_LOG(DEBUG, TAG, "IN");
810
811     VERIFY_NON_NULL(charValue, TAG, "charValue");
812     VERIFY_NON_NULL(address, TAG, "address");
813
814     OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address);
815
816     ca_mutex_lock(g_leCharacteristicMutex);
817
818     if (NULL  == g_gattReadCharPath)
819     {
820         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
821         ca_mutex_unlock(g_leCharacteristicMutex);
822         return CA_STATUS_FAILED;
823     }
824
825     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
826     if (0 != ret)
827     {
828         OIC_LOG_V(ERROR, TAG,
829                   "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret));
830         ca_mutex_unlock(g_leCharacteristicMutex);
831         return CA_STATUS_FAILED;
832     }
833
834     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
835                                 address, NULL);
836     if (0 != ret)
837     {
838         OIC_LOG_V(ERROR, TAG,
839                   "bt_gatt_server_notify failed with return [%s]", CALEGetErrorMsg(ret));
840         ca_mutex_unlock(g_leCharacteristicMutex);
841         return CA_STATUS_FAILED;
842     }
843
844     ca_mutex_unlock(g_leCharacteristicMutex);
845
846     OIC_LOG(DEBUG, TAG, "OUT");
847     return CA_STATUS_OK;
848 }
849
850 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
851 {
852     OIC_LOG(DEBUG, TAG, "IN");
853
854     VERIFY_NON_NULL(charValue, TAG, "charValue");
855
856     ca_mutex_lock(g_leCharacteristicMutex);
857
858     if (NULL  == g_gattReadCharPath)
859     {
860         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
861         ca_mutex_unlock(g_leCharacteristicMutex);
862         return CA_STATUS_FAILED;
863     }
864
865     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
866     if (0 != ret)
867     {
868         OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret));
869         ca_mutex_unlock(g_leCharacteristicMutex);
870         return CA_STATUS_FAILED;
871     }
872
873     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
874                                 NULL, NULL);
875     if (0 != ret)
876     {
877         OIC_LOG_V(ERROR, TAG,
878                   "bt_gatt_server_notify failed with return[%s]", CALEGetErrorMsg(ret));
879         ca_mutex_unlock(g_leCharacteristicMutex);
880         return CA_STATUS_FAILED;
881     }
882
883     ca_mutex_unlock(g_leCharacteristicMutex);
884
885     OIC_LOG(DEBUG, TAG, "OUT");
886     return CA_STATUS_OK;
887 }
888
889 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
890 {
891     OIC_LOG(DEBUG, TAG, "IN");
892
893     ca_mutex_lock(g_leReqRespCbMutex);
894     g_leServerDataReceivedCallback = callback;
895     ca_mutex_unlock(g_leReqRespCbMutex);
896
897     OIC_LOG(DEBUG, TAG, "OUT");
898 }
899
900 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
901 {
902     g_serverErrorCallback = callback;
903 }