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