#include <cynara-creds-gdbus.h>
#include "bluetooth-api.h"
+#include "bluetooth-gatt-server-api.h"
#include "bt-request-handler.h"
#include "bt-service-common.h"
#include "bt-service-util.h"
|| service_function == BT_SET_ADVERTISING
|| service_function == BT_SET_CUSTOM_ADVERTISING
|| service_function == BT_GATT_SERVER_REGISTER
+ || service_function == BT_GATT_SERVER_ADD_SERVICE
+ || service_function == BT_GATT_SERVER_ADD_CHARACTERISTIC
+ || service_function == BT_GATT_SERVER_ADD_DESCRIPTOR
+ || service_function == BT_GATT_SERVER_START_SERVICE
+ || service_function == BT_GATT_SERVER_STOP_SERVICE
+ || service_function == BT_GATT_SERVER_DELETE_SERVICE
|| service_function == BT_START_LE_DISCOVERY
|| service_function == BT_STOP_LE_DISCOVERY)
return TRUE;
break;
}
case BT_GATT_SERVER_REGISTER: {
- BT_DBG("GATT Server instance initialization: Unhandled!!");
+ BT_DBG("GATT Server instance initialization");
+ char *app;
+
+ app = (char *)g_dbus_method_invocation_get_sender(context);
+ BT_INFO("GATT Server Unique Name [%s]", app);
+
+ /* No ADV handle: Set 0 */
+ result = _bt_register_server_instance(app, 0);
+ BT_INFO("GATT Server: Register Server result [%d]", result);
+
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("GATT Server registration failed!!");
+ } else {
+ _bt_save_invocation_context(context, result, app,
+ function_name, NULL);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_DEREGISTER: {
+ char *app;
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ result = _bt_unregister_server_instance(app, 0/* Adv Handle*/);
+ break;
+ }
+ case BT_GATT_SERVER_ADD_SERVICE: {
+ BT_DBG("GATT Server Add Service");
+ int service_type;
+ int num_handles;
+ char *svc_uuid;
+ int instance_id;
+ char *app;
+ int *tmp_inst_id = NULL;
+
+ app = (char *)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &service_type,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, &num_handles,
+ sizeof(int));
+ svc_uuid = (char *)g_variant_get_data(in_param3);
+ __bt_service_get_parameters(in_param4, &instance_id,
+ sizeof(int));
+
+ BT_INFO("GATT Server Service UUID [%s]", svc_uuid);
+ result = _bt_gatt_server_add_service(app, service_type, num_handles, svc_uuid, instance_id);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("GATT Server Add Service failed!!");
+ } else {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_ADD_CHARACTERISTIC: {
+ BT_DBG("GATT Server Add Characteristic");
+ char *char_uuid;
+ char *app;
+ int *tmp_inst_id = NULL;
+ bluetooth_gatt_server_attribute_params_t param;
+ memset(¶m, 0, sizeof(bluetooth_gatt_server_attribute_params_t));
+
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, ¶m,
+ sizeof(bluetooth_gatt_server_attribute_params_t));
+ char_uuid = (char *)g_variant_get_data(in_param2);
+
+ BT_INFO("GATT Server Characteristic UUID [%s]", char_uuid);
+
+ result = _bt_gatt_server_add_characteristic(app, char_uuid, ¶m);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("GATT Server Add Service failed!!");
+ } else {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = param.instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, param.instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_ADD_DESCRIPTOR: {
+ BT_DBG("GATT Server Add Descriptor");
+ char *desc_uuid;
+ int instance_id;
+ int service_handle;
+ bt_gatt_permission_t perm;
+ char *app;
+ int *tmp_inst_id = NULL;
+ memset(&perm, 0, sizeof(bt_gatt_permission_t));
+
+ app = (char *)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &service_handle,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, &instance_id,
+ sizeof(int));
+ desc_uuid = (char *)g_variant_get_data(in_param4);
+ __bt_service_get_parameters(in_param3, &perm,
+ sizeof(bt_gatt_permission_t));
+
+ BT_INFO("GATT Server Descriptor UUID [%s]", desc_uuid);
+
+ result = _bt_gatt_server_add_descriptor(app, desc_uuid, &perm, service_handle, instance_id);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("GATT Server Add Service failed!!");
+ } else {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
break;
}
+ case BT_GATT_SERVER_START_SERVICE: {
+ int service_handle;
+ int instance_id;
+
+ char *app;
+ int *tmp_inst_id = NULL;
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &service_handle,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, &instance_id,
+ sizeof(int));
+
+ result = _bt_gatt_server_start_service(app, service_handle, instance_id);
+
+ if (BLUETOOTH_ERROR_NONE == result) {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_STOP_SERVICE: {
+ int service_handle;
+ int instance_id;
+ char *app;
+ int *tmp_inst_id = NULL;
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &service_handle,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, &instance_id,
+ sizeof(int));
+
+ result = _bt_gatt_server_stop_service(app, service_handle, instance_id);
+
+ if (BLUETOOTH_ERROR_NONE == result) {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_DELETE_SERVICE: {
+ int service_handle;
+ int instance_id;
+ int *tmp_inst_id = NULL;
+ char *app;
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &service_handle,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, &instance_id,
+ sizeof(int));
+
+ result = _bt_gatt_server_delete_service(app, service_handle, instance_id);
+
+ if (BLUETOOTH_ERROR_NONE == result) {
+ tmp_inst_id = g_malloc0(sizeof(int));
+ *tmp_inst_id = instance_id;
+ BT_INFO("GATT Server: Save Instance ID in request Inst id [%d] request_id [%d]",
+ *tmp_inst_id, instance_id);
+ _bt_save_invocation_context(context, result, app,
+ function_name, (gpointer)tmp_inst_id);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_SEND_RESPONSE: {
+ bluetooth_gatt_server_response_params_t param;
+ bluetooth_gatt_att_data_t data;
+ char *app;
+
+ memset(¶m, 0x00, sizeof(bluetooth_gatt_server_response_params_t));
+ memset(&data, 0x00, sizeof(bluetooth_gatt_att_data_t));
+
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &data,
+ sizeof(bluetooth_gatt_att_data_t));
+ __bt_service_get_parameters(in_param2, ¶m,
+ sizeof(bluetooth_gatt_server_response_params_t));
+
+ result = _bt_gatt_server_send_response(app, &data, ¶m);
+
+ break;
+ }
+ case BT_GATT_SERVER_SEND_INDICATION: {
+ bluetooth_gatt_server_indication_params_t param;
+ bluetooth_gatt_att_data_t data;
+ bluetooth_device_address_t address;
+
+ char *app;
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ memset(¶m, 0x00, sizeof(bluetooth_gatt_server_indication_params_t));
+ memset(&data, 0x00, sizeof(bluetooth_gatt_att_data_t));
+ memset(&address, 0x00, sizeof(bluetooth_device_address_t));
+
+ __bt_service_get_parameters(in_param1, &data,
+ sizeof(bluetooth_gatt_att_data_t));
+ __bt_service_get_parameters(in_param2, ¶m,
+ sizeof(bluetooth_gatt_server_indication_params_t));
+ __bt_service_get_parameters(in_param3, ¶m,
+ sizeof(bluetooth_device_address_t));
+
+ result = _bt_gatt_server_send_indication(app, &address, &data, ¶m);
+
+ break;
+ }
+ case BT_GATT_SERVER_UPDATE_VALUE: {
+ bluetooth_gatt_server_update_value_t param;
+ int instance_id;
+ char *app;
+
+ memset(¶m, 0x00, sizeof(bluetooth_gatt_server_response_params_t));
+
+ app = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, &instance_id,
+ sizeof(int));
+ __bt_service_get_parameters(in_param2, ¶m,
+ sizeof(bluetooth_gatt_server_update_value_t));
+
+ result = _bt_gatt_server_update_attribute_value(app, instance_id, ¶m);
+ }
+ case BT_GET_ATT_MTU: {
+ bluetooth_device_address_t address = { {0} };
+ unsigned int mtu = 0;
+
+ __bt_service_get_parameters(in_param1,
+ &address, sizeof(bluetooth_device_address_t));
+ result = _bt_get_att_mtu(&address, &mtu);
+ BT_DBG("MTU: %d", mtu);
+
+ if (result == BLUETOOTH_ERROR_NONE) {
+ g_array_append_vals(*out_param1, &mtu,
+ sizeof(unsigned int));
+ }
+ break;
+ }
case BT_START_LE_DISCOVERY: {
sender = (char *)g_dbus_method_invocation_get_sender(context);
result = _bt_start_le_scan(sender);
case BT_GATT_REGISTER_APPLICATION:
case BT_GATT_REGISTER_SERVICE:
case BT_GATT_SEND_RESPONSE:
+#ifndef GATT_DIRECT
case BT_GATT_SERVER_REGISTER:
+ case BT_GATT_SERVER_ADD_SERVICE:
+ case BT_GATT_SERVER_ADD_CHARACTERISTIC:
+ case BT_GATT_SERVER_ADD_DESCRIPTOR:
+ case BT_GATT_SERVER_START_SERVICE:
+ case BT_GATT_SERVER_STOP_SERVICE:
+ case BT_GATT_SERVER_DELETE_SERVICE:
+ case BT_GATT_SERVER_SEND_RESPONSE:
+ case BT_GATT_SERVER_SEND_INDICATION:
+ case BT_GATT_SERVER_UPDATE_VALUE:
+ case BT_GATT_SERVER_DEREGISTER:
+#endif
+ case BT_GET_ATT_MTU:
case BT_PBAP_CONNECT:
case BT_PBAP_DISCONNECT:
case BT_PBAP_GET_PHONEBOOK_SIZE:
#include "bt-internal-types.h"
#include "bt-service-gatt.h"
+#include "bt-service-gatt.h"
+#include "bt-service-core-device.h"
+#include "bt-service-core-adapter-le.h"
#include <oal-hardware.h>
#include <oal-manager.h>
GSList *service_handles;
} bt_service_app_info_t;
+/* GATT Server Request Info Structure */
+struct gatt_server_req_info {
+ int connection_id; /* This value will uniquely identify a GATT client-server connection */
+ int request_id; /* This is an unique transaction ID assigned against each request by stack */
+ int attribute_handle; /* GATT server attribute handle */
+ int offset; /* GATT server attribute offset on which request is invoked by GATT client */
+ bluetooth_gatt_att_request_type_e request_type; /* Read or Write request */
+ char *addr; /* Remote GATT client address */
+};
+
+/* GATT Client Info List Structure */
+struct gatt_client_info_t {
+ int connection_id; /* This value will uniquely identify a GATT client-server connection */
+ int instance_id; /* This value unique identifies a GATT server instance */
+ char *addr; /* Remote GATT client address */
+};
+
+/* GATT Indicate confirm result */
+struct gatt_indicate_cfm_result_info_t {
+ int result; /* Result of event */
+ char *addr; /* Remote GATT client address */
+ int att_hdl; /* Characteristic Attribute handle */
+ int completed; /* 1 if last event, otheriwse 0 */
+};
+
+/* Request Search Utility method */
+static struct gatt_server_req_info *__bt_gatt_server_find_request_info(int request_id,
+ bluetooth_gatt_att_request_type_e req_type);
+
+static int __bt_gatt_send_indication_to_all_connected_clients(bluetooth_gatt_att_data_t *data,
+ bluetooth_gatt_server_indication_params_t *param);
+
+static void __bt_remove_all_service_handles(int instance_id);
+
+static int __bt_do_unregister_server_instance(int server_instance);
+
+/* Linked List of GATT requests from Remote GATT Clients */
+static GSList *gatt_server_requests = NULL;
+
+/* Linked List of connected Remote GATT clients */
+static GSList *gatt_client_info_list = NULL;
+
+/* Number of clients to be notified to */
+static int num_indicate_clients;
+
/* List of applications */
static bt_service_app_info_t numapps[MAX_APPS_SUPPORTED];
{
bt_service_app_info_t *app = NULL;
int k;
- int result = OAL_STATUS_SUCCESS;
+ int apps[MAX_APPS_SUPPORTED];
BT_DBG("Adv app name [%s]", name);
ret_if(NULL == name);
+ memset(&apps, -1, sizeof(apps));
+
for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
app = &numapps[k];
- /* Search for a app which has same sender */
+ /* Search for a app which has same sender and stop adv is running */
if (!strncasecmp(app->sender, name, strlen(name)) && app->is_initialized == TRUE) {
BT_DBG("Match found, name: %s", name);
+ /* Unregister all service handles with stack */
+ __bt_remove_all_service_handles(app->instance_id);
+
/* If Advertising is enabled, stop it */
if (app->adv_handle > 0) {
BT_INFO("Stop advertising on instance ID [%d]", app->instance_id);
- result = adapter_ble_multi_adv_disable(app->instance_id);
- if (result != OAL_STATUS_SUCCESS) {
- BT_ERR("OAL API adapter_ble_multi_adv_enable Fail %d", result);
- }
+ /* Disable adv if running */
+ BT_INFO("Disable Advertising Adv Handle [%d] sender [%s]",
+ app->adv_handle, name);
+ _bt_set_advertising(app->sender, app->adv_handle, FALSE, FALSE);
}
- /* TODO: Cleanup all Services, chars and Descriptors of the associated GATT server */
- /* Unregister the server instance */
- _bt_unregister_server_instance(name, app->adv_handle);
+ /* Save instances of all apps that need to be unregistered */
+ apps[app->instance_id] = 1;
}
}
+ /* Unregister all apps one by one */
+ for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ if (apps[k] == 1) {
+ BT_INFO("Unregister app[%d]", k);
+ /* Unregister server instance */
+ __bt_do_unregister_server_instance(k);
+ }
+ }
BT_DBG("-");
}
+static int __bt_gatt_send_indication_to_all_connected_clients(bluetooth_gatt_att_data_t *data,
+ bluetooth_gatt_server_indication_params_t *param)
+{
+ GSList *l;
+ int ret = OAL_STATUS_SUCCESS;
+ int result = OAL_STATUS_INTERNAL_ERROR;
+
+ BT_INFO("Current total number of connected clients [%d]", g_slist_length(gatt_client_info_list));
+ for (l = gatt_client_info_list; l != NULL; l = l->next) {
+ struct gatt_client_info_t *info = l->data;
+
+ if (info) {
+ BT_INFO("GATT Remote client address [%s] connection Id [%d]", info->addr, info->connection_id);
+
+ ret = gatts_send_indication(param->instance_id, param->atrribute_handle,
+ info->connection_id, data->length,
+ param->need_confirmation, (char *)(&data->data[0]));
+
+ BT_INFO("Send Indication to GATT client [%s] result: [%d]", info->addr, ret);
+ if (ret == OAL_STATUS_SUCCESS) {
+ BT_INFO("Send Indication sent successfully to GATT client [%s]", info->addr);
+ result = ret;
+ num_indicate_clients++;
+ }
+ }
+ }
+ BT_INFO("Indication sending done for total number of clients [%d]", num_indicate_clients);
+ return result;
+}
+
+static struct gatt_server_req_info *__bt_gatt_server_find_request_info(int request_id,
+ bluetooth_gatt_att_request_type_e req_type)
+{
+ GSList *l;
+
+ for (l = gatt_server_requests; l != NULL; l = l->next) {
+ struct gatt_server_req_info *req_info = l->data;
+
+ if (req_info && req_info->request_id == request_id && req_info->request_type == req_type) {
+ BT_INFO("GATT Server request info found Req ID [%d] handle [%d] conn ID [%d]",
+ req_info->request_id, req_info->attribute_handle, req_info->connection_id);
+ return req_info;
+ }
+ }
+ BT_ERR("Gatt Request not found");
+ return NULL;
+}
+
void _bt_get_adv_handle_from_instance(int server_inst, int *adv_handle)
{
BT_DBG("+");
BT_DBG("-");
}
+void _bt_update_adv_handle(const char *sender, int adv_handle)
+{
+ int k;
+ BT_DBG("Sender [%s] Adv handle [%d]", sender, adv_handle);
+ bt_service_app_info_t *info = NULL;
+
+ for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+ /* Search for a app which has same sender and adv handle as 0 */
+ if (!g_strcmp0(info->sender, sender) && info->adv_handle == 0) {
+ info->adv_handle = adv_handle;
+ }
+ }
+}
+
int _bt_is_sender_gatt_server_with_no_adv(const char *sender, int adv_handle)
{
int k;
/* Search for a app which has same sender and adv handle as 0
It is possible that same sender but different adv handle */
if (!g_strcmp0(info->sender, sender) && info->adv_handle == 0) {
- info->adv_handle = adv_handle;
+ //info->adv_handle = adv_handle;
return info->instance_id;
}
}
if (numapps[k].instance_id == server_instance) {
numapps[k].is_initialized = 0;
numapps[k].instance_id = -1;
+ numapps[k].adv_handle = 0;
numapps[k].adv_instance = -1;
memset(numapps[k].sender, 0x00, sizeof(numapps[k].sender));
memset(numapps[k].uuid, 0x00, sizeof(numapps[k].uuid));
memset(numapps[k].adv_data.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
memset(numapps[k].scan_rsp.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
+ numapps[k].adv_data_len = 0;
+ numapps[k].scan_rsp_len = 0;
break;
}
}
return BLUETOOTH_ERROR_NONE;
}
+static void __bt_remove_all_service_handles(int instance_id)
+{
+ GSList *l;
+ int *handle = NULL;
+ int ret = OAL_STATUS_SUCCESS;
+ int count;
+
+ count = g_slist_length(numapps[instance_id].service_handles);
+ BT_INFO("Before handle removal: current count [%d]", count);
+
+ for (l = numapps[instance_id].service_handles; l != NULL;) {
+ handle = l->data;
+ l = g_slist_next(l);
+
+ if (handle) {
+ BT_INFO("Server Handle to be Removed [%d] Instance ID [%d]", *handle, instance_id);
+ if (_bt_gatt_server_stop_service(numapps[instance_id].sender, *handle, instance_id) != BLUETOOTH_ERROR_NONE)
+ continue;
+
+ ret = gatts_delete_service(instance_id, *handle);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ continue;
+ } else {
+ numapps[instance_id].service_handles = g_slist_remove(numapps[instance_id].service_handles, handle);
+ g_free(handle);
+ handle = NULL;
+ count = g_slist_length(numapps[instance_id].service_handles);
+ BT_INFO("After deleting current count [%d]", count);
+ }
+ }
+ }
+}
+
int _bt_unregister_server_instance(const char *sender, int adv_handle)
{
BT_INFO("Unregister Allocated server instance request Sender [%s] Adv handle [%d]", sender, adv_handle);
int result = BLUETOOTH_ERROR_NONE;
+ int apps[MAX_APPS_SUPPORTED];
int server_instance;
int k;
+ memset(&apps, -1, sizeof(apps));
+
if (adv_handle == 0) {
BT_DBG("Its a direct GATT Server app request to unregister");
/* Unregister server instance for each app with same sender (case: GATT Server with multiple adv handle) */
/* Exact matching of sender */
if (!g_strcmp0(info->sender, sender)) {
BT_INFO("Unregister GATT server instance [%d]", info->instance_id);
- /*TODO Unregister all service handles with stack */
- /*TODO Disable adv if running */
- /* Unregister server instance */
- result = __bt_do_unregister_server_instance(info->instance_id);
+ /* Unregister all service handles with stack */
+ __bt_remove_all_service_handles(info->instance_id);
+
+ /* Disable adv if running */
+ BT_INFO("Disable Advertising Adv Handle [%d] sender [%s]",
+ info->adv_handle, sender);
+ _bt_set_advertising(sender, info->adv_handle, FALSE, FALSE);
+
+ /* Save all instances which need to be unregistered */
+ apps[info->instance_id] = 1;
}
}
} else {
BT_DBG("Its an Internal unregister request by adv application");
server_instance = _bt_get_allocated_server_instance(sender, adv_handle, FALSE);
+ BT_DBG("Its an Internal unregister request by adv application: Adv disabled srv instance [%d]", server_instance);
if (server_instance == -1) {
BT_ERR("No allocated server instance to be removed");
return BLUETOOTH_ERROR_INVALID_PARAM;
}
- BT_INFO("Unregister Adv app server instance [%d]", server_instance);
- /* Unregister server instance */
- result = __bt_do_unregister_server_instance(server_instance);
+ if (!numapps[server_instance].service_handles) {
+ BT_INFO("There are no Service handles with this app, safe to unregister");
+ /* Unregister server instance only if this sender does not have any gatt services in it */
+ result = __bt_do_unregister_server_instance(server_instance);
+ } else {
+ numapps[server_instance].adv_handle = 0;
+ memset(numapps[server_instance].adv_data.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
+ numapps[server_instance].adv_data_len = 0;
+ memset(numapps[server_instance].scan_rsp.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
+ numapps[server_instance].scan_rsp_len = 0;
+ }
+ return result;
}
+
+ /* Unregister all apps one by one */
+ for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ if (apps[k] == 1) {
+ BT_INFO("Unregister app[%d]", k);
+ /* Unregister server instance */
+ __bt_do_unregister_server_instance(k);
+ }
+ }
+
return result;
}
return BLUETOOTH_ERROR_NONE;
}
-
/* Event handlers */
static void __bt_gatt_handle_pending_request_info(int result,
int service_function, void *data, unsigned int size)
continue;
switch (service_function) {
+#ifndef GATT_DIRECT
case BT_GATT_SERVER_REGISTER: {
- bt_service_app_info_t *data = (bt_service_app_info_t*)data;
- if (!g_strcmp0(req_info->sender, data->sender)) {
+ bt_service_app_info_t *param = (bt_service_app_info_t*)data;
+ BT_INFO("Sender [%s] Request Sender [%s]", param->sender, req_info->sender);
+ if (!g_strcmp0(req_info->sender, param->sender)) {
BT_DBG("GATT Server app found [%s]", req_info->sender);
+
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+ g_array_append_vals(out_param, ¶m->instance_id, sizeof(int));
+ _bt_service_method_return(req_info->context, out_param, result);
+
+ g_free(req_info->user_data);
+ _bt_free_info_from_invocation_list(req_info);
+ g_array_free(out_param, TRUE);
+ }
+ break;
+ }
+ case BT_GATT_SERVER_START_SERVICE:
+ case BT_GATT_SERVER_DELETE_SERVICE: {
+ bt_service_app_info_t *param = (bt_service_app_info_t*)data;
+ BT_INFO("Sender [%s] Request Sender [%s]", param->sender, req_info->sender);
+
+ int *saved_instance_id = (int*)req_info->user_data;
+ if (!g_strcmp0(req_info->sender, param->sender) && param->instance_id == *saved_instance_id) {
+ BT_DBG("GATT Server app found [%s] Instance ID [%d] Reply DBUS",
+ req_info->sender, *saved_instance_id);
+
out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
- g_array_append_vals(out_param, &data->instance_id, sizeof(int));
+ g_array_append_vals(out_param, &saved_instance_id, sizeof(int));
_bt_service_method_return(req_info->context, out_param, result);
+
g_free(req_info->user_data);
_bt_free_info_from_invocation_list(req_info);
g_array_free(out_param, TRUE);
}
break;
}
+ case BT_GATT_SERVER_ADD_SERVICE:
+ case BT_GATT_SERVER_ADD_DESCRIPTOR:
+ case BT_GATT_SERVER_ADD_CHARACTERISTIC: {
+ int *handle = (int*)data;
+ BT_INFO("Characteristic added: Handle [%d]", *handle);
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+
+ g_array_append_vals(out_param, handle, sizeof(int));
+ _bt_service_method_return(req_info->context, out_param, result);
+
+ g_free(req_info->user_data);
+ _bt_free_info_from_invocation_list(req_info);
+ g_array_free(out_param, TRUE);
+ break;
+ }
+#endif
+ case BT_CONNECT_LE:
+ case BT_DISCONNECT_LE: {
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+
+ g_array_append_vals(out_param, (bluetooth_device_address_t*)data,
+ sizeof(bluetooth_device_address_t));
+ _bt_service_method_return(req_info->context, out_param, result);
+
+ g_free(req_info->user_data);
+ _bt_free_info_from_invocation_list(req_info);
+
+ g_array_free(out_param, TRUE);
+ }
default:
break;
}
}
}
g_free(uuid_string);
+ g_free(data);
+}
+
+static void __bt_handle_gatt_server_service_added(event_gatts_srvc_prm_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ int svc_handle;
+ int *handle;
+ int count;
+ bt_service_app_info_t *info = NULL;
+ int k;
+
+ char *uuid_str = g_malloc0(BT_UUID_STRING_MAX);
+ _bt_uuid_to_string(&(event->gatt_srvc_id.id.uuid), uuid_str);
+ BT_INFO("GATT Added Service UUID: [%s] Server Ins [%d] Service hdl [%d] Is Primary [%d]\n",
+ uuid_str, event->gatt_srvc_stat.server_inst, svc_handle, event->gatt_srvc_id.is_prmry);
+
+ if (event->gatt_srvc_stat.status != OAL_STATUS_SUCCESS) {
+ result = BLUETOOTH_ERROR_INTERNAL;
+ svc_handle = 0; /* Service handle set to 0 indicates.
+ 0 is reserved by BT SIG, cant be used by app*/
+ } else
+ svc_handle = event->gatt_srvc_stat.servic_hndl;
+
+ BT_INFO("GATT Added Service Status [%d] Server Ins [%d] Service hdl [%d] Is Primary [%d]\n",
+ event->gatt_srvc_stat.status, event->gatt_srvc_stat.server_inst, svc_handle, event->gatt_srvc_id.is_prmry);
+
+ /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */
+ for (k=1; k <MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->gatt_srvc_stat.server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_ADD_SERVICE,
+ (int*)&svc_handle, sizeof(int));
+
+ /* Add Service Handle */
+ if (svc_handle > 0) {
+ handle = g_malloc0(sizeof(int));
+ *handle = svc_handle;
+ numapps[event->gatt_srvc_stat.server_inst].service_handles = g_slist_append(numapps[event->gatt_srvc_stat.server_inst].service_handles, handle);
+ count = g_slist_length(numapps[event->gatt_srvc_stat.server_inst].service_handles);
+ BT_INFO("Added Service handle [%d] to list..current count [%d]", svc_handle, count);
+ }
+ break;
+ }
+ }
+
+ g_free(event);
+ g_free(uuid_str);
+}
+
+static void __bt_handle_gatt_server_characteristic_added(event_gatts_srvc_charctr_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ int char_handle;
+ bt_service_app_info_t *info = NULL;
+ int k;
+ char *uuid_str = g_malloc0(BT_UUID_STRING_MAX);
+
+ BT_INFO("GATT Server Char added status [%d]", event->gatt_srvc_stat.status);
+ BT_INFO("GATT Server_inst: [%d]", event->gatt_srvc_stat.server_inst);
+ BT_INFO("GATT Service Handle: [%d]", event->gatt_srvc_stat.servic_hndl);
+ BT_INFO("GATT Add characteristic Status: [%d]", event->gatt_srvc_stat.status);
+ BT_INFO("GATT Service characteristic Handle: [%d]", event->charctr_hndl);
+
+ if (event->gatt_srvc_stat.status != OAL_STATUS_SUCCESS) {
+ result = BLUETOOTH_ERROR_INTERNAL;
+ char_handle = 0; /* characteristic handle set to 0 indicates.
+ 0 is reserved by BT SIG, cant be used by app*/
+ } else
+ char_handle = event->charctr_hndl;
+
+
+ /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */
+ for (k=1; k <MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->gatt_srvc_stat.server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_ADD_CHARACTERISTIC,
+ (int*)&char_handle, sizeof(int));
+ break;
+ }
+ }
+
+
+ _bt_uuid_to_string(&(event->charctr_uuid), uuid_str);
+ BT_INFO("GATT Added Characteristic: UUID: [%s]", uuid_str);
+
+ g_free(event);
+ g_free(uuid_str);
+}
+
+static void __bt_handle_gatt_server_descriptor_added(event_gatts_srvc_descr_t* event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ int desc_handle;
+ bt_service_app_info_t *info = NULL;
+ int k;
+ char *uuid_str = g_malloc0(BT_UUID_STRING_MAX);
+
+ BT_INFO("GATT Server Descriptor added status [%d]", event->gatt_srvc_stat.status);
+ BT_INFO("GATT Server_inst: [%d]", event->gatt_srvc_stat.server_inst);
+ BT_INFO("GATT Service Handle: [%d]", event->gatt_srvc_stat.servic_hndl);
+ BT_INFO("GATT Add Descriptor Status: [%d]", event->gatt_srvc_stat.status);
+ BT_INFO("GATT Service Descriptor Handle: [%d]", event->descrptr_hndl);
+
+ if (event->gatt_srvc_stat.status != OAL_STATUS_SUCCESS) {
+ result = BLUETOOTH_ERROR_INTERNAL;
+ desc_handle = 0; /* Service handle set to 0 indicates.
+ 0 is reserved by BT SIG, cant be used by app*/
+ } else
+ desc_handle = event->descrptr_hndl;
+
+ /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */
+ for (k=1; k <MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->gatt_srvc_stat.server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_ADD_DESCRIPTOR,
+ (int*)&desc_handle, sizeof(int));
+ break;
+ }
+ }
+
+ _bt_uuid_to_string(&(event->descrptr_uuid), uuid_str);
+ BT_INFO("GATT Added Descriptor: UUID: [%s]", uuid_str);
+
+ g_free(event);
+ g_free(uuid_str);
+}
+
+static void __bt_handle_gatt_server_service_started(event_gatts_srvc_t *event)
+{
+ bt_service_app_info_t *info = NULL;
+ int result = BLUETOOTH_ERROR_NONE;
+ int k;
+ BT_INFO("GATT Server Service Started..");
+
+
+ BT_INFO("GATT Server_inst: [%d]", event->server_inst);
+ BT_INFO("GATT Service Handle: [%d]", event->servic_hndl);
+ BT_INFO("GATT Service Started Status: [%d]", event->status);
+
+ if (event->status != OAL_STATUS_SUCCESS) {
+ BT_ERR("GATT Server Service Start Failed Err: [%d]", event->status);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ /* Check if the just registered Instance ID belongs to requester */
+ for (k=1; k <MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_START_SERVICE,
+ (void*)info, sizeof(bt_service_app_info_t));
+ break;
+ }
+ }
+
+ g_free(event);
+}
+
+static void __bt_handle_gatt_server_service_stopped(event_gatts_srvc_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ bt_service_app_info_t *info = NULL;
+ int k;
+ BT_INFO("GATT Server Service Stopped..");
+
+ BT_INFO("GATT Server_inst: [%d]", event->server_inst);
+ BT_INFO("GATT Service Handle: [%d]", event->servic_hndl);
+ BT_INFO("GATT Service Stopped Status: [%d]", event->status);
+
+ if (event->status != OAL_STATUS_SUCCESS) {
+ BT_ERR("GATT Server Service Stop Failed Err: [%d]", event->status);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ /* Check if the just registered Instance ID belongs to requester */
+ for (k=1; k <MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_STOP_SERVICE,
+ (void*)info, sizeof(bt_service_app_info_t));
+ break;
+ }
+ }
+
+ g_free(event);
+}
+
+static void __bt_handle_gatt_server_service_deleted(event_gatts_srvc_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ bt_service_app_info_t *info = NULL;
+ int k;
+ BT_INFO("GATT Server Service Deleted..");
+
+ BT_INFO("GATT Server_inst: [%d]", event->server_inst);
+ BT_INFO("GATT Service Handle: [%d]", event->servic_hndl);
+ BT_INFO("GATT Service Deleted Status: [%d]", event->status);
+
+ if (event->status != OAL_STATUS_SUCCESS) {
+ BT_ERR("GATT Server Service Delete Failed Err: [%d]", event->status);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ /* Check if the just registered Instance ID belongs to requester */
+ for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_GATT_SERVER_DELETE_SERVICE,
+ (void*)info, sizeof(bt_service_app_info_t));
+ break;
+ }
+ }
+
+ g_free(event);
+}
+
+static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
+{
+ GSList *l;
+ struct gatt_client_info_t *info = NULL;
+ for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
+ info = (struct gatt_client_info_t*)l->data;
+ if (info == NULL)
+ continue;
+
+ if (!g_strcmp0(info->addr, address)) {
+ BT_INFO("Remote GATT client found addr[%s]", info->addr);
+ return info;
+ }
+ }
+ return NULL;
+}
+
+static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn_id(int conn_id)
+{
+ GSList *l;
+ struct gatt_client_info_t *info = NULL;
+
+ for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
+ info = (struct gatt_client_info_t*)l->data;
+ if (info == NULL)
+ continue;
+
+ if (info->connection_id == conn_id) {
+ BT_INFO("Remote GATT client found addr[%s]", info->addr);
+ return info;
+ }
+ }
+ return NULL;
+}
+
+static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_client_info_t *conn_info = NULL;
+ bt_service_app_info_t *info = NULL;
+ bluetooth_device_address_t dev_addr;
+ GVariant *param = NULL;
+ int k;
+
+ char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+
+
+ /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */
+ for(k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE,
+ (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t));
+
+ break;
+ }
+ }
+
+ /* Send event to BT-API */
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("GATT Server Connedted: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]",
+ address, event->server_inst, event->conn_id);
+
+
+ /* Check if device is already in connected list */
+ conn_info = __bt_find_remote_gatt_client_info(address);
+
+ if (!conn_info) {
+ param = g_variant_new("(is)", result, address);
+ /* Send event to application */
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_CONNECTED,
+ param);
+
+ /* Save Connection info */
+ conn_info = g_new0(struct gatt_client_info_t, 1);
+ conn_info->addr = g_strdup(address);
+ BT_INFO("Added GATT client addr[%s]", conn_info->addr);
+ conn_info->connection_id = event->conn_id;
+ conn_info->instance_id = event->server_inst;
+ gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
+ BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
+ }
+
+ g_free(address);
+}
+
+/* GATT Server Dis connected */
+static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_client_info_t *conn_info = NULL;
+ bluetooth_device_address_t dev_addr;
+ bt_service_app_info_t *info = NULL;
+ GVariant *param = NULL;
+ int k;
+
+ char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+
+ /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */
+ for(k = 1; k < MAX_APPS_SUPPORTED; k++) {
+ info = &numapps[k];
+
+ if (info->instance_id == event->server_inst) {
+ BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender);
+ __bt_gatt_handle_pending_request_info(result, BT_DISCONNECT_LE,
+ (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t));
+
+ break;
+ }
+ }
+
+ /* Send event to BT-API */
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("GATT Server DisConnected: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]",
+ address, event->server_inst, event->conn_id);
+
+ param = g_variant_new("(is)", result, address);
+ /* Send event to application */
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_DISCONNECTED,
+ param);
+
+ /* Remove Connection info */
+ conn_info = __bt_find_remote_gatt_client_info(address);
+ if (conn_info) {
+ BT_INFO("Remove GATT client info from List..");
+ /* Remove info from List */
+ gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
+ BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
+ g_free(conn_info->addr);
+ g_free(conn_info);
+ }
+
+ g_free(address);
+}
+
+static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event)
+{
+ char *address;
+ bluetooth_device_address_t dev_addr;
+ GVariant *param = NULL;
+ int result = BLUETOOTH_ERROR_NONE;
+ gboolean need_resp;
+ gboolean is_prepare_write;
+ char *write_val;
+ GVariant *data = NULL;
+ int i;
+ struct gatt_server_req_info *req_info = NULL;
+ BT_INFO("GATT Server Write Requested");
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+
+ BT_INFO("GATT Server Write Req Connection ID: [%d]", event->attr_trans.conn_id);
+ BT_INFO("GATT Server Write Req Transaction ID:[%d]", event->attr_trans.trans_id);
+ BT_INFO("GATT Server Write Req Attribute Handle: [%d]", event->attr_trans.attr_handle);
+ BT_INFO("GATT Server Write Req Attribute Offset: [%d]", event->attr_trans.offset);
+ BT_INFO("GATT Server Write Req value length [%d]", event->length);
+ BT_INFO("GATT Server Write Req needs response: [%d]", event->need_rsp);
+ BT_INFO("GATT Server Write Req Is Prep: [%d]", event->is_prep);
+
+ if (event->length <= 0) {
+ BT_INFO("GATT Server write requested, but length of attr value is 0");
+ g_free(event);
+ return;
+ }
+
+ need_resp = event->need_rsp;
+ is_prepare_write = event->is_prep;
+
+ write_val = g_memdup(&event->value[0], event->length);
+
+ address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("GATT Server Write Request from remote client [%s]",address);
+ /* DEBUG */
+ if (event->length > 0) {
+ for(i=0; i < event->length; i++)
+ BT_DBG("Data[%d] = [0x%x]",i, event->value[i]);
+ }
+ /* Save Write Request Info */
+ req_info = g_new0(struct gatt_server_req_info, 1);
+ req_info->request_id = event->attr_trans.trans_id;
+ req_info->attribute_handle = event->attr_trans.attr_handle;
+ req_info->connection_id = event->attr_trans.conn_id;
+ req_info->addr = address;
+ req_info->offset = event->attr_trans.offset;
+ req_info->request_type = BLUETOOTH_GATT_REQUEST_TYPE_WRITE;
+ gatt_server_requests = g_slist_append(gatt_server_requests, req_info);
+
+ data = g_variant_new_from_data(
+ G_VARIANT_TYPE_BYTESTRING,
+ write_val,
+ event->length,
+ TRUE, NULL, NULL);
+
+ param = g_variant_new("(iiiiiibbsn@ay)", result,
+ event->attr_trans.conn_id,
+ event->attr_trans.trans_id,
+ event->attr_trans.attr_handle,
+ event->attr_trans.offset,
+ event->length,
+ need_resp,
+ is_prepare_write,
+ address,
+ event->length,
+ data);
+
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
+ param);
+
+ g_free(event);
+ g_free(write_val);
+}
+
+static void __bt_handle_gatt_server_read_requested(event_gatts_srvc_read_attr_t *event)
+{
+ char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ bluetooth_device_address_t dev_addr;
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_server_req_info *req_info = NULL;
+ GVariant *param = NULL;
+ gboolean is_long;
+ BT_INFO("GATT Server Read Requested");
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+
+ BT_INFO("GATT Server-Client Connection ID: [%d]", event->attr_trans.conn_id);
+ BT_INFO("GATT Server-Client Transaction ID: [%d]", event->attr_trans.trans_id);
+ BT_INFO("GATT Server Attribute Handle: [%d]", event->attr_trans.attr_handle);
+ BT_INFO("GATT Server Attribute Offset for read: [%d]", event->attr_trans.offset);
+ BT_INFO("GATT Server Attribute is long: [%d]", event->is_long);
+
+ is_long = event->is_long;
+
+ /* Save Read Request Info */
+ req_info = g_new0(struct gatt_server_req_info, 1);
+ req_info->request_id = event->attr_trans.trans_id;
+ req_info->attribute_handle = event->attr_trans.attr_handle;
+ req_info->connection_id = event->attr_trans.conn_id;
+ req_info->addr = address;
+ req_info->offset = event->attr_trans.offset;
+ req_info->request_type = BLUETOOTH_GATT_REQUEST_TYPE_READ;
+ gatt_server_requests = g_slist_append(gatt_server_requests, req_info);
+
+ /* Send event to BT-API */
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("GATT Server Read Request from remote client [%s]",address);
+
+ param = g_variant_new("(iiiiibs)", result,
+ event->attr_trans.conn_id,
+ event->attr_trans.trans_id,
+ event->attr_trans.attr_handle,
+ event->attr_trans.offset,
+ is_long,
+ address);
+
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
+ param);
+
+ g_free(event);
+}
+
+static void __bt_handle_gatt_server_indicate_confirmed(event_gatts_ind_cnfrm_t *event)
+{
+ bluetooth_device_address_t dev_addr;
+ char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ int cur_connected_clients;
+ static int recvd = 0;
+ gboolean completed = 0;
+ GVariant *param = NULL;
+
+ /* OAL event does provide error, so MW assumes event will never contain wrong data,
+ incase of any issues, check with OAL */
+ int result = BLUETOOTH_ERROR_NONE;
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("Indication sent to GATT client [%s] conn_ ID [%d] transaction ID [%d] Att handle [%d]",
+ address, event->conn_id, event->trans_id, event->attr_handle);
+
+
+ cur_connected_clients = g_slist_length(gatt_client_info_list);
+ BT_INFO("Number of connected clients during sending Indication [%d] & current connected count [%d]",
+ num_indicate_clients, cur_connected_clients);
+
+ recvd++;
+ if (recvd == num_indicate_clients) {
+ BT_INFO("Gatt indication confirm event for last GATT client.. [%s]", address);
+ completed = 1; /* Last event */
+ recvd = 0; /* Reset */
+ num_indicate_clients = 0;
+ }
+
+ param = g_variant_new("(isib)",
+ result,
+ address,
+ event->attr_handle,
+ completed);
+
+ /* Send event to BT-API */
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
+ param);
+
+ BT_INFO("Received Indication confirm for client number [%d]", recvd);
+ g_free(event);
+ g_free(address);
+}
+
+/* Tizen Platform Specific */
+static void __bt_handle_gatt_server_notification_changed(event_gatts_notif_t *event)
+{
+ bluetooth_device_address_t dev_addr;
+ char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ GVariant *param = NULL;
+ gboolean notify;
+
+ /* OAL event does provide error, so MW assumes event will never contain wrong data,
+ incase of any issues, check with OAL */
+ int result = BLUETOOTH_ERROR_NONE;
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("notification_changed [%s] conn_ ID [%d] transaction ID [%d] Att handle [%d] Notify[%d]",
+ address, event->conn_id, event->trans_id, event->attr_handle, event->notify);
+
+ /* Set Notifcation status */
+ notify = event->notify;
+
+ param = g_variant_new("(isib)",
+ result,
+ address,
+ event->attr_handle,
+ notify);
+
+ /* Send event to BT-API */
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
+ param);
+
+ g_free(event);
+ g_free(address);
+}
+
+static void __bt_handle_gatt_mtu_changed_event(event_gatts_mtu_changed_t *event)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_client_info_t *conn_info = NULL;
+ GVariant *param = NULL;
+ guint8 status = 0;
+ BT_INFO("GATT Server MTU changed event");
+
+ conn_info = __bt_find_remote_gatt_client_info_from_conn_id(event->conn_id);
+ if (conn_info == NULL) {
+ BT_ERR("Cant find connection Information");
+ g_free(event);
+ return;
+ }
+ BT_INFO("Got connection Info GATT client [%s] MTU Size [%d]",
+ conn_info->addr, event->mtu_size);
+
+ param = g_variant_new("(isqy)",
+ result,
+ conn_info->addr,
+ event->mtu_size,
+ status);
+
+ /* Send event to BT-API */
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED,
+ param);
+ g_free(event);
}
static void __bt_gatt_event_handler(int event_type, gpointer event_data)
__bt_handle_server_instance_registered(event);
break;
}
+ case OAL_EVENT_GATTS_SERVICE_ADDED: {
+ BT_INFO("OAL Event: GATT Service added");
+ event_gatts_srvc_prm_t *service_parm = g_memdup(event_data, sizeof(event_gatts_srvc_prm_t));
+ __bt_handle_gatt_server_service_added(service_parm);
+ break;
+ }
+ case OAL_EVENT_GATTS_CHARACTERISTIC_ADDED: {
+ BT_INFO("OAL Event: GATT characteristic added");
+ event_gatts_srvc_charctr_t *char_parm = g_memdup(event_data, sizeof(event_gatts_srvc_charctr_t));
+ __bt_handle_gatt_server_characteristic_added(char_parm);
+ break;
+ }
+ case OAL_EVENT_GATTS_DESCRIPTOR_ADDED: {
+ BT_INFO("OAL Event: GATT descriptor added");
+ event_gatts_srvc_descr_t *desc_parm = g_memdup(event_data, sizeof(event_gatts_srvc_descr_t));
+ __bt_handle_gatt_server_descriptor_added(desc_parm);
+ break;
+ }
+ case OAL_EVENT_GATTS_SERVICE_STARTED: {
+ BT_INFO("OAL Event: GATT Service started");
+ event_gatts_srvc_t *svc_started = g_memdup(event_data, sizeof(event_gatts_srvc_t));
+ __bt_handle_gatt_server_service_started(svc_started);
+ break;
+ }
+ case OAL_EVENT_GATTS_SERVICE_STOPED: {
+ BT_INFO("OAL Event: GATT Service stopped");
+ event_gatts_srvc_t *svc_stopped = g_memdup(event_data, sizeof(event_gatts_srvc_t));
+ __bt_handle_gatt_server_service_stopped(svc_stopped);
+ break;
+ }
+ case OAL_EVENT_GATTS_SERVICE_DELETED: {
+ BT_INFO("OAL Event: GATT Service deleted");
+ event_gatts_srvc_t *svc_deleted = g_memdup(event_data, sizeof(event_gatts_srvc_t));
+ __bt_handle_gatt_server_service_deleted(svc_deleted);
+ break;
+ }
+ case OAL_EVENT_GATTS_CONNECTION_COMPLETED: {
+ BT_INFO("OAL Event: GATT Server Connected");
+ event_gatts_conn_t* event = g_memdup(event_data, sizeof(event_gatts_conn_t));
+ __bt_handle_gatt_server_connection_state(event);
+ break;
+ }
+ case OAL_EVENT_GATTS_DISCONNECTION_COMPLETED: {
+ BT_INFO("OAL Event: GATT Server Disconnected");
+ event_gatts_conn_t* event = g_memdup(event_data, sizeof(event_gatts_conn_t));
+ __bt_handle_gatt_server_disconnection_state(event);
+ break;
+ }
+ case OAL_EVENT_GATTS_REQUEST_READ: {
+ BT_INFO("OAL Event: GATT Server Read Request");
+ event_gatts_srvc_read_attr_t *read_req = g_memdup(event_data, sizeof(event_gatts_srvc_read_attr_t));
+ __bt_handle_gatt_server_read_requested(read_req);
+ break;
+ }
+ case OAL_EVENT_GATTS_REQUEST_WRITE: {
+ BT_INFO("OAL Event: GATT Server Write Request");
+ event_gatts_srvc_write_attr_t *write_req = g_memdup(event_data, sizeof(event_gatts_srvc_write_attr_t));
+ __bt_handle_gatt_server_write_requested(write_req);
+ break;
+ }
+ case OAL_EVENT_GATTS_IND_CONFIRM: {
+ BT_INFO("OAL Event: GATT Server Indication confirmed");
+ event_gatts_ind_cnfrm_t *parm = g_memdup(event_data, sizeof(event_gatts_ind_cnfrm_t));
+ __bt_handle_gatt_server_indicate_confirmed(parm);
+ break;
+ }
+ case OAL_EVENT_GATTS_NOTIFICATION: { /* Tizen Platform Specific */
+ BT_INFO("OAL Event: GATT Server DisConnected");
+ event_gatts_notif_t* notif = g_memdup(event_data, sizeof(event_gatts_notif_t));
+ __bt_handle_gatt_server_notification_changed(notif);
+ break;
+ }
+ case OAL_EVENT_GATTS_MTU_CHANGED: {
+ BT_INFO("OAL Event: GATT Server MTU changed event callback");
+ event_gatts_mtu_changed_t *mtu_changed = g_memdup(event_data, sizeof(event_gatts_mtu_changed_t));
+ __bt_handle_gatt_mtu_changed_event(mtu_changed);
+ break;
+ }
default:
break;
}
BT_DBG("-");
}
+
+int _bt_gatt_server_add_service(char *sender, int service_type,
+ int num_handles, char *svc_uuid, int instance_id)
+{
+ BT_CHECK_PARAMETER(svc_uuid, return);
+ BT_CHECK_PARAMETER(sender, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ oal_gatt_srvc_id_t svc_data;
+
+ svc_data.is_prmry = service_type;
+ svc_data.id.inst_id = instance_id;
+
+ BT_INFO("Service UUID [%s] Num handles [%d] Instance ID [%d]", svc_uuid, num_handles, instance_id);
+ _bt_string_to_uuid(svc_uuid, (service_uuid_t*)&svc_data.id.uuid);
+
+ ret = gatts_add_service(instance_id, &svc_data, num_handles);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ return BLUETOOTH_ERROR_NONE;
+}
+
+
+int _bt_gatt_server_add_included_service(char *sender, int instance_id,
+ int service_handle, int included_svc_handle)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ ret = gatts_add_included_services(instance_id, service_handle, included_svc_handle);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_add_characteristic(char *sender, char *char_uuid,
+ bluetooth_gatt_server_attribute_params_t *param)
+{
+ BT_CHECK_PARAMETER(char_uuid, return);
+ BT_CHECK_PARAMETER(sender, return);
+ BT_CHECK_PARAMETER(param, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ oal_uuid_t uuid = {{0}};
+
+ BT_INFO("Char UUID [%s] Instance ID [%d]", char_uuid, param->instance_id);
+ _bt_string_to_uuid(char_uuid, (service_uuid_t*)&uuid);
+
+ BT_INFO("Char permission From API [0x%x]", param->permissions);
+
+ ret = gatts_add_characteristics(param->instance_id, param->service_handle, &uuid,
+ param->properties, (int)param->permissions);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_add_descriptor(char *sender, char *desc_uuid,
+ bt_gatt_permission_t *param, int service_handle, int instance_id)
+{
+ BT_CHECK_PARAMETER(desc_uuid, return);
+ BT_CHECK_PARAMETER(sender, return);
+ BT_CHECK_PARAMETER(param, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ oal_uuid_t uuid = {{0}};
+
+ BT_INFO("Descriptor UUID [%s] Instance ID [%d] Service handle [%d]",
+ desc_uuid, service_handle, instance_id);
+
+ _bt_string_to_uuid(desc_uuid, (service_uuid_t*)&uuid);
+
+ BT_INFO("Descriptor permission From API [0x%x]", *param);
+ ret = gatts_add_descriptor(instance_id, service_handle, &uuid, (int)*param);
+
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_start_service(char *sender, int service_handle, int instance_id)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ ret = gatts_start_service(instance_id, service_handle, BT_GATT_TRANSPORT_LE);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_stop_service(char *sender, int service_handle, int instance_id)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ ret = gatts_stop_service(instance_id, service_handle);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_delete_service(char *sender, int service_handle, int instance_id)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ int ret = OAL_STATUS_SUCCESS;
+ GSList *l;
+ int *handle = NULL;
+
+ ret = gatts_delete_service(instance_id, service_handle);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ /* Remove the Service Handle */
+ for (l = numapps[instance_id].service_handles; l != NULL;) {
+ handle = l->data;
+ l = g_slist_next(l);
+ if (handle && *handle == service_handle) {
+ BT_INFO("Remove Service handle [%d]", *handle);
+ numapps[instance_id].service_handles = g_slist_remove(numapps[instance_id].service_handles, handle);
+ g_free(handle);
+ handle = NULL;
+ }
+ }
+
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_send_response(char *sender, bluetooth_gatt_att_data_t *data,
+ bluetooth_gatt_server_response_params_t *param)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ BT_CHECK_PARAMETER(data, return);
+ BT_CHECK_PARAMETER(param, return);
+ struct gatt_server_req_info *req_info = NULL;
+ int ret = OAL_STATUS_SUCCESS;
+
+ oal_gatt_response_t response;
+
+ BT_INFO("GATT Server Response: Req Type [%d] req_id [%d] status [%d] auth_req [%d] offset[%d] data len[%d]",
+ param->req_type, param->request_id,
+ param->response_status, param->auth_req,
+ data->offset, data->length);
+
+ /* Search for matching Request in List */
+ req_info = __bt_gatt_server_find_request_info(param->request_id, param->req_type);
+ if (!req_info) {
+ BT_ERR("GATT Server Req Info not found for current response..return Error");
+ return BLUETOOTH_ERROR_NOT_IN_OPERATION;
+ }
+
+ memset(&response, 0x00, sizeof(oal_gatt_response_t));
+
+ response.handle = req_info->attribute_handle;
+ response.attr_value.auth_req = param->auth_req;
+ response.attr_value.handle = req_info->attribute_handle;
+ response.attr_value.offset = data->offset;
+ response.attr_value.len = data->length;
+ memcpy(&response.attr_value.value, &data->data, data->length);
+
+
+ ret = gatts_send_response(req_info->connection_id, param->request_id,
+ param->response_status, &response);
+
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ BT_INFO("GATT Server Response successfully sent");
+ /* Remove GATT server request from list */
+ gatt_server_requests = g_slist_remove(gatt_server_requests, req_info);
+ g_free(req_info->addr);
+
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_send_indication(char *sender, bluetooth_device_address_t *dev_addr,
+ bluetooth_gatt_att_data_t *data,
+ bluetooth_gatt_server_indication_params_t *param)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ BT_CHECK_PARAMETER(data, return);
+ BT_CHECK_PARAMETER(param, return);
+ char *address;
+ gboolean all_send = FALSE;
+ int ret = OAL_STATUS_SUCCESS;
+ struct gatt_client_info_t *conn;
+
+ address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(address, dev_addr->addr);
+
+ if (memcmp(dev_addr->addr, BDADDR_ANY, 6) == 0) {
+ BT_INFO("GATT Server: Send Indication to all connected GATT clients..");
+ all_send = TRUE;
+ } else {
+ BT_INFO("GATT Server: Send Indication to connected GATT client addr [%s]", address);
+ }
+
+ /* Attempt to send Notification/Indication to all Connected GATT clients */
+ if (all_send) {
+ ret = __bt_gatt_send_indication_to_all_connected_clients(data, param);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ g_free(address);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ } else {
+ conn = __bt_find_remote_gatt_client_info(address);
+ if (conn) {
+ ret = gatts_send_indication(param->instance_id, param->atrribute_handle,
+ conn->connection_id, data->length,
+ param->need_confirmation, (char *)(&data->data[0]));
+
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ BT_INFO("Indication failed to send to Remote GATT Client [%s]", address);
+ g_free(address);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ BT_INFO("Indication sent to Remote GATT Client [%s] wait for Notification completed event from OAL",address);
+ g_free(address);
+ num_indicate_clients = 1;
+ return BLUETOOTH_ERROR_NONE;
+ }
+ BT_ERR("Remote GATT client [%s] is not connected..Cant send Indication!!", address);
+ g_free(address);
+ return BLUETOOTH_ERROR_NOT_CONNECTED;
+ }
+ g_free(address);
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_gatt_server_update_attribute_value(char *sender, int instance_id,
+ bluetooth_gatt_server_update_value_t *param)
+{
+ BT_CHECK_PARAMETER(sender, return);
+ BT_CHECK_PARAMETER(param, return);
+ int ret = OAL_STATUS_SUCCESS;
+
+ oal_gatt_value_t value;
+ BT_INFO("GATT Server Update value: Instance ID [%d] attr handle [%d] Value len [%d]",
+ instance_id, param->attribute_handle, param->length);
+
+
+ memset(&value, 0x00, sizeof(oal_gatt_value_t));
+
+ value.handle = param->attribute_handle;
+ value.len = param->length;
+ memcpy(&value.value, ¶m->data.data, param->length);
+
+ ret = gatts_update_att_value(instance_id, &value);
+
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ BT_INFO("GATT Server Update Attribute Value successfully");
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_get_att_mtu(bluetooth_device_address_t *address,
+ unsigned int *mtu)
+{
+ BT_CHECK_PARAMETER(address, return);
+ BT_CHECK_PARAMETER(mtu, return);
+ struct gatt_client_info_t *conn_info = NULL;
+ char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+ int ret = OAL_STATUS_SUCCESS;
+ int stack_mtu;
+
+ _bt_convert_addr_type_to_string(addr, address->addr);
+
+ BT_INFO("Get current MTU size for the remote client:DevAddress:[%s]",addr);
+
+ conn_info = __bt_find_remote_gatt_client_info(addr);
+ if (conn_info) {
+ BT_INFO("GATT Client [%s] is connected, conn Id [%d] Instance ID [%d]",
+ conn_info->addr, conn_info->connection_id, conn_info->instance_id);
+ } else {
+ BT_ERR("GATT Client [%s] is not yet connected..");
+ return BLUETOOTH_ERROR_NOT_CONNECTED;
+ }
+
+ ret = gatts_get_att_mtu(conn_info->connection_id, &stack_mtu);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ BT_INFO("ATT MTU received from OAL [%d]", stack_mtu);
+ *mtu = (unsigned int)stack_mtu;
+ return BLUETOOTH_ERROR_NONE;
+}