uint32_t data_len;
} __attribute__((packed));
+#define HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED 0xCF
+struct hal_ev_gatt_client_mtu_exchange_completed {
+ int32_t conn_id;
+ int32_t mtu;
+ int32_t status;
+} __attribute__((packed));
#endif //_BT_HAL_MSG_H_
static int bt_client_if = 0;
+struct conn_mtu_s {
+ int conn_id;
+ int mtu;
+};
static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
gboolean auto_connect);
static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
+static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
/* To send stack event to hal-av handler */
return BT_STATUS_UNSUPPORTED;
}
+static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *g_error = NULL;
+ GVariant *reply = NULL;
+ int result = BT_STATUS_SUCCESS;
+ struct hal_ev_gatt_client_mtu_exchange_completed ev;
+ struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
+
+ DBG("+");
+
+ reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+ g_object_unref(proxy);
+ if (reply == NULL) {
+ ERR("Connect LE Dbus Call Error");
+ if (g_error) {
+ ERR("Error occured in RequestAttMtu [%s]", g_error->message);
+ g_clear_error(&g_error);
+ }
+ result = BT_STATUS_FAIL;
+ }
+ g_variant_unref(reply);
+
+ memset(&ev, 0, sizeof(ev));
+ ev.status = result;
+ ev.mtu = conn_mtu->mtu;
+ ev.conn_id = conn_mtu->conn_id;
+
+ if (!event_cb) {
+ ERR("gatt client callback not registered");
+ } else {
+ DBG("sending gatt client MTU exchange completed event");
+ event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
+ }
+
+ g_free(conn_mtu);
+}
+
+
+static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
+{
+ gchar *device_path = NULL;
+ GDBusProxy *device_proxy = NULL;
+ GDBusConnection *conn;
+ hal_gattc_client_info_t *gattc_client = NULL;
+ char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
+ struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
+
+ conn = _bt_hal_get_system_gconn();
+ if (conn == NULL) {
+ ERR("conn NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
+ if (gattc_client == NULL) {
+ INFO("GATT client conn info not found");
+ return BT_STATUS_FAIL;
+ }
+
+ _bt_hal_convert_addr_type_to_string(device_address,
+ (unsigned char *)gattc_client->bd_addr.address);
+
+ device_path = _bt_hal_get_device_object_path(device_address);
+ if (device_path == NULL) {
+ ERR("device_path NULL : [%s]", device_address);
+ return BT_STATUS_FAIL;
+ }
+
+ device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, BT_HAL_BLUEZ_NAME,
+ device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
+
+ g_free(device_path);
+ if (NULL == device_proxy) {
+ ERR("device_proxy returned NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ conn_mtu->conn_id = conn_id;
+ conn_mtu->mtu = mtu;
+
+ g_dbus_proxy_call(device_proxy, "RequestAttMtu",
+ g_variant_new("(q)", mtu),
+ G_DBUS_CALL_FLAGS_NONE,
+ BT_HAL_MAX_DBUS_TIMEOUT,
+ NULL,
+ (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
+ conn_mtu);
+
+ return BT_STATUS_SUCCESS;
+}
+
/** MTU Exchange request from client */
-bt_status_t configure_mtu(int conn_id, int mtu)
+static bt_status_t configure_mtu(int conn_id, int mtu)
{
CHECK_BTGATT_INIT();
- return BT_STATUS_UNSUPPORTED;
+
+ return __hal_configure_mtu(conn_id, mtu);
}
/** Setup scan filter params */
static void __bt_handle_gatt_client_write_desc(void *buf, uint16_t len);
static void __bt_handle_gatt_client_watch_notification(void *buf, uint16_t len);
static void __bt_handle_gatt_client_changed_value(void *buf, uint16_t len);
+static void __bt_hal_handle_gatt_client_mtu_exchange_completed(void *buf, uint16_t len);
/*****************************************************************************************************/
static bool interface_ready(void)
break;
}
+ case HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED:{
+ __bt_hal_handle_gatt_client_mtu_exchange_completed(buf, len);
+ break;
+ }
default:
DBG("Event Currently not handled!!");
break;
}
}
+static void __bt_hal_handle_gatt_client_mtu_exchange_completed(void *buf, uint16_t len)
+{
+ struct hal_ev_gatt_client_mtu_exchange_completed *ev = buf;
+
+ if (bt_gatt_callbacks->client->configure_mtu_cb)
+ bt_gatt_callbacks->client->configure_mtu_cb(ev->conn_id, ev->status, ev->mtu);
+
+}
+
/*******************************************************************************
**
** Function gatt_init
typedef event_gattc_descriptor_result_t event_gattc_write_data;
+typedef struct {
+ oal_status_t status;
+ int conn_id;
+ int mtu;
+} event_gattc_mtu_configured_t;
+
+
/********* AVRCP CT role callback data structures ******************/
#define MEDIA_ATTIRBUTE_STRING_LENGTH 100
typedef struct {
oal_status_t gatt_send_response_acquire(int conn_id, int trans_id,
int status, int fd, int mtu, void *);
+oal_status_t gattc_configure_mtu(int conn_id, int mtu);
+
#endif /* OAL_GATT_H_ */
static void cb_gattc_register_for_notification(int conn_id, int registered, int status,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id);
static void cb_gattc_notify(int conn_id, btgatt_notify_params_t *p_data);
+static void cb_gattc_configure_mtu_cmpl(int conn_id, int status, int mtu);
/*TODO GATT CLient callbacks will be implemented in subsequent patches */
static const btgatt_client_callbacks_t btgatt_client_callbacks = {
.write_descriptor_cb = cb_gattc_write_descriptor,
.execute_write_cb = NULL,
.read_remote_rssi_cb = NULL,
- .configure_mtu_cb = NULL,
+ .configure_mtu_cb = cb_gattc_configure_mtu_cmpl,
#ifdef PLATFORM_ANDROID_HAL
.scan_filter_cfg_cb = NULL,
.scan_filter_param_cb = NULL,
return OAL_STATUS_SUCCESS;
}
+
+static void cb_gattc_configure_mtu_cmpl(int conn_id, int status, int mtu)
+{
+ event_gattc_mtu_configured_t *event;
+ BT_INFO("BTGATT Client configure mtu complete Callback, conn_id: %d, status: %d, mtu: %d",
+ conn_id, status, mtu);
+ event = g_new0(event_gattc_mtu_configured_t, 1);
+ event->conn_id = conn_id;
+ event->mtu = mtu;
+ event->status = convert_to_oal_status(status);
+ send_event(OAL_EVENT_GATTC_MTU_EXCHANGE_COMPLETED, event, sizeof(*event));
+}
+
/************************************ GATT Client ***********************************/
oal_status_t gattc_register(oal_uuid_t* client_uuid)
{
}
return OAL_STATUS_SUCCESS;
}
+
+oal_status_t gattc_configure_mtu(int conn_id, int mtu)
+{
+ int ret;
+
+ API_TRACE("Configure MTU Size: [%d]", mtu);
+ CHECK_OAL_GATT_ENABLED();
+ CHECK_CLIENT_CONNECTION(conn_id);
+
+ /* To prevent crash in case other libraries not support this api */
+ if (gatt_api->client->configure_mtu == NULL) {
+ BT_WARN("configure_mtu is NULL");
+ return OAL_STATUS_NOT_SUPPORT;
+ }
+
+ ret = gatt_api->client->configure_mtu(conn_id, mtu);
+ if (ret != BT_STATUS_SUCCESS) {
+ BT_ERR("Gatt client configure_mtu error: %s", status2string(ret));
+ return convert_to_oal_status(ret);
+ }
+ return OAL_STATUS_SUCCESS;
+}
}
break;
}
+ case BT_REQ_ATT_MTU: {
+ bluetooth_device_address_t address = { {0} };
+ unsigned int mtu;
+ char *addr;
+
+ sender = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1,
+ &address, sizeof(bluetooth_device_address_t));
+ __bt_service_get_parameters(in_param2,
+ &mtu, sizeof(unsigned int));
+ BT_DBG("BT_REQ_ATT_MTU: %d", mtu);
+ result = _bt_request_att_mtu(&address, mtu);
+ if (BLUETOOTH_ERROR_NONE == result) {
+ addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ BT_INFO("GATT Client: Save Invocation data for BT_REQ_ATT_MTU [%s]", sender);
+
+ _bt_convert_addr_type_to_string(addr, address.addr);
+
+ /* Save the informations to invocation */
+ _bt_save_invocation_context(context, result, sender,
+ function_name, (gpointer)addr);
+ } else {
+ g_array_append_vals(*out_param1, &address,
+ sizeof(bluetooth_device_address_t));
+ }
+ break;
+ }
case BT_SET_LE_STATIC_RANDOM_ADDRESS: {
gboolean is_enable;
#define BT_UUID_STRING_MAX 64
#define BT_SENDER_MAX_LENGTH 50
#define MAX_APPS_SUPPORTED 11 /* Slot 0 is not used */
+#define BT_DEFAULT_ATT_MTU 23
#ifdef TIZEN_GATT_CLIENT
#define NUM_UUID 20
static void __bt_handle_client_notification_registered(event_gattc_regdereg_notify_t *event_data,
gboolean is_registered);
static void __bt_handle_client_notification_data(event_gattc_notify_data *event_data);
+static void __bt_handle_client_mtu_exchange_completed(event_gattc_mtu_configured_t *event_data);
#endif
-
static int __bt_unregister_gatt_server_instance(int server_instance);
+/*mtu device list*/
+struct gatt_mtu_info_t {
+ char *addr; /* Remote GATT Server address */
+ int att_mtu;
+};
+
+static GSList *gatt_mtu_info_list = NULL;
+
+static struct gatt_mtu_info_t *__bt_find_mtu_gatt_device(char *address);
+static void __bt_remove_mtu_gatt_device(char *address);
+static void __bt_add_mtu_gatt_device(char *address);
+static void __bt_update_mtu_gatt_device(char *address, int mtu);
+
/* Linked List of GATT requests from Remote GATT Clients */
static GSList *gatt_server_requests = NULL;
g_free(addr);
break;
}
+ case BT_REQ_ATT_MTU: {
+ char *addr = (char*)req_info->user_data;
+ bluetooth_device_address_t address;
+
+ if (!g_strcmp0(addr, (char*)data)) {
+ BT_INFO("GATT Client BT_REQ_ATT_MTU call pending for app [%s] addr [%s]",
+ req_info->sender, addr);
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+ _bt_convert_addr_string_to_type(address.addr, addr);
+
+ g_array_append_vals(out_param, (bluetooth_device_address_t*)&address,
+ 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);
+ }
+ }
#endif
default:
break;
BT_INFO("Total num of connected Remote GATT Clients [%d]", g_slist_length(gatt_client_info_list));
}
+ __bt_add_mtu_gatt_device(address);
+
g_free(address);
}
g_free(conn_info->addr);
g_free(conn_info);
}
+
+ __bt_remove_mtu_gatt_device(address);
}
#else
BT_INFO("Got connection Info GATT client [%s] MTU Size [%d]",
conn_info->addr, event->mtu_size);
+ __bt_update_mtu_gatt_device(conn_info->addr, event->mtu_size);
+
param = g_variant_new("(isqy)",
result,
conn_info->addr,
case OAL_EVENT_GATTC_NOTIFY_DATA: {
BT_INFO("OAL Event: GATT Client Notification Data");
__bt_handle_client_notification_data((event_gattc_notify_data *) event_data);
-
+ break;
+ }
+ case OAL_EVENT_GATTC_MTU_EXCHANGE_COMPLETED: {
+ BT_INFO("OAL Event: GATT Client MTU Exchange Complete");
+ __bt_handle_client_mtu_exchange_completed((event_gattc_mtu_configured_t *) event_data);
+ break;
}
#endif
default:
return BLUETOOTH_ERROR_NONE;
}
+int _bt_request_att_mtu(bluetooth_device_address_t *device_address,
+ unsigned int mtu)
+{
+ struct gatt_server_info_t *conn_info = NULL;
+ char *addr = NULL;
+ int ret = OAL_STATUS_SUCCESS;
+
+ addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(addr, device_address->addr);
+
+ /* Check if remote GATT Server is connected or not */
+ conn_info = __bt_find_remote_gatt_server_info(addr);
+ if (conn_info) {
+ BT_INFO("GATT Server [%s] is connected, conn Id [%d]",
+ conn_info->addr, conn_info->connection_id);
+ } else {
+ BT_ERR("GATT Server is not yet connected..");
+ g_free(addr);
+ return BLUETOOTH_ERROR_NOT_CONNECTED;
+ }
+
+ ret = gattc_configure_mtu(conn_info->connection_id, mtu);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ g_free(addr);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ g_free(addr);
+ return BLUETOOTH_ERROR_NONE;
+}
+
int _bt_get_att_mtu(bluetooth_device_address_t *address,
unsigned int *mtu)
{
#endif
} else
BT_ERR("Local GATT Client connected event for addr[%s], but device is in connected list already", address);
+
+ __bt_add_mtu_gatt_device(address);
} else
BT_ERR("GATT Client Connection failed!!");
} else
BT_INFO("Can not find conn info, already removed!");
+ __bt_remove_mtu_gatt_device(address);
+
/* If outgoing connection Info is present, then remove it */
out_conn_info = __bt_find_gatt_outgoing_conn_info(address);
if (out_conn_info) {
return BLUETOOTH_ERROR_NOT_FOUND;
}
+static void __bt_handle_client_mtu_exchange_completed(event_gattc_mtu_configured_t *event_data)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_server_info_t *conn_info = NULL;
+ GVariant *param = NULL;
+ guint16 mtu = 0;
+ guint8 status = 0;
+
+ conn_info = __bt_find_remote_gatt_server_info_from_conn_id(event_data->conn_id);
+ if (conn_info == NULL) {
+ BT_ERR("Cant find connection Information");
+ return;
+ }
+
+ BT_INFO("GATT Client: MTU Configured from addr [%s] status [%d] MTU size [%d]",
+ conn_info->addr, event_data->status, event_data->mtu);
+
+ if (event_data->status != OAL_STATUS_SUCCESS)
+ result = BLUETOOTH_ERROR_INTERNAL;
+
+ BT_INFO("reply BT_REQ_ATT_MTU ");
+
+ /* DBUS Return fo BT_REQ_ATT_MTU for all the apps */
+ __bt_gatt_handle_pending_request_info(result, BT_REQ_ATT_MTU, conn_info->addr,
+ BT_ADDRESS_STRING_SIZE);
+
+ if (result == BLUETOOTH_ERROR_NONE) {
+ BT_INFO("sending mtu event");
+
+ mtu = event_data->mtu;
+ param = g_variant_new("(isqy)",
+ result,
+ conn_info->addr,
+ mtu,
+ status);
+
+ /* Send event to BT-API */
+ _bt_send_event(BT_DEVICE_EVENT,
+ BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED,
+ param);
+
+ /* Update the MTU for current connection */
+ BT_INFO("Updating the MTU for current connection");
+ __bt_update_mtu_gatt_device(conn_info->addr, event_data->mtu);
+ }
+}
+
+static struct gatt_mtu_info_t *__bt_find_mtu_gatt_device(char *address)
+{
+ GSList *l = NULL;
+ struct gatt_mtu_info_t *info = NULL;
+
+ BT_INFO("+");
+
+ for (l = gatt_mtu_info_list; l != NULL; l = g_slist_next(l)) {
+ info = (struct gatt_mtu_info_t*)l->data;
+ if (info == NULL)
+ continue;
+
+ if (!g_strcmp0(info->addr, address)) {
+ BT_INFO("Remote GATT device found addr[%s]", info->addr);
+ return info;
+ }
+ }
+
+ BT_INFO("Not found Remote GATT device addr[%s]", address);
+ return NULL;
+}
+
+static void __bt_remove_mtu_gatt_device(char *address)
+{
+ struct gatt_mtu_info_t *dev_info = NULL;
+
+ BT_INFO("+");
+
+ dev_info = __bt_find_mtu_gatt_device(address);
+
+ if (dev_info) {
+ BT_INFO("removing the gatt device from mtu list");
+ gatt_mtu_info_list = g_slist_remove(gatt_mtu_info_list, dev_info);
+ g_free(dev_info->addr);
+ g_free(dev_info);
+ }
+}
+
+static void __bt_add_mtu_gatt_device(char *address)
+{
+ struct gatt_mtu_info_t *dev_info = NULL;
+
+ BT_INFO("+");
+
+ dev_info = __bt_find_mtu_gatt_device(address);
+
+ if (!dev_info) {
+ BT_INFO("adding the gatt device in mtu list");
+ dev_info = g_new0(struct gatt_mtu_info_t, 1);
+ dev_info->addr = g_strdup(address);
+ dev_info->att_mtu = BT_DEFAULT_ATT_MTU;
+ gatt_mtu_info_list = g_slist_append(gatt_mtu_info_list, dev_info);
+ }
+}
+
+static void __bt_update_mtu_gatt_device(char *address, int mtu)
+{
+ struct gatt_mtu_info_t *dev_info = NULL;
+
+ BT_INFO("+");
+
+ dev_info = __bt_find_mtu_gatt_device(address);
+
+ if (dev_info) {
+ BT_INFO("Udating the mtu");
+ dev_info->att_mtu = mtu;
+ }
+}
+
+
#endif
int _bt_unregister_gatt_client_instance(const char *sender,
int client_id);
+int _bt_request_att_mtu(bluetooth_device_address_t *device_address, unsigned int mtu);
#endif
//int _bt_gatt_server_enable_application(int instance_id);