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