From: Anupam Roy Date: Wed, 12 Apr 2017 10:37:35 +0000 (+0530) Subject: [CAPI Internal] Support for GATT Server X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b526cf5387c3a9de51ec5936ca5bbd26dcf1a1f;p=platform%2Fcore%2Fapi%2Fbluetooth.git [CAPI Internal] Support for GATT Server This patch adds support for GATT Server API's which are non GATT_DIRECT. All API's calls are handled by BT service and further by OAL and Bluez HAL library layers. All codes are implemented inside #ifndef GATT_DIRECT Change-Id: I6e14eee0c4d7a3d1fa437e73cbc8cfd7d1a7c5e4 Signed-off-by: Anupam Roy --- diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 3cbeb20..c233bdb 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -28,6 +28,10 @@ #include #include +#ifndef GATT_DIRECT +#include +#endif + #include "bluetooth.h" #include "bluetooth_internal.h" @@ -337,6 +341,9 @@ typedef struct { void *parent; char *path; char *uuid; +#ifndef GATT_DIRECT + int handle; +#endif } bt_gatt_common_s; typedef struct { @@ -345,7 +352,10 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifndef GATT_DIRECT + int handle; + int numhandles; +#endif bool is_included_service; bt_gatt_service_type_e service_type; @@ -363,7 +373,10 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifndef GATT_DIRECT + int handle; + bluetooth_device_address_t address; +#endif int permissions; int properties; bt_gatt_write_type_e write_type; @@ -397,7 +410,9 @@ typedef struct { void *parent; char *path; char *uuid; - +#ifndef GATT_DIRECT + int handle; +#endif int permissions; bt_gatt_server_write_value_requested_cb write_value_requested_cb; @@ -827,6 +842,15 @@ int _bt_gatt_client_update_characteristics(bt_gatt_h service); int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic); +#ifndef GATT_DIRECT +/** + * @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/include/mobile/bluetooth_type.h b/include/mobile/bluetooth_type.h index c49bc70..aa81ff5 100644 --- a/include/mobile/bluetooth_type.h +++ b/include/mobile/bluetooth_type.h @@ -1818,6 +1818,7 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, * @param[in] request_id The identification of this request. It will be used to send a response. * @param[in] server The GATT server handle * @param[in] gatt_handle The characteristic or descriptor's GATT handle which has an old value + * @param[in] response_needed Indicates whether a response is required by the remote device - @c true if required, @c false if not * @param[in] offset The requested offset from where the @a gatt_handle value will be updated * @param[in] value The new value * @param[in] len The length of @a value @@ -1828,7 +1829,7 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, */ typedef void (*bt_gatt_server_write_value_requested_cb) (const char *remote_address, int request_id, bt_gatt_server_h server, - bt_gatt_h gatt_handle, int offset, + bt_gatt_h gatt_handle, bool response_needed, int offset, const char *value, int len, void *user_data); /** diff --git a/include/tv/bluetooth_type.h b/include/tv/bluetooth_type.h index d4af7a9..53600a6 100644 --- a/include/tv/bluetooth_type.h +++ b/include/tv/bluetooth_type.h @@ -1819,6 +1819,7 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, * @param[in] request_id The identification of this request. It will be used to send a response. * @param[in] server The GATT server handle * @param[in] gatt_handle The characteristic or descriptor's GATT handle which has an old value + * @param[in] response_needed Indicates whether a response is required by the remote device - @c true if required, @c false if not * @param[in] offset The requested offset from where the @a gatt_handle value will be updated * @param[in] value The new value * @param[in] len The length of @a value @@ -1828,9 +1829,9 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, * @see bt_gatt_server_send_response() */ typedef void (*bt_gatt_server_write_value_requested_cb) (const char *remote_address, - int request_id, bt_gatt_server_h server, - bt_gatt_h gatt_handle, int offset, - const char *value, int len, void *user_data); + int request_id, bt_gatt_server_h server, + bt_gatt_h gatt_handle, bool response_needed, int offset, + const char *value, int len, void *user_data); /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE diff --git a/include/wearable/bluetooth_type.h b/include/wearable/bluetooth_type.h index aa675e7..8560cd4 100644 --- a/include/wearable/bluetooth_type.h +++ b/include/wearable/bluetooth_type.h @@ -1694,6 +1694,7 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, * @param[in] request_id The identification of this request. It will be used to send a response. * @param[in] server The GATT server handle * @param[in] gatt_handle The characteristic or descriptor's GATT handle which has an old value + * @param[in] response_needed Indicates whether a response is required by the remote device - @c true if required, @c false if not * @param[in] offset The requested offset from where the @a gatt_handle value will be updated * @param[in] value The new value * @param[in] len The length of @a value @@ -1703,9 +1704,9 @@ typedef void (*bt_gatt_connection_state_changed_cb)(int result, bool connected, * @see bt_gatt_server_send_response() */ typedef void (*bt_gatt_server_write_value_requested_cb) (const char *remote_address, - int request_id, bt_gatt_server_h server, - bt_gatt_h gatt_handle, int offset, - const char *value, int len, void *user_data); + int request_id, bt_gatt_server_h server, + bt_gatt_h gatt_handle, bool response_needed, int offset, + const char *value, int len, void *user_data); /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 9681b6e..954c549 100755 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -724,6 +724,7 @@ static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **de return BT_ERROR_NONE; } +#ifdef GATT_DIRECT 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) { @@ -776,7 +777,62 @@ static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( } return NULL; } +#else +/* 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; +} +#endif +#ifdef GATT_DIRECT 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) { @@ -829,7 +885,61 @@ static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_cha } return NULL; } +#else +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; +} +#endif + +#ifdef GATT_DIRECT static bt_gatt_server_characteristic_notification_state_changed_cb __bt_gatt_attribute_get_notification_change_cb( bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) @@ -868,7 +978,47 @@ static bt_gatt_server_characteristic_notification_state_changed_cb } return NULL; } +#else +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; +} + +#endif + +#ifdef GATT_DIRECT static bt_gatt_server_notification_sent_cb __bt_gatt_attribute_get_notification_completed_cb( bt_gatt_h service, bt_gatt_h attribute, void **user_data) { @@ -905,6 +1055,42 @@ static bt_gatt_server_notification_sent_cb __bt_gatt_attribute_get_notification_ } return NULL; } +#else +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; +} +#endif static void __bt_free_bt_device_connection_info_s(bt_device_connection_info_s *conn_info) { @@ -969,6 +1155,19 @@ void _bt_hid_event_proxy(int event, hid_event_param_t *param, void *user_data) new_param.user_data = param->user_data; __bt_event_proxy(event, &new_param, user_data); } + +#ifndef GATT_DIRECT +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); +} +#endif + /* LCOV_EXCL_STOP */ static bool __bt_need_to_handle(int event) @@ -1992,6 +2191,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us break; } case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: { +#ifdef GATT_DIRECT bt_gatt_read_req_t *read_req = param->param_data; bt_gatt_server_read_value_requested_cb cb; void *user_data = NULL; @@ -2010,9 +2210,43 @@ 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); +#else + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED"); + 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); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED: { +#ifdef GATT_DIRECT bt_gatt_value_change_t *value_change = param->param_data; bt_gatt_server_write_value_requested_cb cb; void *user_data = NULL; @@ -2022,6 +2256,8 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGE"); if (cb == NULL) { + if (value_change->response_needed == FALSE) + return; bluetooth_gatt_send_response(value_change->req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, BLUETOOTH_ERROR_INTERNAL, 0, NULL, 0); @@ -2029,11 +2265,57 @@ 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, value_change->offset, + gatt_handle, value_change->offset, value_change->response_needed, (char *)value_change->att_value, value_change->val_len, user_data); +#else + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_WRITE_REQUESTED"); + 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); + + 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; + 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); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED: { +#ifdef GATT_DIRECT bt_gatt_char_notify_change_t *value_change = param->param_data; bt_gatt_server_characteristic_notification_state_changed_cb cb; void *user_data = NULL; @@ -2047,9 +2329,28 @@ 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); +#else + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED"); + 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); +#endif break; } case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED: { +#ifdef GATT_DIRECT bt_gatt_indicate_confirm_t *confrim_status = param->param_data; bt_gatt_server_notification_sent_cb cb; void *user_data = NULL; @@ -2063,7 +2364,32 @@ 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); +#else + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED"); + 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; + + 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); + +#endif break; } #ifdef TIZEN_FEATURE_ENABLE_LEGACY_GATT_CLIENT @@ -2111,7 +2437,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us /* TODO : Fix build error temporary */ if (chr->write_value_requested_cb) chr->write_value_requested_cb(NULL, 0, (bt_gatt_server_h)serv, (bt_gatt_h)chr, - 0, (char*)char_val->char_value, char_val->val_len, + 0, TRUE, (char*)char_val->char_value, char_val->val_len, chr->write_value_requested_user_data); } } diff --git a/src/bluetooth-device.c b/src/bluetooth-device.c index 315f836..800eb4c 100644 --- a/src/bluetooth-device.c +++ b/src/bluetooth-device.c @@ -792,7 +792,7 @@ int bt_device_get_att_mtu(const char *remote_address, unsigned int *mtu) } *mtu = mtu_value; - + BT_INFO("Got MTU: Remote address [%s] MTU Size [%u]", remote_address, mtu_value); return ret; } diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index f790f01..3ff0add 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -24,6 +24,11 @@ #include "bluetooth_internal.h" #include "bluetooth_type_internal.h" +#ifndef GATT_DIRECT +#include "bluetooth-gatt-server-api.h" +int instance_id; +#endif + #define BT_ADDR_STR_LEN 17 static GSList *gatt_client_list = NULL; @@ -902,10 +907,20 @@ 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 GATT_DIRECT 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); +#else + 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); + } +#endif + } g_strfreev(svc->include_handles); @@ -1296,6 +1311,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; +#ifndef GATT_DIRECT + int k; + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1313,6 +1333,7 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, return BT_ERROR_INVALID_PARAMETER; } +#ifdef GATT_DIRECT if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, value, value_length)); @@ -1321,7 +1342,26 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, return ret; } } +#else + 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; + } + } +#endif g_free(*val); *val = NULL; if (value_length > 0) @@ -1344,6 +1384,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; +#ifndef GATT_DIRECT + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1441,8 +1485,20 @@ 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 GATT_DIRECT ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, *val, *val_len)); +#else + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_update_value_t)); + param.length = *val_len; + memcpy(¶m.data.data[0], *val, *val_len); + + param.attribute_handle = handle->handle; + ret = _bt_get_error_code(bluetooth_gatt_server_update_characteristic(instance_id, + ¶m)); + +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -1467,6 +1523,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; +#ifndef GATT_DIRECT + bluetooth_gatt_server_update_value_t param; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1547,8 +1607,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 GATT_DIRECT ret = _bt_get_error_code(bluetooth_gatt_update_characteristic(handle->path, *val, *val_len)); +#else + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_update_value_t)); + param.length = *val_len; + memcpy(¶m.data.data[0], *val, *val_len); + + param.attribute_handle = handle->handle; + ret = _bt_get_error_code(bluetooth_gatt_server_update_characteristic(instance_id, + ¶m)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -1666,10 +1737,15 @@ bt_gatt_service_s* __bt_gatt_service_create(const char *uuid, return NULL; svc->type = BT_GATT_TYPE_SERVICE; +#ifdef GATT_DIRECT if (strlen(uuid) == 8) svc->uuid = _bt_convert_uuid_to_uuid128(uuid); else svc->uuid = strdup(uuid); +#else + svc->uuid = _bt_convert_uuid_to_uuid128(uuid); + +#endif if (svc->uuid == NULL) { g_free(svc); return NULL; @@ -1701,7 +1777,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; - +#ifndef GATT_DIRECT + 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; @@ -1725,7 +1804,10 @@ int bt_gatt_service_add_characteristic(bt_gatt_h service, svc->characteristics = g_slist_append(svc->characteristics, chr); chr->parent = (void *)service; - +#ifndef GATT_DIRECT + BT_INFO("Current handle count of service [%d]", svc->numhandles); + svc->numhandles += 2; +#endif return BT_ERROR_NONE; } @@ -1748,6 +1830,10 @@ 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; +#ifndef GATT_DIRECT + BT_INFO("Current handle count of service [%d]", svc->numhandles); + svc->numhandles = 1; /* Initalize numhandles to 1 */ +#endif return BT_ERROR_NONE; } @@ -1964,10 +2050,14 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, chr->type = BT_GATT_TYPE_CHARACTERISTIC; chr->role = BT_GATT_ROLE_SERVER; +#ifdef GATT_DIRECT if (strlen(uuid) == 8) chr->uuid = _bt_convert_uuid_to_uuid128(uuid); else chr->uuid = g_strdup(uuid); +#else + chr->uuid = _bt_convert_uuid_to_uuid128(uuid); +#endif if (chr->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -2000,6 +2090,9 @@ int bt_gatt_characteristic_add_descriptor(bt_gatt_h characteristic, bt_gatt_h descriptor) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)characteristic; +#ifndef GATT_DIRECT + bt_gatt_service_s *svc = (bt_gatt_service_s *)chr->parent; +#endif bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)descriptor; BT_CHECK_GATT_SUPPORT(); @@ -2021,6 +2114,10 @@ int bt_gatt_characteristic_add_descriptor(bt_gatt_h characteristic, chr->descriptors = g_slist_append(chr->descriptors, desc); desc->parent = (void *)characteristic; +#ifndef GATT_DIRECT + BT_INFO("Current handle count of service [%d]", svc->numhandles); + svc->numhandles += 1; /* Initalize numhandles to 1 */ +#endif return BT_ERROR_NONE; } @@ -2243,10 +2340,14 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, desc->type = BT_GATT_TYPE_DESCRIPTOR; desc->role = BT_GATT_ROLE_SERVER; +#ifdef GATT_DIRECT if (strlen(uuid) == 8) desc->uuid = _bt_convert_uuid_to_uuid128(uuid); else desc->uuid = g_strdup(uuid); +#else + desc->uuid = _bt_convert_uuid_to_uuid128(uuid); +#endif if (desc->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -2303,7 +2404,11 @@ int bt_gatt_server_initialize(void) } if (!is_gatt_server_initialized) { +#ifndef GATT_DIRECT + 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)", @@ -2338,14 +2443,34 @@ int bt_gatt_server_deinitialize(void) g_slist_free(gatt_server_list); gatt_server_list = NULL; +#ifndef GATT_DIRECT + 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)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } +#else ret = _bt_get_error_code(bluetooth_gatt_deinit()); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return BT_ERROR_OPERATION_FAILED; } +#ifndef GATT_DIRECT + instance_id = -1; +#endif is_gatt_server_initialized = false; is_gatt_server_started = false; return BT_ERROR_NONE; @@ -2375,6 +2500,7 @@ int bt_gatt_server_create(bt_gatt_server_h *server) *server = (bt_gatt_server_h)serv; + BT_INFO("Creating a GATT Server"); gatt_server_list = g_slist_append(gatt_server_list, serv); return BT_ERROR_NONE; @@ -2446,6 +2572,9 @@ int bt_gatt_server_set_characteristic_notification_state_change_cb(bt_gatt_h gat int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) { int ret = BT_ERROR_NONE; +#ifndef GATT_DIRECT + bluetooth_gatt_server_attribute_params_t param; +#endif bt_gatt_server_s *serv = (bt_gatt_server_s *)server; bt_gatt_service_s *svc = (bt_gatt_service_s *)service; GSList *char_l; @@ -2465,9 +2594,15 @@ int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) BT_ERR("Already Server started"); return BT_ERROR_OPERATION_FAILED; } - +#ifndef GATT_DIRECT + 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); +#else ret = _bt_get_error_code(bluetooth_gatt_add_service(svc->uuid, - &svc->path)); + &svc->path)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; @@ -2477,65 +2612,98 @@ int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) GSList *desc_l; bt_gatt_characteristic_s *chr = char_l->data; +#ifndef GATT_DIRECT + /* 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); +#else ret = _bt_get_error_code(bluetooth_gatt_add_new_characteristic( svc->path, chr->uuid, (bt_gatt_permission_t)chr->permissions, (bt_gatt_characteristic_property_t)chr->properties, &chr->path)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); goto fail; } + /* Only in platform */ +#ifdef GATT_DIRECT ret = _bt_get_error_code(bluetooth_gatt_set_characteristic_value(chr->path, chr->value, chr->value_length)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); goto fail; } - +#endif for (desc_l = chr->descriptors; desc_l; desc_l = g_slist_next(desc_l)) { bt_gatt_descriptor_s *desc = desc_l->data; +#ifndef GATT_DIRECT + /* 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); +#else ret = _bt_get_error_code(bluetooth_gatt_add_descriptor( - chr->path, desc->uuid, - (bt_gatt_permission_t)desc->permissions, - &desc->path)); - + chr->path, desc->uuid, + (bt_gatt_permission_t)desc->permissions, + &desc->path)); +#endif if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); goto fail; } + /* Only in platform */ +#ifdef GATT_DIRECT ret = _bt_get_error_code(bluetooth_gatt_set_descriptor_value(desc->path, - desc->value, desc->value_length)); + desc->value, desc->value_length)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); goto fail; } +#endif } } + /* Only in platform */ +#ifdef GATT_DIRECT 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; } +#endif serv->services = g_slist_append(serv->services, svc); + BT_INFO("@@Appending one service to the server, current service count [%d]", g_slist_length(serv->services)); svc->parent = (void *)server; - return ret; fail: + /* Only in platform */ + BT_ERR("Registering Service failed!!!!!"); +#ifdef GATT_DIRECT bluetooth_gatt_unregister_service(svc->path); +#endif return ret; } @@ -2576,7 +2744,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 GATT_DIRECT ret = bluetooth_gatt_unregister_application(); +#else + ret = bluetooth_gatt_server_unregister(instance_id); +#endif is_gatt_server_started = false; return ret; @@ -2585,14 +2757,41 @@ int bt_gatt_server_unregister_all_services(bt_gatt_server_h server) int bt_gatt_server_start(void) { int ret = BT_ERROR_NONE; - +#ifndef GATT_DIRECT + GSList *l; + GSList *l1; +#endif BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_GATT_SERVER_INIT_STATUS(); if (!is_gatt_server_started) { +#ifdef GATT_DIRECT ret = bluetooth_gatt_register_application(); +#else + /* 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); + } + } + } + + /* No need to RegisterApplication, when last service gets started, automatically + application will be registered */ + //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; @@ -2622,10 +2821,40 @@ int bt_gatt_server_send_response(int request_id, bt_gatt_att_request_type_e requ return BT_ERROR_INVALID_PARAMETER; } +#ifdef GATT_DIRECT ret = _bt_get_error_code(bluetooth_gatt_send_response(request_id, request_type, resp_status, offset, value, value_length)); - +#else + 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)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", + _bt_convert_error_to_string(ret), ret); + return BT_ERROR_OPERATION_FAILED; + } +#endif if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -2641,6 +2870,13 @@ int bt_gatt_server_notify_characteristic_changed_value(bt_gatt_h characteristic, bluetooth_device_address_t addr_hex = { {0,} }; int ret = BT_ERROR_NONE; +#ifndef GATT_DIRECT + int attribute_handle; + bluetooth_gatt_att_data_t indication; + bluetooth_gatt_server_indication_params_t param; + int k; +#endif + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_GATT_SERVER_INIT_STATUS(); @@ -2649,27 +2885,85 @@ int bt_gatt_server_notify_characteristic_changed_value(bt_gatt_h characteristic, _bt_convert_address_to_hex(&addr_hex, device_address); +#ifdef GATT_DIRECT if (chr->value_length > 0 && chr->value) { if (handle->role == BT_GATT_ROLE_SERVER && handle->path) { ret = bluetooth_gatt_server_set_notification(handle->path, - &addr_hex); + &addr_hex); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); return ret; } ret = _bt_get_error_code(bluetooth_gatt_update_characteristic( - handle->path, - chr->value, - chr->value_length)); + handle->path, + chr->value, + chr->value_length)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + _bt_convert_error_to_string(ret), ret); return ret; } } } +#else + 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); +#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 559e33e..2242228 100644 --- a/test/bt_unit_test.c +++ b/test/bt_unit_test.c @@ -2523,11 +2523,12 @@ void __bt_gatt_server_notification_sent_cb(int result, void __bt_gatt_server_write_value_requested_cb(const char *remote_address, int request_id, bt_gatt_server_h server, - bt_gatt_h gatt_handle, int offset, + bt_gatt_h gatt_handle, bool response_needed, int offset, const char *value, int len, void *user_data) { int i, resp_status = BT_ERROR_NONE; TC_PRT("remote_address : %s", remote_address); + TC_PRT("Response needed : %d", response_needed); TC_PRT("offset : %d", offset); TC_PRT("len [%d] : ", len); for (i = 0; i < len; i++)