From: DoHyun Pyun Date: Wed, 20 Sep 2017 09:25:13 +0000 (+0900) Subject: Add the GATT Relay feature for the dual stack adaptation X-Git-Tag: submit/tizen_4.0/20170922.014023^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=19e7c6271fbcc1043e8fc372c2d0f35d9f1b7ab8;p=platform%2Fcore%2Fapi%2Fbluetooth.git Add the GATT Relay feature for the dual stack adaptation Change-Id: If7830aacb1f45d725616d06216af51ee8452b32b Signed-off-by: DoHyun Pyun --- diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index bba2f2f..3290c4c 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -28,6 +28,10 @@ #include #include +#ifdef TIZEN_FEATURE_GATT_RELAY +#include +#endif + #include "bluetooth.h" #include "bluetooth_internal.h" @@ -324,6 +328,9 @@ typedef struct { void *parent; char *path; char *uuid; +#ifdef TIZEN_FEATURE_GATT_RELAY + int handle; +#endif } bt_gatt_common_s; typedef struct { @@ -332,7 +339,10 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifdef TIZEN_FEATURE_GATT_RELAY + int handle; + int numhandles; +#endif bool is_included_service; bt_gatt_service_type_e service_type; @@ -350,7 +360,10 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifdef TIZEN_FEATURE_GATT_RELAY + int handle; + bluetooth_device_address_t address; +#endif int permissions; int properties; bt_gatt_write_type_e write_type; @@ -390,7 +403,9 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifdef TIZEN_FEATURE_GATT_RELAY + int handle; +#endif int permissions; bt_gatt_server_write_value_requested_cb write_value_requested_cb; @@ -758,6 +773,15 @@ int _bt_gatt_client_update_characteristics(bt_gatt_h service); int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic); +#ifdef TIZEN_FEATURE_GATT_RELAY +/** + * @internal + * @brief Since the GATT Server call back and event proxy call backs have different prototype it is wrapper function. + */ +void _bt_gatt_server_event_proxy(int event, gatt_server_event_param_t *param, void *user_data); +#endif + + /** * @ingroup CAPI_NETWORK_BLUETOOTH_LE_MODULE * @brief Reads the maximum data length of LE packets supported by the controller. diff --git a/packaging/capi-network-bluetooth.spec b/packaging/capi-network-bluetooth.spec index 0cb44c1..7ffaa8b 100644 --- a/packaging/capi-network-bluetooth.spec +++ b/packaging/capi-network-bluetooth.spec @@ -52,6 +52,10 @@ export CFLAGS="$CFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPP export CXXFLAGS="$CXXFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT" export FFLAGS="$FFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT" +#export CFLAGS="$CFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY" +#export CXXFLAGS="$CXXFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY" +#export FFLAGS="$FFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY" + %ifarch aarch64 echo arch64 export CFLAGS+=" -DARCH64" diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 31ff603..6a5892d 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -635,6 +635,193 @@ static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **de return BT_ERROR_NONE; } +#ifdef TIZEN_FEATURE_GATT_RELAY +/* Search for handle */ +static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb(int att_handle, bt_gatt_server_h *server, + bt_gatt_h *gatt_handle, void **user_data) +{ + const GSList *gatt_server_list = NULL; + const GSList *l1, *l2, *l3, *l4; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv) + return NULL; + + for (l2 = serv->services; l2 != NULL; l2 = l2->next) { + bt_gatt_service_s *svc = l2->data; + for (l3 = svc->characteristics; l3 != NULL; l3 = l3->next) { + bt_gatt_characteristic_s *chr = l3->data; + + if (chr) { + if (chr->handle == att_handle) { + if (chr->read_requested_cb) { + BT_INFO("GATT Server: Handle search match found! Its a characteristic: UUID [%s]", chr->uuid); + *user_data = chr->read_requested_user_data; + *gatt_handle = chr; + *server = serv; + return chr->read_requested_cb; + } else + return NULL; + } else { + for (l4 = chr->descriptors; l4 != NULL; l4 = l4->next) { + bt_gatt_descriptor_s *desc = l4->data; + + if (desc && desc->handle == att_handle) { + if (desc->read_requested_cb) { + *user_data = desc->read_requested_user_data; + *gatt_handle = desc; + *server = serv; + BT_INFO("GATT Server: Handle search match found! Its a Desc UUID [%s]", desc->uuid); + return desc->read_requested_cb; + } else + return NULL; + } + } + } + } + } + } + } + return NULL; +} + +static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_change_cb(int att_handle, bt_gatt_h *server, + bt_gatt_h *gatt_handle, void **user_data) +{ + const GSList *gatt_server_list = NULL; + const GSList *l1, *l2, *l3, *l4; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv) + return NULL; + + for (l2 = serv->services; l2 != NULL; l2 = l2->next) { + bt_gatt_service_s *svc = l2->data; + for (l3 = svc->characteristics; l3 != NULL; l3 = l3->next) { + bt_gatt_characteristic_s *chr = l3->data; + + if (chr) { + if (chr->handle == att_handle) { + if (chr->write_value_requested_cb) { + BT_INFO("GATT Server: Handle search match found! Its a characteristic: UUID [%s]", chr->uuid); + *user_data = chr->write_value_requested_user_data; + *gatt_handle = chr; + *server = svc; + return chr->write_value_requested_cb; + } else + return NULL; + } else { + for (l4 = chr->descriptors; l4 != NULL; l4 = l4->next) { + bt_gatt_descriptor_s *desc = l4->data; + + if (desc && desc->handle == att_handle) { + if (desc->write_value_requested_cb) { + *user_data = desc->write_value_requested_user_data; + *gatt_handle = desc; + *server = svc; + BT_INFO("GATT Server: Handle search match found! Its a Desc UUID [%s]", desc->uuid); + return desc->write_value_requested_cb; + } else + return NULL; + } + } + } + } + } + } + } + return NULL; +} + +static bt_gatt_server_characteristic_notification_state_changed_cb + __bt_gatt_attribute_get_notification_change_cb( + bt_gatt_server_h *server, int handle, bt_gatt_h *char_handle, void **user_data) +{ + const GSList *gatt_server_list = NULL; + const GSList *l1, *l2, *l3; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv) + return NULL; + + for (l2 = serv->services; l2 != NULL; l2 = l2->next) { + bt_gatt_service_s *svc = l2->data; + + for (l3 = svc->characteristics; l3 != NULL; l3 = l3->next) { + bt_gatt_characteristic_s *chr = l3->data; + + if (chr && chr->handle == handle) { + if (chr->notified_cb) { + *user_data = chr->notified_user_data; + *char_handle = (bt_gatt_h*) chr; + *server = serv; + return chr->notification_changed_cb; + } else + return NULL; + } + } + } + } + return NULL; +} + +static bt_gatt_server_notification_sent_cb __bt_gatt_attribute_get_notification_completed_cb( + bt_gatt_server_h *server, int handle, bt_gatt_h *char_handle, void **user_data) +{ + const GSList *gatt_server_list = NULL; + const GSList *l1, *l2, *l3; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv) + return NULL; + + for (l2 = serv->services; l2 != NULL; l2 = l2->next) { + bt_gatt_service_s *svc = l2->data; + + for (l3 = svc->characteristics; l3 != NULL; l3 = l3->next) { + bt_gatt_characteristic_s *chr = l3->data; + + if (chr && chr->handle == handle) { + if (chr->notified_cb) { + *user_data = chr->notified_user_data; + *char_handle = (bt_gatt_h*) chr; + *server = serv; + return chr->notified_cb; + } else + return NULL; + } + } + } + } + return NULL; +} + +void _bt_gatt_server_event_proxy(int event, gatt_server_event_param_t *param, void *user_data) +{ + bluetooth_event_param_t new_param; + new_param.event = param->event; + new_param.param_data = param->param_data; + new_param.result = param->result; + new_param.user_data = NULL; + __bt_event_proxy(event, &new_param, user_data); +} +#else static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) { @@ -691,6 +878,7 @@ static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( return NULL; } + static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_change_cb( bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) { @@ -822,6 +1010,7 @@ static bt_gatt_server_notification_sent_cb __bt_gatt_attribute_get_notification_ } return NULL; } +#endif static void __bt_free_bt_device_connection_info_s(bt_device_connection_info_s *conn_info) { @@ -1064,7 +1253,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us auth_information = (bluetooth_authentication_request_info_t *)(param->param_data); _bt_convert_address_to_string(&device_addr, &auth_information->device_address); - BT_DBG("BUETOOTH_EVENT_PIN_REQUEST: name = %s address = %s", auth_information->device_name, + BT_DBG("BUETOOTH_EVENT_PIN_REQUEST: name = %s address = %s", auth_information->device_name.name, device_addr); ((bt_adapter_authentication_req_cb)bt_event_slot_container[event_index].callback) @@ -1078,7 +1267,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us auth_information = (bluetooth_authentication_request_info_t *)(param->param_data); _bt_convert_address_to_string(&device_addr, &auth_information->device_address); - BT_DBG("BLUETOOTH_EVENT_PASSKEY_REQUEST: name = %s address = %s", auth_information->device_name, + BT_DBG("BLUETOOTH_EVENT_PASSKEY_REQUEST: name = %s address = %s", auth_information->device_name.name, device_addr); ((bt_adapter_authentication_req_cb)bt_event_slot_container[event_index].callback) @@ -1970,10 +2159,48 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us param->param_data); break; case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: { +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_server_read_requested_info_t *read_req = + (bluetooth_gatt_server_read_requested_info_t *)(param->param_data); + bt_gatt_server_read_value_requested_cb cb_read; + void *user_data_read = NULL; + bt_gatt_h gatt_handle = NULL; + bt_gatt_server_h serv = NULL; + + cb_read = __bt_gatt_attribute_get_read_cb(read_req->attribute_handle, + &serv, &gatt_handle, &user_data_read); + + /* Copy data */ + _bt_convert_address_to_string(&device_addr, &read_req->device_address); + + BT_INFO("GATT Server Read Req: Addr [%s]", device_addr); + BT_INFO("GATT Server Read Req: Att handle[%d]", read_req->attribute_handle); + BT_INFO("GATT Server Read Req: Conn ID [%d]", read_req->connection_id); + BT_INFO("GATT Server Read Req: Trans ID [%d]", read_req->request_id); + BT_INFO("GATT Server Read Req: Offset [%d]", read_req->offset); + BT_INFO("GATT Server Read Req: Is Long [%d]", read_req->is_long); + + if (cb_read == NULL) { + BT_INFO("GATT Server: App has not set the Read requested callback..for the current handle"); + + bt_gatt_server_send_response(read_req->request_id, + BT_GATT_REQUEST_TYPE_READ, 0, + BLUETOOTH_ERROR_INTERNAL, NULL, 0); + + BT_INFO("GATT Server: Internal response sent for Read Request"); + return; + } + + cb_read(device_addr, read_req->request_id, serv, gatt_handle, read_req->offset, user_data_read); + + if (device_addr != NULL) + free(device_addr); +#else bt_gatt_read_req_t *read_req = param->param_data; bt_gatt_server_read_value_requested_cb cb; void *user_data = NULL; bt_gatt_h gatt_handle = NULL; + cb = __bt_gatt_attribute_get_read_cb(read_req->service_handle, read_req->att_handle, &gatt_handle, &user_data); @@ -1988,9 +2215,63 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us cb(read_req->address, read_req->req_id, read_req->service_handle, gatt_handle, read_req->offset, user_data); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED: { +#ifdef TIZEN_FEATURE_GATT_RELAY + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_WRITE_REQUESTED"); + bt_gatt_server_write_value_requested_cb cb_wr; + void *user_data_write = NULL; + bt_gatt_h gatt_handle = NULL; + bt_gatt_h server = NULL; + bluetooth_gatt_server_write_requested_info_t *write_req = + (bluetooth_gatt_server_write_requested_info_t *)(param->param_data); + + char *val = g_malloc0(write_req->length); + + memcpy(val, write_req->data.data, write_req->length); + cb_wr = __bt_gatt_attribute_get_value_change_cb(write_req->attribute_handle, + &server, &gatt_handle, &user_data_write); + + /* Copy data */ + _bt_convert_address_to_string(&device_addr, &write_req->device_address); + + BT_INFO("GATT Server Write Req: Address [%s]", device_addr); + BT_INFO("GATT Server Write Req: Att handle [%d]", write_req->attribute_handle); + BT_INFO("GATT Server Write Req: Conn ID [%d]", write_req->connection_id); + BT_INFO("GATT Server Write Req: Trans ID [%d]", write_req->request_id); + BT_INFO("GATT Server Write Req: Offset [%d]", write_req->offset); + BT_INFO("GATT Server Write Req: Length [%d]", write_req->length); + BT_INFO("GATT Server Write Req: Need Resp [%d]", write_req->need_resp); + + if (cb_wr == NULL) { + BT_INFO("GATT Server: App has not set the Write requested callback..for the current handle"); + + if (write_req->need_resp) { + BT_INFO("GATT Server: Send Response to Remote GATT client"); + + bt_gatt_server_send_response(write_req->request_id, + BT_GATT_REQUEST_TYPE_WRITE, 0, + BLUETOOTH_ERROR_INTERNAL, NULL, 0); + + BT_INFO("GATT Server: Internal response sent for Write Request"); + } + + return; + } + + cb_wr(device_addr, write_req->request_id, server, gatt_handle, + write_req->need_resp, write_req->offset, + val, write_req->length, user_data_write); + + /* Free Data */ + if (val != NULL) + g_free(val); + + if (device_addr != NULL) + free(device_addr); +#else bt_gatt_value_change_t *value_change = param->param_data; bt_gatt_server_write_value_requested_cb cb; void *user_data = NULL; @@ -2012,9 +2293,28 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us cb(value_change->address, value_change->req_id, value_change->service_handle, gatt_handle, (bool)value_change->response_needed, value_change->offset, (char *)value_change->att_value, value_change->val_len, user_data); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED: { + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED"); +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_server_notification_changed_t *notif_info = + (bluetooth_gatt_server_notification_changed_t*)(param->param_data); + + bt_gatt_server_characteristic_notification_state_changed_cb cb; + bt_gatt_server_h server_handle = NULL; + bt_gatt_h char_handle = NULL; + void *user_data_cfm = NULL; + + cb = __bt_gatt_attribute_get_notification_change_cb(&server_handle, + notif_info->handle, &char_handle, &user_data_cfm); + + if (cb == NULL) + return; + + cb(notif_info->notification, server_handle, char_handle, user_data_cfm); +#else bt_gatt_char_notify_change_t *value_change = param->param_data; bt_gatt_server_characteristic_notification_state_changed_cb cb; void *user_data = NULL; @@ -2028,9 +2328,38 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us cb(value_change->att_notify, value_change->service_handle, gatt_handle, user_data); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED: { +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_server_indicate_confirmed_info_t *cfm_info = + (bluetooth_gatt_server_indicate_confirmed_info_t*)(param->param_data); + bt_gatt_server_notification_sent_cb cb; + bt_gatt_server_h server_handle = NULL; + bt_gatt_h char_handle = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED"); + + void *user_data_cfm = NULL; + + cb = __bt_gatt_attribute_get_notification_completed_cb(&server_handle, + cfm_info->handle, &char_handle, &user_data_cfm); + + if (cb == NULL) + return; + + /* Copy data */ + _bt_convert_address_to_string(&device_addr, &cfm_info->device_address); + + cb(_bt_get_error_code(param->result), device_addr, + server_handle, char_handle, + cfm_info->completed, user_data_cfm); + + /* Free Data */ + if (device_addr != NULL) + free(device_addr); +#else bt_gatt_indicate_confirm_t *confrim_status = param->param_data; bt_gatt_server_notification_sent_cb cb; void *user_data = NULL; @@ -2044,7 +2373,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us cb(_bt_get_error_code(param->result), confrim_status->address, confrim_status->service_handle, confrim_status->att_handle, confrim_status->complete, user_data); - +#endif break; } case BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED: diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index b05bf20..66eb05a 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -24,6 +24,12 @@ #include "bluetooth_internal.h" #include "bluetooth_type_internal.h" +#ifdef TIZEN_FEATURE_GATT_RELAY +#include "bluetooth-gatt-server-api.h" +/* TODO_40 : 4.0 merge - Need to check if it is ok to use the grobal variable or not. */ +int instance_id; +#endif + #define BT_ADDR_STR_LEN 17 static GSList *gatt_client_list = NULL; @@ -922,10 +928,19 @@ static void __bt_gatt_free_service(bt_gatt_h gatt_handle) g_slist_free_full(svc->characteristics, __bt_gatt_free_characteristic); if (svc->role == BT_GATT_ROLE_SERVER) { +#ifdef TIZEN_FEATURE_GATT_RELAY + BT_INFO("GATT Server Delete Service: service handle [%d] Inst ID [%d]", svc->handle, instance_id); + ret = _bt_get_error_code(bluetooth_gatt_server_delete_service(svc->handle, instance_id)); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + } +#else ret = _bt_get_error_code(bluetooth_gatt_unregister_service(svc->path)); if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x) : Failed to unregister service", _bt_convert_error_to_string(ret), ret); +#endif } g_strfreev(svc->include_handles); @@ -1344,6 +1359,11 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; +#ifdef TIZEN_FEATURE_GATT_RELAY + int k; + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1361,6 +1381,27 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, return BT_ERROR_INVALID_PARAMETER; } +#ifdef TIZEN_FEATURE_GATT_RELAY + if (handle->role == BT_GATT_ROLE_SERVER && handle->handle) { + + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_update_value_t)); + + /* DEBUG */ + for (k = 0; k < value_length; k++) + BT_DBG("New Value[%d] = [0x%x]", k, value[k]); + + param.length = value_length; + memcpy(¶m.data.data[0], value, value_length); + + param.attribute_handle = handle->handle; + ret = _bt_get_error_code(bluetooth_gatt_server_update_characteristic(instance_id, + ¶m)); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + } +#else if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, value, value_length)); @@ -1369,7 +1410,7 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, return ret; } } - +#endif g_free(*val); *val = NULL; if (value_length > 0) @@ -1392,6 +1433,10 @@ int bt_gatt_set_int_value(bt_gatt_h gatt_handle, bt_data_type_int_e type, bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1479,8 +1524,18 @@ int bt_gatt_set_int_value(bt_gatt_h gatt_handle, bt_data_type_int_e type, } if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { +#ifdef TIZEN_FEATURE_GATT_RELAY + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_update_value_t)); + memcpy(¶m.data.data[0], *val, *val_len); + + param.length = *val_len; + param.attribute_handle = handle->handle; + ret = _bt_get_error_code(bluetooth_gatt_server_update_characteristic(instance_id, + ¶m)); +#else ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, *val, *val_len)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -1505,6 +1560,10 @@ int bt_gatt_set_float_value(bt_gatt_h gatt_handle, bt_data_type_float_e type, bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1572,8 +1631,19 @@ int bt_gatt_set_float_value(bt_gatt_h gatt_handle, bt_data_type_float_e type, } if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { +#ifdef TIZEN_FEATURE_GATT_RELAY + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_update_value_t)); + memcpy(¶m.data.data[0], *val, *val_len); + + param.length = *val_len; + param.attribute_handle = handle->handle; + + ret = _bt_get_error_code(bluetooth_gatt_server_update_characteristic(instance_id, + ¶m)); +#else ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, *val, *val_len)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -1691,10 +1761,14 @@ static bt_gatt_service_s* __bt_gatt_service_create(const char *uuid, return NULL; svc->type = BT_GATT_TYPE_SERVICE; +#ifdef TIZEN_FEATURE_GATT_RELAY + svc->uuid = _bt_convert_uuid_to_uuid128(uuid); +#else if (strlen(uuid) == 8) svc->uuid = _bt_convert_uuid_to_uuid128(uuid); else svc->uuid = strdup(uuid); +#endif if (svc->uuid == NULL) { g_free(svc); return NULL; @@ -1726,7 +1800,10 @@ int bt_gatt_service_create(const char *uuid, bt_gatt_service_type_e type, return BT_ERROR_OUT_OF_MEMORY; svc->role = BT_GATT_ROLE_SERVER; svc->is_included_service = false; - +#ifdef TIZEN_FEATURE_GATT_RELAY + BT_INFO("Current handle count of service [%d]", svc->numhandles); + svc->numhandles = 1; /* Initalize numhandles to 1 */ +#endif *service = (bt_gatt_h)svc; return BT_ERROR_NONE; @@ -1750,7 +1827,11 @@ int bt_gatt_service_add_characteristic(bt_gatt_h service, svc->characteristics = g_slist_append(svc->characteristics, chr); chr->parent = (void *)service; +#ifdef TIZEN_FEATURE_GATT_RELAY + BT_INFO("Current handle count of service [%d]", svc->numhandles); + svc->numhandles += 2; +#endif return BT_ERROR_NONE; } @@ -1773,6 +1854,11 @@ int bt_gatt_service_add_included_service(bt_gatt_h service, svc->included_services = g_slist_append(svc->included_services, included_svc); included_svc->parent = (void *)service; +#ifdef TIZEN_FEATURE_GATT_RELAY + BT_INFO("Current handle count of service [%d]", svc->numhandles); + + svc->numhandles = 1; /* Initalize numhandles to 1 */ +#endif return BT_ERROR_NONE; } @@ -1987,10 +2073,14 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, chr->type = BT_GATT_TYPE_CHARACTERISTIC; chr->role = BT_GATT_ROLE_SERVER; +#ifdef TIZEN_FEATURE_GATT_RELAY + chr->uuid = _bt_convert_uuid_to_uuid128(uuid); +#else if (strlen(uuid) == 8) chr->uuid = _bt_convert_uuid_to_uuid128(uuid); else chr->uuid = g_strdup(uuid); +#endif if (chr->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -2044,6 +2134,15 @@ int bt_gatt_characteristic_add_descriptor(bt_gatt_h characteristic, chr->descriptors = g_slist_append(chr->descriptors, desc); desc->parent = (void *)characteristic; +#ifdef TIZEN_FEATURE_GATT_RELAY +{ + bt_gatt_service_s *svc = (bt_gatt_service_s *)chr->parent; + + BT_INFO("Current handle count of service [%d]", svc->numhandles); + + svc->numhandles += 1; /* Initalize numhandles to 1 */ +} +#endif return BT_ERROR_NONE; } @@ -2251,10 +2350,15 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, desc->type = BT_GATT_TYPE_DESCRIPTOR; desc->role = BT_GATT_ROLE_SERVER; + +#ifdef TIZEN_FEATURE_GATT_RELAY + desc->uuid = _bt_convert_uuid_to_uuid128(uuid); +#else if (strlen(uuid) == 8) desc->uuid = _bt_convert_uuid_to_uuid128(uuid); else desc->uuid = g_strdup(uuid); +#endif if (desc->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -2311,7 +2415,11 @@ int bt_gatt_server_initialize(void) } if (!is_gatt_server_initialized) { +#ifdef TIZEN_FEATURE_GATT_RELAY + ret = _bt_get_error_code(bluetooth_gatt_server_init(&instance_id, _bt_gatt_server_event_proxy, NULL)); +#else ret = _bt_get_error_code(bluetooth_gatt_init()); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", @@ -2346,7 +2454,15 @@ int bt_gatt_server_deinitialize(void) g_slist_free(gatt_server_list); gatt_server_list = NULL; +#ifdef TIZEN_FEATURE_GATT_RELAY ret = _bt_get_error_code(bluetooth_gatt_deinit()); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } + + ret = _bt_get_error_code(bluetooth_gatt_server_unregister(instance_id)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", @@ -2354,6 +2470,22 @@ int bt_gatt_server_deinitialize(void) return BT_ERROR_OPERATION_FAILED; } + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } + + instance_id = -1; +#else + ret = _bt_get_error_code(bluetooth_gatt_deinit()); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } +#endif is_gatt_server_initialized = false; is_gatt_server_started = false; return BT_ERROR_NONE; @@ -2451,9 +2583,118 @@ int bt_gatt_server_set_characteristic_notification_state_change_cb(bt_gatt_h gat return BT_ERROR_NONE; } +#ifdef TIZEN_FEATURE_GATT_RELAY int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) { int ret = BT_ERROR_NONE; + bluetooth_gatt_server_attribute_params_t param; + bt_gatt_server_s *serv = (bt_gatt_server_s *)server; + bt_gatt_service_s *svc = (bt_gatt_service_s *)service; + GSList *char_l; + + BT_CHECK_GATT_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_GATT_SERVER_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(server); + BT_CHECK_INPUT_PARAMETER(service); + + if (g_slist_find(serv->services, svc)) { + BT_ERR("Already added service."); + return BT_ERROR_ALREADY_DONE; + } + + if (is_gatt_server_started) { + BT_ERR("Already Server started"); + return BT_ERROR_OPERATION_FAILED; + } + + BT_INFO("Service number of total handles [%d]", svc->numhandles); + + ret = _bt_get_error_code(bluetooth_gatt_server_add_service(svc->uuid, svc->type, + svc->numhandles, instance_id, &svc->handle)); + + BT_INFO("Service added handle [%d]", svc->handle); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + for (char_l = svc->characteristics; char_l; char_l = g_slist_next(char_l)) { + GSList *desc_l; + bt_gatt_characteristic_s *chr = char_l->data; + + /* Add Characteristic to GATT database */ + memset(¶m, 0x00, sizeof(param)); + param.permissions = chr->permissions; + param.properties = chr->properties; + param.service_handle = svc->handle; + param.instance_id = instance_id; + + BT_INFO("GATT Server Add Char: UUID [%s] permission [%d] properties [%d] service handle [%d] Inst ID [%d]", + chr->uuid, chr->permissions, chr->properties, svc->handle, instance_id); + + ret = _bt_get_error_code(bluetooth_gatt_server_add_new_characteristic(chr->uuid, ¶m, &chr->handle)); + + BT_INFO("Char added handle [%d]", chr->handle); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + goto fail; + } + + for (desc_l = chr->descriptors; desc_l; desc_l = g_slist_next(desc_l)) { + bt_gatt_descriptor_s *desc = desc_l->data; + + /* Add descriptor to GATT database */ + BT_INFO("GATT Server Add Descriptor: UUID [%s] permission [%d] service handle [%d] Inst ID [%d]", + desc->uuid, desc->permissions, svc->handle, instance_id); + + ret = _bt_get_error_code(bluetooth_gatt_server_add_descriptor(desc->uuid, (bt_gatt_permission_t)desc->permissions, + svc->handle, instance_id, &desc->handle)); + + BT_INFO("Descriptor added handle [%d]", desc->handle); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + goto fail; + } + + ret = _bt_get_error_code(bluetooth_gatt_set_descriptor_value(desc->path, + desc->value, desc->value_length)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + goto fail; + } + } + } + + ret = _bt_get_error_code(bluetooth_gatt_register_service(svc->path)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + goto fail; + } + + serv->services = g_slist_append(serv->services, svc); + svc->parent = (void *)server; + + return ret; + +fail: + bluetooth_gatt_unregister_service(svc->path); + + return ret; +} +#else +int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) +{ + int ret = BT_ERROR_NONE; + bt_gatt_server_s *serv = (bt_gatt_server_s *)server; bt_gatt_service_s *svc = (bt_gatt_service_s *)service; GSList *char_l; @@ -2518,35 +2759,20 @@ int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) _bt_convert_error_to_string(ret), ret); goto fail; } - - ret = _bt_get_error_code(bluetooth_gatt_set_descriptor_value(desc->path, - desc->value, desc->value_length)); - - if (ret != BT_ERROR_NONE) { - BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); - goto fail; - } } } - ret = _bt_get_error_code(bluetooth_gatt_register_service(svc->path)); - - if (ret != BT_ERROR_NONE) { - BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); - goto fail; - } - serv->services = g_slist_append(serv->services, svc); svc->parent = (void *)server; return ret; fail: - bluetooth_gatt_unregister_service(svc->path); + BT_ERR("Registering Service failed!!!!!"); return ret; } +#endif int bt_gatt_server_unregister_service(bt_gatt_server_h server, bt_gatt_h service) @@ -2584,7 +2810,11 @@ int bt_gatt_server_unregister_all_services(bt_gatt_server_h server) g_slist_free_full(serv->services, __bt_gatt_free_service); serv->services = NULL; +#ifdef TIZEN_FEATURE_GATT_RELAY + ret = bluetooth_gatt_server_unregister(instance_id); +#else ret = bluetooth_gatt_unregister_application(); +#endif is_gatt_server_started = false; return ret; @@ -2599,8 +2829,32 @@ int bt_gatt_server_start(void) BT_CHECK_GATT_SERVER_INIT_STATUS(); if (!is_gatt_server_started) { - ret = bluetooth_gatt_register_application(); +#ifdef TIZEN_FEATURE_GATT_RELAY +{ + GSList *l; + GSList *l1; + + /* Kick Start all services*/ + BT_INFO("Total GATT Servers for this application [%d]", g_slist_length(gatt_server_list)); + for (l = gatt_server_list; l; l = g_slist_next(l)) { + bt_gatt_server_s *server = (bt_gatt_server_s *)l->data; + BT_INFO("Total GATT Services for this current server(server) of this App [%d]", g_slist_length(server->services)); + + for (l1 = server->services; l1; l1 = g_slist_next(l1)) { + bt_gatt_service_s *service = (bt_gatt_service_s *)l1->data; + BT_DBG("Service handle [%d] Service UUID [%s]", service->handle, service->uuid); + /* Mark the service Registered */ + ret = _bt_get_error_code(bluetooth_gatt_server_start_service(service->handle, instance_id)); + + if (ret != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + } +} +#else + ret = bluetooth_gatt_register_application(); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -2630,10 +2884,34 @@ int bt_gatt_server_send_response(int request_id, bt_gatt_att_request_type_e requ return BT_ERROR_INVALID_PARAMETER; } +#ifdef TIZEN_FEATURE_GATT_RELAY + bluetooth_gatt_att_data_t resp; + bluetooth_gatt_server_response_params_t param; + + memset(&resp, 0x00, sizeof(resp)); + memset(¶m, 0x00, sizeof(param)); + + /* Copy response data */ + resp.length = value_length; + resp.offset = offset; + memcpy(&resp.data[0], value, value_length); + + /* Copy Response parameters */ + param.req_type = request_type; + param.request_id = request_id; + param.response_status = resp_status; + param.auth_req = 0; /* Default value set to 0 as Platform API does not provide this option */ + + BT_INFO("GATT Server Send Response: Response type [%d]", request_type); + BT_INFO("Req ID [%d] data_len [%d] offset [%d] Resp Status [%d]", + request_id, value_length, offset, resp_status); + + ret = _bt_get_error_code(bluetooth_gatt_server_send_response(¶m, &resp)); +#else ret = _bt_get_error_code(bluetooth_gatt_send_response(request_id, request_type, resp_status, offset, value, value_length)); - +#endif if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -2657,6 +2935,70 @@ int bt_gatt_server_notify_characteristic_changed_value(bt_gatt_h characteristic, _bt_convert_address_to_hex(&addr_hex, device_address); +#ifdef TIZEN_FEATURE_GATT_RELAY +{ + int attribute_handle; + bluetooth_gatt_att_data_t indication; + bluetooth_gatt_server_indication_params_t param; + int k; + + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { + attribute_handle = chr->handle; + } else { + BT_ERR("Type is invalid(type:%d)", handle->type); + return BT_ERROR_INVALID_PARAMETER; + } + + if (!(chr->properties & BT_GATT_PROPERTY_INDICATE) && + !(chr->properties & BT_GATT_PROPERTY_NOTIFY)) { + BT_ERR("Characteristic [%d] does not have either Notifcation or Indicate property enabled", attribute_handle); + return BT_ERROR_INVALID_PARAMETER; + } + + BT_INFO("GATT Server: Notify/Indicate char value changed to Remote GATT client"); + if (!device_address) + BT_INFO("Indication to be Multicasted!"); + else + BT_INFO("Indication to be Unicasted.. [%s]", device_address); + + if (chr->value_length > 0 && chr->value) { + if (handle->role == BT_GATT_ROLE_SERVER) { + + /* DEBUG */ + for (k = 0; k < chr->value_length; k++) + BT_DBG("Indication Data [%d] = [0x%x]", k, chr->value[k]); + + /* Copy Indication data */ + indication.length = chr->value_length; + indication.offset = 0; /* Default value */ + memcpy(&indication.data[0], chr->value, chr->value_length); + + /* Copy Indication parameters */ + param.atrribute_handle = attribute_handle; + + if (chr->properties & BT_GATT_PROPERTY_INDICATE) { + BT_DBG("Characteritsic [%d]has Indicate Property", attribute_handle); + param.need_confirmation = TRUE; + } else { + param.need_confirmation = FALSE; + BT_DBG("Enable Notifcation for the characteristic [%d]", attribute_handle); + } + param.instance_id = instance_id; + ret = _bt_get_error_code(bluetooth_gatt_server_send_indication(&addr_hex, ¶m, &indication)); + BT_INFO("Sent Indication to Remote GATT client: result [%d]", ret); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } + } + } + + /* Save the Remote GATT client address to be used for notification later on */ + memcpy(&chr->address.addr, &addr_hex.addr, BLUETOOTH_ADDRESS_LENGTH); +} +#else if (chr->value_length > 0 && chr->value) { if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { ret = bluetooth_gatt_server_set_notification(handle->path, @@ -2677,7 +3019,7 @@ int bt_gatt_server_notify_characteristic_changed_value(bt_gatt_h characteristic, } } } - +#endif chr->notified_cb = callback; chr->notified_user_data = user_data; diff --git a/test/bt_unit_test.c b/test/bt_unit_test.c index dd866f7..4b92564 100644 --- a/test/bt_unit_test.c +++ b/test/bt_unit_test.c @@ -1733,9 +1733,15 @@ static void __bt_adapter_le_scan_result_cb( if (bt_adapter_le_get_scan_result_manufacturer_data( info, pkt_type, &manufacturer_id, &manufacturer_data, &manufacturer_data_len) == BT_ERROR_NONE) { - TC_PRT("Manufacturer data[ID:%.4X, 0x%.2X%.2X...(len:%d)]", - manufacturer_id, manufacturer_data[0], - manufacturer_data[1], manufacturer_data_len); + + if (manufacturer_data_len > 1) { + TC_PRT("Manufacturer data[ID:%.4X, 0x%.2X%.2X...(len:%d)]", + manufacturer_id, manufacturer_data[0], + manufacturer_data[1], manufacturer_data_len); + } else { + TC_PRT("Manufacturer data[ID:%.4X, len:%d]", manufacturer_id, manufacturer_data_len); + } + g_free(manufacturer_data); } if (bt_adapter_le_get_scan_result_ibeacon_report(info, pkt_type,