f06d8c6ca448ebfae54b6e545024820f0281caa1
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / caleserver_vd.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 "octhread.h"
25 #include "caqueueingthread.h"
26 #include "cagattservice.h"
27 #include "oic_string.h"
28 #include "oic_malloc.h"
29 #include "caleutil.h"
30 #include "caadapterutils.h"
31 #include <glib.h>
32 #ifndef BLE_TIZEN_40
33 #include <bluetooth_internal.h>
34 #endif
35
36 /**
37  * Logging tag for module name
38  */
39 #define TAG "OIC_CA_LE_SERVER_VD"
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 oc_mutex g_leServerStateMutex = NULL;
86
87 /**
88  * Mutex to synchronize writing operations on the characteristics.
89  */
90 static  oc_mutex g_leCharacteristicMutex = NULL;
91
92 /**
93  * Mutex to synchronize to creation of OIC service.
94  */
95 static  oc_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  oc_mutex g_leReqRespCbMutex = NULL;
102
103 /**
104  * Mutex to synchronize the task to be pushed to thread pool.
105  */
106 static oc_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 oc_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     CAResult_t res = CA_STATUS_OK;
133     if (connected)
134     {
135         OIC_LOG_V(DEBUG, TAG, "Connected to [%s]", remoteAddress);
136         char *addr = OICStrdup(remoteAddress);
137         oc_mutex_lock(g_LEClientListMutex);
138         res  = CAAddLEClientInfoToList(&g_LEClientList, addr);
139         if (CA_STATUS_OK != res)
140         {
141             OIC_LOG(ERROR, TAG, "CAAddLEClientInfoToList failed");
142             oc_mutex_unlock(g_LEClientListMutex);
143             OICFree(addr);
144             return;
145         }
146         oc_mutex_unlock(g_LEClientListMutex);
147
148         /*
149          * TV Easysetup does not use IoTivity BLE advertisement.
150          */
151
152         // res = CALEStopAdvertise();
153         // if (CA_STATUS_OK != res)
154         // {
155         //     OIC_LOG_V(ERROR, TAG, "Failed to stop advertising [%d]", res);
156         //     return;
157         // }
158     }
159     else
160     {
161         OIC_LOG_V(DEBUG, TAG, "Disconnected from [%s]", remoteAddress);
162         oc_mutex_lock(g_LEClientListMutex);
163         CARemoveLEClientInfoFromList(&g_LEClientList, remoteAddress);
164         oc_mutex_unlock(g_LEClientListMutex);
165
166         /*
167          * TV Easysetup does not use IoTivity BLE advertisement.
168          */
169
170         // res = CALEStartAdvertise();
171         // if (CA_STATUS_OK != res)
172         // {
173         //     OIC_LOG_V(ERROR, TAG, "Failed to start advertising [%d]", res);
174         //     return;
175         // }
176     }
177 }
178
179 #ifdef BLE_TIZEN_30
180 void CALEServerNotificationSentCB(int result, const char *remote_address, bt_gatt_server_h server,
181                                   bt_gatt_h characteristic, bool completed, void *user_data)
182 #else
183 void CALEServerNotificationSentCB(int result, char *remote_address, bt_gatt_server_h server,
184                                   bt_gatt_h characteristic, bool completed, void *user_data)
185 #endif
186 {
187     (void)server;
188     (void)characteristic;
189     (void)completed;
190     (void)user_data;
191
192     OIC_LOG_V(DEBUG, TAG, "Notification to the device[%s] result[%d]", remote_address, result);
193 }
194
195 CAResult_t CAStartLEGattServer()
196 {
197     OIC_LOG(DEBUG, TAG, "IN");
198
199     oc_mutex_lock(g_leServerStateMutex);
200     if (true == g_isLEGattServerStarted)
201     {
202         OIC_LOG(ERROR, TAG, "Gatt Server is already running");
203         oc_mutex_unlock(g_leServerStateMutex);
204         return CA_STATUS_OK;
205     }
206
207     CAResult_t ret = CAInitLEGattServer();
208     if (CA_STATUS_OK != ret)
209     {
210         OIC_LOG_V(ERROR, TAG, "CAInitLEGattServer failed[%d]", ret);
211         oc_mutex_unlock(g_leServerStateMutex);
212         CATerminateLEGattServer();
213         return CA_STATUS_FAILED;
214     }
215
216     ret  = CAAddNewLEServiceInGattServer(CA_GATT_SERVICE_UUID);
217     if (CA_STATUS_OK != ret)
218     {
219         OIC_LOG_V(ERROR, TAG, "CAAddNewLEServiceInGattServer failed[%d]", ret);
220         oc_mutex_unlock(g_leServerStateMutex);
221         CATerminateLEGattServer();
222         return CA_STATUS_FAILED;
223     }
224
225     static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID;
226     char charReadValue[] = {33, 44, 55, 66}; // These are initial random values
227
228     // For Read Characteristics.
229     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue,
230                                               sizeof(charReadValue), true);
231     if (CA_STATUS_OK != ret)
232     {
233         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
234         oc_mutex_unlock(g_leServerStateMutex);
235         CATerminateLEGattServer();
236         return CA_STATUS_FAILED;
237     }
238
239     static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID;
240     char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
241
242
243     ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue,
244             sizeof(charWriteValue), false); // For Write Characteristics.
245     if (CA_STATUS_OK != ret )
246     {
247         OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
248         oc_mutex_unlock(g_leServerStateMutex);
249         CATerminateLEGattServer();
250         return CA_STATUS_FAILED;
251     }
252
253     ret = CARegisterLEServicewithGattServer(g_gattSvcPath);
254     if (CA_STATUS_OK != ret )
255     {
256         OIC_LOG_V(ERROR, TAG, "CARegisterLEServicewithGattServer failed[%d]", ret);
257         oc_mutex_unlock(g_leServerStateMutex);
258         CATerminateLEGattServer();
259         return CA_STATUS_FAILED;
260     }
261
262     /*
263      * TV Easysetup does not use IoTivity BLE advertisement.
264      */
265
266     // ret = CALEStartAdvertise();
267     // if (CA_STATUS_OK != ret)
268     // {
269     //     OIC_LOG_V(ERROR, TAG, "CALEStartAdvertise failed[%d]", ret);
270     //     oc_mutex_unlock(g_leServerStateMutex);
271     //     CATerminateLEGattServer();
272     //     return CA_STATUS_FAILED;
273     // }
274
275     g_isLEGattServerStarted = true;
276
277     oc_mutex_unlock(g_leServerStateMutex);
278
279     OIC_LOG(DEBUG, TAG, "OUT");
280     return CA_STATUS_OK;
281 }
282
283 void CALENotificationCb(bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle,
284                         void *user_data)
285 {
286     (void)server;
287     (void)gatt_handle;
288     (void)user_data;
289
290     OIC_LOG(DEBUG, TAG, "IN");
291     if (notify)
292     {
293         OIC_LOG(DEBUG, TAG, "Notification is subscribed by the client");
294         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
295                            true, "notifyChar success");
296     }
297     else
298     {
299         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
300                            false, "notifyChar failure");
301     }
302     OIC_LOG(DEBUG, TAG, "OUT");
303 }
304
305 CAResult_t CALEStartAdvertise()
306 {
307     OIC_LOG(DEBUG, TAG, "IN");
308
309     CAResult_t res = CALEStartAdvertiseImpl(CA_GATT_SERVICE_UUID);
310     if (CA_STATUS_OK != res)
311     {
312         OIC_LOG_V(ERROR, TAG, "CALEStartAdvertiseImpl failed[%d]", res);
313     }
314
315     OIC_LOG(DEBUG, TAG, "OUT");
316     return res;
317 }
318
319 CAResult_t CALEStartAdvertiseImpl(const char *serviceUUID)
320 {
321     OIC_LOG(DEBUG, TAG, "IN");
322
323     int res = bt_adapter_le_create_advertiser(&g_hAdvertiser);
324     if (NULL == g_hAdvertiser || BT_ERROR_NONE != res)
325     {
326         OIC_LOG_V(ERROR, TAG, "g_hAdvertiser is NULL/ Result is %d", res);
327         return CA_STATUS_FAILED;
328     }
329
330     res = bt_adapter_le_add_advertising_service_uuid(g_hAdvertiser,
331                                                      BT_ADAPTER_LE_PACKET_ADVERTISING,
332                                                      serviceUUID);
333     if (BT_ERROR_NONE != res)
334     {
335         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_add_advertising_service_uuid failed with ret[%s]",
336                   CALEGetErrorMsg(res));
337         return CA_STATUS_FAILED;
338     }
339
340     res = bt_adapter_le_set_advertising_device_name(g_hAdvertiser,
341                                                     BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true);
342     if (BT_ERROR_NONE != res)
343     {
344         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_set_advertising_device_name failed with ret[%s]",
345                   CALEGetErrorMsg(res));
346         return CA_STATUS_FAILED;
347     }
348
349     res = bt_adapter_le_start_advertising_new(g_hAdvertiser, NULL, NULL);
350     if (BT_ERROR_NONE != res)
351     {
352         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_advertising_new failed with ret[%s]",
353                   CALEGetErrorMsg(res));
354         return CA_STATUS_FAILED;
355     }
356
357     OIC_LOG(DEBUG, TAG, "OUT");
358     return CA_STATUS_OK;
359 }
360
361 CAResult_t CALEStopAdvertise()
362 {
363     OIC_LOG(DEBUG, TAG, "IN");
364     if (NULL != g_hAdvertiser)
365     {
366         int ret  = bt_adapter_le_stop_advertising(g_hAdvertiser);
367         if (0 != ret)
368         {
369             OIC_LOG_V(ERROR, TAG,
370                       "bt_adapter_le_stop_advertising failed with ret[%s]", CALEGetErrorMsg(ret));
371         }
372
373         ret = bt_adapter_le_destroy_advertiser(g_hAdvertiser);
374         if (0 != ret)
375         {
376             OIC_LOG_V(ERROR, TAG,
377                       "bt_adapter_le_destroy_advertiser failed with ret[%s]", CALEGetErrorMsg(ret));
378         }
379         g_hAdvertiser = NULL;
380     }
381     else
382     {
383         OIC_LOG(ERROR, TAG, "Advertising is not running");
384         return CA_STATUS_FAILED;
385     }
386
387     OIC_LOG(DEBUG, TAG, "OUT");
388     return CA_STATUS_OK;
389 }
390
391 CAResult_t CAStopLEGattServer()
392 {
393     OIC_LOG(DEBUG, TAG, "IN");
394
395     oc_mutex_lock(g_leServerStateMutex);
396
397     if (false == g_isLEGattServerStarted)
398     {
399         OIC_LOG(ERROR, TAG, "Gatt Server is not running to stop");
400         oc_mutex_unlock(g_leServerStateMutex);
401         return CA_STATUS_OK;
402     }
403
404     g_isLEGattServerStarted = false;
405
406     oc_mutex_lock(g_LEClientListMutex);
407     CADisconnectAllClient(g_LEClientList);
408     g_LEClientList = NULL;
409     oc_mutex_unlock(g_LEClientListMutex);
410
411     /*
412      * TV Easysetup does not use IoTivity BLE advertisement.
413      */
414
415     // CAResult_t res = CALEStopAdvertise();
416     // {
417     //     OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res);
418     // }
419
420     CAResult_t res = CADeInitLEGattServer();
421     if (CA_STATUS_OK != res)
422     {
423         OIC_LOG_V(ERROR, TAG, "CADeInitLEGattService failed with ret[%d]", res);
424     }
425
426     GMainContext  *context_event_loop = NULL;
427     // Required for waking up the thread which is running in gmain loop
428     if (NULL != g_eventLoop)
429     {
430         context_event_loop = g_main_loop_get_context(g_eventLoop);
431
432         if (context_event_loop)
433         {
434             OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %p", (void *)context_event_loop);
435             g_main_context_wakeup(context_event_loop);
436
437             // Kill g main loops and kill threads
438             g_main_loop_quit(g_eventLoop);
439         }
440         g_eventLoop = NULL;
441     }
442     else
443     {
444         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
445     }
446
447     oc_mutex_unlock(g_leServerStateMutex);
448
449     OIC_LOG(DEBUG, TAG, "OUT");
450     return CA_STATUS_OK;
451 }
452
453 CAResult_t CAInitializeLEGattServer()
454 {
455     OIC_LOG(DEBUG, TAG, "IN");
456
457     CAResult_t ret = CAInitGattServerMutexVariables();
458     if (CA_STATUS_OK != ret )
459     {
460         OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!");
461         CATerminateGattServerMutexVariables();
462         return CA_SERVER_NOT_STARTED;
463     }
464     OIC_LOG(DEBUG, TAG, "OUT");
465     return ret;
466 }
467
468 void CATerminateLEGattServer()
469 {
470     OIC_LOG(DEBUG, TAG, "IN");
471
472     // Service and characteristics path will be freed by the platform.
473     oc_mutex_lock(g_leServiceMutex);
474     g_gattSvcPath = NULL;
475     oc_mutex_unlock(g_leServiceMutex);
476
477     oc_mutex_lock(g_leCharacteristicMutex);
478     g_gattReadCharPath = NULL;
479     g_gattWriteCharPath = NULL;
480     oc_mutex_unlock(g_leCharacteristicMutex);
481
482     oc_mutex_lock(g_leServerThreadPoolMutex);
483     g_leServerThreadPool = NULL;
484     oc_mutex_unlock(g_leServerThreadPoolMutex);
485
486     // Terminating all mutex variables.
487     CATerminateGattServerMutexVariables();
488     OIC_LOG(DEBUG, TAG, "OUT");
489 }
490
491 CAResult_t CAInitGattServerMutexVariables()
492 {
493     OIC_LOG(DEBUG, TAG, "IN");
494     if (NULL == g_leServerStateMutex)
495     {
496         g_leServerStateMutex = oc_mutex_new();
497         if (NULL == g_leServerStateMutex)
498         {
499             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
500             return CA_STATUS_FAILED;
501         }
502     }
503
504     if (NULL == g_leServiceMutex)
505     {
506         g_leServiceMutex = oc_mutex_new();
507         if (NULL == g_leServiceMutex)
508         {
509             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
510             return CA_STATUS_FAILED;
511         }
512     }
513
514     if (NULL == g_leCharacteristicMutex)
515     {
516         g_leCharacteristicMutex = oc_mutex_new();
517         if (NULL == g_leCharacteristicMutex)
518         {
519             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
520             return CA_STATUS_FAILED;
521         }
522     }
523
524     if (NULL == g_leReqRespCbMutex)
525     {
526         g_leReqRespCbMutex = oc_mutex_new();
527         if (NULL == g_leReqRespCbMutex)
528         {
529             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
530             return CA_STATUS_FAILED;
531         }
532     }
533
534     if (NULL == g_leServerThreadPoolMutex)
535     {
536         g_leServerThreadPoolMutex = oc_mutex_new();
537         if (NULL == g_leServerThreadPoolMutex)
538         {
539             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
540             return CA_STATUS_FAILED;
541         }
542     }
543
544     if (NULL == g_LEClientListMutex)
545     {
546         g_LEClientListMutex = oc_mutex_new();
547         if (NULL == g_LEClientListMutex)
548         {
549             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
550             return CA_STATUS_FAILED;
551         }
552     }
553
554     OIC_LOG(DEBUG, TAG, "OUT");
555     return CA_STATUS_OK;
556 }
557
558 void CATerminateGattServerMutexVariables()
559 {
560     OIC_LOG(DEBUG, TAG, "IN");
561     oc_mutex_free(g_leServerStateMutex);
562     g_leServerStateMutex = NULL;
563
564     oc_mutex_free(g_leServiceMutex);
565     g_leServiceMutex = NULL;
566
567     oc_mutex_free(g_leCharacteristicMutex);
568     g_leCharacteristicMutex = NULL;
569
570     oc_mutex_free(g_leReqRespCbMutex);
571     g_leReqRespCbMutex = NULL;
572
573     oc_mutex_free(g_leServerThreadPoolMutex);
574     g_leServerThreadPoolMutex = NULL;
575
576     oc_mutex_free(g_LEClientListMutex);
577     g_LEClientListMutex = NULL;
578
579     OIC_LOG(DEBUG, TAG, "OUT");
580 }
581
582 CAResult_t CAInitLEGattServer()
583 {
584     OIC_LOG(DEBUG, TAG, "IN");
585
586     int ret =  bt_gatt_server_initialize();
587     if (0 != ret)
588     {
589         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]",
590                   CALEGetErrorMsg(ret));
591         return CA_STATUS_FAILED;
592     }
593
594     if (!g_gattServer)
595     {
596         OIC_LOG(DEBUG, TAG, "g_gattServer is NULL. create gatt server..");
597         ret = bt_gatt_server_create(&g_gattServer);
598         if (0 != ret)
599         {
600             OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]",
601                       CALEGetErrorMsg(ret));
602             bt_gatt_server_deinitialize();
603             return CA_STATUS_FAILED;
604         }
605     }
606
607     OIC_LOG(DEBUG, TAG, "OUT");
608     return CA_STATUS_OK;
609 }
610
611 CAResult_t CADeInitLEGattServer()
612 {
613     OIC_LOG(DEBUG, TAG, "IN");
614
615     int ret = bt_gatt_server_unregister_all_services(g_gattServer);
616     if (0 != ret)
617     {
618         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]",
619                   CALEGetErrorMsg(ret));
620         // CONPRO-1181 continue even bt API fails during DeInit
621         //return CA_STATUS_FAILED;
622     }
623
624     ret = bt_gatt_server_destroy(g_gattServer);
625     if (0 != ret)
626     {
627         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]",
628                   CALEGetErrorMsg(ret));
629         // CONPRO-1181 continue even bt API fails during DeInit
630         //return CA_STATUS_FAILED;
631     }
632     g_gattServer = NULL;
633
634     ret =  bt_gatt_server_deinitialize();
635     if (0 != ret)
636     {
637         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]",
638                   CALEGetErrorMsg(ret));
639         // CONPRO-1181 continue even bt API fails during DeInit
640         //return CA_STATUS_FAILED;
641     }
642
643     OIC_LOG(DEBUG, TAG, "OUT");
644     return CA_STATUS_OK;
645 }
646
647 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
648 {
649     OIC_LOG(DEBUG, TAG, "IN");
650     oc_mutex_lock(g_leServerThreadPoolMutex);
651     g_leServerThreadPool = handle;
652     oc_mutex_unlock(g_leServerThreadPoolMutex);
653     OIC_LOG(DEBUG, TAG, "OUT");
654 }
655
656 CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID)
657 {
658     OIC_LOG(DEBUG, TAG, "IN");
659
660     VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID");
661
662     OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID);
663
664     bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY;
665
666     oc_mutex_lock(g_leServiceMutex);
667     int ret = bt_gatt_service_create(serviceUUID, type, &g_gattSvcPath);
668     if (0 != ret)
669     {
670         oc_mutex_unlock(g_leServiceMutex);
671         OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]",
672                     CALEGetErrorMsg(ret));
673         return CA_STATUS_FAILED;
674     }
675     oc_mutex_unlock(g_leServiceMutex);
676
677     if (g_gattSvcPath)
678     {
679         OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)g_gattSvcPath);
680     }
681
682     OIC_LOG(DEBUG, TAG, "OUT");
683     return CA_STATUS_OK;
684 }
685
686 #ifdef BLE_TIZEN_30
687 void CALEGattRemoteCharacteristicWriteCb(const char *remoteAddress, int request_id,
688                                          bt_gatt_server_h server, bt_gatt_h gatt_handle,
689                                          bool response_needed, int offset, const char *charValue,
690                                          int charLen, void *userData)
691 #else
692 void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server,
693                                          bt_gatt_h gatt_handle, int offset, char *charValue,
694                                          int charLen, void *userData)
695 #endif
696 {
697     (void)server;
698     (void)gatt_handle;
699     (void)userData;
700
701     OIC_LOG(INFO, TAG, "IN - WriteCharCB");
702
703     if (NULL == charValue || NULL == remoteAddress)
704     {
705         OIC_LOG(ERROR, TAG, "Param callback values are NULL");
706         return;
707     }
708
709     OIC_LOG_V(DEBUG, TAG, "len [%d]", charLen);
710
711     uint8_t *data = OICMalloc(charLen);
712     if (NULL == data)
713     {
714         OIC_LOG(ERROR, TAG, "Malloc failed!");
715         return;
716     }
717
718     memcpy(data, charValue, charLen);
719
720     oc_mutex_lock(g_leReqRespCbMutex);
721     if (NULL == g_leServerDataReceivedCallback)
722     {
723         OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!");
724         oc_mutex_unlock(g_leReqRespCbMutex);
725         OICFree(data);
726         return;
727     }
728
729     OIC_LOG(INFO, TAG, "Sending data up !");
730     uint32_t sentLength = 0;
731     g_leServerDataReceivedCallback(remoteAddress, data, charLen,
732                                     &sentLength);
733     oc_mutex_unlock(g_leReqRespCbMutex);
734     OICFree(data);
735
736 #ifdef BLE_TIZEN_30
737     //response
738     OIC_LOG_V(INFO, TAG, "response_needed flag : %d", response_needed);
739     if (response_needed)
740     {
741         OIC_LOG(INFO, TAG, "send response to remote client");
742         bt_gatt_server_send_response(request_id,
743                 BT_GATT_REQUEST_TYPE_WRITE, offset,
744                 BT_ERROR_NONE, NULL, 0);
745     }
746 #endif
747
748     OIC_LOG(INFO, TAG, "OUT - WriteCharCB");
749 }
750
751 CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath)
752 {
753     OIC_LOG(DEBUG, TAG, "IN");
754
755     VERIFY_NON_NULL(svcPath, TAG, "svcPath");
756
757     OIC_LOG_V(DEBUG, TAG, "svcPath: %s", (char *)svcPath);
758
759     int ret = bt_gatt_server_register_service(g_gattServer, svcPath);
760     if (0 != ret)
761     {
762         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]",
763                   CALEGetErrorMsg(ret));
764         return CA_STATUS_FAILED;
765     }
766
767 #ifdef BLE_TIZEN_30
768     ret = bt_gatt_server_start();
769     if (0 != ret)
770     {
771         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_start failed with ret[%s]",
772                 CALEGetErrorMsg(ret));
773         return CA_STATUS_FAILED;
774     }
775 #endif
776
777 #ifdef BLE_TIZEN_30
778     ret = bt_gatt_server_set_write_value_requested_cb(g_gattWriteCharPath,
779 #else
780     ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath,
781 #endif
782                                               CALEGattRemoteCharacteristicWriteCb, NULL);
783
784     if (0 != ret)
785     {
786         OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]",
787                   CALEGetErrorMsg(ret));
788         return CA_STATUS_FAILED;
789     }
790
791     OIC_LOG(DEBUG, TAG, "OUT");
792     return CA_STATUS_OK;
793 }
794
795 CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID,
796                                                const char *charValue, int charValueLen, bool read)
797 {
798
799     OIC_LOG(DEBUG, TAG, "IN");
800
801     int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
802     int properties;
803     if (read)
804     {
805         properties = BT_GATT_PROPERTY_INDICATE | BT_GATT_PROPERTY_READ;
806     }
807     else
808     {
809         properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ;
810     }
811
812     bt_gatt_h charPath = NULL;
813
814     int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue,
815                                             charValueLen, &charPath);
816
817     if (0 != ret || NULL == charPath)
818     {
819         OIC_LOG_V(ERROR, TAG,
820                   "bt_gatt_add_characteristic  failed with ret [%s]", CALEGetErrorMsg(ret));
821         return CA_STATUS_FAILED;
822     }
823
824     OIC_LOG_V(DEBUG, TAG,
825               "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath);
826
827     if (read)
828     {
829 #ifdef BLE_TIZEN_30
830         ret = bt_gatt_server_set_characteristic_notification_state_change_cb(charPath,
831                                                                              CALENotificationCb,
832                                                                              NULL);
833 #else
834         ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL);
835 #endif
836         if (0 != ret)
837         {
838             OIC_LOG_V(ERROR, TAG,
839 #ifdef BLE_TIZEN_30
840                       "bt_gatt_server_set_characteristic_notification_state_change_cb failed with ret[%s]",
841 #else
842                       "bt_gatt_server_set_notification_state_change_cb  failed with ret[%s]",
843 #endif
844                       CALEGetErrorMsg(ret));
845             return CA_STATUS_FAILED;
846         }
847     }
848
849     ret =  bt_gatt_service_add_characteristic(svcPath, charPath);
850     if (0 != ret)
851     {
852         OIC_LOG_V(ERROR, TAG,
853                   "bt_gatt_service_add_characteristic  failed with ret[%s]",
854                   CALEGetErrorMsg(ret));
855         return CA_STATUS_FAILED;
856     }
857
858     oc_mutex_lock(g_leCharacteristicMutex);
859
860     /**
861       * NOTE : Currently this sequence of adding characterstic works both on android and tizen.
862       * With previous logic it was faling on android in some devices giving wrong attribute
863       * handle error. This issue needs to be fixed in Android BT layer but we have applied
864       * workaround for now so that it should work with both Android and Tizen devices.
865       */
866     if (read)
867     {
868             g_gattReadCharPath = charPath;
869     } else {
870         char desc_value[2] = {0, 0};  // Notification enabled.
871         bt_gatt_h descriptor = NULL;
872         permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
873         ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, permissions,
874                                         desc_value, sizeof(desc_value),
875                                         &descriptor);
876         if (0 != ret)
877         {
878             oc_mutex_unlock(g_leCharacteristicMutex);
879             OIC_LOG_V(ERROR, TAG,
880                       "bt_gatt_descriptor_create  failed with ret[%s]",
881                       CALEGetErrorMsg(ret));
882             return CA_STATUS_FAILED;
883         }
884
885         ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor);
886         if (0 != ret)
887         {
888             oc_mutex_unlock(g_leCharacteristicMutex);
889             OIC_LOG_V(ERROR, TAG,
890                       "bt_gatt_characteristic_add_descriptor  failed with ret[%s]",
891                       CALEGetErrorMsg(ret));
892             return CA_STATUS_FAILED;
893         }
894         g_gattWriteCharPath = charPath;
895     }
896
897     oc_mutex_unlock(g_leCharacteristicMutex);
898
899     OIC_LOG(DEBUG, TAG, "OUT");
900     return CA_STATUS_OK;
901 }
902
903 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue,
904                                                uint32_t charValueLen)
905 {
906     OIC_LOG(DEBUG, TAG, "IN");
907
908     VERIFY_NON_NULL(charValue, TAG, "charValue");
909     VERIFY_NON_NULL(address, TAG, "address");
910
911     OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address);
912
913     oc_mutex_lock(g_leCharacteristicMutex);
914
915     oc_mutex_lock(g_LEClientListMutex);
916     if (CA_STATUS_FAILED == CAIsLEClientInfoInList(g_LEClientList, address))
917     {
918         OIC_LOG_V(ERROR, TAG, "%s device is not connected", address);
919         oc_mutex_unlock(g_LEClientListMutex);
920         oc_mutex_unlock(g_leCharacteristicMutex);
921         return CA_STATUS_FAILED;
922     }
923     oc_mutex_unlock(g_LEClientListMutex);
924
925     if (NULL  == g_gattReadCharPath)
926     {
927         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
928         oc_mutex_unlock(g_leCharacteristicMutex);
929         return CA_STATUS_FAILED;
930     }
931
932     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
933     if (0 != ret)
934     {
935         OIC_LOG_V(ERROR, TAG,
936                   "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret));
937         oc_mutex_unlock(g_leCharacteristicMutex);
938         return CA_STATUS_FAILED;
939     }
940
941 #ifdef BLE_TIZEN_30
942     ret = bt_gatt_server_notify_characteristic_changed_value(g_gattReadCharPath,
943                                                              CALEServerNotificationSentCB,
944                                                              address, NULL);
945 #else
946     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
947                                 NULL);
948 #endif
949
950     if (0 != ret)
951     {
952         OIC_LOG_V(ERROR, TAG,
953 #ifdef BLE_TIZEN_30
954                   "bt_gatt_server_notify_characteristic_changed_value failed with return [%s]",
955 #else
956                   "bt_gatt_server_notify failed with return [%s]",
957 #endif
958                   CALEGetErrorMsg(ret));
959         oc_mutex_unlock(g_leCharacteristicMutex);
960         return CA_STATUS_FAILED;
961     }
962
963     oc_mutex_unlock(g_leCharacteristicMutex);
964
965     OIC_LOG(DEBUG, TAG, "OUT");
966     return CA_STATUS_OK;
967 }
968
969 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
970 {
971     OIC_LOG(DEBUG, TAG, "IN");
972
973     VERIFY_NON_NULL(charValue, TAG, "charValue");
974
975     oc_mutex_lock(g_leCharacteristicMutex);
976
977     if (NULL  == g_gattReadCharPath)
978     {
979         OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
980         oc_mutex_unlock(g_leCharacteristicMutex);
981         return CA_STATUS_FAILED;
982     }
983
984     int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
985     if (0 != ret)
986     {
987         OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret));
988         oc_mutex_unlock(g_leCharacteristicMutex);
989         return CA_STATUS_FAILED;
990     }
991
992 #ifdef BLE_TIZEN_30
993     ret = bt_gatt_server_notify_characteristic_changed_value(g_gattReadCharPath,
994                                                              CALEServerNotificationSentCB,
995                                                              NULL, NULL);
996 #else
997     ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
998                                 NULL);
999 #endif
1000     if (0 != ret)
1001     {
1002         OIC_LOG_V(ERROR, TAG,
1003 #ifdef BLE_TIZEN_30
1004                   "bt_gatt_server_notify_characteristic_changed_value failed with return[%s]",
1005 #else
1006                   "bt_gatt_server_notify failed with return[%s]",
1007 #endif
1008                   CALEGetErrorMsg(ret));
1009         oc_mutex_unlock(g_leCharacteristicMutex);
1010         return CA_STATUS_FAILED;
1011     }
1012
1013     oc_mutex_unlock(g_leCharacteristicMutex);
1014
1015     OIC_LOG(DEBUG, TAG, "OUT");
1016     return CA_STATUS_OK;
1017 }
1018
1019 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
1020 {
1021     OIC_LOG(DEBUG, TAG, "IN");
1022
1023     oc_mutex_lock(g_leReqRespCbMutex);
1024     g_leServerDataReceivedCallback = callback;
1025     oc_mutex_unlock(g_leReqRespCbMutex);
1026
1027     OIC_LOG(DEBUG, TAG, "OUT");
1028 }
1029
1030 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
1031 {
1032     g_serverErrorCallback = callback;
1033 }
1034
1035 bool CALEServerIsConnected(const char* address)
1036 {
1037     (void)address;
1038     //@Todo
1039     return true;
1040 }
1041
1042 uint16_t CALEServerGetMtuSize(const char* address)
1043 {
1044     OIC_LOG(DEBUG, TAG, "IN");
1045     VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
1046
1047     unsigned int mtu = CA_DEFAULT_BLE_MTU_SIZE;
1048     int ret = 0;
1049     unsigned int cached_mtu;
1050
1051     oc_mutex_lock(g_LEClientListMutex);
1052     cached_mtu  = CAClientInfoGetMTUSize(g_LEClientList, address);
1053     if (cached_mtu > 0 && cached_mtu > CA_BLE_MTU_HEADER_SIZE)
1054     {
1055         OIC_LOG_V(INFO, TAG, "Cached MTU Size is %d",cached_mtu);
1056         oc_mutex_unlock(g_LEClientListMutex);
1057         return cached_mtu -CA_BLE_MTU_HEADER_SIZE;
1058     }
1059
1060 #ifdef BLE_TIZEN_55
1061     ret = bt_gatt_server_get_device_mtu(address, &mtu);
1062     if (0 != ret)
1063     {
1064         OIC_LOG_V(ERROR, TAG,
1065                   "bt_gatt_server_get_device_mtu failed with return [%s]", CALEGetErrorMsg(ret));
1066         return CA_DEFAULT_BLE_MTU_SIZE;
1067     }
1068 #else
1069 #ifdef BLE_TIZEN_40
1070     bt_gatt_client_h client = NULL;
1071     ret = bt_gatt_client_create(address, &client);
1072     if (0 != ret)
1073     {
1074         OIC_LOG_V(ERROR, TAG,
1075                   "bt_gatt_client_create failed with return [%s]", CALEGetErrorMsg(ret));
1076         oc_mutex_unlock(g_LEClientListMutex);
1077         return CA_DEFAULT_BLE_MTU_SIZE;
1078     }
1079
1080     ret = bt_gatt_client_get_att_mtu(client, &mtu);
1081     if (0 != ret)
1082     {
1083         OIC_LOG_V(ERROR, TAG,
1084                   "bt_gatt_client_get_att_mtu failed with return [%s]", CALEGetErrorMsg(ret));
1085         oc_mutex_unlock(g_LEClientListMutex);
1086         return CA_DEFAULT_BLE_MTU_SIZE;
1087     }
1088
1089     ret = bt_gatt_client_destroy(client);
1090     if (0 != ret)
1091     {
1092         OIC_LOG_V(ERROR, TAG,
1093                   "bt_gatt_client_destroy failed with return [%s]", CALEGetErrorMsg(ret));
1094         oc_mutex_unlock(g_LEClientListMutex);
1095         return CA_DEFAULT_BLE_MTU_SIZE;
1096     }
1097 #else
1098     ret = bt_device_get_att_mtu(address, &mtu);
1099     if (0 != ret)
1100     {
1101         OIC_LOG_V(ERROR, TAG,
1102                   "bt_device_get_att_mtu failed with return [%s]", CALEGetErrorMsg(ret));
1103         return CA_DEFAULT_BLE_MTU_SIZE;
1104     }
1105 #endif // BLE_TIZEN_40
1106 #endif // BLE_TIZEN_55
1107
1108     ret  = CAClientInfoUpdateMTUSize(g_LEClientList, address,mtu);
1109     if (CA_STATUS_OK != ret)
1110     {
1111         OIC_LOG(ERROR, TAG, "CAClientInfoUpdateMTUSize Update failed");
1112         oc_mutex_unlock(g_LEClientListMutex);
1113         return CA_DEFAULT_BLE_MTU_SIZE;
1114     }
1115
1116     oc_mutex_unlock(g_LEClientListMutex);
1117     OIC_LOG_V(INFO, TAG, "mtu size(including header) from bt_device_get_att_mtu is %d", mtu);
1118     OIC_LOG(DEBUG, TAG, "OUT");
1119     return mtu - CA_BLE_MTU_HEADER_SIZE;
1120 }