1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "caleserver.h"
23 #include "cacommonutil.h"
25 #include "caqueueingthread.h"
26 #include "cagattservice.h"
27 #include "oic_string.h"
28 #include "oic_malloc.h"
30 #include "caadapterutils.h"
33 * Logging tag for module name
35 #define TAG "OIC_CA_LE_SERVER_VD"
38 * The handle of the OIC server.
40 static bt_gatt_server_h g_gattServer = NULL;
43 * The handle of the OIC service.
45 static bt_gatt_h g_gattSvcPath = NULL;
48 * The handle of the OIC read characteristics.
50 static bt_gatt_h g_gattReadCharPath = NULL;
53 * The handle of the OIC write characteristics.
55 static bt_gatt_h g_gattWriteCharPath = NULL;
58 * The handle to control Bluetooth LE advertising.
60 static bt_advertiser_h g_hAdvertiser = NULL;
63 * Callback register with LE adapter. This callback is called on reception of any
64 * data from the remote device.
66 static CABLEDataReceivedCallback g_leServerDataReceivedCallback = NULL;
69 * Callback to notify any error in LE adapter.
71 static CABLEErrorHandleCallback g_serverErrorCallback = NULL;
74 * To keep the state of GATT server if started or not.
76 static bool g_isLEGattServerStarted = false;
79 * Mutex to synchronize the calls to start and stop server.
81 static oc_mutex g_leServerStateMutex = NULL;
84 * Mutex to synchronize writing operations on the characteristics.
86 static oc_mutex g_leCharacteristicMutex = NULL;
89 * Mutex to synchronize to creation of OIC service.
91 static oc_mutex g_leServiceMutex = NULL;
94 * Mutex to synchronize access to the requestResponse callback to be called
95 * when the data needs to be sent from GATTClient.
97 static oc_mutex g_leReqRespCbMutex = NULL;
100 * Mutex to synchronize the task to be pushed to thread pool.
102 static oc_mutex g_leServerThreadPoolMutex = NULL;
105 * Reference to threadpool.
107 static ca_thread_pool_t g_leServerThreadPool = NULL;
110 * GmainLoop to manage the threads to receive the callback from the platfrom.
112 static GMainLoop *g_eventLoop = NULL;
115 * This contains the list of OIC clients connected to the server.
117 static LEClientInfoList *g_LEClientList = NULL;
120 * Mutex to synchronize access to LE ClientList.
122 static oc_mutex g_LEClientListMutex = NULL;
124 void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddress)
126 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address");
128 CAResult_t res = CA_STATUS_OK;
131 OIC_LOG_V(DEBUG, TAG, "Connected to [%s]", remoteAddress);
132 char *addr = OICStrdup(remoteAddress);
133 oc_mutex_lock(g_LEClientListMutex);
134 res = CAAddLEClientInfoToList(&g_LEClientList, addr);
135 if (CA_STATUS_OK != res)
137 OIC_LOG(ERROR, TAG, "CAAddLEClientInfoToList failed");
138 oc_mutex_unlock(g_LEClientListMutex);
142 oc_mutex_unlock(g_LEClientListMutex);
145 * TV Easysetup does not use IoTivity BLE advertisement.
148 // res = CALEStopAdvertise();
149 // if (CA_STATUS_OK != res)
151 // OIC_LOG_V(ERROR, TAG, "Failed to stop advertising [%d]", res);
157 OIC_LOG_V(DEBUG, TAG, "Disconnected from [%s]", remoteAddress);
158 oc_mutex_lock(g_LEClientListMutex);
159 CARemoveLEClientInfoFromList(&g_LEClientList, remoteAddress);
160 oc_mutex_unlock(g_LEClientListMutex);
163 * TV Easysetup does not use IoTivity BLE advertisement.
166 // res = CALEStartAdvertise();
167 // if (CA_STATUS_OK != res)
169 // OIC_LOG_V(ERROR, TAG, "Failed to start advertising [%d]", res);
176 void CALEServerNotificationSentCB(int result, const char *remote_address, bt_gatt_server_h server,
177 bt_gatt_h characteristic, bool completed, void *user_data)
179 void CALEServerNotificationSentCB(int result, char *remote_address, bt_gatt_server_h server,
180 bt_gatt_h characteristic, bool completed, void *user_data)
184 (void)characteristic;
188 OIC_LOG_V(DEBUG, TAG, "Notification to the device[%s] result[%d]", remote_address, result);
191 CAResult_t CAStartLEGattServer()
193 OIC_LOG(DEBUG, TAG, "IN");
195 oc_mutex_lock(g_leServerStateMutex);
196 if (true == g_isLEGattServerStarted)
198 OIC_LOG(ERROR, TAG, "Gatt Server is already running");
199 oc_mutex_unlock(g_leServerStateMutex);
203 CAResult_t ret = CAInitLEGattServer();
204 if (CA_STATUS_OK != ret)
206 OIC_LOG_V(ERROR, TAG, "CAInitLEGattServer failed[%d]", ret);
207 oc_mutex_unlock(g_leServerStateMutex);
208 CATerminateLEGattServer();
209 return CA_STATUS_FAILED;
212 ret = CAAddNewLEServiceInGattServer(CA_GATT_SERVICE_UUID);
213 if (CA_STATUS_OK != ret)
215 OIC_LOG_V(ERROR, TAG, "CAAddNewLEServiceInGattServer failed[%d]", ret);
216 oc_mutex_unlock(g_leServerStateMutex);
217 CATerminateLEGattServer();
218 return CA_STATUS_FAILED;
221 static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID;
222 char charReadValue[] = {33, 44, 55, 66}; // These are initial random values
224 // For Read Characteristics.
225 ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue,
226 sizeof(charReadValue), true);
227 if (CA_STATUS_OK != ret)
229 OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
230 oc_mutex_unlock(g_leServerStateMutex);
231 CATerminateLEGattServer();
232 return CA_STATUS_FAILED;
235 static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID;
236 char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
239 ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue,
240 sizeof(charWriteValue), false); // For Write Characteristics.
241 if (CA_STATUS_OK != ret )
243 OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret);
244 oc_mutex_unlock(g_leServerStateMutex);
245 CATerminateLEGattServer();
246 return CA_STATUS_FAILED;
249 ret = CARegisterLEServicewithGattServer(g_gattSvcPath);
250 if (CA_STATUS_OK != ret )
252 OIC_LOG_V(ERROR, TAG, "CARegisterLEServicewithGattServer failed[%d]", ret);
253 oc_mutex_unlock(g_leServerStateMutex);
254 CATerminateLEGattServer();
255 return CA_STATUS_FAILED;
259 * TV Easysetup does not use IoTivity BLE advertisement.
262 // ret = CALEStartAdvertise();
263 // if (CA_STATUS_OK != ret)
265 // OIC_LOG_V(ERROR, TAG, "CALEStartAdvertise failed[%d]", ret);
266 // oc_mutex_unlock(g_leServerStateMutex);
267 // CATerminateLEGattServer();
268 // return CA_STATUS_FAILED;
271 g_isLEGattServerStarted = true;
273 oc_mutex_unlock(g_leServerStateMutex);
275 OIC_LOG(DEBUG, TAG, "OUT");
279 void CALENotificationCb(bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle,
286 OIC_LOG(DEBUG, TAG, "IN");
289 OIC_LOG(DEBUG, TAG, "Notification is subscribed by the client");
290 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
291 true, "notifyChar success");
295 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
296 false, "notifyChar failure");
298 OIC_LOG(DEBUG, TAG, "OUT");
301 CAResult_t CALEStartAdvertise()
303 OIC_LOG(DEBUG, TAG, "IN");
305 CAResult_t res = CALEStartAdvertiseImpl(CA_GATT_SERVICE_UUID);
306 if (CA_STATUS_OK != res)
308 OIC_LOG_V(ERROR, TAG, "CALEStartAdvertiseImpl failed[%d]", res);
311 OIC_LOG(DEBUG, TAG, "OUT");
315 CAResult_t CALEStartAdvertiseImpl(const char *serviceUUID)
317 OIC_LOG(DEBUG, TAG, "IN");
319 int res = bt_adapter_le_create_advertiser(&g_hAdvertiser);
320 if (NULL == g_hAdvertiser || BT_ERROR_NONE != res)
322 OIC_LOG_V(ERROR, TAG, "g_hAdvertiser is NULL/ Result is %d", res);
323 return CA_STATUS_FAILED;
326 res = bt_adapter_le_add_advertising_service_uuid(g_hAdvertiser,
327 BT_ADAPTER_LE_PACKET_ADVERTISING,
329 if (BT_ERROR_NONE != res)
331 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_add_advertising_service_uuid failed with ret[%s]",
332 CALEGetErrorMsg(res));
333 return CA_STATUS_FAILED;
336 res = bt_adapter_le_set_advertising_device_name(g_hAdvertiser,
337 BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true);
338 if (BT_ERROR_NONE != res)
340 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_set_advertising_device_name failed with ret[%s]",
341 CALEGetErrorMsg(res));
342 return CA_STATUS_FAILED;
345 res = bt_adapter_le_start_advertising_new(g_hAdvertiser, NULL, NULL);
346 if (BT_ERROR_NONE != res)
348 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_advertising_new failed with ret[%s]",
349 CALEGetErrorMsg(res));
350 return CA_STATUS_FAILED;
353 OIC_LOG(DEBUG, TAG, "OUT");
357 CAResult_t CALEStopAdvertise()
359 OIC_LOG(DEBUG, TAG, "IN");
360 if (NULL != g_hAdvertiser)
362 int ret = bt_adapter_le_stop_advertising(g_hAdvertiser);
365 OIC_LOG_V(ERROR, TAG,
366 "bt_adapter_le_stop_advertising failed with ret[%s]", CALEGetErrorMsg(ret));
369 ret = bt_adapter_le_destroy_advertiser(g_hAdvertiser);
372 OIC_LOG_V(ERROR, TAG,
373 "bt_adapter_le_destroy_advertiser failed with ret[%s]", CALEGetErrorMsg(ret));
375 g_hAdvertiser = NULL;
379 OIC_LOG(ERROR, TAG, "Advertising is not running");
380 return CA_STATUS_FAILED;
383 OIC_LOG(DEBUG, TAG, "OUT");
387 CAResult_t CAStopLEGattServer()
389 OIC_LOG(DEBUG, TAG, "IN");
391 oc_mutex_lock(g_leServerStateMutex);
393 if (false == g_isLEGattServerStarted)
395 OIC_LOG(ERROR, TAG, "Gatt Server is not running to stop");
396 oc_mutex_unlock(g_leServerStateMutex);
400 g_isLEGattServerStarted = false;
402 oc_mutex_lock(g_LEClientListMutex);
403 CADisconnectAllClient(g_LEClientList);
404 g_LEClientList = NULL;
405 oc_mutex_unlock(g_LEClientListMutex);
408 * TV Easysetup does not use IoTivity BLE advertisement.
411 // CAResult_t res = CALEStopAdvertise();
413 // OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res);
416 CAResult_t res = CADeInitLEGattServer();
417 if (CA_STATUS_OK != res)
419 OIC_LOG_V(ERROR, TAG, "CADeInitLEGattService failed with ret[%d]", res);
422 GMainContext *context_event_loop = NULL;
423 // Required for waking up the thread which is running in gmain loop
424 if (NULL != g_eventLoop)
426 context_event_loop = g_main_loop_get_context(g_eventLoop);
428 if (context_event_loop)
430 OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %p", (void *)context_event_loop);
431 g_main_context_wakeup(context_event_loop);
433 // Kill g main loops and kill threads
434 g_main_loop_quit(g_eventLoop);
440 OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
443 oc_mutex_unlock(g_leServerStateMutex);
445 OIC_LOG(DEBUG, TAG, "OUT");
449 CAResult_t CAInitializeLEGattServer()
451 OIC_LOG(DEBUG, TAG, "IN");
453 CAResult_t ret = CAInitGattServerMutexVariables();
454 if (CA_STATUS_OK != ret )
456 OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!");
457 CATerminateGattServerMutexVariables();
458 return CA_SERVER_NOT_STARTED;
460 OIC_LOG(DEBUG, TAG, "OUT");
464 void CATerminateLEGattServer()
466 OIC_LOG(DEBUG, TAG, "IN");
468 // Service and characteristics path will be freed by the platform.
469 oc_mutex_lock(g_leServiceMutex);
470 g_gattSvcPath = NULL;
471 oc_mutex_unlock(g_leServiceMutex);
473 oc_mutex_lock(g_leCharacteristicMutex);
474 g_gattReadCharPath = NULL;
475 g_gattWriteCharPath = NULL;
476 oc_mutex_unlock(g_leCharacteristicMutex);
478 oc_mutex_lock(g_leServerThreadPoolMutex);
479 g_leServerThreadPool = NULL;
480 oc_mutex_unlock(g_leServerThreadPoolMutex);
482 // Terminating all mutex variables.
483 CATerminateGattServerMutexVariables();
484 OIC_LOG(DEBUG, TAG, "OUT");
487 CAResult_t CAInitGattServerMutexVariables()
489 OIC_LOG(DEBUG, TAG, "IN");
490 if (NULL == g_leServerStateMutex)
492 g_leServerStateMutex = oc_mutex_new();
493 if (NULL == g_leServerStateMutex)
495 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
496 return CA_STATUS_FAILED;
500 if (NULL == g_leServiceMutex)
502 g_leServiceMutex = oc_mutex_new();
503 if (NULL == g_leServiceMutex)
505 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
506 return CA_STATUS_FAILED;
510 if (NULL == g_leCharacteristicMutex)
512 g_leCharacteristicMutex = oc_mutex_new();
513 if (NULL == g_leCharacteristicMutex)
515 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
516 return CA_STATUS_FAILED;
520 if (NULL == g_leReqRespCbMutex)
522 g_leReqRespCbMutex = oc_mutex_new();
523 if (NULL == g_leReqRespCbMutex)
525 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
526 return CA_STATUS_FAILED;
530 if (NULL == g_leServerThreadPoolMutex)
532 g_leServerThreadPoolMutex = oc_mutex_new();
533 if (NULL == g_leServerThreadPoolMutex)
535 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
536 return CA_STATUS_FAILED;
540 if (NULL == g_LEClientListMutex)
542 g_LEClientListMutex = oc_mutex_new();
543 if (NULL == g_LEClientListMutex)
545 OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
546 return CA_STATUS_FAILED;
550 OIC_LOG(DEBUG, TAG, "OUT");
554 void CATerminateGattServerMutexVariables()
556 OIC_LOG(DEBUG, TAG, "IN");
557 oc_mutex_free(g_leServerStateMutex);
558 g_leServerStateMutex = NULL;
560 oc_mutex_free(g_leServiceMutex);
561 g_leServiceMutex = NULL;
563 oc_mutex_free(g_leCharacteristicMutex);
564 g_leCharacteristicMutex = NULL;
566 oc_mutex_free(g_leReqRespCbMutex);
567 g_leReqRespCbMutex = NULL;
569 oc_mutex_free(g_leServerThreadPoolMutex);
570 g_leServerThreadPoolMutex = NULL;
572 oc_mutex_free(g_LEClientListMutex);
573 g_LEClientListMutex = NULL;
575 OIC_LOG(DEBUG, TAG, "OUT");
578 CAResult_t CAInitLEGattServer()
580 OIC_LOG(DEBUG, TAG, "IN");
582 int ret = bt_gatt_server_initialize();
585 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]",
586 CALEGetErrorMsg(ret));
587 return CA_STATUS_FAILED;
592 OIC_LOG(DEBUG, TAG, "g_gattServer is NULL. create gatt server..");
593 ret = bt_gatt_server_create(&g_gattServer);
596 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]",
597 CALEGetErrorMsg(ret));
598 bt_gatt_server_deinitialize();
599 return CA_STATUS_FAILED;
603 OIC_LOG(DEBUG, TAG, "OUT");
607 CAResult_t CADeInitLEGattServer()
609 OIC_LOG(DEBUG, TAG, "IN");
611 int ret = bt_gatt_server_unregister_all_services(g_gattServer);
614 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]",
615 CALEGetErrorMsg(ret));
616 // CONPRO-1181 continue even bt API fails during DeInit
617 //return CA_STATUS_FAILED;
620 ret = bt_gatt_server_destroy(g_gattServer);
623 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]",
624 CALEGetErrorMsg(ret));
625 // CONPRO-1181 continue even bt API fails during DeInit
626 //return CA_STATUS_FAILED;
630 ret = bt_gatt_server_deinitialize();
633 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]",
634 CALEGetErrorMsg(ret));
635 // CONPRO-1181 continue even bt API fails during DeInit
636 //return CA_STATUS_FAILED;
639 OIC_LOG(DEBUG, TAG, "OUT");
643 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
645 OIC_LOG(DEBUG, TAG, "IN");
646 oc_mutex_lock(g_leServerThreadPoolMutex);
647 g_leServerThreadPool = handle;
648 oc_mutex_unlock(g_leServerThreadPoolMutex);
649 OIC_LOG(DEBUG, TAG, "OUT");
652 CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID)
654 OIC_LOG(DEBUG, TAG, "IN");
656 VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID");
658 OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID);
660 bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY;
662 oc_mutex_lock(g_leServiceMutex);
663 int ret = bt_gatt_service_create(serviceUUID, type, &g_gattSvcPath);
666 oc_mutex_unlock(g_leServiceMutex);
667 OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]",
668 CALEGetErrorMsg(ret));
669 return CA_STATUS_FAILED;
671 oc_mutex_unlock(g_leServiceMutex);
675 OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)g_gattSvcPath);
678 OIC_LOG(DEBUG, TAG, "OUT");
683 void CALEGattRemoteCharacteristicWriteCb(const char *remoteAddress, int request_id,
684 bt_gatt_server_h server, bt_gatt_h gatt_handle,
685 bool response_needed, int offset, const char *charValue,
686 int charLen, void *userData)
688 void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server,
689 bt_gatt_h gatt_handle, int offset, char *charValue,
690 int charLen, void *userData)
697 OIC_LOG(INFO, TAG, "IN - WriteCharCB");
699 if (NULL == charValue || NULL == remoteAddress)
701 OIC_LOG(ERROR, TAG, "Param callback values are NULL");
705 OIC_LOG_V(DEBUG, TAG, "len [%d]", charLen);
707 uint8_t *data = OICMalloc(charLen);
710 OIC_LOG(ERROR, TAG, "Malloc failed!");
714 memcpy(data, charValue, charLen);
716 oc_mutex_lock(g_leReqRespCbMutex);
717 if (NULL == g_leServerDataReceivedCallback)
719 OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!");
720 oc_mutex_unlock(g_leReqRespCbMutex);
725 OIC_LOG(INFO, TAG, "Sending data up !");
726 uint32_t sentLength = 0;
727 g_leServerDataReceivedCallback(remoteAddress, data, charLen,
729 oc_mutex_unlock(g_leReqRespCbMutex);
734 OIC_LOG_V(INFO, TAG, "response_needed flag : %d", response_needed);
737 OIC_LOG(INFO, TAG, "send response to remote client");
738 bt_gatt_server_send_response(request_id,
739 BT_GATT_REQUEST_TYPE_WRITE, offset,
740 BT_ERROR_NONE, NULL, 0);
744 OIC_LOG(INFO, TAG, "OUT - WriteCharCB");
747 CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath)
749 OIC_LOG(DEBUG, TAG, "IN");
751 VERIFY_NON_NULL(svcPath, TAG, "svcPath");
753 OIC_LOG_V(DEBUG, TAG, "svcPath: %s", (char *)svcPath);
755 int ret = bt_gatt_server_register_service(g_gattServer, svcPath);
758 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]",
759 CALEGetErrorMsg(ret));
760 return CA_STATUS_FAILED;
764 ret = bt_gatt_server_start();
767 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_start failed with ret[%s]",
768 CALEGetErrorMsg(ret));
769 return CA_STATUS_FAILED;
774 ret = bt_gatt_server_set_write_value_requested_cb(g_gattWriteCharPath,
776 ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath,
778 CALEGattRemoteCharacteristicWriteCb, NULL);
782 OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]",
783 CALEGetErrorMsg(ret));
784 return CA_STATUS_FAILED;
787 OIC_LOG(DEBUG, TAG, "OUT");
791 CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID,
792 const char *charValue, int charValueLen, bool read)
795 OIC_LOG(DEBUG, TAG, "IN");
797 int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
801 properties = BT_GATT_PROPERTY_INDICATE | BT_GATT_PROPERTY_READ;
805 properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ;
808 bt_gatt_h charPath = NULL;
810 int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue,
811 charValueLen, &charPath);
813 if (0 != ret || NULL == charPath)
815 OIC_LOG_V(ERROR, TAG,
816 "bt_gatt_add_characteristic failed with ret [%s]", CALEGetErrorMsg(ret));
817 return CA_STATUS_FAILED;
820 OIC_LOG_V(DEBUG, TAG,
821 "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath);
826 ret = bt_gatt_server_set_characteristic_notification_state_change_cb(charPath,
830 ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL);
834 OIC_LOG_V(ERROR, TAG,
836 "bt_gatt_server_set_characteristic_notification_state_change_cb failed with ret[%s]",
838 "bt_gatt_server_set_notification_state_change_cb failed with ret[%s]",
840 CALEGetErrorMsg(ret));
841 return CA_STATUS_FAILED;
845 ret = bt_gatt_service_add_characteristic(svcPath, charPath);
848 OIC_LOG_V(ERROR, TAG,
849 "bt_gatt_service_add_characteristic failed with ret[%s]",
850 CALEGetErrorMsg(ret));
851 return CA_STATUS_FAILED;
854 oc_mutex_lock(g_leCharacteristicMutex);
858 g_gattReadCharPath = charPath;
862 char desc_value[2] = {0, 0}; // Notification enabled.
863 bt_gatt_h descriptor = NULL;
864 permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE;
865 ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, permissions,
866 desc_value, sizeof(desc_value),
870 oc_mutex_unlock(g_leCharacteristicMutex);
871 OIC_LOG_V(ERROR, TAG,
872 "bt_gatt_descriptor_create failed with ret[%s]",
873 CALEGetErrorMsg(ret));
874 return CA_STATUS_FAILED;
877 ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor);
880 oc_mutex_unlock(g_leCharacteristicMutex);
881 OIC_LOG_V(ERROR, TAG,
882 "bt_gatt_characteristic_add_descriptor failed with ret[%s]",
883 CALEGetErrorMsg(ret));
884 return CA_STATUS_FAILED;
886 g_gattWriteCharPath = charPath;
889 oc_mutex_unlock(g_leCharacteristicMutex);
891 OIC_LOG(DEBUG, TAG, "OUT");
895 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue,
896 uint32_t charValueLen)
898 OIC_LOG(DEBUG, TAG, "IN");
900 VERIFY_NON_NULL(charValue, TAG, "charValue");
901 VERIFY_NON_NULL(address, TAG, "address");
903 OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address);
905 oc_mutex_lock(g_leCharacteristicMutex);
907 oc_mutex_lock(g_LEClientListMutex);
908 if (CA_STATUS_FAILED == CAIsLEClientInfoInList(g_LEClientList, address))
910 OIC_LOG_V(ERROR, TAG, "%s device is not connected", address);
911 oc_mutex_unlock(g_LEClientListMutex);
912 oc_mutex_unlock(g_leCharacteristicMutex);
913 return CA_STATUS_FAILED;
915 oc_mutex_unlock(g_LEClientListMutex);
917 if (NULL == g_gattReadCharPath)
919 OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
920 oc_mutex_unlock(g_leCharacteristicMutex);
921 return CA_STATUS_FAILED;
924 int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
927 OIC_LOG_V(ERROR, TAG,
928 "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret));
929 oc_mutex_unlock(g_leCharacteristicMutex);
930 return CA_STATUS_FAILED;
934 ret = bt_gatt_server_notify_characteristic_changed_value(g_gattReadCharPath,
935 CALEServerNotificationSentCB,
938 ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
944 OIC_LOG_V(ERROR, TAG,
946 "bt_gatt_server_notify_characteristic_changed_value failed with return [%s]",
948 "bt_gatt_server_notify failed with return [%s]",
950 CALEGetErrorMsg(ret));
951 oc_mutex_unlock(g_leCharacteristicMutex);
952 return CA_STATUS_FAILED;
955 oc_mutex_unlock(g_leCharacteristicMutex);
957 OIC_LOG(DEBUG, TAG, "OUT");
961 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
963 OIC_LOG(DEBUG, TAG, "IN");
965 VERIFY_NON_NULL(charValue, TAG, "charValue");
967 oc_mutex_lock(g_leCharacteristicMutex);
969 if (NULL == g_gattReadCharPath)
971 OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL");
972 oc_mutex_unlock(g_leCharacteristicMutex);
973 return CA_STATUS_FAILED;
976 int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen);
979 OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret));
980 oc_mutex_unlock(g_leCharacteristicMutex);
981 return CA_STATUS_FAILED;
985 ret = bt_gatt_server_notify_characteristic_changed_value(g_gattReadCharPath,
986 CALEServerNotificationSentCB,
989 ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB,
994 OIC_LOG_V(ERROR, TAG,
996 "bt_gatt_server_notify_characteristic_changed_value failed with return[%s]",
998 "bt_gatt_server_notify failed with return[%s]",
1000 CALEGetErrorMsg(ret));
1001 oc_mutex_unlock(g_leCharacteristicMutex);
1002 return CA_STATUS_FAILED;
1005 oc_mutex_unlock(g_leCharacteristicMutex);
1007 OIC_LOG(DEBUG, TAG, "OUT");
1008 return CA_STATUS_OK;
1011 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
1013 OIC_LOG(DEBUG, TAG, "IN");
1015 oc_mutex_lock(g_leReqRespCbMutex);
1016 g_leServerDataReceivedCallback = callback;
1017 oc_mutex_unlock(g_leReqRespCbMutex);
1019 OIC_LOG(DEBUG, TAG, "OUT");
1022 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
1024 g_serverErrorCallback = callback;
1027 bool CALEServerIsConnected(const char* address)
1034 uint16_t CALEServerGetMtuSize(const char* address)
1036 OIC_LOG(DEBUG, TAG, "IN");
1037 VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
1040 int ret = bt_device_get_att_mtu(address, &mtu);
1043 OIC_LOG_V(ERROR, TAG,
1044 "bt_device_get_att_mtu failed with return [%s]", CALEGetErrorMsg(ret));
1045 return CA_DEFAULT_BLE_MTU_SIZE;
1047 OIC_LOG_V(INFO, TAG, "mtu size(including header) from bt_device_get_att_mtu is %d", mtu);
1048 OIC_LOG(DEBUG, TAG, "OUT");
1049 return mtu - CA_BLE_MTU_HEADER_SIZE;