X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service-adaptation%2Fservices%2Fdevice%2Fbt-service-core-device.c;h=58b751888d9cf1a6e8fc528e65825f2234cb88e6;hb=92d30a83d0610031da3f7e7e33adfd6c713dd427;hp=2955a8d628972e925b416286e5dfcdaf434bbcca;hpb=779a52726cf9b05824e8fa0e74e794c047e913ab;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service-adaptation/services/device/bt-service-core-device.c b/bt-service-adaptation/services/device/bt-service-core-device.c index 2955a8d..58b7518 100644 --- a/bt-service-adaptation/services/device/bt-service-core-device.c +++ b/bt-service-adaptation/services/device/bt-service-core-device.c @@ -46,6 +46,10 @@ #endif #include "bt-service-device-internal.h" +#ifdef TIZEN_GATT_CLIENT +#include "bt-service-gatt.h" +#endif + /* OAL headers */ #include #include @@ -120,6 +124,36 @@ static int bond_retry_count; static char *passkey_watcher; static GSList *pin_info_list = NULL; +#ifdef TIZEN_GATT_CLIENT +typedef struct { + char *address; + float interval_min; + float interval_max; + GSList *senders; +} bt_connected_le_dev_t; + +typedef struct { + char *sender; + float interval_min; + float interval_max; + guint16 latency; + guint16 time_out; + float key; +} bt_le_conn_param_t; + +static GSList *le_connected_dev_list = NULL; + +#define BT_LE_CONN_INTERVAL_MIN 7.5 /* msec */ +#define BT_LE_CONN_INTERVAL_MAX 4000 /* msec */ +#define BT_LE_CONN_SUPER_TO_MIN 100 /* msec */ +#define BT_LE_CONN_SUPER_TO_MAX 32000 /* msec */ +#define BT_LE_CONN_SLAVE_LATENCY_MAX 499 +#define BT_LE_CONN_TO_SPLIT 10 /* msec */ +#define BT_LE_CONN_INTERVAL_SPLIT 1.25 /* msec */ + +static void _bt_handle_le_connected_dev_info(const char *address, gboolean connected); +#endif + /* Forward declaration */ static void __bt_device_event_handler(int event_type, gpointer event_data); static void __bt_device_remote_device_found_callback(gpointer event_data, gboolean is_ble); @@ -1337,6 +1371,14 @@ static void __bt_device_conn_state_changed_callback(event_dev_conn_status_t *acl /* Update local cache */ _bt_update_remote_dev_property(address, DEV_PROP_CONNECTED, (void *)&conn_info); +#ifdef TIZEN_GATT_CLIENT + /*handle LE connected device info*/ + if (type) { + BT_DBG("handle LE connected device info"); + _bt_handle_le_connected_dev_info(address, connected); + } +#endif + BT_DBG("-"); } @@ -1916,6 +1958,10 @@ gboolean _bt_is_device_connected(bluetooth_device_address_t *device_address, int case BT_PROFILE_CONN_HSP: svc_id = HFP_HS_SERVICE_ID; /* Remote is HFP HF Unit */ break; +#ifdef TIZEN_GATT_CLIENT + case BT_PROFILE_CONN_GATT: + return _bt_is_remote_gatt_device_connected(device_address); /* Remote is GATT client or Server */ +#endif default: BT_DBG("Unknown svc_type: %d", svc_type); return FALSE; @@ -2100,3 +2146,287 @@ int _bt_unset_pin_code(bluetooth_device_address_t *device_address) BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } + +#ifdef TIZEN_GATT_CLIENT +static bt_connected_le_dev_t *__bt_get_le_connected_dev_info(const char *address) +{ + GSList *l = NULL; + bt_connected_le_dev_t *dev; + + if (!address) + return NULL; + + for (l = le_connected_dev_list; l; l = g_slist_next(l)) { + dev = l->data; + + if (g_strcmp0(dev->address, address) == 0) + return dev; + } + return NULL; +} + +static void __bt_le_conn_param_free(void *data) +{ + bt_le_conn_param_t *param = (bt_le_conn_param_t *)data; + + BT_DBG("%s", param->sender); + g_free(param->sender); + g_free(param); +} + +static void _bt_add_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = g_malloc0(sizeof(bt_connected_le_dev_t)); + dev->address = g_strdup(address); + + le_connected_dev_list = g_slist_append(le_connected_dev_list, dev); + + return; +} + +static void _bt_remove_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return; + + g_slist_free_full(dev->senders, __bt_le_conn_param_free); + le_connected_dev_list = g_slist_remove(le_connected_dev_list, dev); + g_free(dev->address); + g_free(dev); + + return; +} + + +static void _bt_handle_le_connected_dev_info(const char *address, gboolean connected) +{ + BT_DBG("+"); + + if (connected) + _bt_add_le_connected_dev_info(address); + else + _bt_remove_le_connected_dev_info(address); +} + +static bt_le_conn_param_t *__bt_get_le_conn_param_info(bt_connected_le_dev_t *dev, const char *sender) +{ + GSList *l = NULL; + bt_le_conn_param_t *param = NULL; + + if (!dev || !sender) + return NULL; + + for (l = dev->senders; l; l = g_slist_next(l)) { + param = l->data; + if (g_strcmp0(param->sender, sender) == 0) + return param; + } + + return NULL; +} + +static gint __bt_compare_le_conn_param_key(gpointer *a, gpointer *b) +{ + bt_le_conn_param_t *parama = (bt_le_conn_param_t *)a; + bt_le_conn_param_t *paramb = (bt_le_conn_param_t *)b; + + return parama->key > paramb->key; +} + + +int _bt_add_le_conn_param_info(const char *address, const char *sender, + float interval_min, float interval_max, guint16 latency, guint16 time_out) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + bt_le_conn_param_t *data = NULL; + + BT_DBG("+"); + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + + data = g_malloc0(sizeof(bt_le_conn_param_t)); + data->sender = g_strdup(sender); + data->interval_min = interval_min; + data->interval_max = interval_max; + data->latency = latency; + data->time_out = time_out; + data->key = interval_min + (interval_max - interval_min)/2; + + if (param == NULL) { + BT_DBG("Add param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_append(dev->senders, data); + } else { + BT_DBG("Update param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + dev->senders = g_slist_append(dev->senders, data); + } + + /* Sorting. First element have the minimum interval */ + dev->senders = g_slist_sort(dev->senders, + (GCompareFunc)__bt_compare_le_conn_param_key); + + return BLUETOOTH_ERROR_NONE; +} + + +static int __bt_le_set_conn_parameter(const char *address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out) +{ + bt_address_t dev_addr = { {0} }; + guint32 min, max, to; + + BT_INFO("Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", + interval_min, interval_max, latency, time_out); + + min = interval_min / BT_LE_CONN_INTERVAL_SPLIT; + max = interval_max / BT_LE_CONN_INTERVAL_SPLIT; + to = time_out / BT_LE_CONN_TO_SPLIT; + + BT_INFO("updating: Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d", + min, max, latency, to); + + _bt_convert_addr_string_to_type(dev_addr.addr, address); + + return gattc_conn_param_update(&dev_addr, min, max, latency, to); +} + +int _bt_remove_le_conn_param_info(const char *address, const char *sender) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + if (param) { + BT_DBG("Remove param %s %s ", address, sender); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + } + + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_le_connection_update(const char *sender, + unsigned char *device_address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + guint32 min_supervision_to; + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + BT_INFO("Sender %s, Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", + sender, interval_min, interval_max, latency, time_out); + + if (interval_min > interval_max || + interval_min < BT_LE_CONN_INTERVAL_MIN || + interval_max > BT_LE_CONN_INTERVAL_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + if (time_out < BT_LE_CONN_SUPER_TO_MIN || + time_out > BT_LE_CONN_SUPER_TO_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + if (latency > BT_LE_CONN_SLAVE_LATENCY_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + /* + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, + * where Conn_Interval_Max is given in milliseconds. + */ + + min_supervision_to = (1 + latency) * interval_max * 2; + if (time_out <= min_supervision_to) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + _bt_convert_addr_type_to_string(address, device_address); + BT_DBG("Remote device address: %s", address); + + _bt_add_le_conn_param_info(address, sender, interval_min, interval_max, 0, 2000); + + dev = __bt_get_le_connected_dev_info(address); + if (dev == NULL) { + BT_DBG("device not found in the list"); + ret = BLUETOOTH_ERROR_NOT_CONNECTED; + goto fail; + } + + if (g_slist_length(dev->senders) == 1) + goto update; + else { + param = dev->senders->data; + + BT_DBG("dev %f, param %f, input %f", dev->interval_min, param->interval_min, interval_min); + + if (dev->interval_min == param->interval_min && dev->interval_max == param->interval_max) { + BT_DBG("Skip due to same interval"); + return ret; + } + + interval_min = param->interval_min; + interval_max = param->interval_max; + } + +update: + ret = __bt_le_set_conn_parameter(address, interval_min, interval_max, latency, time_out); + + if (ret != OAL_STATUS_SUCCESS) { + _bt_remove_le_conn_param_info(address, sender); + BT_DBG("fail to update the LE connection parameter"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + BT_DBG("updated LE connection parameter"); + dev->interval_min = interval_min; + dev->interval_max = interval_max; + + return BLUETOOTH_ERROR_NONE; +fail: + return ret; +} + +#endif