From 0407e3f0b7b799c7b0d831291ee4577419f1dcee Mon Sep 17 00:00:00 2001 From: DoHyun Pyun Date: Fri, 12 Aug 2016 17:51:55 +0900 Subject: [PATCH] Merge the code from private branch:devel/bluetooth/master ================================================= commit 2fca83fc8992b0475434b40f911eba47e623935e Author: Anurag Biradar Date: Fri Aug 5 15:11:55 2016 +0530 HID: Adding support for dual HID Roles ================================================== Change-Id: I06b445bddbba372d3977904e5225d6ca54b12cb7 Signed-off-by: DoHyun Pyun --- attrib/gatt-service.c | 236 -------- attrib/gatt-service.h | 18 - client/main.c | 1 - gdbus/client.c | 26 +- lib/mgmt.h | 72 +-- lib/uuid.c | 4 +- lib/uuid.h | 3 + monitor/broadcom.c | 706 ++++++++++++++++++++++++ monitor/display.h | 4 + monitor/packet.c | 27 + monitor/packet.h | 8 + obexd/client/manager.c | 7 + obexd/client/session.c | 27 + obexd/client/session.h | 2 + obexd/plugins/messages-tizen.c | 15 +- plugins/dbusoob.c | 73 ++- plugins/neard.c | 7 + profiles/audio/a2dp.c | 13 +- profiles/audio/avdtp.c | 35 +- profiles/audio/avrcp.c | 5 +- profiles/audio/player.c | 8 +- profiles/health/hdp.c | 1 - profiles/input/device.c | 232 +++++++- profiles/input/device.h | 9 + profiles/input/manager.c | 35 +- profiles/input/server.c | 84 ++- profiles/network/bnep.c | 2 + src/adapter.c | 1182 ++++++++++++++-------------------------- src/adapter.h | 58 +- src/adapter_le_vsc_features.c | 39 +- src/adapter_le_vsc_features.h | 6 +- src/attrib-server.c | 15 +- src/device.c | 648 ++++++---------------- src/device.h | 8 +- src/gatt-client.c | 86 +-- src/gatt-database.c | 225 ++++++-- src/main.conf | 89 +++ src/main_hive.conf | 87 +++ src/profile.c | 143 +---- src/shared/att.c | 12 +- src/shared/gatt-client.c | 232 ++++---- src/shared/gatt-db.c | 6 +- src/shared/gatt-db.h | 4 +- src/shared/gatt-server.c | 19 + 44 files changed, 2449 insertions(+), 2070 deletions(-) create mode 100644 src/main.conf create mode 100644 src/main_hive.conf diff --git a/attrib/gatt-service.c b/attrib/gatt-service.c index 7b88380..2cca42f 100644 --- a/attrib/gatt-service.c +++ b/attrib/gatt-service.c @@ -41,9 +41,6 @@ #include "src/attrib-server.h" #include "attrib/gatt-service.h" #include "src/log.h" -#ifdef __TIZEN_PATCH__ -#include "src/device.h" -#endif struct gatt_info { bt_uuid_t uuid; @@ -78,10 +75,6 @@ static GSList *parse_opts(gatt_option opt1, va_list args) struct attrib_cb *cb; GSList *l = NULL; -#ifdef __TIZEN_PATCH__ - if (opt == GATT_OPT_INVALID) - return NULL; -#endif info = g_new0(struct gatt_info, 1); l = g_slist_append(l, info); @@ -216,62 +209,6 @@ static int find_callback(gconstpointer a, gconstpointer b) return cb->event - event; } -#ifdef __TIZEN_PATCH__ -static gboolean add_descriptor(struct btd_adapter *adapter, - uint16_t *handle, struct gatt_info *info) -{ - uint16_t h = *handle; - struct attribute *a; - bt_uuid_t bt_uuid; - uint8_t atval[ATT_MAX_VALUE_LEN]; - GSList *l; - - if (info->uuid.type != BT_UUID16 && info->uuid.type != BT_UUID128) { - error("Discriptors UUID or properties are missing"); - return FALSE; - } - - /* Description declaration */ - if (info->uuid.type == BT_UUID16) - bt_uuid16_create(&bt_uuid, info->uuid.value.u16); - else - bt_uuid128_create(&bt_uuid, info->uuid.value.u128); - - put_uuid_le(&info->uuid, &atval[0]); -/* API not available in bluez 5.25 - * att_put_uuid(info->uuid, &atval[0]);*/ - - a = attrib_db_add(adapter, h++, &bt_uuid, ATT_AUTHENTICATION, - ATT_AUTHENTICATION, atval, info->uuid.type / 8); - - if (a == NULL) { - return FALSE; - } - - for (l = info->callbacks; l != NULL; l = l->next) { - struct attrib_cb *cb = l->data; - - switch (cb->event) { - case ATTRIB_READ: - a->read_cb = cb->fn; - break; - case ATTRIB_WRITE: - a->write_cb = cb->fn; - break; - } - - a->cb_user_data = cb->user_data; - } - - if (info->value_handle != NULL) - *info->value_handle = a->handle; - - *handle = h; - - return TRUE; -} -#endif - static gboolean add_characteristic(struct btd_adapter *adapter, uint16_t *handle, struct gatt_info *info) { @@ -398,179 +335,6 @@ static void service_attr_del(struct btd_adapter *adapter, uint16_t start_handle, } } -#ifdef __TIZEN_PATCH__ -static int is_gatt_connected(gconstpointer a1, gconstpointer a2) -{ - const struct btd_device *dev = a1; - - if (device_get_gatt_connected(dev)) - return 0; - else - return -1; -} - -bool gatt_send_noty_ind(struct btd_adapter *adapter, const bt_uuid_t *uuid, - uint8_t *value, size_t len) -{ - struct attribute *a; - GAttrib *attrib; - GList *l, *connections; - struct btd_device *dev; - uint16_t desc_handle; - - a = attribute_find(adapter, uuid); - if (!a) - return FALSE; - - desc_handle = a->handle + 1; - - connections = (GList *)btd_adapter_get_connections(adapter); - - do { - l = g_list_find_custom(connections, GUINT_TO_POINTER(NULL), - is_gatt_connected); - if (l) { - dev = l->data; - attrib = attrib_from_device(dev); - if (attrib) { - /* Send the characteristic handle and value - * as notification or indication*/ - attrib_send_noty_ind(dev, attrib, a->handle, - desc_handle, value, len); - g_attrib_unref(attrib); - } - connections = (GList *)g_slist_next(connections); - } else - break; - } while(l); - - return TRUE; -} - -bool gatt_update_db(struct btd_adapter *adapter, const bt_uuid_t *uuid, - uint8_t *value, size_t len) -{ - struct attribute *a; - uint8_t status; - - a = attribute_find(adapter, uuid); - if (!a) - return FALSE; - status = attrib_db_update(adapter, a->handle, NULL, value, len, NULL); - - if (status) - return FALSE; - - return TRUE; -} - -bool gatt_add_descriptor(struct btd_adapter *adapter, uint16_t *handle, - uint16_t start_handle, gatt_option opt1, ...) -{ - va_list args; - GSList *disc, *l; - uint16_t disc_handle = *handle; - - va_start(args, opt1); - disc = parse_opts(opt1, args); - va_end(args); - - for (l = disc; l != NULL; l = l->next) { - struct gatt_info *info = l->data; - - DBG("New Descriptor: handle 0x%04x, start handle 0x%04x", - disc_handle, start_handle); - if (!add_descriptor(adapter, &disc_handle, info)) { - goto fail; - } - } - - g_slist_free_full(disc, free_gatt_info); - *handle = disc_handle; - - return TRUE; - -fail: - g_slist_free_full(disc, free_gatt_info); - return FALSE; -} - -bool gatt_add_characteristic(struct btd_adapter *adapter, - uint16_t *handle, uint16_t start_handle, - gatt_option opt1, ...) -{ - va_list args; - GSList *chrs, *l; - uint16_t char_handle = *handle; - - va_start(args, opt1); - chrs = parse_opts(opt1, args); - va_end(args); - - for (l = chrs; l != NULL; l = l->next) { - struct gatt_info *info = l->data; - - DBG("New characteristic: handle 0x%04x, start handle 0x%04x", - char_handle, start_handle); - if (!add_characteristic(adapter, &char_handle, info)) { - service_attr_del(adapter, start_handle, - char_handle - 1); - goto fail; - } - } - - g_slist_free_full(chrs, free_gatt_info); - *handle = char_handle; - - return TRUE; - -fail: - g_slist_free_full(chrs, free_gatt_info); - return FALSE; -} - -void attrib_remove_service(struct btd_adapter *adapter, uint16_t start_handle, - uint16_t end_handle) -{ - DBG("gatt_remove_service"); - service_attr_del(adapter, start_handle, end_handle); -} - -uint16_t gatt_prim_service_add(struct btd_adapter *adapter, uint16_t uuid, - bt_uuid_t *svc_uuid, unsigned int size, - uint16_t *start_handle) -{ - char uuidstr[MAX_LEN_UUID_STR]; - uint16_t handle, h; - - bt_uuid_to_string(svc_uuid, uuidstr, MAX_LEN_UUID_STR); - if (svc_uuid->type != BT_UUID16 && svc_uuid->type != BT_UUID128) { - error("Invalid service uuid: %s", uuidstr); - return FALSE; - } - - handle = attrib_db_find_avail(adapter, svc_uuid, size); - if (handle == 0) { - error("Not enough free handles to register service"); - goto fail; - } - - DBG("New service: handle 0x%04x, UUID %s, %d attributes", - handle, uuidstr, size); - - /* service declaration */ - h = handle; - *start_handle = handle; - if (add_service_declaration(adapter, h++, uuid, svc_uuid) == NULL) - goto fail; - - return h; - -fail: - return 0; -} -#endif - gboolean gatt_service_add(struct btd_adapter *adapter, uint16_t uuid, bt_uuid_t *svc_uuid, gatt_option opt1, ...) { diff --git a/attrib/gatt-service.h b/attrib/gatt-service.h index a1b3fee..d6c61e2 100644 --- a/attrib/gatt-service.h +++ b/attrib/gatt-service.h @@ -67,21 +67,3 @@ typedef enum { gboolean gatt_service_add(struct btd_adapter *adapter, uint16_t uuid, bt_uuid_t *svc_uuid, gatt_option opt1, ...); -#ifdef __TIZEN_PATCH__ -bool gatt_add_descriptor(struct btd_adapter *adapter, uint16_t *handle, - uint16_t start_handle, gatt_option opt1, ...); -bool gatt_add_characteristic(struct btd_adapter *adapter, - uint16_t *handle, uint16_t start_handle, - gatt_option opt1, ...); -uint16_t gatt_prim_service_add(struct btd_adapter *adapter, uint16_t uuid, - bt_uuid_t *svc_uuid, unsigned int size, - uint16_t *start_handle); -void attrib_remove_service(struct btd_adapter *adapter, uint16_t start_handle, - uint16_t end_handle); -bool gatt_update_db(struct btd_adapter *adapter, const bt_uuid_t *uuid, - uint8_t *value, size_t len); -bool gatt_send_noty_ind(struct btd_adapter *adapter, const bt_uuid_t *uuid, - uint8_t *value, size_t len); -bool gatt_send_service_changed_ind(struct btd_adapter *adapter, bt_uuid_t *uuid, - uint16_t start_handle, uint16_t end_handle); -#endif diff --git a/client/main.c b/client/main.c index 4faa9c6..6cc9740 100644 --- a/client/main.c +++ b/client/main.c @@ -1170,7 +1170,6 @@ static void cmd_info(const char *arg) print_uuids(proxy); print_property(proxy, "Modalias"); #ifdef __TIZEN_PATCH__ - print_property(proxy, "Flag"); print_property(proxy, "ManufacturerDataLen"); #endif print_property(proxy, "ManufacturerData"); diff --git a/gdbus/client.c b/gdbus/client.c index 068e778..a011e19 100644 --- a/gdbus/client.c +++ b/gdbus/client.c @@ -853,28 +853,30 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method, if (client == NULL) return FALSE; - data = g_try_new0(struct method_call_data, 1); - if (data == NULL) - return FALSE; - - data->function = function; - data->user_data = user_data; - data->destroy = destroy; - msg = dbus_message_new_method_call(client->service_name, proxy->obj_path, proxy->interface, method); - if (msg == NULL) { - g_free(data); + if (msg == NULL) return FALSE; - } if (setup) { DBusMessageIter iter; dbus_message_iter_init_append(msg, &iter); - setup(&iter, data->user_data); + setup(&iter, user_data); } + if (!function) + return g_dbus_send_message(client->dbus_conn, msg); + + data = g_try_new0(struct method_call_data, 1); + if (data == NULL) + return FALSE; + + data->function = function; + data->user_data = user_data; + data->destroy = destroy; + + if (g_dbus_send_message_with_reply(client->dbus_conn, msg, &call, METHOD_CALL_TIMEOUT) == FALSE) { dbus_message_unref(msg); diff --git a/lib/mgmt.h b/lib/mgmt.h index c89d7d0..0917c3b 100644 --- a/lib/mgmt.h +++ b/lib/mgmt.h @@ -882,7 +882,7 @@ static const char *mgmt_status[] = { #define MGMT_MAX_ADVERTISING_LENGTH 31 -#define MGMT_MAX_MANUFACTURER_DATA_LENGTH 31 +#define MGMT_MAX_EIR_MANUFACTURER_DATA_LENGTH 100 #define MGMT_IRK_SIZE 16 @@ -970,10 +970,6 @@ struct mgmt_cp_stop_le_discovery { uint8_t type; } __packed; -/* BEGIN TIZEN_Bluetooth :: LE auto connection */ -#define MGMT_OP_DISABLE_LE_AUTO_CONNECT (TIZEN_OP_CODE_BASE + 0x0c) -/* END TIZEN_Bluetooth */ - #define MGMT_OP_LE_CONN_UPDATE (TIZEN_OP_CODE_BASE + 0x0d) struct mgmt_cp_le_conn_update { uint16_t interval_min; @@ -985,7 +981,7 @@ struct mgmt_cp_le_conn_update { #define MGMT_OP_SET_MANUFACTURER_DATA (TIZEN_OP_CODE_BASE + 0x0e) struct mgmt_cp_set_manufacturer_data { - uint8_t data[MGMT_MAX_MANUFACTURER_DATA_LENGTH]; + uint8_t data[MGMT_MAX_EIR_MANUFACTURER_DATA_LENGTH]; } __packed; #define MGMT_OP_LE_SET_SCAN_PARAMS (TIZEN_OP_CODE_BASE + 0x0f) @@ -1060,62 +1056,6 @@ struct mgmt_cp_set_dev_rpa_res_support { uint8_t res_support; } __packed; -/* Currently there is no support in kernel for below MGMT cmd opcodes. */ -#if 0 // Not defined in kernel -#define MGMT_OP_READ_RSSI (TIZEN_OP_CODE_BASE + 0x11) -struct mgmt_cp_read_rssi { - bdaddr_t bdaddr; -} __packed; -struct mgmt_rp_read_rssi { - uint8_t status; - bdaddr_t bdaddr; - int8_t rssi; -} __packed; - -#define MGMT_OP_L2CAP_CONN_PARAM_UPDATE (TIZEN_OP_CODE_BASE + 0x12) -struct mgmt_cp_l2cap_conn_param_update { - bdaddr_t bdaddr; - uint16_t interval_min; - uint16_t interval_max; - uint16_t latency; - uint16_t supervision_time_out; -} __packed; - -#define MGMT_OP_WRITE_SEC_CONN_HOST_SUPPORT (TIZEN_OP_CODE_BASE + 0x13) -#define MGMT_WRITE_SEC_CONN_HOST_SUPPORT_SIZE 1 -struct mgmt_cp_write_sec_conn_host_support { - uint8_t secure_connection_host_support; -} __packed; -struct mgmt_rp_write_sec_conn_host_support { - uint8_t status; -} __packed; - -#define MGMT_OP_READ_SEC_CONN_HOST_SUPPORT (TIZEN_OP_CODE_BASE + 0x14) -struct mgmt_rp_read_sec_conn_host_support { - uint8_t status; - uint8_t sec_conn_host_support; -} __packed; - -#define MGMT_OP_WRITE_AUTH_PAYLOAD_TIMEOUT (TIZEN_OP_CODE_BASE + 0x15) -struct mgmt_cp_write_auth_payload_timeout { - bdaddr_t bdaddr; - uint16_t auth_payload_timeout; -} __packed; -struct mgmt_rp_write_auth_payload_timeout { - uint8_t status; -} __packed; - -#define MGMT_OP_READ_AUTH_PAYLOAD_TIMEOUT (TIZEN_OP_CODE_BASE + 0x16) -struct mgmt_cp_read_auth_payload_timeout { - bdaddr_t bdaddr; -} __packed; -struct mgmt_rp_read_auth_payload_timeout { - uint8_t status; - uint16_t auth_payload_timeout; -} __packed; -#endif - - /* BEGIN TIZEN_Bluetooth :: name update changes */ #define MGMT_EV_DEVICE_NAME_UPDATE (TIZEN_EV_BASE + 0x01) struct mgmt_ev_device_name_update { @@ -1202,14 +1142,6 @@ struct mgmt_ev_le_data_length_changed { int16_t max_rx_time; } __packed; -/* Currently there is no support in kernel for below MGMT events. */ -#if 0 // Not defined in kernel -#define MGMT_EV_NEW_LOCAL_IRK (TIZEN_EV_BASE + 0x0b) -struct mgmt_ev_new_local_irk { - uint8_t irk[16]; -} __packed; -#endif - static const char *mgmt_tizen_op[] = { "<0x0000>", "Set Advertising Parameters", diff --git a/lib/uuid.c b/lib/uuid.c index 20b67d0..ac071fa 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -183,14 +183,14 @@ static inline int is_uuid128(const char *string) static inline int is_base_uuid128(const char *string) { uint16_t uuid; - char dummy; + char dummy[2]; if (!is_uuid128(string)) return 0; return sscanf(string, "0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]", - &uuid, &dummy, &dummy, &dummy, &dummy) == 5; + &uuid, dummy, dummy, dummy, dummy) == 5; } static inline int is_uuid32(const char *string) diff --git a/lib/uuid.h b/lib/uuid.h index 542ef60..6ba8e12 100644 --- a/lib/uuid.h +++ b/lib/uuid.h @@ -91,6 +91,9 @@ extern "C" { #define HDP_SINK_UUID "00001402-0000-1000-8000-00805f9b34fb" #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +#define HID_DEVICE_UUID "00001124-0000-1000-8000-00805f9b43bf" +#endif #define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb" diff --git a/monitor/broadcom.c b/monitor/broadcom.c index a3c3443..58ac37d 100644 --- a/monitor/broadcom.c +++ b/monitor/broadcom.c @@ -35,6 +35,9 @@ #include "ll.h" #include "vendor.h" #include "broadcom.h" +#ifdef __TIZEN_PATCH__ +#include "uuid.h" +#endif static void print_status(uint8_t status) { @@ -93,6 +96,599 @@ static void launch_ram_cmd(const void *data, uint8_t size) print_field("Address: 0x%8.8x", addr); } +#ifdef __TIZEN_PATCH__ +static void set_advt_param_multi_subcmd(const void *data, uint8_t size) +{ + uint8_t adv_instance = get_u8(data + size - 2); + int8_t tx_power = *((int8_t *)(data + size - 1)); + + print_le_set_adv_parameters_cmd(data, size - 2); + + print_field("Advertising Instance: %u", adv_instance); + print_field("TX Power: %d", tx_power); +} + +static void set_advt_data_subcmd(const void *data, uint8_t size) +{ + uint8_t adv_instance = get_u8(data + size - 1); + + print_le_set_adv_data_cmd(data, size - 1); + + print_field("Advertising Instance: %u", adv_instance); +} + +static void set_scan_rsp_data_multi_subcmd(const void *data, uint8_t size) +{ + uint8_t adv_instance = get_u8(data + size - 1); + + print_le_set_scan_rsp_data_cmd(data, size - 1); + + print_field("Advertising Instance: %u", adv_instance); +} + +static void set_random_addr_multi_subcmd(const void *data, uint8_t size) +{ + uint8_t adv_instance = get_u8(data + size - 1); + + print_le_set_random_address_cmd(data, size - 1); + + print_field("Advertising Instance: %u", adv_instance); +} + +static void set_adv_enable_multi_subcmd(const void *data, uint8_t size) +{ + uint8_t adv_instance = get_u8(data + size - 1); + + print_le_set_adv_enable_cmd(data, size - 1); + + print_field("Advertising Instance: %u", adv_instance); +} + +static void enable_custom_feature_subcmd(const void *data, uint8_t size) +{ + uint8_t enable = get_u8(data); + const char *str; + + switch (enable) { + case 0x00: + str = "Disable"; + break; + case 0x01: + str = "Enable"; + break; + default: + str = "Reserved"; + break; + } + + print_field("%s offloaded RPA feature (0x%2.2x)", str, enable); +} + +static void add_irk_to_list_subcmd(const void *data, uint8_t size) +{ + uint8_t addr_type = get_u8(data + 16); + const uint8_t *addr = data + 17; + const char *str; + + print_field("LE IRK (1st byte LSB)"); + packet_hexdump(data, 16); + + switch (addr_type) { + case 0x00: + str = "Public Address"; + break; + case 0x01: + str = "Random Address"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Address type : %s (0x%2.2x)", str, addr_type); + print_field("Address : %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +static void remove_irk_from_list_subcmd(const void *data, uint8_t size) +{ + uint8_t addr_type = get_u8(data); + const uint8_t *addr = data + 1; + const char *str; + + switch (addr_type) { + case 0x00: + str = "Public Address"; + break; + case 0x01: + str = "Random Address"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Address type : %s (0x%2.2x)", str, addr_type); + print_field("Address : %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +static void read_irk_list_entry_subcmd(const void *data, uint8_t size) +{ + uint8_t index = get_u8(data); + + print_field("LE Read IRK List entry index : %u", index); +} + +static void apcf_enable_subcmd(const void *data, uint8_t size) +{ + uint8_t enable = get_u8(data); + const char *str; + + switch (enable) { + case 0x00: + str = "Disable"; + break; + case 0x01: + str = "Enable"; + break; + default: + str = "Reserved"; + break; + } + + print_field("%s APCF feature (0x%2.2x)", str, enable); +} + +static const struct { + uint8_t bit; + const char *str; +} apcf_feature_table[] = { + { 0, "Broadcast Address filter" }, + { 1, "Service Data Change filter" }, + { 2, "Service UUID check" }, + { 3, "Service Solicitation UUID check" }, + { 4, "Local Name check" }, + { 5, "Manufacturer Data check" }, + { 6, "Service Data check" }, + { } +}; + +static void print_apcf_feature(const char *label, uint16_t feature) +{ + int i; + uint16_t mask; + + mask = feature; + + print_field("%s", label); + + for (i = 0; apcf_feature_table[i].str; i++) { + if (feature & (1 << apcf_feature_table[i].bit)) { + print_field(" %s", apcf_feature_table[i].str); + mask &= ~(1 << apcf_feature_table[i].bit); + } + } + + if (mask) + print_field(" Unknown features (0x%4.4x)", mask); +} + +static void apcf_set_filtering_param_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + uint16_t feature_selection = get_le16(data + 2); + uint16_t list_logic = get_le16(data + 4); + uint16_t filter_logic = get_u8(data + 6); + uint8_t rssi_high = get_u8(data + 8); + uint8_t delivery_mode = get_u8(data + 9); + uint16_t onfound_timeout = get_le16(data + 10); + uint8_t onfound_timeout_cnt = get_u8(data + 12); + uint8_t rssi_low = get_u8(data + 13); + uint16_t onlost_timeout = get_le16(data + 14); + uint16_t no_of_tracking_entries; + const char *str; + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + + print_apcf_feature("Feature Selection", feature_selection); + print_apcf_feature("List Logic Type (OR)", ~list_logic); + print_apcf_feature("List Logic Type (AND)", list_logic); + print_apcf_feature("Filter Logic Type (OR)", ~(filter_logic << 3)); + print_apcf_feature("Filter Logic Type (AND)", filter_logic << 3); + print_field("RSSI High Threshold : %d dBm", rssi_high); + + switch (delivery_mode) { + case 0x00: + str = "Immediate"; + break; + case 0x01: + str = "On Found"; + break; + case 0x02: + str = "Batched"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Delivery_mode : %s", str); + print_field("On Found Timeout : %d miliseconds", onfound_timeout); + print_field("On Found Timeout Count : %d", onfound_timeout_cnt); + print_field("RSSI Low Threshold : %d dBm", rssi_low); + print_field("On Lost Timeout : %d miliseconds", onlost_timeout); + + if (size >= 18) { + no_of_tracking_entries = get_le16(data + 16); + print_field("Number of Tracking Entries : %d", + no_of_tracking_entries); + } +} + +static void apcf_broadcaster_addr_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + uint8_t type = get_u8(data + 7); + char *str; + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + packet_print_addr("Address", data + 2, type == 0x00 ? false : true); +} + +static void apcf_service_uuid_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + char *str; + const uint8_t *uuid; + uint16_t uuid16; + uint32_t uuid32; + + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + + switch ((size - 2) / 2) { + case 2: + uuid16 = get_le16(data + 2); + print_field(" UUID : %s (0x%4.4x)", + uuid16_to_str(uuid16), uuid16); + + uuid16 = get_le16(data + 4); + print_field(" UUID Mask: %s (0x%4.4x)", + uuid16_to_str(uuid16), uuid16); + break; + case 4: + uuid32 = get_le32(data + 2); + print_field(" UUID :%s (0x%8.8x)", + uuid32_to_str(uuid32), uuid32); + + uuid32 = get_le32(data + 6); + print_field(" UUID Mask:%s (0x%8.8x)", + uuid32_to_str(uuid32), uuid32); + break; + case 16: + uuid = data + 2; + print_field(" UUID :%8.8x-%4.4x-%4.4x-%4.4x-%8.8x%4.4x", + get_le32(&uuid[12]), get_le16(&uuid[10]), + get_le16(&uuid[8]), get_le16(&uuid[6]), + get_le32(&uuid[2]), get_le16(&uuid[0])); + uuid = data + 18; + print_field(" UUID :%8.8x-%4.4x-%4.4x-%4.4x-%8.8x%4.4x", + get_le32(&uuid[12]), get_le16(&uuid[10]), + get_le16(&uuid[8]), get_le16(&uuid[6]), + get_le32(&uuid[2]), get_le16(&uuid[0])); + break; + default: + print_field("Invalid UUIDs"); + packet_hexdump(data + 2, size - 2); + break; + } + + return; +} + +static void apcf_service_solicitation_uuid_subcmd(const void *data, uint8_t size) +{ + apcf_service_uuid_subcmd(data, size); +} + +static void apcf_local_name_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + char *str; + char name[30] = { 0 }; + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + + memcpy(name, data + 2, size - 2 < 29 ? size - 2 : 29); + print_field("Local Name : %s", name); +} + +static void apcf_manufacturer_data_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + char *str; + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + + print_field("Manufacturer data"); + packet_hexdump(data + 2, (size - 2 ) / 2); + + print_field("Manufacturer data Mask"); + packet_hexdump(data + 2 + (size - 2) / 2, (size - 2 ) / 2); +} + +static void apcf_service_data_subcmd(const void *data, uint8_t size) +{ + uint8_t add = get_u8(data); + uint8_t index = get_u8(data + 1); + char *str; + + switch (add) { + case 0x00: + str = "Add"; + break; + case 0x01: + str = "Delete"; + break; + case 0x02: + str = "Clear"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Action : %s for filter [%d]", str, index); + + print_field("Service data"); + packet_hexdump(data + 2, (size - 2 ) / 2); + + print_field("Service data Mask"); + packet_hexdump(data + 2 + (size - 2) / 2, (size - 2 ) / 2); +} + +struct subcmd_data { + uint8_t subcmd; + const char *str; + void (*cmd_func) (const void *data, uint8_t size); + uint8_t cmd_size; + bool cmd_fixed; +}; + +static void print_subcmd(const struct subcmd_data *subcmd_data, + const void *data, uint8_t size) +{ + const char *subcmd_color; + + if (subcmd_data->cmd_func) + subcmd_color = COLOR_BLUE; + else + subcmd_color = COLOR_WHITE_BG; + + print_indent(6, subcmd_color, "", subcmd_data->str, COLOR_OFF, + " (0x%2.2x)", subcmd_data->subcmd); + + if (!subcmd_data->cmd_func) { + packet_hexdump(data, size); + return; + } + + if (subcmd_data->cmd_fixed) { + if (size != subcmd_data->cmd_size) { + print_text(COLOR_ERROR, "invalid packet size"); + packet_hexdump(data, size); + return; + } + } else { + if (size < subcmd_data->cmd_size) { + print_text(COLOR_ERROR, "too short packet"); + packet_hexdump(data, size); + return; + } + } + + subcmd_data->cmd_func(data, size); +} + +static const struct subcmd_data le_multi_advt_table[] = { + { 0x01, "LE Set Advertising Parameters Multi Sub Command", + set_advt_param_multi_subcmd, 23, true }, + { 0x02, "LE Set Advertising Data Multi Sub Command", + set_advt_data_subcmd, 33, false }, + { 0x03, "LE Set Scan Response Data Multi Sub Command", + set_scan_rsp_data_multi_subcmd, 33, false }, + { 0x04, "LE Set Random Address Multi Sub Command", + set_random_addr_multi_subcmd, 7, true }, + { 0x05, "LE Set Advertise Enable Multi Sub Command", + set_adv_enable_multi_subcmd, 2, true }, + { } +}; + +static void le_multi_advt_cmd(const void *data, uint8_t size) +{ + uint8_t subcmd = *((const uint8_t *)data); + struct subcmd_data unknown; + const struct subcmd_data *subcmd_data = &unknown; + int i; + + unknown.subcmd = subcmd; + unknown.str = "Unknown Sub Command"; + unknown.cmd_func = NULL; + unknown.cmd_size = 0; + unknown.cmd_fixed = true; + + for (i = 0; le_multi_advt_table[i].str; i++) { + if (le_multi_advt_table[i].subcmd == subcmd) { + subcmd_data = &le_multi_advt_table[i]; + break; + } + } + + print_subcmd(subcmd_data, data + 1, size - 1); +} + +static const struct subcmd_data le_rpa_offload_table[] = { + { 0x01, "Enable customer specific feature", + enable_custom_feature_subcmd, 1, true }, + { 0x02, "Add IRK to the list", + add_irk_to_list_subcmd, 23, true }, + { 0x03, "Remove IRK from the list", + remove_irk_from_list_subcmd, 7, true }, + { 0x04, "Clear IRK list", + null_cmd, 0, true }, + { 0x05, "Read IRK list entry", + read_irk_list_entry_subcmd, 1, true }, + { } +}; + +static void le_rpa_offload_cmd(const void *data, uint8_t size) +{ + uint8_t subcmd = *((const uint8_t *)data); + struct subcmd_data unknown; + const struct subcmd_data *subcmd_data = &unknown; + int i; + + unknown.subcmd = subcmd; + unknown.str = "Unknown Sub Command"; + unknown.cmd_func = NULL; + unknown.cmd_size = 0; + unknown.cmd_fixed = true; + + for (i = 0; le_rpa_offload_table[i].str; i++) { + if (le_rpa_offload_table[i].subcmd == subcmd) { + subcmd_data = &le_rpa_offload_table[i]; + break; + } + } + + print_subcmd(subcmd_data, data + 1, size - 1); +} + +static const struct subcmd_data le_apcf_table[] = { + { 0x00, "APCF Enable", + apcf_enable_subcmd, 1, true }, + { 0x01, "APCF Set Filtering Parameters", + apcf_set_filtering_param_subcmd, 15, false }, + { 0x02, "APCF Broadcaster Address", + apcf_broadcaster_addr_subcmd, 9, true }, + { 0x03, "APCF Service UUID", + apcf_service_uuid_subcmd, 2, false }, + { 0x04, "APCF Service Solicitation UUID", + apcf_service_solicitation_uuid_subcmd, 2, false }, + { 0x05, "APCF Local Name", + apcf_local_name_subcmd, 2, false }, + { 0x06, "APCF Manufacturer Data", + apcf_manufacturer_data_subcmd, 2, false }, + { 0x07, "APCF Service Data", + apcf_service_data_subcmd, 2, false }, + { } +}; + +static void le_apcf_cmd(const void *data, uint8_t size) +{ + uint8_t subcmd = *((const uint8_t *)data); + struct subcmd_data unknown; + const struct subcmd_data *subcmd_data = &unknown; + int i; + + unknown.subcmd = subcmd; + unknown.str = "Unknown Sub Command"; + unknown.cmd_func = NULL; + unknown.cmd_size = 0; + unknown.cmd_fixed = true; + + for (i = 0; le_apcf_table[i].str; i++) { + if (le_apcf_table[i].subcmd == subcmd) { + subcmd_data = &le_apcf_table[i]; + break; + } + } + + print_subcmd(subcmd_data, data + 1, size - 1); +} +#endif + static void read_vid_pid_rsp(const void *data, uint8_t size) { uint8_t status = get_u8(data); @@ -132,6 +728,97 @@ static void read_verbose_version_info_rsp(const void *data, uint8_t size) print_field("Build number: %u (0x%4.4x)", build_num, build_num); } +#ifdef __TIZEN_PATCH__ +static void get_vendor_capabilities_rsp(const void *data, uint8_t size) +{ + uint8_t status = get_u8(data); + uint8_t max_advt_instances = get_u8(data + 1); + uint8_t offloaded_resolution_of_private_address = get_u8(data + 2); + uint16_t total_scan_results_storage = get_le16(data + 3); + uint8_t max_irk_list_sz = get_u8(data + 5); + uint8_t filtering_support = get_u8(data + 6); + uint8_t max_filter = get_u8(data + 7); + uint8_t activity_energy_info_support = get_u8(data + 8); + uint8_t onlost_follow_per_filter = get_u8(data + 9); + + print_status(status); + print_field("The Number of advertisement instances supported: %u", + max_advt_instances); + print_field("BT chip capability of RPA: %s", + offloaded_resolution_of_private_address ? + "Capable" : "Not Capable"); + print_field("Storage for scan results: %u bytes", + total_scan_results_storage); + print_field("The Number of IRK entries supported: %u", max_irk_list_sz); + print_field("Support Filtering in BT chip: %s", + filtering_support ? "Supported" : "Not Supported"); + print_field("The Number of filters supported: %u", max_filter); + print_field("Supports reporting of activity and energy info: %s", + activity_energy_info_support ? + "Capable" : "Not Capable"); + print_field("The Number of advertisers that can be analysed for " + "onlost per filter: %u", onlost_follow_per_filter); +} + +static void le_multi_advt_rsp(const void *data, uint8_t size) +{ + uint8_t status = get_u8(data); + uint8_t subcmd = get_u8(data + 1); + int i; + const char *str = "Unknown Sub Command"; + + print_status(status); + + for (i = 0; le_multi_advt_table[i].str; i++) { + if (le_multi_advt_table[i].subcmd == subcmd) { + str = le_multi_advt_table[i].str; + break; + } + } + + print_field("Multi Advertise OPcode: %s (%u)", str, subcmd); +} + +static void le_rpa_offload_rsp(const void *data, uint8_t size) +{ + uint8_t status = get_u8(data); + uint8_t subcmd = get_u8(data + 1); + int i; + const char *str = "Unknown Sub Command"; + + print_status(status); + + for (i = 0; le_rpa_offload_table[i].str; i++) { + if (le_rpa_offload_table[i].subcmd == subcmd) { + str = le_rpa_offload_table[i].str; + break; + } + } + + print_field("RPA Offload OPcode: %s (%u)", str, subcmd); +} + +static void le_apcf_rsp(const void *data, uint8_t size) +{ + uint8_t status = get_u8(data); + uint8_t subcmd = get_u8(data + 1); + int i; + const char *str = "Unknown Sub Command"; + + print_status(status); + + for (i = 0; le_apcf_table[i].str; i++) { + if (le_apcf_table[i].subcmd == subcmd) { + str = le_apcf_table[i].str; + break; + } + } + + print_field("Advertising Packet Content Filter OPcode: %s (%u)", + str, subcmd); +} +#endif + static const struct vendor_ocf vendor_ocf_table[] = { { 0x001, "Write BD ADDR", write_bd_addr_cmd, 6, true, @@ -157,6 +844,25 @@ static const struct vendor_ocf vendor_ocf_table[] = { { 0x079, "Read Verbose Config Version Info", null_cmd, 0, true, read_verbose_version_info_rsp, 7, true }, +#ifdef __TIZEN_PATCH__ + { 0x0153, "LE Get Vendor Capabilities", + null_cmd, 0, true, + get_vendor_capabilities_rsp, 10, false }, + { 0x0154, "LE Multi Advertise", + le_multi_advt_cmd, 1, false, + le_multi_advt_rsp, 2, true }, + { 0x0155, "LE RPA Offload", + le_rpa_offload_cmd, 1, false, + le_rpa_offload_rsp, 2, false }, +#if 0 + { 0x0156, "LE Batch Scan", + le_batch_scan_cmd, 1, false, + le_batch_scan_rsp, 2, true }, +#endif + { 0x0157, "LE APCF", + le_apcf_cmd, 1, false, + le_apcf_rsp, 2, false }, +#endif { } }; diff --git a/monitor/display.h b/monitor/display.h index 36e189a..fc75b45 100644 --- a/monitor/display.h +++ b/monitor/display.h @@ -43,7 +43,11 @@ bool use_color(void); #define COLOR_INFO COLOR_OFF #define COLOR_DEBUG COLOR_WHITE +#ifdef __TIZEN_PATCH__ +#define FALLBACK_TERMINAL_WIDTH 130 +#else #define FALLBACK_TERMINAL_WIDTH 80 +#endif #define print_indent(indent, color1, prefix, title, color2, fmt, args...) \ do { \ diff --git a/monitor/packet.c b/monitor/packet.c index 322bba6..7b7822f 100644 --- a/monitor/packet.c +++ b/monitor/packet.c @@ -9073,3 +9073,30 @@ void packet_todo(void) printf("\t%s\n", le_meta_event_table[i].str); } } + +#ifdef __TIZEN_PATCH__ +void print_le_set_adv_parameters_cmd(const void *data, uint8_t size) +{ + le_set_adv_parameters_cmd(data, size); +} + +void print_le_set_random_address_cmd(const void *data, uint8_t size) +{ + le_set_random_address_cmd(data, size); +} + +void print_le_set_adv_data_cmd(const void *data, uint8_t size) +{ + le_set_adv_data_cmd(data, size); +} + +void print_le_set_scan_rsp_data_cmd(const void *data, uint8_t size) +{ + le_set_scan_rsp_data_cmd(data, size); +} + +void print_le_set_adv_enable_cmd(const void *data, uint8_t size) +{ + le_set_adv_enable_cmd(data, size); +} +#endif diff --git a/monitor/packet.h b/monitor/packet.h index 322f101..59cbd6e 100644 --- a/monitor/packet.h +++ b/monitor/packet.h @@ -90,3 +90,11 @@ void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index, bool in, const void *data, uint16_t size); void packet_todo(void); + +#ifdef __TIZEN_PATCH__ +void print_le_set_adv_parameters_cmd(const void *data, uint8_t size); +void print_le_set_random_address_cmd(const void *data, uint8_t size); +void print_le_set_adv_data_cmd(const void *data, uint8_t size); +void print_le_set_scan_rsp_data_cmd(const void *data, uint8_t size); +void print_le_set_adv_enable_cmd(const void *data, uint8_t size); +#endif diff --git a/obexd/client/manager.c b/obexd/client/manager.c index 8eaceaf..32853fc 100644 --- a/obexd/client/manager.c +++ b/obexd/client/manager.c @@ -253,9 +253,16 @@ static DBusMessage *remove_session(DBusConnection *connection, ERROR_INTERFACE ".NotAuthorized", "Not Authorized"); +#ifdef __TIZEN_PATCH__ + obc_session_update(session, message, connection); +#endif release_session(session); +#ifdef __TIZEN_PATCH__ + return NULL; +#else return dbus_message_new_method_return(message); +#endif } static const GDBusMethodTable client_methods[] = { diff --git a/obexd/client/session.c b/obexd/client/session.c index 391d713..75bc3cb 100644 --- a/obexd/client/session.c +++ b/obexd/client/session.c @@ -117,6 +117,10 @@ struct obc_session { guint process_id; char *folder; struct callback_data *callback; +#ifdef __TIZEN_PATCH__ + DBusMessage *message; + DBusConnection *connection; +#endif }; static GSList *sessions = NULL; @@ -142,6 +146,17 @@ struct obc_session *obc_session_ref(struct obc_session *session) return session; } +#ifdef __TIZEN_PATCH__ +void obc_session_update(struct obc_session *session, DBusMessage *message, + DBusConnection *connection) +{ + DBG("+"); + session->message = dbus_message_ref(message); + session->connection = dbus_connection_ref(connection); + DBG("-"); +} +#endif + static void session_unregistered(struct obc_session *session) { char *path; @@ -266,6 +281,18 @@ static void disconnect_complete(GObex *obex, GError *err, GObexPacket *rsp, if (err) error("%s", err->message); +#ifdef __TIZEN_PATCH__ + if (session->message) { + /* Dbus reply need to be done */ + DBG("Dbus reply for remove_session"); + g_dbus_send_reply(session->connection, session->message, + DBUS_TYPE_INVALID); + dbus_message_unref(session->message); + dbus_connection_unref(session->connection); + session->message = NULL; + session->connection = NULL; + } +#endif /* Disconnect transport */ if (session->id > 0 && session->transport != NULL) { session->transport->disconnect(session->id); diff --git a/obexd/client/session.h b/obexd/client/session.h index 10d0272..14704be 100644 --- a/obexd/client/session.h +++ b/obexd/client/session.h @@ -82,4 +82,6 @@ void obc_session_cancel(struct obc_session *session, guint id, gboolean remove); #ifdef __TIZEN_PATCH__ void release_session(struct obc_session *session); +void obc_session_update(struct obc_session *session, DBusMessage *message, + DBusConnection *connection); #endif diff --git a/obexd/plugins/messages-tizen.c b/obexd/plugins/messages-tizen.c index 7613484..4797da6 100644 --- a/obexd/plugins/messages-tizen.c +++ b/obexd/plugins/messages-tizen.c @@ -1154,8 +1154,19 @@ int messages_push_message(void *session, const char *folder, DBG("session->cwd %s +\n", s->cwd); - if (folder) - folder_path = g_strdup(folder); + if (g_ascii_strncasecmp(s->cwd, "/telecom/msg", + strlen("/telecom/msg")) != 0) { + DBG("Path Not Set properly"); + return -1; + } + + if ((folder[0] == '\0') && (g_strcmp0(s->cwd, "/telecom/msg") == 0)) { + DBG("Invalid Folders"); + return -1; + } + + if ((folder[0] != '\0')) + folder_path = g_strconcat("/telecom/msg/", folder, NULL); else folder_path = g_strdup(s->cwd); diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c index 2563dc5..20a90f6 100644 --- a/plugins/dbusoob.c +++ b/plugins/dbusoob.c @@ -23,6 +23,7 @@ * */ +#ifdef __TIZEN_PATCH__ #ifdef HAVE_CONFIG_H #include #endif @@ -38,7 +39,6 @@ #include "src/log.h" #include "src/dbus-common.h" #include "src/adapter.h" -#include "src/oob.h" #include "src/device.h" #include "src/eir.h" #include "src/agent.h" @@ -75,8 +75,10 @@ static struct oob_request *find_oob_request(struct btd_adapter *adapter) return NULL; } -static void read_local_data_complete(struct btd_adapter *adapter, uint8_t *hash, - uint8_t *randomizer) +static void read_local_data_complete(struct btd_adapter *adapter, + const uint8_t *hash192, const uint8_t *randomizer192, + const uint8_t *hash256, const uint8_t *randomizer256, + void *user_data) { struct DBusMessage *reply; struct oob_request *oob_request; @@ -85,10 +87,14 @@ static void read_local_data_complete(struct btd_adapter *adapter, uint8_t *hash, if (!oob_request) return; - if (hash && randomizer) + if ((hash192 && randomizer192) || (hash256 && randomizer256)) reply = g_dbus_create_reply(oob_request->msg, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash192, 16, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer192, 16, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &hash256, hash256 ? 16 : 0, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &randomizer256, randomizer256 ? 16 : 0, DBUS_TYPE_INVALID); else reply = btd_error_failed(oob_request->msg, @@ -126,12 +132,7 @@ static DBusMessage *read_local_data(DBusConnection *conn, DBusMessage *msg, oob_request->msg = dbus_message_ref(msg); handler = g_new0(struct oob_handler, 1); -#ifdef __TIZEN_PATCH__ - handler->read_local_cb = (oob_read_local_cb_t)oob_read_local_data_complete; -#else - handler->read_local_cb = oob_read_local_data_complete; -#endif - handler->user_data = dbus_message_ref(oob_request->msg); + handler->read_local_cb = read_local_data_complete; btd_adapter_set_oob_handler(oob_request->adapter, handler); @@ -142,24 +143,39 @@ static DBusMessage *add_remote_data(DBusConnection *conn, DBusMessage *msg, void *data) { struct btd_adapter *adapter = data; - uint8_t *hash, *randomizer; - int32_t hlen, rlen; - const char *addr; + const char *addr = NULL; + uint8_t *hash192 = NULL; + uint8_t *randomizer192 = NULL; + int32_t h192_len = 0; + int32_t r192_len = 0; + uint8_t *hash256 = NULL; + uint8_t *randomizer256 = NULL; + int32_t h256_len = 0; + int32_t r256_len = 0; bdaddr_t bdaddr; + uint8_t addr_type = 0; + bool valid_len; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash192, &h192_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer192, &r192_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash256, &h256_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer256, &r256_len, DBUS_TYPE_INVALID)) return btd_error_invalid_args(msg); - if (hlen != 16 || rlen != 16 || bachk(addr)) + valid_len = (h192_len == 16 && r192_len == 16) || + (h256_len == 16 && r256_len == 16); + + if (!valid_len || bachk(addr)) return btd_error_invalid_args(msg); str2ba(addr, &bdaddr); - if (btd_adapter_add_remote_oob_data(adapter, &bdaddr, hash, randomizer)) + if (btd_adapter_add_remote_oob_ext_data(adapter, &bdaddr, addr_type, + hash192, randomizer192, + hash256, randomizer256)) return btd_error_failed(msg, "Request failed"); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); @@ -171,6 +187,7 @@ static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg, struct btd_adapter *adapter = data; const char *addr; bdaddr_t bdaddr; + uint8_t addr_type = 0; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)) @@ -181,7 +198,7 @@ static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg, str2ba(addr, &bdaddr); - if (btd_adapter_remove_remote_oob_data(adapter, &bdaddr)) + if (btd_adapter_remove_remote_oob_ext_data(adapter, &bdaddr, addr_type)) return btd_error_failed(msg, "Request failed"); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); @@ -189,15 +206,18 @@ static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg, static const GDBusMethodTable oob_methods[] = { { GDBUS_METHOD("AddRemoteData", - GDBUS_ARGS({ "address", "s" }, { "hash", "ay" }, - { "randomizer", "ay" }), NULL, + GDBUS_ARGS({ "address", "s" }, + { "hash192", "ay" }, { "randomizer192", "ay" }, + { "hash256", "ay" }, { "randomizer256", "ay" }), + NULL, add_remote_data) }, { GDBUS_METHOD("RemoveRemoteData", GDBUS_ARGS({ "address", "s" }), NULL, remove_remote_data) }, { GDBUS_ASYNC_METHOD("ReadLocalData", - NULL, GDBUS_ARGS({ "hash", "ay" }, - { "randomizer", "ay" }), + NULL, GDBUS_ARGS( + {"hash192", "ay" }, { "randomizer192", "ay" }, + {"hash256", "ay" }, { "randomizer256", "ay" }), read_local_data) }, { } }; @@ -220,7 +240,7 @@ static int oob_probe(struct btd_adapter *adapter) static void oob_remove(struct btd_adapter *adapter) { - read_local_data_complete(adapter, NULL, NULL); + read_local_data_complete(adapter, NULL, NULL, NULL, NULL, NULL); g_dbus_unregister_interface(connection, adapter_get_path(adapter), OOB_INTERFACE); @@ -238,8 +258,6 @@ static int dbusoob_init(void) connection = btd_get_dbus_connection(); - oob_register_cb(read_local_data_complete); - return btd_register_adapter_driver(&oob_driver); } @@ -252,3 +270,4 @@ static void dbusoob_exit(void) BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, dbusoob_init, dbusoob_exit) +#endif diff --git a/plugins/neard.c b/plugins/neard.c index cabcf34..4f068c3 100644 --- a/plugins/neard.c +++ b/plugins/neard.c @@ -259,9 +259,16 @@ static DBusMessage *create_request_oob_reply(struct btd_adapter *adapter, return reply; } +#ifdef __TIZEN_PATCH__ +static void read_local_complete(struct btd_adapter *adapter, + const uint8_t *hash, const uint8_t *randomizer, + const uint8_t *hash256, const uint8_t *randomizer256, + void *user_data) +#else static void read_local_complete(struct btd_adapter *adapter, const uint8_t *hash, const uint8_t *randomizer, void *user_data) +#endif { DBusMessage *msg = user_data; DBusMessage *reply; diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c index 2d5c746..47f6be9 100644 --- a/profiles/audio/a2dp.c +++ b/profiles/audio/a2dp.c @@ -166,6 +166,7 @@ static void setup_free(struct a2dp_setup *s) avdtp_unref(s->session); g_slist_free_full(s->cb, g_free); g_slist_free_full(s->caps, g_free); + g_free(s); } @@ -210,11 +211,21 @@ static void finalize_setup_errno(struct a2dp_setup *s, int err, { GSourceFunc finalize; va_list args; +#ifdef __TIZEN_PATCH__ + struct avdtp_error *avdtp_err; +#else struct avdtp_error avdtp_err; +#endif if (err < 0) { +#ifdef __TIZEN_PATCH__ + avdtp_err = g_new(struct avdtp_error, 1); + avdtp_error_init(avdtp_err, AVDTP_ERRNO, -err); + s->err = avdtp_err; +#else avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err); s->err = &avdtp_err; +#endif } va_start(args, cb1); @@ -901,7 +912,7 @@ static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep, DBG("Source %p: Suspend_Ind", sep); #ifdef __TIZEN_PATCH__ - a2dp_sep->remote_suspended = TRUE; + a2dp_sep->remote_suspended = TRUE; #endif if (a2dp_sep->suspend_timer) { diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c index 0733702..6e7410b 100644 --- a/profiles/audio/avdtp.c +++ b/profiles/audio/avdtp.c @@ -103,11 +103,7 @@ static unsigned int seids; #endif #define ABORT_TIMEOUT 2 #define DISCONNECT_TIMEOUT 1 -#ifdef __TIZEN_PATCH__ -#define START_TIMEOUT 2 -#else #define START_TIMEOUT 1 -#endif #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -849,13 +845,23 @@ static void handle_transport_connect(struct avdtp *session, GIOChannel *io, goto proceed; DBG("sk %d, omtu %d, send buffer size %d", sk, omtu, buf_size); +#ifdef __TIZEN_PATCH__ + min_buf_size = omtu * 10; +#else min_buf_size = omtu * 2; +#endif if (buf_size < min_buf_size) { DBG("send buffer size to be increassed to %d", min_buf_size); set_send_buffer_size(sk, min_buf_size); } - +#ifdef __TIZEN_PATCH__ + else { + DBG("send buffer size to be decreassed to %d", + min_buf_size); + set_send_buffer_size(sk, min_buf_size); + } +#endif proceed: if (!stream->open_acp && sep->cfm && sep->cfm->open) sep->cfm->open(session, sep, stream, NULL, sep->user_data); @@ -1130,7 +1136,6 @@ static void avdtp_sep_set_state(struct avdtp *session, avdtp_state_t state) { struct avdtp_stream *stream = sep->stream; - #ifdef __TIZEN_PATCH__ #if (defined(__BROADCOM_QOS_PATCH__) || defined(TIZEN_WEARABLE)) || \ defined(__SPRD_QOS_PATCH__) @@ -1337,7 +1342,6 @@ static void connection_lost(struct avdtp *session, int err) if (service) btd_service_connecting_complete(service, -err); #endif - g_slist_foreach(session->streams, (GFunc) release_stream, session); session->streams = NULL; @@ -1379,9 +1383,9 @@ static gboolean disconnect_timeout(gpointer user_data) struct btd_device *device = NULL; struct btd_adapter *adapter = NULL; const bdaddr_t *bdaddr = NULL; -#endif DBG(""); +#endif /* Fix : REVERSE_INULL */ #ifdef __TIZEN_PATCH__ @@ -2471,6 +2475,21 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond, } if (session->in.message_type == AVDTP_MSG_TYPE_COMMAND) { +#ifdef __TIZEN_PATCH__ + struct btd_service *service; + + service = btd_device_get_service(session->device, A2DP_SINK_UUID); + if (service != NULL) { + DBG("A2dp state %d", btd_service_get_state( + btd_device_get_service(session->device, A2DP_SINK_UUID))); + + if (btd_service_get_state(btd_device_get_service(session->device, + A2DP_SINK_UUID)) == BTD_SERVICE_STATE_DISCONNECTING) { + DBG("avdtp:%p , disconnect timer is going on", session); + return FALSE; + } + } +#endif if (!avdtp_parse_cmd(session, session->in.transaction, session->in.signal_id, session->in.buf, diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index 72d4906..dafa974 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -3893,9 +3893,12 @@ static char *avrcp_event_to_string(uint8_t event) } } -static gboolean avrcp_get_playback_status(struct avrcp *session) +static gboolean avrcp_get_playback_status(gpointer user_data) { + struct avrcp *session = user_data; + avrcp_get_play_status(session); + return TRUE; } #endif diff --git a/profiles/audio/player.c b/profiles/audio/player.c index e7ee747..436d193 100644 --- a/profiles/audio/player.c +++ b/profiles/audio/player.c @@ -1413,16 +1413,18 @@ void media_player_set_metadata(struct media_player *mp, struct media_item *item, const char *key, void *data, size_t len) { - char *value, *curval; #ifdef __TIZEN_PATCH__ + char *value; char *end, *temp; +#else + char *value, *curval; #endif value = g_strndup(data, len); #ifdef __TIZEN_PATCH__ temp = value; - while (g_utf8_validate(temp, -1, &end) == FALSE) { + while (g_utf8_validate(temp, -1, (const gchar **)&end) == FALSE) { temp = g_utf8_find_next_char(end, NULL); if (temp == NULL) { *end = '\0'; @@ -1435,8 +1437,8 @@ void media_player_set_metadata(struct media_player *mp, DBG("%s: %s", key, value); - curval = g_hash_table_lookup(mp->track, key); #ifndef __TIZEN_PATCH__ + curval = g_hash_table_lookup(mp->track, key); if (g_strcmp0(curval, value) == 0) { g_free(value); return; diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c index fbead13..bc3b38a 100644 --- a/profiles/health/hdp.c +++ b/profiles/health/hdp.c @@ -603,7 +603,6 @@ static DBusMessage *channel_acquire_continue(struct hdp_tmp_dc_data *data, } fd = mcap_mdl_get_fd(data->hdp_chann->mdl); - if (fd >= 0) return g_dbus_create_reply(data->msg, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); diff --git a/profiles/input/device.c b/profiles/input/device.c index a494ea2..99abadb 100644 --- a/profiles/input/device.c +++ b/profiles/input/device.c @@ -87,6 +87,9 @@ struct input_device { uint8_t report_req_pending; guint report_req_timer; uint32_t report_rsp_id; +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + char *role; +#endif }; static int idle_timeout = 0; @@ -308,7 +311,6 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data if (hidp_recv_intr_data(chan, idev) && (cond == G_IO_IN)) return TRUE; } - ba2str(&idev->dst, address); DBG("Device %s disconnected", address); @@ -333,8 +335,12 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data btd_service_disconnecting_complete(idev->service, 0); /* Enter the auto-reconnect mode if needed */ +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (idev->role == NULL) + input_device_enter_reconnect_mode(idev); +#else input_device_enter_reconnect_mode(idev); - +#endif return FALSE; } @@ -522,7 +528,6 @@ static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data /* Close interrupt channel */ if (idev->intr_io && !(cond & G_IO_NVAL)) g_io_channel_shutdown(idev->intr_io, TRUE, NULL); - return FALSE; } @@ -1002,10 +1007,21 @@ cleanup: static bool is_connected(struct input_device *idev) { +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (idev->role == NULL) { + if (idev->uhid) + return (idev->intr_io != NULL && idev->ctrl_io != NULL); + else + return ioctl_is_connected(idev); + } else { + return (idev->intr_io != NULL && idev->ctrl_io != NULL); + } +#else if (idev->uhid) return (idev->intr_io != NULL && idev->ctrl_io != NULL); else return ioctl_is_connected(idev); +#endif } static int connection_disconnect(struct input_device *idev, uint32_t flags) @@ -1016,9 +1032,14 @@ static int connection_disconnect(struct input_device *idev, uint32_t flags) /* Standard HID disconnect */ if (idev->intr_io) g_io_channel_shutdown(idev->intr_io, TRUE, NULL); + if (idev->ctrl_io) g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL); +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (idev->role != NULL) + btd_service_disconnecting_complete(idev->service, 0); +#endif if (idev->uhid) return 0; else @@ -1031,10 +1052,17 @@ static int input_device_connected(struct input_device *idev) if (idev->intr_io == NULL || idev->ctrl_io == NULL) return -ENOTCONN; - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (idev->role == NULL) { + err = hidp_add_connection(idev); + if (err < 0) + return err; + } +#else err = hidp_add_connection(idev); if (err < 0) return err; +#endif btd_service_connecting_complete(idev->service, 0); @@ -1052,11 +1080,19 @@ static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err, err = -EIO; goto failed; } - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (idev->role == NULL) { + err = input_device_connected(idev); + if (err < 0) + goto failed; + } else { + btd_service_connecting_complete(idev->service, 0); + } +#else err = input_device_connected(idev); if (err < 0) goto failed; - +#endif if (idev->uhid) cond |= G_IO_IN; @@ -1109,7 +1145,6 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err, g_error_free(err); goto failed; } - idev->intr_io = io; if (idev->uhid) @@ -1230,7 +1265,9 @@ int input_device_connect(struct btd_service *service) DBG(""); idev = btd_service_get_user_data(service); - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + DBG("Role=%s", idev->role); +#endif if (idev->ctrl_io) return -EBUSY; @@ -1251,7 +1288,9 @@ int input_device_disconnect(struct btd_service *service) flags = device_is_temporary(idev->device) ? (1 << HIDP_VIRTUAL_CABLE_UNPLUG) : 0; - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + DBG("Role=%s", idev->role); +#endif err = connection_disconnect(idev, flags); if (err < 0) return err; @@ -1328,6 +1367,28 @@ static struct input_device *input_device_new(struct btd_service *service) return idev; } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +static struct input_device *input_device_role_new(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct btd_profile *p = btd_service_get_profile(service); + const char *path = device_get_path(device); + struct btd_adapter *adapter = device_get_adapter(device); + struct input_device *idev; + + idev = g_new0(struct input_device, 1); + bacpy(&idev->src, btd_adapter_get_address(adapter)); + bacpy(&idev->dst, device_get_address(device)); + idev->service = btd_service_ref(service); + idev->device = btd_device_ref(device); + idev->path = g_strdup(path); + idev->role = g_strdup("device"); + idev->disable_sdp = 0; + idev->uhid = NULL; + return idev; +} +#endif + static gboolean property_get_reconnect_mode( const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) @@ -1345,6 +1406,37 @@ static const GDBusPropertyTable input_properties[] = { { } }; +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +static DBusMessage *hid_device_fd(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + struct input_device *idev = user_data; + GError *gerr = NULL; + DBusMessage *reply; + int ctrl_fd = -1; + int intr_fd = -1; + if (idev->ctrl_io == NULL || idev->intr_io == NULL) { + DBG("Return error reply"); + reply = g_dbus_create_error(msg, ERROR_INTERFACE ".InputError", + "%s", "NotConnected"); + g_error_free(gerr); + } else { + ctrl_fd = g_io_channel_unix_get_fd(idev->ctrl_io); + intr_fd = g_io_channel_unix_get_fd(idev->intr_io); + reply = g_dbus_create_reply(msg, DBUS_TYPE_UNIX_FD, + &ctrl_fd, DBUS_TYPE_UNIX_FD, &intr_fd ,DBUS_TYPE_INVALID); + } + + return reply; +} +static const GDBusMethodTable input_device_methods[] = { + { GDBUS_ASYNC_METHOD("GetFD", + NULL, GDBUS_ARGS({ "fd", "h" } , {"fd", "h"}), + hid_device_fd) }, + { } +}; +#endif + int input_device_register(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); @@ -1381,6 +1473,34 @@ int input_device_register(struct btd_service *service) return 0; } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +int input_device_role_register(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + const char *path = device_get_path(device); + struct input_device *idev; + + DBG("%s", path); + + idev = input_device_role_new(service); + if (!idev) + return -EINVAL; + if (g_dbus_register_interface(btd_get_dbus_connection(), + idev->path, INPUT_INTERFACE, + input_device_methods, NULL, + NULL, idev, + NULL) == FALSE) { + error("Unable to register %s interface", INPUT_INTERFACE); + input_device_free(idev); + return -EINVAL; + } + btd_service_set_user_data(service, idev); + + return 0; +} + +#endif + static struct input_device *find_device(const bdaddr_t *src, const bdaddr_t *dst) { @@ -1398,6 +1518,25 @@ static struct input_device *find_device(const bdaddr_t *src, return btd_service_get_user_data(service); } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +static struct input_device *find_device_role(const bdaddr_t *src, + const bdaddr_t *dst) +{ + struct btd_device *device; + struct btd_service *service; + + device = btd_adapter_find_device(adapter_find(src), dst, BDADDR_BREDR); + if (device == NULL) + return NULL; + + service = btd_device_get_service(device, HID_DEVICE_UUID); + if (service == NULL) + return NULL; + + return btd_service_get_user_data(service); +} +#endif + void input_device_unregister(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); @@ -1412,6 +1551,19 @@ void input_device_unregister(struct btd_service *service) input_device_free(idev); } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +void input_device_role_unregister(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + const char *path = device_get_path(device); + struct input_device *idev = btd_service_get_user_data(service); + + DBG("%s", path); + + input_device_free(idev); +} +#endif + static int input_device_connadd(struct input_device *idev) { int err; @@ -1443,6 +1595,16 @@ bool input_device_exists(const bdaddr_t *src, const bdaddr_t *dst) return false; } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +bool input_device_role_exists(const bdaddr_t *src, const bdaddr_t *dst) +{ + if (find_device_role(src, dst)) + return true; + + return false; +} +#endif + int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, GIOChannel *io) { @@ -1480,6 +1642,58 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, return 0; } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +int input_device_role_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, + GIOChannel *io) +{ + struct input_device *idev = find_device_role(src, dst); + GIOCondition cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL; + + DBG("idev %p psm %d", idev, psm); + + if (!idev) + return -ENOENT; + + switch (psm) { + case L2CAP_PSM_HIDP_CTRL: + if (idev->ctrl_io) + return -EALREADY; + idev->ctrl_io = g_io_channel_ref(io); + idev->ctrl_watch = g_io_add_watch(idev->ctrl_io, cond, + ctrl_watch_cb, idev); + break; + case L2CAP_PSM_HIDP_INTR: + if (idev->intr_io) + return -EALREADY; + idev->intr_io = g_io_channel_ref(io); + idev->intr_watch = g_io_add_watch(idev->intr_io, cond, + intr_watch_cb, idev); + break; + } + if (idev->intr_io && idev->ctrl_io) { + btd_service_connecting_complete(idev->service, 0); + } + return 0; +} + +int input_device_role_close_channels(const bdaddr_t *src, const bdaddr_t *dst) +{ + struct input_device *idev = find_device(src, dst); + + if (!idev) + return -ENOENT; + + if (idev->intr_io) + g_io_channel_shutdown(idev->intr_io, TRUE, NULL); + + if (idev->ctrl_io) + g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL); + + return 0; +} + +#endif + int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst) { struct input_device *idev = find_device(src, dst); diff --git a/profiles/input/device.h b/profiles/input/device.h index 51a9aee..20aba31 100644 --- a/profiles/input/device.h +++ b/profiles/input/device.h @@ -33,6 +33,15 @@ void input_enable_userspace_hid(bool state); int input_device_register(struct btd_service *service); void input_device_unregister(struct btd_service *service); +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +int input_device_role_register(struct btd_service *service); +void input_device_role_unregister(struct btd_service *service); +bool input_device_role_exists(const bdaddr_t *src, const bdaddr_t *dst); +int input_device_role_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, + GIOChannel *io); +int input_device_role_close_channels(const bdaddr_t *src, const bdaddr_t *dst); +#endif + bool input_device_exists(const bdaddr_t *src, const bdaddr_t *dst); int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, GIOChannel *io); diff --git a/profiles/input/manager.c b/profiles/input/manager.c index 1d31b06..6d96c86 100644 --- a/profiles/input/manager.c +++ b/profiles/input/manager.c @@ -53,7 +53,19 @@ static void hid_server_remove(struct btd_profile *p, { server_stop(btd_adapter_get_address(adapter)); } +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +static int hid_device_probe(struct btd_profile *p, struct btd_adapter *adapter) +{ + DBG("hid device probe"); + return server_start(btd_adapter_get_address(adapter)); +} +static void hid_device_remove(struct btd_profile *p, + struct btd_adapter *adapter) +{ + server_stop(btd_adapter_get_address(adapter)); +} +#endif static struct btd_profile input_profile = { .name = "input-hid", .local_uuid = HID_UUID, @@ -69,7 +81,23 @@ static struct btd_profile input_profile = { .adapter_probe = hid_server_probe, .adapter_remove = hid_server_remove, }; +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +static struct btd_profile input_device_profile = { + .name = "hid-device", + .local_uuid = HID_DEVICE_UUID, + .remote_uuid = HID_DEVICE_UUID, + .auto_connect = false, + .connect = input_device_connect, + .disconnect = input_device_disconnect, + + .device_probe = input_device_role_register, + .device_remove = input_device_role_unregister, + + .adapter_probe = hid_device_probe, + .adapter_remove = hid_device_remove, +}; +#endif static GKeyFile *load_config_file(const char *file) { GKeyFile *keyfile; @@ -117,7 +145,9 @@ static int input_init(void) } btd_profile_register(&input_profile); - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + btd_profile_register(&input_device_profile); +#endif if (config) g_key_file_free(config); @@ -127,6 +157,9 @@ static int input_init(void) static void input_exit(void) { btd_profile_unregister(&input_profile); +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + btd_profile_unregister(&input_device_profile); +#endif } BLUETOOTH_PLUGIN_DEFINE(input, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, diff --git a/profiles/input/server.c b/profiles/input/server.c index eb3fcf8..2ee3b9b 100644 --- a/profiles/input/server.c +++ b/profiles/input/server.c @@ -57,6 +57,9 @@ struct input_server { GIOChannel *ctrl; GIOChannel *intr; struct confirm_data *confirm; +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + char *role; +#endif }; static int server_cmp(gconstpointer s, gconstpointer user_data) @@ -182,7 +185,14 @@ static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data) sixaxis_browse_sdp(&src, &dst, chan, psm); return; } - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (ret == -ENOENT) { + DBG("Connection request for device role"); + ret = input_device_role_set_channel(&src, &dst, psm, chan); + if (ret == 0) + return; + } +#endif error("Refusing input device connect: %s (%d)", strerror(-ret), -ret); /* Send unplug virtual cable to unknown devices */ @@ -208,8 +218,15 @@ static void auth_callback(DBusError *derr, void *user_data) } if (!input_device_exists(&server->src, &confirm->dst) && - !dev_is_sixaxis(&server->src, &confirm->dst)) + !dev_is_sixaxis(&server->src, &confirm->dst)) { +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (!input_device_role_exists(&server->src, &confirm->dst)) { + return; + } +#else return; +#endif + } if (!bt_io_accept(confirm->io, connect_event_cb, server, NULL, &err)) { error("bt_io_accept: %s", err->message); @@ -260,8 +277,15 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data) } if (!input_device_exists(&src, &dst) && !dev_is_sixaxis(&src, &dst)) { +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (!input_device_role_exists(&src, &dst)) { + error("Refusing connection from %s: unknown device", addr); + goto drop; + } +#else error("Refusing connection from %s: unknown device", addr); goto drop; +#endif } server->confirm = g_new0(struct confirm_data, 1); @@ -344,3 +368,59 @@ void server_stop(const bdaddr_t *src) servers = g_slist_remove(servers, server); g_free(server); } + +#ifdef TIZEN_BT_HID_DEVICE_ENABLE +int server_device_start(const bdaddr_t *src) +{ + struct input_server *server; + GError *err = NULL; + + server = g_new0(struct input_server, 1); + bacpy(&server->src, src); + + server->ctrl = bt_io_listen(connect_event_cb, NULL, + server, NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, src, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, + BT_IO_OPT_INVALID); + if (!server->ctrl) { + error("Failed to listen on control channel"); + } + + server->intr = bt_io_listen(NULL, confirm_event_cb, + server, NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, src, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, + BT_IO_OPT_INVALID); + if (!server->intr) { + error("Failed to listen on interrupt channel"); + } + server->role = strdup("device"); + servers = g_slist_append(servers, server); + + return 0; +} + +void server_device_stop(const bdaddr_t *src) +{ + struct input_server *server; + GSList *l; + + l = g_slist_find_custom(servers, src, server_cmp); + if (!l) + return; + + server = l->data; + + g_io_channel_shutdown(server->intr, TRUE, NULL); + g_io_channel_unref(server->intr); + + g_io_channel_shutdown(server->ctrl, TRUE, NULL); + g_io_channel_unref(server->ctrl); + g_free(server->role); + servers = g_slist_remove(servers, server); + g_free(server); +} +#endif diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c index 95a8e74..c03c2c8 100644 --- a/profiles/network/bnep.c +++ b/profiles/network/bnep.c @@ -780,7 +780,9 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr, failed_bridge: bnep_del_from_bridge(iface, bridge); +#ifndef __TIZEN_PATCH__ failed_conn: +#endif bnep_conndel(addr); return err; diff --git a/src/adapter.c b/src/adapter.c index 7310d56..d27fa59 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -113,7 +113,7 @@ #define check_address(address) bachk(address) #define ADV_DATA_MAX_LENGTH 31 #define SCAN_RESPONSE_DATA_LENGTH_MAX 31 -#define MANUFACTURER_DATA_LENGTH_MAX 28 +#define EIR_MANUFACTURER_DATA_LENGTH_MAX 100 #define PRIVATE_ADDR_TIMEOUT (15 * 60) #define BT_DISC_TYPE_BREDR 1 @@ -123,6 +123,8 @@ #define DISCOV_TYPE_BREDR 1 #define DISCOV_TYPE_LE 6 +#define LE_BEARER_POSTFIX " LE" +#define LE_BEARER_POSTFIX_LEN 3 #endif /* __TIZEN_PATCH__ */ @@ -254,7 +256,7 @@ struct btd_adapter { char *stored_alias; /* stored adapter name alias */ #ifdef __TIZEN_PATCH__ bool le_privacy_enabled; /* whether LE Privacy feature enabled */ - char local_irk[MGMT_IRK_SIZE]; /* adapter local IRK */ + uint8_t *local_irk; /* adapter local IRK */ uint8_t disc_type; bool ipsp_intialized; /* Ipsp Initialization state */ struct le_data_length_read_handler *read_handler; @@ -303,19 +305,9 @@ struct btd_adapter { GSList *adv_list; /* List of advertising instance */ bool advertising; /* Advertising active */ gchar *version; /* Bluetooth Version */ -#if 0 // Not used - bool secure_connection; /* Secure Connection active*/ - uint16_t auth_payload_timeout; /* Authenticated payload timeout value*/ - - bool set_new_rpa; /* RPA to be set */ - bool rpa_is_set; /* RPA is set */ -#endif - uint8_t adv_tx_power; - bool le_discovering; /* LE Discovery active */ GSList *le_discovery_list; /* list of LE discovery clients */ - gboolean le_auto_connect; /* LE Auto connection */ #endif GSList *pin_callbacks; @@ -343,15 +335,8 @@ struct btd_adapter { bool is_default; /* true if adapter is default one */ }; - #ifdef __TIZEN_PATCH__ enum { - DISABLE_PRIVACY, - ENABLE_PRIVACY, - GEN_IRK_THEN_ENABLE_PRIVACY -}; - -enum { DEINIT_6LOWPAN, INIT_6LOWPAN }; @@ -1564,77 +1549,6 @@ void btd_adapter_unpair_device(struct btd_adapter *adapter, device_unpair(dev, TRUE); DBG("-"); } - -gboolean adapter_clear_le_white_list(struct btd_adapter *adapter) -{ - if (mgmt_send(adapter->mgmt, MGMT_OP_CLEAR_DEV_WHITE_LIST, - adapter->dev_id, 0, NULL, - NULL, NULL, NULL) > 0) - return TRUE; - else - return FALSE; -} - -gboolean adapter_add_le_white_list(struct btd_adapter *adapter, struct btd_device *device) -{ - struct mgmt_cp_add_dev_white_list cp; - const bdaddr_t *dst; - char device_addr[18]; - - memset(&cp, 0, sizeof(cp)); - - dst = device_get_address(device); - - ba2str(device_get_address(device), device_addr); - DBG("addr %s bdaddr type %d", device_addr, btd_device_get_bdaddr_type(device)); - - if ( btd_device_get_bdaddr_type(device) == BDADDR_LE_PUBLIC) - cp.bdaddr_type = 0x0; - else - cp.bdaddr_type = 0x1; - - memcpy(&cp.bdaddr, dst, sizeof(bdaddr_t)); - - if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_DEV_WHITE_LIST, - adapter->dev_id, sizeof(cp), &cp, - NULL, NULL, NULL) > 0) - return TRUE; - - DBG("Unable to add white list"); - - return FALSE; -} - -gboolean btd_adapter_is_le_auto_connect(struct btd_adapter *adapter) -{ - return adapter->le_auto_connect; -} - -void btd_adapter_set_le_auto_connect(struct btd_adapter *adapter, gboolean auto_connect) -{ - adapter->le_auto_connect = auto_connect; -} - -gboolean btd_adapter_disable_le_auto_connect(struct btd_adapter *adapter) -{ - if (btd_adapter_is_le_auto_connect(adapter) == FALSE) { - error("le auto connection is not going on"); - return FALSE; - } - - DBG("disable le auto connect : %u", adapter->dev_id); - - if (mgmt_send(adapter->mgmt, MGMT_OP_DISABLE_LE_AUTO_CONNECT, - adapter->dev_id, 0, NULL, - NULL, NULL, NULL) > 0) { - btd_adapter_set_le_auto_connect(adapter, FALSE); - return TRUE; - } - - error("Failed to disable le auto conn : %u", adapter->dev_id); - - return FALSE; -} #endif void btd_adapter_remove_device(struct btd_adapter *adapter, @@ -1989,6 +1903,7 @@ static void start_le_discovery_complete(uint8_t status, uint16_t length, const struct mgmt_cp_start_discovery *rp = param; DBG("status 0x%02x", status); + DBG("Discovery Type 0x%02x", rp->type); if (length < sizeof(*rp)) { error("Wrong size of start discovery return parameters"); return; @@ -1998,8 +1913,6 @@ static void start_le_discovery_complete(uint8_t status, uint16_t length, adapter->discovery_type |= rp->type; adapter->discovery_enable = 0x01; - DBG("Discovery Type 0x%02x", rp->type); - if (adapter->le_discovering) return; @@ -2026,40 +1939,24 @@ static void start_le_discovery_complete(uint8_t status, uint16_t length, static gboolean start_discovery_timeout(gpointer user_data) { struct btd_adapter *adapter = user_data; -#ifdef __TIZEN_PATCH__ - struct mgmt_cp_start_discovery cp; - uint8_t new_type = 0; -#else +#ifndef __TIZEN_PATCH__ struct mgmt_cp_start_service_discovery *sd_cp; - uint8_t new_type; #endif + uint8_t new_type; DBG(""); adapter->discovery_idle_timeout = 0; #ifdef __TIZEN_PATCH__ - if (adapter->disc_type == BT_DISC_TYPE_BREDR_ONLY) { - - if (adapter->current_settings & MGMT_SETTING_BREDR) - new_type = (1 << BDADDR_BREDR); - else - new_type = 0; - - } else if (adapter->disc_type == BT_DISC_TYPE_LE_ONLY) { - - if (adapter->current_settings & MGMT_SETTING_LE) - new_type = (1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM); - - } else if (adapter->disc_type == BT_DISC_TYPE_LE_BREDR) { - - if (adapter->current_settings & MGMT_SETTING_BREDR) - new_type = (1 << BDADDR_BREDR); - else - new_type = 0; - if (adapter->current_settings & MGMT_SETTING_LE) - new_type |= (1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM); - } + if (adapter->disc_type == BT_DISC_TYPE_BREDR_ONLY) + new_type = SCAN_TYPE_BREDR; + else if (adapter->disc_type == BT_DISC_TYPE_LE_ONLY) + new_type = SCAN_TYPE_LE; + else if (adapter->disc_type == BT_DISC_TYPE_LE_BREDR) + new_type = SCAN_TYPE_DUAL; + else + new_type = 0; if (adapter->discovery_enable == 0x01) { /* @@ -2067,7 +1964,7 @@ static gboolean start_discovery_timeout(gpointer user_data) * same type, then just keep it. */ if (adapter->disc_type == BT_DISC_TYPE_BREDR_ONLY) { - if ((adapter->discovery_type & new_type) == 0x01) { + if ((adapter->discovery_type & new_type) == SCAN_TYPE_BREDR) { if (adapter->discovering) return FALSE; @@ -2079,7 +1976,7 @@ static gboolean start_discovery_timeout(gpointer user_data) } } else if (adapter->disc_type == BT_DISC_TYPE_LE_ONLY) { - if ((adapter->discovery_type & new_type) == 0x06) { + if ((adapter->discovery_type & new_type) == SCAN_TYPE_LE) { if (adapter->le_discovering) return FALSE; @@ -2093,14 +1990,15 @@ static gboolean start_discovery_timeout(gpointer user_data) } DBG("adapter->disc_type [%d]", adapter->disc_type); + struct mgmt_cp_start_discovery cp; if (adapter->disc_type == BT_DISC_TYPE_BREDR_ONLY) { - cp.type = 0x01; + cp.type = new_type; mgmt_send(adapter->mgmt, MGMT_OP_START_DISCOVERY, adapter->dev_id, sizeof(cp), &cp, start_discovery_complete, adapter, NULL); } else if (adapter->disc_type == BT_DISC_TYPE_LE_ONLY) { - cp.type = 0x06; + cp.type = new_type; mgmt_send(adapter->mgmt, MGMT_OP_START_LE_DISCOVERY, adapter->dev_id, sizeof(cp), &cp, start_le_discovery_complete, adapter, NULL); @@ -2203,12 +2101,6 @@ static void trigger_start_discovery(struct btd_adapter *adapter, guint delay) if (!(adapter->current_settings & MGMT_SETTING_POWERED)) return; -#ifdef __TIZEN_PATCH__ - if (delay == 0) { - start_discovery_timeout((gpointer)adapter); - return; - } -#endif adapter->discovery_idle_timeout = g_timeout_add_seconds(delay, start_discovery_timeout, adapter); } @@ -2222,38 +2114,15 @@ static void suspend_discovery_complete(uint8_t status, uint16_t length, DBG("status 0x%02x", status); if (status == MGMT_STATUS_SUCCESS) { -#ifdef __TIZEN_PATCH__ - adapter->discovery_type &= (~0x01); -#else adapter->discovery_type = 0x00; -#endif - adapter->discovery_enable = 0x00; - return; - } -} - -#ifdef __TIZEN_PATCH__ -static void suspend_le_discovery_complete(uint8_t status, uint16_t length, - const void *param, void *user_data) -{ - struct btd_adapter *adapter = user_data; - - DBG("status 0x%02x", status); - - if (status == MGMT_STATUS_SUCCESS) { - adapter->discovery_type &= (~0x06); adapter->discovery_enable = 0x00; return; } } -#endif static void suspend_discovery(struct btd_adapter *adapter) { struct mgmt_cp_stop_discovery cp; -#ifdef __TIZEN_PATCH__ - struct mgmt_cp_stop_le_discovery le_cp; -#endif DBG(""); @@ -2263,14 +2132,8 @@ static void suspend_discovery(struct btd_adapter *adapter) * If there are no clients discovering right now, then there is * also nothing to suspend. */ -#ifdef __TIZEN_PATCH__ - if (adapter->discovery_list == NULL && adapter->le_discovery_list == NULL ) - return; -#else if (!adapter->discovery_list) return; -#endif - /* * In case of being inside the idle phase, make sure to remove @@ -2286,26 +2149,11 @@ static void suspend_discovery(struct btd_adapter *adapter) if (adapter->discovery_enable == 0x00) return; -#ifdef __TIZEN_PATCH__ - if (adapter->discovery_list) { - cp.type = 0x01; - mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, - adapter->dev_id, sizeof(cp), &cp, - suspend_discovery_complete, adapter, NULL); - } - if (adapter->le_discovery_list) { - le_cp.type = 0x06; - mgmt_send(adapter->mgmt, MGMT_OP_STOP_LE_DISCOVERY, - adapter->dev_id, sizeof(le_cp), &le_cp, - suspend_le_discovery_complete, adapter, NULL); - } -#else cp.type = adapter->discovery_type; mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, adapter->dev_id, sizeof(cp), &cp, suspend_discovery_complete, adapter, NULL); -#endif } static void resume_discovery(struct btd_adapter *adapter) @@ -2326,35 +2174,8 @@ static void resume_discovery(struct btd_adapter *adapter) * idle time for a normal discovery. So just trigger the default * restart procedure. */ -#ifdef __TIZEN_PATCH__ - adapter->disc_type = BT_DISC_TYPE_BREDR_ONLY; -#endif trigger_start_discovery(adapter, IDLE_DISCOV_TIMEOUT); } - -#ifdef __TIZEN_PATCH__ -static void resume_le_discovery(struct btd_adapter *adapter) -{ - DBG(""); - - adapter->discovery_suspended = false; - - /* - * If there are no clients discovering right now, then there is - * also nothing to resume. - */ - if (adapter->le_discovery_list == NULL) - return; - - /* - * Treat a suspended discovery session the same as extra long - * idle time for a normal discovery. So just trigger the default - * restart procedure. - */ - adapter->disc_type = BT_DISC_TYPE_LE_ONLY; - trigger_start_discovery(adapter, IDLE_LE_DISCOV_TIMEOUT); -} -#endif #endif static void discovering_callback(uint16_t index, uint16_t length, @@ -2544,7 +2365,6 @@ static void discovery_cleanup(struct btd_adapter *adapter) adapter->discovery_found = NULL; } -#ifndef __TIZEN_PATCH__ static gboolean remove_temp_devices(gpointer user_data) { struct btd_adapter *adapter = user_data; @@ -2565,7 +2385,6 @@ static gboolean remove_temp_devices(gpointer user_data) return FALSE; } -#endif static gint g_strcmp(gconstpointer a, gconstpointer b) { @@ -2800,14 +2619,8 @@ static void discovery_destroy(void *user_data) * If there are other client discoveries in progress, then leave * it active. If not, then make sure to stop the restart timeout. */ - -#ifdef __TIZEN_PATCH__ - if (adapter->discovery_list || adapter->le_discovery_list) - return; -#else if (adapter->discovery_list) return; -#endif adapter->discovery_type = 0x00; @@ -2822,10 +2635,55 @@ static void discovery_destroy(void *user_data) } discovery_cleanup(adapter); -#ifndef __TIZEN_PATCH__ + adapter->temp_devices_timeout = g_timeout_add_seconds(TEMP_DEV_TIMEOUT, remove_temp_devices, adapter); -#endif +} + +static void discovery_disconnect(DBusConnection *conn, void *user_data) +{ + struct watch_client *client = user_data; + struct btd_adapter *adapter = client->adapter; + struct mgmt_cp_stop_discovery cp; + + DBG("owner %s", client->owner); + + adapter->set_filter_list = g_slist_remove(adapter->set_filter_list, + client); + + adapter->discovery_list = g_slist_remove(adapter->discovery_list, + client); + + /* + * There is no need for extra cleanup of the client since that + * will be done by the destroy callback. + * + * However in case this is the last client, the discovery in + * the kernel needs to be disabled. + */ + if (adapter->discovery_list) { + update_discovery_filter(adapter); + return; + } + + /* + * In the idle phase of a discovery, there is no need to stop it + * and so it is enough to send out the signal and just return. + */ + if (adapter->discovery_enable == 0x00) { + adapter->discovering = false; + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "Discovering"); + + trigger_passive_scanning(adapter); + return; + } + + cp.type = adapter->discovery_type; + + mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, + adapter->dev_id, sizeof(cp), &cp, + stop_discovery_complete, adapter, NULL); } /* @@ -2891,181 +2749,62 @@ static void le_discovery_destroy(void *user_data) } discovery_cleanup(adapter); -#ifndef __TIZEN_PATCH__ - adapter->temp_devices_timeout = g_timeout_add_seconds(TEMP_DEV_TIMEOUT, - remove_temp_devices, adapter); -#endif -} -#endif - -static void discovery_disconnect(DBusConnection *conn, void *user_data) -{ - struct watch_client *client = user_data; - struct btd_adapter *adapter = client->adapter; - struct mgmt_cp_stop_discovery cp; - - DBG("owner %s", client->owner); - - adapter->set_filter_list = g_slist_remove(adapter->set_filter_list, - client); - - adapter->discovery_list = g_slist_remove(adapter->discovery_list, - client); - - /* - * There is no need for extra cleanup of the client since that - * will be done by the destroy callback. - * - * However in case this is the last client, the discovery in - * the kernel needs to be disabled. - */ - if (adapter->discovery_list) { - update_discovery_filter(adapter); - return; - } - - /* - * In the idle phase of a discovery, there is no need to stop it - * and so it is enough to send out the signal and just return. - */ - if (adapter->discovery_enable == 0x00) { - adapter->discovering = false; - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "Discovering"); - -#ifdef __TIZEN_PATCH__ - if (adapter->discovering == false && adapter->le_discovering == false) { - trigger_passive_scanning(adapter); - return; - } -#else - trigger_passive_scanning(adapter); - return; -#endif - } - -#ifdef __TIZEN_PATCH__ - cp.type = 0x01; -#else - cp.type = adapter->discovery_type; -#endif - - mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, - adapter->dev_id, sizeof(cp), &cp, - stop_discovery_complete, adapter, NULL); } -#ifdef __TIZEN_PATCH__ static void le_discovery_disconnect(DBusConnection *conn, void *user_data) { struct watch_client *client = user_data; - struct btd_adapter *adapter = client->adapter; - struct mgmt_cp_stop_le_discovery cp; - - DBG("owner %s", client->owner); - - adapter->le_discovery_list = g_slist_remove(adapter->le_discovery_list, - client); - - /* - * There is no need for extra cleanup of the client since that - * will be done by the destroy callback. - * - * However in case this is the last client, the discovery in - * the kernel needs to be disabled. - */ - if (adapter->le_discovery_list) - return; - - /* - * In the idle phase of a discovery, there is no need to stop it - * and so it is enough to send out the signal and just return. - */ - if (adapter->discovery_enable == 0x00) { - adapter->le_discovering = false; - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "LEDiscovering"); - - if (adapter->discovering == false && adapter->le_discovering == false) { - trigger_passive_scanning(adapter); - return; - } - } - - cp.type = 0x06; - - mgmt_send(adapter->mgmt, MGMT_OP_STOP_LE_DISCOVERY, - adapter->dev_id, sizeof(cp), &cp, - stop_discovery_complete, adapter, NULL); -} -#endif - -static DBusMessage *start_discovery(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct btd_adapter *adapter = user_data; - const char *sender = dbus_message_get_sender(msg); - struct watch_client *client; - bool is_discovering; - - DBG("sender %s", sender); - - if (!(adapter->current_settings & MGMT_SETTING_POWERED)) - return btd_error_not_ready(msg); - - is_discovering = get_discovery_client(adapter, sender, &client); - - /* - * Every client can only start one discovery, if the client - * already started a discovery then return an error. - */ - if (is_discovering) - return btd_error_busy(msg); - - /* - * If there was pre-set filter, just reconnect it to discovery_list, - * and trigger scan. - */ - if (client) { - adapter->set_filter_list = g_slist_remove( - adapter->set_filter_list, client); - adapter->discovery_list = g_slist_prepend( - adapter->discovery_list, client); - update_discovery_filter(adapter); - return dbus_message_new_method_return(msg); - } - - client = g_new0(struct watch_client, 1); - - client->adapter = adapter; - client->owner = g_strdup(sender); - client->discovery_filter = NULL; - client->watch = g_dbus_add_disconnect_watch(dbus_conn, sender, - discovery_disconnect, client, - discovery_destroy); - adapter->discovery_list = g_slist_prepend(adapter->discovery_list, + struct btd_adapter *adapter = client->adapter; + struct mgmt_cp_stop_le_discovery cp; + + DBG("owner %s", client->owner); + + adapter->le_discovery_list = g_slist_remove(adapter->le_discovery_list, client); -#ifdef __TIZEN_PATCH__ - adapter->disc_type = BT_DISC_TYPE_BREDR_ONLY; -#endif + /* + * There is no need for extra cleanup of the client since that + * will be done by the destroy callback. + * + * However in case this is the last client, the discovery in + * the kernel needs to be disabled. + */ + if (adapter->le_discovery_list) + return; /* - * Just trigger the discovery here. In case an already running - * discovery in idle phase exists, it will be restarted right - * away. + * In the idle phase of a discovery, there is no need to stop it + * and so it is enough to send out the signal and just return. */ - update_discovery_filter(adapter); + if (adapter->discovery_enable == 0x00) { + adapter->le_discovering = false; + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "LEDiscovering"); - return dbus_message_new_method_return(msg); + if (adapter->discovering == false && adapter->le_discovering == false) { + trigger_passive_scanning(adapter); + return; + } + } + + cp.type = 0x06; + + mgmt_send(adapter->mgmt, MGMT_OP_STOP_LE_DISCOVERY, + adapter->dev_id, sizeof(cp), &cp, + stop_discovery_complete, adapter, NULL); } -#ifdef __TIZEN_PATCH__ + static int set_adv_data_flag(uint8_t *adv_data, uint8_t *data, int data_len) { adv_data[0] = 2; adv_data[1] = EIR_FLAGS; - adv_data[2] = EIR_GEN_DISC; +#ifdef TIZEN_KITT + adv_data[2] = EIR_GEN_DISC | EIR_CONTROLLER | + EIR_SIM_HOST | EIR_BREDR_UNSUP; +#else + adv_data[2] = EIR_GEN_DISC | EIR_CONTROLLER | EIR_SIM_HOST; +#endif memcpy(adv_data + 3, data, data_len); return data_len + 3; @@ -3164,11 +2903,6 @@ int adapter_le_set_missed_adv_data(uint8_t *p_data, uint8_t data_len, int len; data = g_malloc0(ADV_DATA_MAX_LENGTH); - /* Fix : NULL_RETURNS */ - if (data == NULL) { - return -1; - } - memcpy(data, p_data, data_len); len = data_len; @@ -3383,7 +3117,7 @@ static DBusMessage *adapter_set_advertising(DBusConnection *conn, return btd_error_invalid_args(msg); if (adapter_le_is_supported_multi_advertising() && slot_id > 0) - err = adapter_le_enable_multi_adv(enable, slot_id); + err = adapter_le_enable_multi_adv(adapter, enable, slot_id); else err = set_mode(adapter, MGMT_OP_SET_ADVERTISING, enable); @@ -3493,6 +3227,8 @@ static DBusMessage *adapter_set_advertising_data(DBusConnection *conn, dbus_int32_t slot_id; uint8_t *adv_data = NULL; int adv_len = 0; + char *adapter_name = adapter->name; + char le_name[MAX_NAME_LENGTH + 1] = { 0 }; DBG("Set advertising data"); @@ -3508,8 +3244,20 @@ static DBusMessage *adapter_set_advertising_data(DBusConnection *conn, if (len > ADV_DATA_MAX_LENGTH - 3) return btd_error_invalid_args(msg); + if (adapter->le_static_addr.b[5] != 0) { + char *ptr = NULL; + + g_strlcpy(le_name, adapter_name, + sizeof(le_name) - LE_BEARER_POSTFIX_LEN); + if (!g_utf8_validate(le_name, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_strlcat(le_name, LE_BEARER_POSTFIX, sizeof(le_name)); + adapter_name = le_name; + } + adapter_le_set_missed_adv_data(value, len, FALSE, - adapter->name, adapter->adv_tx_power, &adv_data, &adv_len); + adapter_name, adapter->adv_tx_power, &adv_data, &adv_len); if (adapter_le_is_supported_multi_advertising() && slot_id > 0) { if (adapter_le_set_multi_adv_data(slot_id, FALSE, adv_len, adv_data)) { @@ -3764,6 +3512,9 @@ static DBusMessage *adapter_set_scan_rsp_data(DBusConnection *conn, uint8_t *adv_data = NULL; int adv_len = 0; + char *adapter_name = adapter->name; + char le_name[MAX_NAME_LENGTH + 1] = { 0 }; + DBG("Set scan response data"); if (!(adapter->current_settings & MGMT_SETTING_POWERED)) @@ -3778,8 +3529,20 @@ static DBusMessage *adapter_set_scan_rsp_data(DBusConnection *conn, if (len > SCAN_RESPONSE_DATA_LENGTH_MAX) return btd_error_invalid_args(msg); + if (adapter->le_static_addr.b[5] != 0) { + char *ptr = NULL; + + g_strlcpy(le_name, adapter_name, + sizeof(le_name) - LE_BEARER_POSTFIX_LEN); + if (!g_utf8_validate(le_name, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_strlcat(le_name, LE_BEARER_POSTFIX, sizeof(le_name)); + adapter_name = le_name; + } + adapter_le_set_missed_adv_data(value, len, TRUE, - adapter->name, adapter->adv_tx_power, &adv_data, &adv_len); + adapter_name, adapter->adv_tx_power, &adv_data, &adv_len); if (adapter_le_is_supported_multi_advertising() && slot_id > 0) { if (adapter_le_set_multi_adv_data(slot_id, TRUE, adv_len, (uint8_t *)adv_data)) { @@ -4099,85 +3862,6 @@ static DBusMessage *adapter_set_le_static_address(DBusConnection *conn, return dbus_message_new_method_return(msg); } -#if 0 // Not used -static void read_sec_conn_host_support_complete(uint8_t status, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_rp_read_sec_conn_host_support *rp = param; - struct btd_adapter *adapter = user_data; - - if (status != MGMT_STATUS_SUCCESS) { - error("Failed to read secure conn parameter: %s (0x%02x)", - mgmt_errstr(status), status); - return; - } - - if (length < sizeof(*rp)) { - error("Wrong size of read secure connections host support"); - return; - } - - if (rp->sec_conn_host_support) - adapter->secure_connection = TRUE; - else - adapter->secure_connection = FALSE; - - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "SecureConnection"); -} - -static DBusMessage *read_sec_conn_host_support(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct btd_adapter *adapter = user_data; - - mgmt_send(adapter->mgmt, MGMT_OP_READ_SEC_CONN_HOST_SUPPORT, - adapter->dev_id, 0, NULL, - read_sec_conn_host_support_complete, adapter, NULL); - - return dbus_message_new_method_return(msg); -} - -static void write_sec_conn_host_support_complete(uint8_t status, - uint16_t length, const void *param, void *user_data) -{ - const struct mgmt_rp_write_sec_conn_host_support *rp = param; - if (status != MGMT_STATUS_SUCCESS) { - error("Failed to write secure connections host \ - support parameter: %s (0x%02x)", - mgmt_errstr(status), status); - return; - } - - if (length < sizeof(*rp)) { - error("Wrong size of write secure connections host\ - support parameter"); - return; - } -} - -static DBusMessage *write_sec_conn_host_support(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - - struct mgmt_cp_write_sec_conn_host_support cp; - dbus_bool_t enable = FALSE; - struct btd_adapter *adapter = user_data; - - if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, - &enable, DBUS_TYPE_INVALID)) - return btd_error_invalid_args(msg); - - memset(&cp, 0, sizeof(cp)); - cp.secure_connection_host_support = enable; - mgmt_send(adapter->mgmt, MGMT_OP_WRITE_SEC_CONN_HOST_SUPPORT, - adapter->dev_id, sizeof(cp), &cp, - write_sec_conn_host_support_complete, - NULL, NULL); - return dbus_message_new_method_return(msg); -} -#endif - static DBusMessage *adapter_enable_rssi(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -4320,7 +4004,7 @@ static void adapter_get_adv_tx_power(void *data) return; } #endif - +#ifdef __BROADCOM_PATCH__ static DBusMessage *set_wbs_parameters(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -4405,6 +4089,7 @@ static DBusMessage *set_nb_parameters(DBusConnection *conn, return dbus_message_new_method_return(msg); } +#endif /* __BROADCOM_PATCH__ */ #ifdef __TIZEN_PATCH__ void btd_adapter_set_read_le_data_length_handler( @@ -4775,20 +4460,82 @@ static DBusMessage *adapter_set_manufacturer_data(DBusConnection *conn, DBUS_TYPE_INVALID)) return btd_error_invalid_args(msg); - if (len > MANUFACTURER_DATA_LENGTH_MAX) + if (len > EIR_MANUFACTURER_DATA_LENGTH_MAX) return btd_error_invalid_args(msg); memcpy(&cp, value, len); if (mgmt_send(adapter->mgmt, MGMT_OP_SET_MANUFACTURER_DATA, - adapter->dev_id, MANUFACTURER_DATA_LENGTH_MAX, + adapter->dev_id, EIR_MANUFACTURER_DATA_LENGTH_MAX, &cp, NULL, NULL, NULL) > 0) return dbus_message_new_method_return(msg); return btd_error_failed(msg, "Set manufacturer data failed"); } + #endif /* __TIZEN_PATCH__ */ + +static DBusMessage *start_discovery(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + struct btd_adapter *adapter = user_data; + const char *sender = dbus_message_get_sender(msg); + struct watch_client *client; + bool is_discovering; + + DBG("sender %s", sender); + + if (!(adapter->current_settings & MGMT_SETTING_POWERED)) + return btd_error_not_ready(msg); + + is_discovering = get_discovery_client(adapter, sender, &client); + + /* + * Every client can only start one discovery, if the client + * already started a discovery then return an error. + */ + if (is_discovering) + return btd_error_busy(msg); + + /* + * If there was pre-set filter, just reconnect it to discovery_list, + * and trigger scan. + */ + if (client) { + adapter->set_filter_list = g_slist_remove( + adapter->set_filter_list, client); + adapter->discovery_list = g_slist_prepend( + adapter->discovery_list, client); + update_discovery_filter(adapter); + return dbus_message_new_method_return(msg); + } + + client = g_new0(struct watch_client, 1); + + client->adapter = adapter; + client->owner = g_strdup(sender); + client->discovery_filter = NULL; + client->watch = g_dbus_add_disconnect_watch(dbus_conn, sender, + discovery_disconnect, client, + discovery_destroy); + adapter->discovery_list = g_slist_prepend(adapter->discovery_list, + client); + +#ifdef __TIZEN_PATCH__ + adapter->disc_type = BT_DISC_TYPE_BREDR_ONLY; +#endif + + /* + * Just trigger the discovery here. In case an already running + * discovery in idle phase exists, it will be restarted right + * away. + */ + update_discovery_filter(adapter); + + return dbus_message_new_method_return(msg); +} + static bool parse_uuids(DBusMessageIter *value, GSList **uuids) { DBusMessageIter arriter; @@ -5353,9 +5100,7 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, data->adapter = adapter; data->id = id; -/* Because of timing issue, sometimes pscan / iscan value was wrong. */ -#if 0 -/* #ifdef __TIZEN_PATCH__ */ +#ifdef __TIZEN_PATCH__ /* * Use mgmt_send_nowait to avoid dbus timeout in a state of bonding. */ @@ -5547,7 +5292,6 @@ static void iter_append_uuid(gpointer key, gpointer value, gpointer user_data) } #ifdef __TIZEN_PATCH__ - static gboolean property_get_le_discovering(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { @@ -5559,20 +5303,6 @@ static gboolean property_get_le_discovering(const GDBusPropertyTable *property, return TRUE; } -#if 0 // Not used -static gboolean property_get_secure_connection(const GDBusPropertyTable - *property, DBusMessageIter *iter, void *user_data) -{ - struct btd_adapter *adapter = user_data; - dbus_bool_t secure_connection = adapter->secure_connection; - - dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, - &secure_connection); - - return TRUE; -} -#endif - static gboolean property_get_connectable(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { @@ -6043,15 +5773,6 @@ static const GDBusMethodTable adapter_methods[] = { adapter_start_le_discovery) }, { GDBUS_ASYNC_METHOD("StopLEDiscovery", NULL, NULL, adapter_stop_le_discovery) }, -#if 0 // Not used - { GDBUS_METHOD("EnableSecureConnection", - GDBUS_ARGS({"enable", "b"}), NULL, - write_sec_conn_host_support)}, - - { GDBUS_METHOD("ReadSecureConnection", NULL, - NULL, read_sec_conn_host_support)}, -#endif - { GDBUS_METHOD("SetAdvertising", GDBUS_ARGS({ "enable", "b" }, { "slot_id", "i" }), NULL, @@ -6140,7 +5861,7 @@ static const GDBusMethodTable adapter_methods[] = { GDBUS_ARGS({ "address", "s" }), GDBUS_ARGS({ "device", "o" }), find_device) }, -#ifdef __TIZEN_PATCH__ +#ifdef __BROADCOM_PATCH__ { GDBUS_METHOD("SetWbsParameters", GDBUS_ARGS({ "role", "s" }, { "bt_address", "s" }), NULL, @@ -6149,10 +5870,10 @@ static const GDBusMethodTable adapter_methods[] = { GDBUS_ARGS({ "role", "s" }, { "bt_address", "s" }), NULL, set_nb_parameters) }, +#endif { GDBUS_METHOD("SetManufacturerData", GDBUS_ARGS({ "value", "ay" }), NULL, adapter_set_manufacturer_data) }, -#endif { GDBUS_ASYNC_METHOD("CreateDevice", GDBUS_ARGS({ "address", "s" }), NULL, create_device) }, @@ -6219,9 +5940,6 @@ static const GDBusPropertyTable adapter_properties[] = { { "Modalias", "s", property_get_modalias, NULL, property_exists_modalias }, #ifdef __TIZEN_PATCH__ -#if 0 // Not used - { "SecureConnection", "b", property_get_secure_connection }, -#endif { "Connectable", "b", property_get_connectable, property_set_connectable }, { "Version", "s", property_get_version }, @@ -6644,21 +6362,6 @@ static void load_irks_complete(uint8_t status, uint16_t length, DBG("IRKs loaded for hci%u", adapter->dev_id); } -#ifdef __TIZEN_PATCH__ -static void load_devices_rpa_res_support(struct btd_adapter *adapter) -{ - GSList *l; - - DBG("%s", adapter->path); - - for (l = adapter->devices; l; l = l->next) { - struct btd_device *device = l->data; - - btd_adapter_set_dev_rpa_res_support(adapter, device); - } -} -#endif - static void load_irks(struct btd_adapter *adapter, GSList *irks) { struct mgmt_cp_load_irks *cp; @@ -6894,6 +6597,29 @@ static void load_devices(struct btd_adapter *adapter) goto device_exist; } +#ifdef __TIZEN_PATCH__ +{ + char **techno; + + techno = g_key_file_get_string_list(key_file, "General", + "SupportedTechnologies", NULL, NULL); + + /* KITT: Encryption fail with MIC Failure error + Problem happend when two LTK is stored on both RPA and IDA address folder + Here, if IDA dev info is loaded before RPA info, both RPA dev and IDA dev + are created and problem happend.(If RPA info is loaded first, IDA is not + loaded. (upper device_exist case)) + Fix: skip a loadding info in case of 'no technologies' */ + + if (!techno) { + DBG("No SupportedTechnologies. Skipping"); + goto free; + } + + g_strfreev(techno); +} +#endif + device = device_create_from_storage(adapter, entry->d_name, key_file); if (!device) @@ -6965,10 +6691,6 @@ free: g_slist_free_full(params, g_free); g_slist_free_full(added_devices, probe_devices); - -#ifdef __TIZEN_PATCH__ - load_devices_rpa_res_support(adapter); -#endif } int btd_adapter_block_address(struct btd_adapter *adapter, @@ -8553,11 +8275,18 @@ static void load_config(struct btd_adapter *adapter) str = g_key_file_get_string(key_file, "General", "LocalIrk", &gerr); if (gerr || !str || strlen(str) != 34) { - memset(adapter->local_irk, 0, MGMT_IRK_SIZE); g_error_free(gerr); gerr = NULL; - } else - str2buf(&str[2], (uint8_t *)adapter->local_irk, MGMT_IRK_SIZE); + + g_free(adapter->local_irk); + adapter->local_irk = NULL; + } else { + if (adapter->local_irk) + g_free(adapter->local_irk); + + adapter->local_irk = g_malloc0(MGMT_IRK_SIZE); + str2buf(&str[2], adapter->local_irk, MGMT_IRK_SIZE); + } } #endif @@ -8616,8 +8345,6 @@ static struct btd_adapter *btd_adapter_new(uint16_t index) DBG("LE Privacy is enabled."); else DBG("LE Privacy is disabled."); - - adapter->central_rpa_res_support = 0x00; #endif adapter->auths = g_queue_new(); @@ -8737,6 +8464,24 @@ const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter) return &adapter->bdaddr; } +#ifdef __TIZEN_PATCH__ +const bdaddr_t *btd_adapter_get_le_address(struct btd_adapter *adapter) +{ + if (adapter->le_static_addr.b[5] != 0) + return &adapter->le_static_addr; + else + return &adapter->bdaddr; +} + +uint8_t btd_adapter_get_le_address_type(struct btd_adapter * adapter) +{ + if (adapter->le_static_addr.b[5] != 0) + return BDADDR_LE_RANDOM; + else + return BDADDR_LE_PUBLIC; +} +#endif + static gboolean confirm_name_timeout(gpointer user_data) { struct btd_adapter *adapter = user_data; @@ -9265,8 +9010,14 @@ static void adapter_remove_connection(struct btd_adapter *adapter, return; adapter->connections = g_slist_remove(adapter->connections, device); - +#ifdef __TIZEN_PATCH__ + DBG("isPaired %d, isBonded %d", device_is_paired(device, bdaddr_type), + device_is_bonded(device, bdaddr_type)); + if ((device_is_temporary(device) && !device_is_retrying(device)) || + (!device_is_bonded(device, bdaddr_type))) { +#else if (device_is_temporary(device) && !device_is_retrying(device)) { +#endif const char *path = device_get_path(device); DBG("Removing temporary device %s", path); @@ -10081,40 +9832,20 @@ void adapter_check_version(struct btd_adapter *adapter, uint8_t hci_ver) break; case 6: ver = "Bluetooth 4.0"; - break; - case 7: - ver = "Bluetooth 4.1"; - break; - default: - ver = "Unknown"; - break; - } - - if (adapter->version) - g_free(adapter->version); - - adapter->version = g_strdup(ver); -} - -#if 0 // Not used -static void new_local_irk_callback(uint16_t index, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_ev_new_local_irk *ev = param; - struct btd_adapter *adapter = user_data; - - if (length < sizeof(*ev)) { - error("Too small size of Local IRK generated"); - return; + break; + case 7: + ver = "Bluetooth 4.1"; + break; + default: + ver = "Unknown"; + break; } - DBG("Local IRK generated for hci%u", index); + if (adapter->version) + g_free(adapter->version); - memset(adapter->local_irk, 0, sizeof(adapter->local_irk)); - memcpy(adapter->local_irk, (char *)ev->irk, sizeof(adapter->local_irk)); - store_adapter_info(adapter); + adapter->version = g_strdup(ver); } -#endif static void hardware_error_callback(uint16_t index, uint16_t length, const void *param, void *user_data) @@ -10187,6 +9918,7 @@ static void multi_adv_state_change_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { const struct mgmt_ev_vendor_specific_multi_adv_state_changed *ev = param; + struct btd_adapter *adapter = user_data; if (length < sizeof(*ev)) { error("Too small adv state change event"); @@ -10198,7 +9930,31 @@ static void multi_adv_state_change_callback(uint16_t index, uint16_t length, if ((ev->adv_instance > 0 && ev->adv_instance < adapter_le_get_max_adv_instance()) && ev->state_change_reason == 0) - adapter_le_enable_multi_adv(TRUE, ev->adv_instance); + adapter_le_enable_multi_adv(adapter, TRUE, ev->adv_instance); +} + +static void le_conn_update_completed_callback(uint16_t index, uint16_t length, + const void *param, void *user_data) +{ + const struct mgmt_ev_conn_updated *ev = param; + struct btd_adapter *adapter = user_data; + struct btd_device *device; + char addr[18]; + GSList *list; + + if (length < sizeof(*ev)) { + error("Too small le conn update completed event"); + return; + } + + ba2str(&ev->addr.bdaddr, addr); + list = g_slist_find_custom(adapter->devices, addr, + device_address_cmp); + if (list) { + device = list->data; + if (device_get_conn_update_state(device)) + device_set_conn_update_state(device, false); + } } static void bt_6lowpan_conn_state_change_callback(uint16_t index, uint16_t length, @@ -10266,29 +10022,6 @@ static void bt_le_data_length_changed_callback(uint16_t index, uint16_t length, ev->max_rx_octets, ev->max_rx_time); } -static void le_conn_update_completed_callback(uint16_t index, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_ev_conn_updated *ev = param; - struct btd_adapter *adapter = user_data; - struct btd_device *device; - char addr[18]; - GSList *list; - - if (length < sizeof(*ev)) { - error("Too small le conn update completed event"); - return; - } - - ba2str(&ev->addr.bdaddr, addr); - list = g_slist_find_custom(adapter->devices, addr, - device_address_cmp); - if (list) { - device = list->data; - if (device_get_conn_update_state(device)) - device_set_conn_update_state(device, false); - } -} #endif struct btd_adapter_pin_cb_iter *btd_adapter_pin_cb_iter_new( @@ -10458,10 +10191,7 @@ static void bonding_complete(struct btd_adapter *adapter, if (device != NULL) device_bonding_complete(device, addr_type, status); -#ifdef __TIZEN_PATCH__ - //resume_discovery(adapter); - //resume_le_discovery(adapter); -#else +#ifndef __TIZEN_PATCH__ resume_discovery(adapter); #endif check_oob_bonding_complete(adapter, bdaddr, status); @@ -11196,11 +10926,11 @@ static void new_irk_callback(uint16_t index, uint16_t length, #else device = btd_adapter_get_device(adapter, &ev->rpa, - BDADDR_LE_RANDOM); + BDADDR_LE_RANDOM); #endif duplicate = btd_adapter_find_device(adapter, &addr->bdaddr, - addr->type); + addr->type); if (duplicate == device) duplicate = NULL; } else { @@ -11271,10 +11001,6 @@ static void new_irk_callback(uint16_t index, uint16_t length, #endif btd_device_set_temporary(device, false); - -#ifdef __TIZEN_PATCH__ - btd_adapter_set_dev_rpa_res_support(adapter, device); -#endif } static void store_conn_param(struct btd_adapter *adapter, const bdaddr_t *peer, @@ -11418,6 +11144,62 @@ int btd_adapter_remove_remote_oob_data(struct btd_adapter *adapter, return -EIO; } +#ifdef __TIZEN_PATCH__ +int btd_adapter_add_remote_oob_ext_data(struct btd_adapter *adapter, + const bdaddr_t *bdaddr, uint8_t bdaddr_type, + uint8_t *hash192, uint8_t *randomizer192, + uint8_t *hash256, uint8_t *randomizer256) +{ + struct mgmt_cp_add_remote_oob_data cp; + char addr[18]; + + ba2str(bdaddr, addr); + DBG("hci%d bdaddr %s type %d", adapter->dev_id, addr, bdaddr_type); + + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.addr.bdaddr, bdaddr); + cp.addr.type = bdaddr_type; + + if (hash192 && randomizer192) { + memcpy(cp.hash192, hash192, 16); + memcpy(cp.rand192, randomizer192, 16); + } + + if (hash256 && randomizer256) { + memcpy(cp.hash256, hash256, 16); + memcpy(cp.rand256, randomizer256, 16); + } + + if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_REMOTE_OOB_DATA, + adapter->dev_id, sizeof(cp), &cp, + NULL, NULL, NULL) > 0) + return 0; + + return -EIO; +} + +int btd_adapter_remove_remote_oob_ext_data(struct btd_adapter *adapter, + const bdaddr_t *bdaddr, uint8_t bdaddr_type) +{ + struct mgmt_cp_remove_remote_oob_data cp; + char addr[18]; + + ba2str(bdaddr, addr); + DBG("hci%d bdaddr %s type %d", adapter->dev_id, addr, bdaddr_type); + + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.addr.bdaddr, bdaddr); + cp.addr.type = bdaddr_type; + + if (mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + adapter->dev_id, sizeof(cp), &cp, + NULL, NULL, NULL) > 0) + return 0; + + return -EIO; +} +#endif + bool btd_adapter_ssp_enabled(struct btd_adapter *adapter) { if (adapter->current_settings & MGMT_SETTING_SSP) @@ -11443,6 +11225,10 @@ static void read_local_oob_data_complete(uint8_t status, uint16_t length, const struct mgmt_rp_read_local_oob_data *rp = param; struct btd_adapter *adapter = user_data; const uint8_t *hash, *randomizer; +#ifdef __TIZEN_PATCH__ + const uint8_t *hash256 = NULL; + const uint8_t *randomizer256 = NULL; +#endif if (status != MGMT_STATUS_SUCCESS) { btd_error(adapter->dev_id, @@ -11461,13 +11247,25 @@ static void read_local_oob_data_complete(uint8_t status, uint16_t length, } else { hash = rp->hash192; randomizer = rp->rand192; +#ifdef __TIZEN_PATCH__ + if (length > 32) { + hash256 = rp->hash256; + randomizer256 = rp->rand256; + } +#endif } if (!adapter->oob_handler || !adapter->oob_handler->read_local_cb) return; +#ifdef __TIZEN_PATCH__ + adapter->oob_handler->read_local_cb(adapter, hash, randomizer, + hash256, randomizer256, + adapter->oob_handler->user_data); +#else adapter->oob_handler->read_local_cb(adapter, hash, randomizer, adapter->oob_handler->user_data); +#endif g_free(adapter->oob_handler); adapter->oob_handler = NULL; @@ -11639,8 +11437,8 @@ static int adapter_register(struct btd_adapter *adapter) #ifdef __TIZEN_PATCH__ if (adapter->le_privacy_enabled && - (adapter->supported_settings & MGMT_SETTING_PRIVACY)) - set_privacy(adapter, true); + (adapter->supported_settings & MGMT_SETTING_PRIVACY)) + set_privacy(adapter, true); else DBG("LE privacy feature not configured or supported"); #endif @@ -11966,33 +11764,47 @@ static void set_privacy_complete(uint8_t status, uint16_t length, static bool set_privacy(struct btd_adapter *adapter, bool privacy) { struct mgmt_cp_set_privacy cp; - static const char testblock[MGMT_IRK_SIZE]; memset(&cp, 0, sizeof(cp)); - if (privacy) { - if (!memcmp(adapter->local_irk, testblock, MGMT_IRK_SIZE)) { - cp.privacy = GEN_IRK_THEN_ENABLE_PRIVACY; - memset(cp.irk, 0, MGMT_IRK_SIZE); - } else { - cp.privacy = ENABLE_PRIVACY; - memcpy(cp.irk, adapter->local_irk, MGMT_IRK_SIZE); + if (privacy && !adapter->local_irk) { + int fd; + + DBG("Generate local irk"); + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + goto fail; + + adapter->local_irk = g_malloc0(MGMT_IRK_SIZE); + if (read(fd, adapter->local_irk, MGMT_IRK_SIZE) != + MGMT_IRK_SIZE) { + error("Cannot read local irk"); + close(fd); + goto fail; } - } else { - cp.privacy = DISABLE_PRIVACY; - memset(cp.irk, 0, MGMT_IRK_SIZE); + close(fd); + + store_adapter_info(adapter); } + + if (privacy) { + cp.privacy = 0x01; + memcpy(cp.irk, adapter->local_irk, MGMT_IRK_SIZE); + } + if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PRIVACY, - adapter->dev_id, sizeof(cp), &cp, - set_privacy_complete, adapter, NULL) > 0) + adapter->dev_id, sizeof(cp), &cp, + set_privacy_complete, adapter, NULL) > 0) return true; +fail: error("Failed to set privacy and load local irk for index %u", - adapter->dev_id); - + adapter->dev_id); return false; } + int btd_adapter_connect_ipsp(struct btd_adapter *adapter, const bdaddr_t *bdaddr, uint8_t bdaddr_type) @@ -12352,13 +12164,6 @@ static void read_info_complete(uint8_t status, uint16_t length, rssi_disabled_callback, adapter, NULL); -#if 0 // Not used - mgmt_register(adapter->mgmt, MGMT_EV_NEW_LOCAL_IRK, - adapter->dev_id, - new_local_irk_callback, - adapter, NULL); -#endif - mgmt_register(adapter->mgmt, MGMT_EV_HARDWARE_ERROR, adapter->dev_id, hardware_error_callback, @@ -12746,176 +12551,3 @@ bool btd_le_connect_before_pairing(void) return false; } - -#ifdef __TIZEN_PATCH__ -#if 0 // Not used -static void read_rssi_complete(uint8_t status, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_rp_read_rssi *rp = param; - struct btd_device *device = user_data; - - if (status != MGMT_STATUS_SUCCESS) { - error("read RSSI failed: %s (0x%02x)", - mgmt_errstr(status), status); - return; - } - - if (length < sizeof(*rp)) { - error("Too small read rssi response"); - return; - } - - if (!rp->status) { - device_set_rssi(device, rp->rssi); - } - return; -} - -int btd_adapter_read_rssi(struct btd_adapter *adapter, bdaddr_t *bdaddr, - struct btd_device *device) -{ - struct mgmt_cp_read_rssi cp; - - DBG("btd_adapter_read_rssi"); - memset(&cp, 0, sizeof(cp)); - bacpy(&cp.bdaddr, bdaddr); - - if (mgmt_send(adapter->mgmt, MGMT_OP_READ_RSSI, - adapter->dev_id, sizeof(cp), &cp, - read_rssi_complete, device, NULL) > 0) - return 0; - return -EIO; -} - -int btd_adapter_l2cap_conn_param_update(struct btd_adapter *adapter, - bdaddr_t *bdaddr, uint16_t interval_min, - uint16_t interval_max, uint16_t latency, - uint16_t supervision_time_out) -{ - struct mgmt_cp_l2cap_conn_param_update cp; - - memset(&cp, 0, sizeof(cp)); - if (bdaddr) - bacpy(&cp.bdaddr, bdaddr); - else - return -EIO; - - cp.interval_min = interval_min; - cp.interval_max = interval_max; - cp.latency = latency; - cp.supervision_time_out = supervision_time_out; - if (mgmt_send(adapter->mgmt, MGMT_OP_L2CAP_CONN_PARAM_UPDATE, - adapter->dev_id, sizeof(cp), &cp, - NULL, NULL, NULL) > 0) - return 0; - - return -EIO; -} - -static void write_auth_payload_timeout_complete(uint8_t status, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_rp_write_auth_payload_timeout *rp = param; - - if (status != MGMT_STATUS_SUCCESS) { - error("Failed to write auth payload timeout: %s (0x%02x)", - mgmt_errstr(status), status); - return; - } - - if (length < sizeof(*rp)) { - error("Wrong size of write auth payload timeout parameter"); - return; - } -} - -int btd_adapter_write_auth_payload_timeout(struct btd_adapter *adapter, - bdaddr_t *bdaddr, uint32_t payload_timeout, - struct btd_device *device) -{ - struct mgmt_cp_write_auth_payload_timeout cp; - memset(&cp, 0, sizeof(cp)); - bacpy(&cp.bdaddr, bdaddr); - - if (payload_timeout > 65536) - return -EIO; - else - cp.auth_payload_timeout = payload_timeout; - - if (mgmt_send(adapter->mgmt, MGMT_OP_WRITE_AUTH_PAYLOAD_TIMEOUT, - adapter->dev_id, sizeof(cp), &cp, - write_auth_payload_timeout_complete, device, NULL) > 0) - return 0; - return -EIO; -} - -static void read_auth_payload_timeout_complete(uint8_t status, uint16_t length, - const void *param, void *user_data) -{ - const struct mgmt_rp_read_auth_payload_timeout *rp = param; - struct btd_device *device = user_data; - if (status != MGMT_STATUS_SUCCESS) { - error("read auth payload timeout failed: %s (0x%02x)", - mgmt_errstr(status), status); - return; - } - - if (length < sizeof(*rp)) { - error("Too small read payload response"); - return; - } - - if (!rp->status) { - device_set_payload_timeout(device, rp->auth_payload_timeout); - } - return; -} - -int btd_adapter_read_auth_payload_timeout(struct btd_adapter *adapter, - bdaddr_t *bdaddr, struct btd_device *device) -{ - struct mgmt_cp_read_auth_payload_timeout cp; - memset(&cp, 0, sizeof(cp)); - bacpy(&cp.bdaddr, bdaddr); - - if (mgmt_send(adapter->mgmt, MGMT_OP_READ_AUTH_PAYLOAD_TIMEOUT, - adapter->dev_id, sizeof(cp), &cp, - read_auth_payload_timeout_complete, device, NULL) > 0) - return 0; - return -EIO; -} -#endif - -int btd_adapter_le_conn_update(struct btd_adapter *adapter, bdaddr_t *bdaddr, - uint16_t interval_min, uint16_t interval_max, - uint16_t latency, uint16_t supervision_time_out) -{ - struct mgmt_cp_le_conn_update cp; - - memset(&cp, 0, sizeof(cp)); - - if (NULL != bdaddr) - bacpy(&cp.bdaddr, bdaddr); - else - return -EIO; - - cp.interval_min = interval_min; - cp.interval_max = interval_max; - cp.latency = latency; - cp.supervision_time_out = supervision_time_out; - - if (mgmt_send(adapter->mgmt, MGMT_OP_LE_CONN_UPDATE, - adapter->dev_id, sizeof(cp), &cp, - NULL, NULL, NULL) > 0) - return 0; - - return -EIO; -} - -GSList *btd_adapter_get_connections(struct btd_adapter *adapter) -{ - /* Return the connected device list */ - return adapter->connections; -} -#endif /* __TIZEN_PATCH__ */ diff --git a/src/adapter.h b/src/adapter.h index ee28c0f..71c7665 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -53,6 +53,14 @@ uint16_t btd_adapter_get_index(struct btd_adapter *adapter); typedef void (*adapter_cb) (struct btd_adapter *adapter, gpointer user_data); +#ifdef __TIZEN_PATCH__ +typedef void (*oob_ext_read_local_cb_t) (struct btd_adapter *adapter, + const uint8_t *hash192, + const uint8_t *randomizer192, + const uint8_t *hash256, + const uint8_t *randomizer256, + void *user_data); +#endif typedef void (*oob_read_local_cb_t) (struct btd_adapter *adapter, const uint8_t *hash, const uint8_t *randomizer, @@ -62,7 +70,11 @@ typedef void (*oob_bonding_cb_t) (struct btd_adapter *adapter, void *user_data); struct oob_handler { +#ifdef __TIZEN_PATCH__ + oob_ext_read_local_cb_t read_local_cb; +#else oob_read_local_cb_t read_local_cb; +#endif oob_bonding_cb_t bonding_cb; bdaddr_t remote_addr; void *user_data; @@ -115,6 +127,10 @@ struct btd_device *btd_adapter_find_device(struct btd_adapter *adapter, const char *adapter_get_path(struct btd_adapter *adapter); const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter); +#ifdef __TIZEN_PATCH__ +const bdaddr_t *btd_adapter_get_le_address(struct btd_adapter *adapter); +uint8_t btd_adapter_get_le_address_type(struct btd_adapter * adapter); +#endif int adapter_set_name(struct btd_adapter *adapter, const char *name); int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec); @@ -221,6 +237,16 @@ int btd_adapter_add_remote_oob_data(struct btd_adapter *adapter, int btd_adapter_remove_remote_oob_data(struct btd_adapter *adapter, const bdaddr_t *bdaddr); +#ifdef __TIZEN_PATCH__ +int btd_adapter_add_remote_oob_ext_data(struct btd_adapter *adapter, + const bdaddr_t *bdaddr, uint8_t bdaddr_type, + uint8_t *hash192, uint8_t *randomizer192, + uint8_t *hash256, uint8_t *randomizer256); + +int btd_adapter_remove_remote_oob_ext_data(struct btd_adapter *adapter, + const bdaddr_t *bdaddr, uint8_t bdaddr_type); +#endif + int btd_adapter_gatt_server_start(struct btd_adapter *adapter); void btd_adapter_gatt_server_stop(struct btd_adapter *adapter); @@ -250,33 +276,6 @@ void btd_adapter_for_each_device(struct btd_adapter *adapter, bool btd_le_connect_before_pairing(void); #ifdef __TIZEN_PATCH__ -#if 0 // Not used -int btd_adapter_read_rssi(struct btd_adapter *adapter, bdaddr_t *bdaddr, - struct btd_device *device); - -int btd_adapter_l2cap_conn_param_update(struct btd_adapter *adapter, - bdaddr_t *bdaddr, uint16_t interval_min, - uint16_t interval_max, uint16_t latency, - uint16_t supervision_time_out); - -int btd_adapter_write_auth_payload_timeout(struct btd_adapter *adapter, - bdaddr_t *bdaddr, uint32_t payload_timeout, - struct btd_device *device); -int btd_adapter_read_auth_payload_timeout(struct btd_adapter *adapter, - bdaddr_t *bdaddr, struct btd_device *device); -#endif - -int btd_adapter_le_conn_update(struct btd_adapter *adapter, bdaddr_t *bdaddr, - uint16_t interval_min, uint16_t interval_max, - uint16_t latency, uint16_t supervision_time_out); -gboolean adapter_clear_le_white_list(struct btd_adapter *adapter); -gboolean adapter_add_le_white_list(struct btd_adapter *adapter, struct btd_device *device); - -gboolean btd_adapter_is_le_auto_connect(struct btd_adapter *adapter); -void btd_adapter_set_le_auto_connect(struct btd_adapter *adapter, gboolean auto_connect); -gboolean btd_adapter_disable_le_auto_connect(struct btd_adapter *adapter); -void adapter_check_version(struct btd_adapter *adapter, uint8_t hci_ver); -GSList *btd_adapter_get_connections(struct btd_adapter *adapter); int btd_adapter_connect_ipsp(struct btd_adapter *adapter, const bdaddr_t *bdaddr, uint8_t bdaddr_type); @@ -289,6 +288,7 @@ uint8_t btd_adapter_get_rpa_res_support_value( int btd_adapter_set_dev_rpa_res_support(struct btd_adapter *adapter, struct btd_device *device); +#endif typedef void (*read_max_data_length_cb_t) (struct btd_adapter *adapter, const uint16_t max_txOctects, @@ -313,7 +313,9 @@ struct le_data_length_read_default_data_length_handler { }; int btd_adapter_le_set_data_length(struct btd_adapter *adapter, bdaddr_t *bdaddr, - uint16_t max_tx_octets, uint16_t max_tx_time); + uint16_t max_tx_octets, uint16_t max_tx_time); +#ifdef __TIZEN_PATCH__ +void adapter_check_version(struct btd_adapter *adapter, uint8_t hci_ver); #ifdef TIZEN_WEARABLE charging_state_e get_charging_state(struct btd_adapter *adapter); #endif /* TIZEN_WEARABLE */ diff --git a/src/adapter_le_vsc_features.c b/src/adapter_le_vsc_features.c index d6a68f8..2ab3d14 100644 --- a/src/adapter_le_vsc_features.c +++ b/src/adapter_le_vsc_features.c @@ -11,6 +11,31 @@ static apater_le_vsc_rp_get_vendor_cap ble_vsc_cb = { -1, }; +static int update_le_address(const bdaddr_t *le_addr) +{ + int hdev = 0; + le_set_random_address_cp cp; + + hdev = hci_open_dev(0); + if (hdev < 0) { + error("Cannot open hdev"); + return -1; + } + + bacpy(&cp.bdaddr, le_addr); + + if (hci_send_cmd(hdev, OGF_LE_CTL, OCF_LE_SET_RANDOM_ADDRESS, + LE_SET_RANDOM_ADDRESS_CP_SIZE, &cp) < 0) { + error("hci_send_cmd is failed"); + hci_close_dev(hdev); + return -1; + } + + hci_close_dev(hdev); + + return 0; +} + static int send_vsc_command(uint16_t ocf, uint8_t *cp, uint8_t cp_len, uint8_t *rp, uint8_t rp_len) { @@ -200,13 +225,23 @@ gboolean adapter_le_set_multi_adv_data(uint8_t inst_id, gboolean is_scan_rsp, return TRUE; } -gboolean adapter_le_enable_multi_adv (gboolean enable, uint8_t inst_id) +gboolean adapter_le_enable_multi_adv (struct btd_adapter *adapter, + gboolean enable, uint8_t inst_id) { int ret; adapter_le_vsc_cp_enable_multi_adv cp; apater_le_vsc_rp_multi_adv rp; + uint8_t bdaddr_type; + const bdaddr_t *bdaddr; DBG(""); + if (enable) { + bdaddr_type = btd_adapter_get_le_address_type(adapter); + if (bdaddr_type == BDADDR_LE_RANDOM) { + bdaddr = btd_adapter_get_le_address(adapter); + update_le_address(bdaddr); + } + } memset(&cp, 0, sizeof(cp)); cp.subcode = SUB_CMD_LE_MULTI_ADV_ENB; @@ -663,7 +698,7 @@ gboolean adapter_le_enable_offloading(gboolean enable) return TRUE; } -gboolean adapter_le_add_irk_to_list(uint8_t *le_irk, const bdaddr_t *bdaddr, uint8_t bdaddr_type) +gboolean adapter_le_add_irk_to_list(const uint8_t *le_irk, const bdaddr_t *bdaddr, uint8_t bdaddr_type) { int ret; adapter_le_vsc_cp_add_irk_to_list cp; diff --git a/src/adapter_le_vsc_features.h b/src/adapter_le_vsc_features.h index e5ec624..0bbc866 100644 --- a/src/adapter_le_vsc_features.h +++ b/src/adapter_le_vsc_features.h @@ -476,8 +476,8 @@ gboolean adapter_le_set_multi_adv_params (adapter_le_adv_inst_info_t *p_inst, gboolean adapter_le_set_multi_adv_data(uint8_t inst_id, gboolean is_scan_rsp, uint8_t data_len, uint8_t *p_data); -gboolean adapter_le_enable_multi_adv (gboolean enable, uint8_t inst_id); - +gboolean adapter_le_enable_multi_adv (struct btd_adapter *adapter, + gboolean enable, uint8_t inst_id); gboolean adapter_le_enable_scan_filtering (gboolean enable); @@ -496,7 +496,7 @@ gboolean adapter_le_clear_scan_filter_data(int client_if, int filter_index); gboolean adapter_le_enable_offloading(gboolean enable); -gboolean adapter_le_add_irk_to_list(uint8_t *le_irk, const bdaddr_t *bdaddr, uint8_t bdaddr_type); +gboolean adapter_le_add_irk_to_list(const uint8_t *le_irk, const bdaddr_t *bdaddr, uint8_t bdaddr_type); gboolean adapter_le_remove_irk_to_list(const bdaddr_t *bdaddr, uint8_t bdaddr_type); diff --git a/src/attrib-server.c b/src/attrib-server.c index 06293fa..31989af 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -1049,11 +1049,6 @@ static void channel_remove(struct gatt_channel *channel) { channel->server->clients = g_slist_remove(channel->server->clients, channel); -#ifdef __TIZEN_PATCH__ - if (channel->server->clients == NULL) { - device_set_gatt_connected(channel->device, FALSE); - } -#endif channel_free(channel); } @@ -1292,9 +1287,6 @@ guint attrib_channel_attach(GAttrib *attrib) channel->cleanup_id = g_io_add_watch(io, G_IO_HUP, channel_watch_cb, channel); -#ifdef __TIZEN_PATCH__ - device_set_attrib(device, channel->id, channel->attrib); -#endif channel->device = btd_device_ref(device); server->clients = g_slist_append(server->clients, channel); @@ -1778,15 +1770,12 @@ static uint8_t attrib_get_ccc_info(struct btd_device *device, uint16_t handle) /* Get the CCC value */ value = g_key_file_get_string(key_file, group, "Value", NULL); - if (!value) { - /* Fix : RESOURCE_LEAK */ - g_free(filename); - g_key_file_free(key_file); + if (!value) return 0; - } sscanf(value, "%hX", &cccval); + g_free(value); g_free(filename); g_key_file_free(key_file); diff --git a/src/device.c b/src/device.c index 998c3eb..6feb69d 100644 --- a/src/device.c +++ b/src/device.c @@ -319,7 +319,6 @@ struct btd_device { GIOChannel *att_io; guint store_id; #ifdef __TIZEN_PATCH__ - guint attachid; /* Attrib server attach */ bool legacy_pairing; char *manufacturer_data; int manufacturer_data_len; @@ -331,8 +330,6 @@ struct btd_device { uint8_t disc_reason; uint8_t last_bdaddr_type; uint8_t auth_bdaddr_type; - gboolean le_auto_connect; - guint auto_id; gboolean ipsp_connected; /* IPSP Connection state */ char if_name[16 + 1]; /* BT interface UP after IPSP connection */ uint8_t rpa_res_support; /* RPA Resolution capability of device */ @@ -372,10 +369,6 @@ typedef enum { static int device_browse_gatt(struct btd_device *device, DBusMessage *msg); static int device_browse_sdp(struct btd_device *device, DBusMessage *msg); -#ifdef __TIZEN_PATCH__ -static int device_custom_browse_sdp(struct btd_device *device, - DBusMessage *msg, uuid_t *search); -#endif static struct bearer_state *get_state(struct btd_device *dev, uint8_t bdaddr_type) @@ -771,13 +764,6 @@ static void gatt_server_cleanup(struct btd_device *device) static void attio_cleanup(struct btd_device *device) { -#ifdef __TIZEN_PATCH__ - if (device->attachid) { - attrib_channel_detach(device->attrib, device->attachid); - device->attachid = 0; - } -#endif - if (device->att_disconn_id) bt_att_unregister_disconnect(device->att, device->att_disconn_id); @@ -870,14 +856,6 @@ static void device_free(gpointer user_data) if (device->disconnect) dbus_message_unref(device->disconnect); -#ifdef __TIZEN_PATCH__ - if (device->auto_id) - g_source_remove(device->auto_id); - - if (device->le_auto_connect) - btd_adapter_disable_le_auto_connect(device->adapter); -#endif - DBG("%p", device); if (device->authr) { @@ -909,22 +887,6 @@ gboolean device_is_bredrle(struct btd_device *device) return (device->remote_feature_flags & (DEV_SIMUL_CONTROLLER | DEV_SIMUL_HOST)); } - -#if 0 /* caller of below function exists but currently commented */ -static uint8_t device_get_paired_state(struct btd_device *device) -{ - uint8_t paired = DEV_PAIRED_NONE; - - if (device->bredr_state.paired && device->le_state.paired) - paired = DEV_PAIRED_BREDR_LE; - else if (device->le_state.paired) - paired = DEV_PAIRED_LE; - else if (device->bredr_state.paired) - paired = DEV_PAIRED_BREDR; - - return paired; -} -#endif #endif bool device_is_paired(struct btd_device *device, uint8_t bdaddr_type) @@ -1039,6 +1001,24 @@ static gboolean dev_property_get_alias(const GDBusPropertyTable *property, return TRUE; } +#ifdef __TIZEN_PATCH__ +static gboolean dev_property_get_alias_set(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device *device = data; + dbus_bool_t val; + + if (device->alias != NULL) + val = TRUE; + else + val = FALSE; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val); + + return TRUE; +} +#endif + static void set_alias(GDBusPendingPropertySet id, const char *alias, void *data) { @@ -1330,7 +1310,6 @@ static gboolean dev_property_get_trusted_profiles(const GDBusPropertyTable *prop (map << MAP_SHIFT_OFFSET) | (sap << SAP_SHIFT_OFFSET); - DBG("TrustedProfiles : %d", val); dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val); return TRUE; @@ -1429,6 +1408,34 @@ static gboolean dev_property_get_last_addr_type(const GDBusPropertyTable *proper return TRUE; } +static gboolean dev_property_get_att_mtu(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device *device = data; + dbus_uint16_t mtu = bt_gatt_client_get_mtu(device->client); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &mtu); + + return TRUE; +} + +static gboolean dev_property_get_gatt_connected(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device *device = data; + dbus_bool_t gatt_connected; + + if (device->gatt_connected) + gatt_connected = TRUE; + else + gatt_connected = FALSE; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, + &gatt_connected); + + return TRUE; +} + static gboolean dev_property_get_ipsp_conn_state(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { @@ -1458,17 +1465,6 @@ static gboolean dev_property_get_ipsp_conn_bt_iface_name(const GDBusPropertyTabl return TRUE; } - -static gboolean dev_property_get_att_mtu(const GDBusPropertyTable *property, - DBusMessageIter *iter, void *data) -{ - struct btd_device *device = data; - dbus_uint16_t mtu = bt_gatt_client_get_mtu(device->client); - - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &mtu); - - return TRUE; -} #endif static gboolean dev_property_get_connected(const GDBusPropertyTable *property, @@ -1494,24 +1490,6 @@ static gboolean dev_property_get_connected(const GDBusPropertyTable *property, return TRUE; } -#ifdef __TIZEN_PATCH__ -static gboolean dev_property_get_gatt_connected(const GDBusPropertyTable *property, - DBusMessageIter *iter, void *data) -{ - struct btd_device *device = data; - dbus_bool_t gatt_connected; - - if (device->gatt_connected) - gatt_connected = TRUE; - else - gatt_connected = FALSE; - - dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, - &gatt_connected); - - return TRUE; -} -#endif static gboolean dev_property_get_uuids(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) @@ -1572,18 +1550,8 @@ static gboolean dev_property_get_adapter(const GDBusPropertyTable *property, return TRUE; } -#ifdef __TIZEN_PATCH__ -static gboolean property_get_flag(const GDBusPropertyTable *property, - DBusMessageIter *iter, void *user_data) -{ - struct btd_device *device = user_data; - dbus_uint16_t val = device->le_adv_data.flags; - - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &val); - - return TRUE; -} +#ifdef __TIZEN_PATCH__ static gboolean property_get_manufacturer_data_len(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { @@ -2165,6 +2133,12 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid) service = find_connectable_service(dev, HSP_HS_UUID); if (service) return g_slist_prepend(dev->pending, service); + } else if (g_strcmp0(uuid, HID_UUID) == 0) { + DBG("HID service not found, add HID service"); + btd_device_add_uuid(dev, uuid); + service = find_connectable_service(dev, HID_UUID); + if (service) + return g_slist_prepend(dev->pending, service); } #endif return dev->pending; @@ -2263,8 +2237,13 @@ static DBusMessage *connect_profiles(struct btd_device *dev, uint8_t bdaddr_type dev->pending = create_pending_list(dev, uuid); if (!dev->pending) { if (dev->svc_refreshed) { +#ifdef __TIZEN_PATCH__ + if (!uuid && find_service_with_state(dev->services, + BTD_SERVICE_STATE_CONNECTED)) +#else if (find_service_with_state(dev->services, BTD_SERVICE_STATE_CONNECTED)) +#endif return dbus_message_new_method_return(msg); else return btd_error_not_available(msg); @@ -2666,6 +2645,9 @@ static void store_gatt_db(struct btd_device *device) key_file = g_key_file_new(); g_key_file_load_from_file(key_file, filename, 0, NULL); + /* Remove current attributes since it might have changed */ + g_key_file_remove_group(key_file, "Attributes", NULL); + saver.key_file = key_file; saver.device = device; @@ -3120,59 +3102,6 @@ static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg, } #ifdef __TIZEN_PATCH__ -#if 0 // Not used -static DBusMessage *read_rssi(DBusConnection *conn, DBusMessage *msg, - void *user_data) -{ - struct btd_device *device = user_data; - DBG("read_rssi"); - int status = btd_adapter_read_rssi(device->adapter, - &device->bdaddr, device); - if (status != 0) - return btd_error_failed(msg, "Unable to read rssi"); - else - return dbus_message_new_method_return(msg); -} - -static DBusMessage *l2cap_conn_param_update(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct btd_device *device = user_data; - uint32_t interval_min, interval_max, latency, time_out; - int status; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &interval_min, - DBUS_TYPE_UINT32, &interval_max, - DBUS_TYPE_UINT32, &latency, - DBUS_TYPE_UINT32, &time_out, - DBUS_TYPE_INVALID)) - return btd_error_invalid_args(msg); - - status = btd_adapter_l2cap_conn_param_update(device->adapter, - &device->bdaddr, interval_min, - interval_max, latency, time_out); - if (status != 0) - return btd_error_failed(msg, "Unable to update L2cap connection parameter"); - else - return dbus_message_new_method_return(msg); -} - -static DBusMessage *read_auth_payload_timeout(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct btd_device *device = user_data; - DBG("read_auth_payload_timeout"); - int status = btd_adapter_read_auth_payload_timeout(device->adapter, - &device->bdaddr, device); - if (status != 0) - return btd_error_failed(msg, - "Unable to read auth payload timeout"); - else - return dbus_message_new_method_return(msg); -} -#endif - static DBusMessage *discover_services(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -3306,58 +3235,6 @@ static DBusMessage *cancel_discover(DBusConnection *conn, return dbus_message_new_method_return(msg); } -#ifndef __TIZEN_PATCH__ -/* Its not used */ -static DBusMessage *write_auth_payload_timeout(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct btd_device *device = user_data; - dbus_uint32_t payload_timeout; - - DBG("write_auth_payload_timeout"); - - if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, - &payload_timeout, DBUS_TYPE_INVALID)) - return btd_error_invalid_args(msg); - - int status = btd_adapter_write_auth_payload_timeout(device->adapter, - &device->bdaddr, payload_timeout, device); - - if (status != 0) - return btd_error_failed(msg, - "Unable to write auth payload timeout"); - else - return dbus_message_new_method_return(msg); -} -#endif -void device_set_attrib(struct btd_device *device, guint attachid, GAttrib *attrib) -{ - if (device == NULL) { - error("device is NULL"); - return; - } - - device->attachid = attachid; - device->attrib = g_attrib_ref(attrib); -} - -void device_unset_attrib(struct btd_device *device) -{ - if (device == NULL) { - error("device is NULL"); - return; - } - - if (device->attrib == NULL) { - error("attrib is NULL"); - return; - } - - device->attachid = 0; - - g_attrib_unref(device->attrib); - device->attrib = NULL; -} void device_set_gatt_connected(struct btd_device *device, gboolean connected) { @@ -3377,103 +3254,87 @@ void device_set_gatt_connected(struct btd_device *device, gboolean connected) DEVICE_INTERFACE, "GattConnected"); } -static gboolean att_connect(gpointer user_data) -{ - struct btd_device *device = user_data; - - device->auto_id = 0; - - device_connect_le(device); - - return FALSE; -} - static DBusMessage *connect_le(DBusConnection *conn, DBusMessage *msg, void *user_data) { - struct btd_device *device = user_data; + struct btd_device *dev = user_data; dbus_bool_t auto_connect = FALSE; + int err; - DBG("bdaddr_type %d", device->bdaddr_type); - - if (!device->le) { - DBG("device->le is not set. Find or create device object"); - device = btd_adapter_get_device(device->adapter, - &device->bdaddr, BDADDR_LE_PUBLIC); - if (device == NULL) { - error("Cannot create device object"); + if (!dev->le) { + /* + * If a LE connection is requested without device discovery, + * we try to get device object. Here, technology can be updated + * if there is matched device object. Or, a new device object + * will be created. + */ + dev = btd_adapter_get_device(dev->adapter, &dev->bdaddr, + BDADDR_LE_PUBLIC); + if (dev == NULL) { + error("Unable to get device object"); return btd_error_not_supported(msg); } } - if (device->gatt_connected) - return btd_error_already_connected(msg); - - device->auto_connect = FALSE; + if (dev->le_state.connected) + return dbus_message_new_method_return(msg); - if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, - &auto_connect, DBUS_TYPE_INVALID)) + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &auto_connect, + DBUS_TYPE_INVALID)) return btd_error_invalid_args(msg); - if (auto_connect) { - DBG("Start LE auto connection"); - - if (device->le_auto_connect) { - DBG("Already auto connection is started..."); - return btd_error_already_connected(msg); - } - - if (btd_adapter_is_le_auto_connect(device->adapter)) { - DBG("Already auto connection is started"); - return btd_error_already_connected(msg); - } - device->le_auto_connect = TRUE; + btd_device_set_temporary(dev, false); - /* Clear White list */ - adapter_clear_le_white_list(device->adapter); + if (auto_connect) { + DBG("Start BLE auto connection"); + dev->disable_auto_connect = FALSE; + device_set_auto_connect(dev, TRUE); - /* Add device to White list */ - adapter_add_le_white_list(device->adapter, device); + return dbus_message_new_method_return(msg); } - if (device->auto_id == 0) - device->auto_id = g_timeout_add(200, att_connect, device); + err = device_connect_le(dev); + if (err < 0) + return btd_error_failed(msg, strerror(-err)); - return dbus_message_new_method_return(msg); + dev->connect = dbus_message_ref(msg); + + return NULL; } static DBusMessage *disconnect_le(DBusConnection *conn, DBusMessage *msg, void *user_data) { - struct btd_device *device = user_data; + struct btd_device *dev = user_data; - if (!device->le) + if (!dev->le) return btd_error_not_supported(msg); - if (device->le_auto_connect && !device->le_state.connected) { - DBG("le_auto_connect : %d, le_connected : %d, attrib : %p", - device->le_auto_connect, - device->le_state.connected, - device->attrib); - - DBG("Cancel LE auto connection"); - - btd_adapter_disable_le_auto_connect(device->adapter); - device->le_auto_connect = FALSE; + /* + * Disable connections through passive sccanning + */ + if (dev->auto_connect) { + DBG("Stop BLE auto connection"); + dev->disable_auto_connect = FALSE; + device_set_auto_connect(dev, FALSE); - return dbus_message_new_method_return(msg); + if (!dev->le_state.connected) { + g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID); + return NULL; + } + } else if (!dev->le_state.connected) { + return btd_error_not_connected(msg); } - if (!device->le_state.connected) - return btd_error_not_connected(msg); + dev->disconnects = g_slist_append(dev->disconnects, + dbus_message_ref(msg)); - btd_adapter_disconnect_device(device->adapter, &device->bdaddr, - device->bdaddr_type); + btd_adapter_disconnect_device(dev->adapter, &dev->bdaddr, + dev->bdaddr_type); - return dbus_message_new_method_return(msg); + return NULL; } -#ifdef __TIZEN_PATCH__ static DBusMessage *connect_ipsp(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -3570,7 +3431,6 @@ static DBusMessage *set_trusted_profile(DBusConnection *conn, dbus_bool_t profile_trusted; const char *pattern; char *uuid; - uint32_t value; uint32_t pbap = dev->trusted_profiles.pbap; uint32_t map = dev->trusted_profiles.map; uint32_t sap = dev->trusted_profiles.sap; @@ -3608,7 +3468,6 @@ static DBusMessage *set_trusted_profile(DBusConnection *conn, btd_device_set_trusted_profiles(dev, pbap, map, sap); return dbus_message_new_method_return(msg); } -#endif static DBusMessage *is_connected_profile(DBusConnection *conn, DBusMessage *msg, void *user_data) @@ -3658,38 +3517,6 @@ static DBusMessage *is_connected_profile(DBusConnection *conn, DBusMessage *msg, return reply; } -static DBusMessage *le_conn_update(DBusConnection *conn, DBusMessage *msg, - void *user_data) -{ - struct btd_device *device = user_data; - uint32_t interval_min, interval_max, latency, time_out; - int status; - char addr[BT_ADDRESS_STRING_SIZE]; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &interval_min, - DBUS_TYPE_UINT32, &interval_max, - DBUS_TYPE_UINT32, &latency, - DBUS_TYPE_UINT32, &time_out, - DBUS_TYPE_INVALID)) - return btd_error_invalid_args(msg); - - ba2str(&device->bdaddr, addr); - - DBG("Remote device address: %s", addr); - DBG("Interval min: %u, Interval max: %u, Latency: %u, Timeout: %u", - interval_min, interval_max, latency, time_out); - - status = btd_adapter_le_conn_update(device->adapter, - &device->bdaddr, interval_min, - interval_max, latency, time_out); - - if (status != 0) - return btd_error_failed(msg, "Unable to update LE connection"); - else - return dbus_message_new_method_return(msg); -} - static DBusMessage *update_le_conn_parm(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -3721,12 +3548,10 @@ static DBusMessage *update_le_conn_parm(DBusConnection *conn, DBusMessage *msg, if (fd < 0) return btd_error_not_connected(msg); -#ifdef __TIZEN_PATCH__ if (device_get_conn_update_state(device)) return btd_error_in_progress(msg); else device_set_conn_update_state(device, true); -#endif if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, ¶m.min, DBUS_TYPE_UINT32, ¶m.max, @@ -3864,9 +3689,8 @@ static DBusMessage *device_get_ida(DBusConnection *conn, DBusMessage *msg, id_address = g_strdup(device_idaddr); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &id_address, - DBUS_TYPE_INVALID); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &id_address, + DBUS_TYPE_INVALID); return reply; } @@ -3892,41 +3716,25 @@ static const GDBusMethodTable device_methods[] = { { GDBUS_ASYNC_METHOD("DisconnectProfile", GDBUS_ARGS({ "UUID", "s" }), NULL, disconnect_profile) }, #ifdef __TIZEN_PATCH__ - { GDBUS_ASYNC_METHOD("Pair", - GDBUS_ARGS({ "conn_type", "y" }), NULL, - pair_device) }, + { GDBUS_ASYNC_METHOD("Pair", GDBUS_ARGS({ "conn_type", "y" }), NULL, + pair_device) }, #else { GDBUS_ASYNC_METHOD("Pair", NULL, NULL, pair_device) }, #endif { GDBUS_METHOD("CancelPairing", NULL, NULL, cancel_pairing) }, #ifdef __TIZEN_PATCH__ -#if 0 // Not used - { GDBUS_METHOD("ReadRSSI", NULL, NULL, read_rssi) }, - { GDBUS_METHOD("L2capConnParamUpdate", - GDBUS_ARGS({ "interval_min", "u" }, - { "interval_max", "u" }, { "latency", "u" }, - { "time_out", "u" }), NULL, - l2cap_conn_param_update) }, - { GDBUS_METHOD("WritePayloadTimeout", - GDBUS_ARGS({"auth_payload_timeout", "u"}), - NULL, write_auth_payload_timeout)}, - { GDBUS_METHOD("ReadPayloadTimeout", NULL, - NULL, read_auth_payload_timeout)}, -#endif - { GDBUS_METHOD("ConnectLE", - GDBUS_ARGS({ "auto_connect", "b"}), - NULL, connect_le) }, - { GDBUS_METHOD("DisconnectLE", NULL, NULL, disconnect_le) }, + { GDBUS_ASYNC_METHOD("ConnectLE", GDBUS_ARGS({ "auto_connect", "b"}), + NULL, connect_le) }, + { GDBUS_ASYNC_METHOD("DisconnectLE", NULL, NULL, disconnect_le) }, { GDBUS_METHOD("IsConnectedProfile", GDBUS_ARGS({ "UUID", "s" }), - GDBUS_ARGS({ "IsConnected", "b" }), is_connected_profile)}, - { GDBUS_METHOD("LeConnUpdate", - GDBUS_ARGS({ "interval_min", "u" }, + GDBUS_ARGS({ "IsConnected", "b" }), + is_connected_profile)}, + { GDBUS_METHOD("LeConnUpdate", GDBUS_ARGS({ "interval_min", "u" }, { "interval_max", "u" }, { "latency", "u" }, { "time_out", "u" }), NULL, - update_le_conn_parm) }, - { GDBUS_ASYNC_METHOD("DiscoverServices", - GDBUS_ARGS({ "pattern", "s" }), NULL, - discover_services) }, + update_le_conn_parm) }, + { GDBUS_ASYNC_METHOD("DiscoverServices", GDBUS_ARGS({ "pattern", "s" }), + NULL, discover_services) }, { GDBUS_METHOD("CancelDiscovery", NULL, NULL, cancel_discover) }, { GDBUS_ASYNC_METHOD("ConnectIpsp", NULL, NULL, connect_ipsp) }, { GDBUS_ASYNC_METHOD("DisconnectIpsp", NULL, NULL, disconnect_ipsp) }, @@ -3934,16 +3742,14 @@ static const GDBusMethodTable device_methods[] = { GDBUS_ARGS({"max_tx_octets", "q" }, { "max_tx_time", "q" }), NULL, le_set_data_length)}, - { GDBUS_ASYNC_METHOD("RequestAttMtu", - GDBUS_ARGS({ "mtu", "q" }), + { GDBUS_ASYNC_METHOD("RequestAttMtu", GDBUS_ARGS({ "mtu", "q" }), GDBUS_ARGS({ "mtu", "q" }, { "status", "y"}), - request_att_mtu) }, - { GDBUS_METHOD("GetIDAddress", NULL, - GDBUS_ARGS({ "IDAdress", "s" }), - device_get_ida) }, + request_att_mtu) }, + { GDBUS_METHOD("GetIDAddress", NULL, GDBUS_ARGS({ "IDAdress", "s" }), + device_get_ida) }, { GDBUS_METHOD("SetTrustedProfile", - GDBUS_ARGS({ "uuid", "s"}, { "trusted", "b"}), - NULL, set_trusted_profile) }, + GDBUS_ARGS({ "uuid", "s"}, { "trusted", "b"}), NULL, + set_trusted_profile) }, #endif { } }; @@ -3964,6 +3770,7 @@ static const GDBusPropertyTable device_properties[] = { { "LegacyPairing", "b", dev_property_get_legacy }, { "RSSI", "n", dev_property_get_rssi, NULL, dev_property_exists_rssi }, #ifdef __TIZEN_PATCH__ + {"IsAliasSet", "b", dev_property_get_alias_set }, { "Connected", "y", dev_property_get_connected }, #else { "Connected", "b", dev_property_get_connected }, @@ -3975,7 +3782,6 @@ static const GDBusPropertyTable device_properties[] = { #ifdef __TIZEN_PATCH__ /* To handle Failed Legacy Pairing when initiated from Remote device*/ { "LegacyPaired", "b", dev_property_get_paired }, - { "Flag", "q", property_get_flag }, { "ManufacturerDataLen", "q", property_get_manufacturer_data_len }, { "ManufacturerData", "ay", property_get_manufacturer_data }, { "GattConnected", "b", dev_property_get_gatt_connected }, @@ -4005,18 +3811,15 @@ static const GDBusPropertyTable device_properties[] = { #ifdef __TIZEN_PATCH__ static const GDBusSignalTable device_signals[] = { { GDBUS_SIGNAL("Disconnected", - GDBUS_ARGS({ "bdaddr_type", "y" }, { "reason", "y" }, { "name", "s" })) }, - { GDBUS_SIGNAL("DeviceConnected", - GDBUS_ARGS({ "bdaddr_type", "y"})) }, + GDBUS_ARGS({ "bdaddr_type", "y" }, { "reason", "y" }, + { "name", "s" })) }, + { GDBUS_SIGNAL("DeviceConnected", GDBUS_ARGS({ "bdaddr_type", "y"})) }, { GDBUS_SIGNAL("ProfileStateChanged", GDBUS_ARGS({ "profile", "s"}, {"state", "i"})) }, { GDBUS_SIGNAL("AdvReport", - GDBUS_ARGS({"Address","s"}, - { "Address Type", "y" }, - { "Adv Type", "y"}, - { "RSSI", "i"}, - { "AdvDataLen", "i"}, - { "AdvData", "ay"})) }, + GDBUS_ARGS({"Address","s"}, { "Address Type", "y" }, + { "Adv Type", "y"}, { "RSSI", "i"}, + { "AdvDataLen", "i"}, { "AdvData", "ay"})) }, { GDBUS_SIGNAL("LEDataLengthChanged", GDBUS_ARGS({"max_tx_octets","q"}, { "max_tx_time", "q" }, @@ -4596,7 +4399,7 @@ static int load_chrc(char *handle, char *value, &uuid, 0, properties, NULL, NULL, NULL); if (!att || gatt_db_attribute_get_handle(att) != value_handle) { - warn("saving characteristic to db failed"); + warn("loading characteristic to db failed"); return -EIO; } @@ -4623,13 +4426,13 @@ static int load_incl(struct gatt_db *db, char *handle, char *value, att = gatt_db_get_attribute(db, start); if (!att) { - warn("saving included service to db failed - no such service"); + warn("loading included service to db failed - no such service"); return -EIO; } att = gatt_db_service_add_included(service, att); if (!att) { - warn("saving included service to db failed"); + warn("loading included service to db failed"); return -EIO; } @@ -4666,7 +4469,7 @@ static int load_service(struct gatt_db *db, char *handle, char *value) att = gatt_db_insert_service(db, start, &uuid, primary, end - start + 1); if (!att) { - DBG("ERROR saving service to db!"); + error("Unable load service into db!"); return -EIO; } @@ -4749,8 +4552,10 @@ static int load_gatt_db_impl(GKeyFile *key_file, char **keys, } g_free(value); - if (ret) + if (ret) { + gatt_db_clear(db); return ret; + } } if (current_service) @@ -4821,8 +4626,13 @@ static bool device_match_profile(struct btd_device *device, return false; if (g_slist_find_custom(uuids, profile->remote_uuid, - bt_uuid_strcmp) == NULL) + bt_uuid_strcmp) == NULL) { +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (strcmp(profile->name, "hid-device") == 0) + return true; +#endif return false; + } return true; } @@ -4904,13 +4714,13 @@ static void accept_gatt_service(struct gatt_db_attribute *attr, void *user_data) static void device_accept_gatt_profiles(struct btd_device *device) { +#ifndef __TIZEN_PATCH__ GSList *l; -#ifdef __TIZEN_PATCH__ - gatt_db_foreach_service(device->db, NULL, accept_gatt_service, device); -#else for (l = device->services; l != NULL; l = g_slist_next(l)) service_accept(l->data); +#else + gatt_db_foreach_service(device->db, NULL, accept_gatt_service, device); #endif } @@ -5312,7 +5122,7 @@ void device_set_rpa(struct btd_device *device, const bdaddr_t *rpa) } } -void device_set_irk_value(struct btd_device *device, const char *val) +void device_set_irk_value(struct btd_device *device, const uint8_t *val) { memcpy(&device->irk_val, val, sizeof(device->irk_val)); } @@ -5719,7 +5529,7 @@ int device_addr_type_cmp(gconstpointer a, gconstpointer b) #ifdef TIZEN_WEARABLE void device_change_pkt_type(gpointer data, gpointer user_data) { - uint16_t pkt_type = (uint16_t)user_data; + int pkt_type = (int)user_data; struct btd_device *device = data; struct hci_conn_info_req *cr; set_conn_ptype_cp cp; @@ -5758,7 +5568,7 @@ void device_change_pkt_type(gpointer data, gpointer user_data) cp.handle = cr->conn_info->handle; g_free(cr); - cp.pkt_type = cpu_to_le16(pkt_type); + cp.pkt_type = cpu_to_le16((uint16_t)pkt_type); ba2str(&device->bdaddr, addr); DBG("Handle %d, Addr %s", cp.handle, addr); @@ -5829,6 +5639,10 @@ static struct btd_service *probe_service(struct btd_device *device, return NULL; } + /* + * Profile based auto connection is not used in Tizen. + * Instead, the applications request auto connection with address. + */ #ifndef __TIZEN_PATCH__ if (profile->auto_connect) device_set_auto_connect(device, TRUE); @@ -6392,13 +6206,6 @@ static void register_gatt_services(struct btd_device *device) device_svc_resolved(device, device->bdaddr_type, 0); } -#ifdef __TIZEN_PATCH__ -static void gatt_client_debug_func(const char *str, void *user_data) -{ - DBG("%s", str); -} -#endif - static void gatt_client_init(struct btd_device *device); static void gatt_client_ready_cb(bool success, uint8_t att_ecode, @@ -6463,15 +6270,8 @@ static void gatt_client_init(struct btd_device *device) return; } - -#ifdef __TIZEN_PATCH__ - if (!bt_gatt_client_set_debug(device->client, gatt_client_debug_func, - NULL, NULL)) { - error("Failed to set debug function"); - } -#else bt_gatt_client_set_debug(device->client, gatt_debug, NULL, NULL); -#endif + /* Notify attio so it can react to notifications */ g_slist_foreach(device->attios, attio_connected, device->attrib); @@ -6496,6 +6296,10 @@ static void gatt_client_init(struct btd_device *device) gatt_client_cleanup(device); return; } + + device->gatt_cache_used = !gatt_db_isempty(device->db); + + btd_gatt_client_connected(device->client_dbus); } static void gatt_server_init(struct btd_device *device, struct gatt_db *db) @@ -6591,7 +6395,7 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io) return false; } -#if 0 +#ifndef __TIZEN_PATCH__ if (sec_level == BT_IO_SEC_LOW && dev->le_state.paired) { DBG("Elevating security level since LTK is available"); @@ -6613,15 +6417,6 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io) return false; } -#if 0 - dev->attachid = attrib_channel_attach(attrib); - if (dev->attachid == 0) { - g_attrib_unref(attrib); - error("Attribute server attach failure!"); - return false; - } -#endif - dev->attrib = attrib; dev->att = g_attrib_get_att(attrib); @@ -6679,14 +6474,6 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) g_io_channel_unref(device->att_io); device->att_io = NULL; -#ifdef __TIZEN_PATCH__ - if (btd_adapter_is_le_auto_connect(device->adapter)) { - DBG("LE auto connection is done"); - btd_adapter_set_le_auto_connect(device->adapter, FALSE); - device->le_auto_connect = FALSE; - } -#endif - if (gerr) { DBG("%s", gerr->message); @@ -6761,10 +6548,6 @@ int device_connect_le(struct btd_device *dev) GIOChannel *io; GError *gerr = NULL; char addr[18]; -#ifdef __TIZEN_PATCH__ - bdaddr_t *dba; - bdaddr_t le_auto_connect_ba = { {0, } }; -#endif /* There is one connection attempt going on */ if (dev->att_io) @@ -6787,7 +6570,6 @@ int device_connect_le(struct btd_device *dev) * This connection will help us catch any PDUs that comes before * pairing finishes */ -#ifndef __TIZEN_PATCH__ io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, btd_adapter_get_address(adapter), @@ -6797,31 +6579,6 @@ int device_connect_le(struct btd_device *dev) BT_IO_OPT_CID, ATT_CID, BT_IO_OPT_SEC_LEVEL, sec_level, BT_IO_OPT_INVALID); -#else - if (dev->le_auto_connect) - dba = &le_auto_connect_ba; - else - dba = &dev->bdaddr; - - io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr, - BT_IO_OPT_SOURCE_BDADDR, - btd_adapter_get_address(adapter), - BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC, - BT_IO_OPT_DEST_BDADDR, dba, - BT_IO_OPT_DEST_TYPE, dev->bdaddr_type, - BT_IO_OPT_CID, ATT_CID, - BT_IO_OPT_SEC_LEVEL, sec_level, - BT_IO_OPT_INVALID); - - if (dev->le_auto_connect) { - if (io) - btd_adapter_set_le_auto_connect(adapter, TRUE); - else { - btd_adapter_set_le_auto_connect(dev->adapter, FALSE); - dev->le_auto_connect = FALSE; - } - } -#endif if (io == NULL) { if (dev->bonding) { @@ -6992,59 +6749,17 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg) &device->bdaddr, &uuid, browse_cb, req, NULL, req->sdp_flags); if (err < 0) { - browse_request_free(req); - return err; - } - - return err; -} - #ifdef __TIZEN_PATCH__ -static int device_custom_browse_sdp(struct btd_device *device, - DBusMessage *msg, uuid_t *search) -{ - struct btd_adapter *adapter = device->adapter; - struct browse_req *req; - uuid_t uuid; - int err; - - if (device->browse) - return -EBUSY; - - req = g_new0(struct browse_req, 1); - req->device = device; - if (search) { - memcpy(&uuid, search, sizeof(uuid_t)); - } else { - sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); - } - - req->sdp_flags = get_sdp_flags(device); - - err = bt_search_service(btd_adapter_get_address(adapter), - &device->bdaddr, &uuid, browse_cb, req, NULL, - req->sdp_flags); - if (err < 0) { + device->browse = NULL; +#endif browse_request_free(req); return err; } - device->browse = req; - - if (msg) { - const char *sender = dbus_message_get_sender(msg); - - req->msg = dbus_message_ref(msg); - /* Track the request owner to cancel it - * automatically if the owner exits */ - req->listener_id = g_dbus_add_disconnect_watch(dbus_conn, - sender, - browse_request_exit, - req, NULL); - } return err; } +#ifdef __TIZEN_PATCH__ void device_set_last_addr_type(struct btd_device *device, uint8_t type) { if (!device) @@ -7088,9 +6803,8 @@ void device_set_ipsp_connected(struct btd_device *device, gboolean connected, DBUS_TYPE_STRING, &iface_name, DBUS_TYPE_INVALID); } - void device_le_data_length_changed(struct btd_device *device, uint16_t max_tx_octets, - uint16_t max_tx_time, uint16_t max_rx_octets,uint16_t max_rx_time) + uint16_t max_tx_time, uint16_t max_rx_octets, uint16_t max_rx_time) { if (device == NULL) { error("device is NULL"); @@ -8342,18 +8056,7 @@ guint btd_device_add_attio_callback(struct btd_device *device, attio->dcfunc = dcfunc; attio->user_data = user_data; -#ifdef __TIZEN_PATCH__ - /* - * User space auto connection is not used. - * Instead of this, BT chip can trigger auto connection - * by adding remote address to white list and - * setting 0x01 to "Initiator_Filter_Policy" - * when LE Create Connection is happened. - */ - device_set_auto_connect(device, FALSE); -#else device_set_auto_connect(device, TRUE); -#endif /* Check if there is no GAttrib associated to the device created by a * incoming connection */ @@ -8403,19 +8106,6 @@ gboolean btd_device_remove_attio_callback(struct btd_device *device, guint id) g_free(attio); -#ifdef __TIZEN_PATCH__ - if (device->auto_id) { - g_source_remove(device->auto_id); - device->auto_id = 0; - } - - if (device->le_auto_connect) { - device->le_auto_connect = FALSE; - btd_adapter_disable_le_auto_connect(device->adapter); - DBG("remove attio callback"); - } -#endif - return TRUE; } diff --git a/src/device.h b/src/device.h index cf247ba..0a18596 100644 --- a/src/device.h +++ b/src/device.h @@ -22,10 +22,6 @@ * */ -#ifdef __TIZEN_PATCH__ -#include "attrib/gattrib.h" -#endif - #define DEVICE_INTERFACE "org.bluez.Device1" struct btd_device; @@ -98,8 +94,6 @@ void device_set_remote_feature_flag(struct btd_device *device, int flags); gboolean device_is_bredrle(struct btd_device *device); void device_set_disconnect_reason(struct btd_device *device, uint8_t reason); void device_set_gatt_connected(struct btd_device *device, gboolean connected); -void device_set_attrib(struct btd_device *device, guint attachid, GAttrib *attrib); -void device_unset_attrib(struct btd_device *device); void device_unpair(struct btd_device *device, gboolean remove_stored); gboolean device_get_gatt_connected(const struct btd_device *device); void device_set_rpa(struct btd_device *device, const bdaddr_t *rpa_addr); @@ -109,7 +103,7 @@ int device_rpa_cmp(gconstpointer a, gconstpointer b); int device_addr_cmp(gconstpointer a, gconstpointer b); void device_remove_stored_folder(struct btd_device *device); const uint8_t *device_get_irk_value(struct btd_device *device); -void device_set_irk_value(struct btd_device *device, const char *val); +void device_set_irk_value(struct btd_device *device, const uint8_t *val); void device_set_conn_update_state(struct btd_device *device, bool state); bool device_get_conn_update_state(struct btd_device *device); void btd_device_set_trusted_profiles(struct btd_device *device, diff --git a/src/gatt-client.c b/src/gatt-client.c index 71b4c2d..398e00f 100644 --- a/src/gatt-client.c +++ b/src/gatt-client.c @@ -881,10 +881,10 @@ static void write_characteristic_cb(struct gatt_db_attribute *attr, int err, static void notify_characteristic_cb(struct gatt_db_attribute *attr, int err, void *user_data) { - struct characteristic *chrc = user_data; - - if (err) + if (err) { + error("Failed to notify_characteristic_cb : %d", err); return; + } } #endif @@ -1240,51 +1240,22 @@ static bool match_notify_sender(const void *a, const void *b) return strcmp(client->owner, sender) == 0; } -#if defined __TIZEN_PATCH__ && defined GATT_NO_RELAY -struct char_value { - uint8_t *data; - uint8_t len; - char *chrc_path; -}; - -static void emit_value_changed_signal_to_dest(gpointer data, gpointer user_data) +#ifdef __TIZEN_PATCH__ +void gatt_characteristic_value_changed(struct notify_client *client, const uint8_t *data, uint16_t data_len, void *user_data) { + struct characteristic *chrc = user_data; + char *chrc_path = strdup(chrc->path); dbus_int32_t result = 0; - struct notify_client *notify_client = data; - struct char_value *value = user_data; +#ifdef GATT_NO_RELAY g_dbus_emit_signal_to_dest(btd_get_dbus_connection(), - notify_client->owner, value->chrc_path, + client->owner, chrc_path, GATT_CHARACTERISTIC_IFACE, "GattValueChanged", DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &value->chrc_path, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &value->data, value->len, + DBUS_TYPE_STRING, &chrc_path, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_len, DBUS_TYPE_INVALID); -} -#endif - -#ifdef __TIZEN_PATCH__ -void gatt_characteristic_value_changed(void *data, uint8_t data_len, void *user_data) -{ - struct characteristic *chrc = user_data; - char *chrc_path = strdup(chrc->path); -#ifdef GATT_NO_RELAY - struct char_value *value; - - value = new0(struct char_value, 1); - value->len = data_len; - value->data = data; - value->chrc_path = chrc_path; - - queue_foreach(chrc->notify_clients, - emit_value_changed_signal_to_dest, value); - - - if (value) - g_free(value); #else - dbus_int32_t result = 0; - g_dbus_emit_signal(btd_get_dbus_connection(), chrc->path, GATT_CHARACTERISTIC_IFACE, "GattValueChanged", DBUS_TYPE_INT32, &result, @@ -1316,7 +1287,7 @@ static void notify_cb(uint16_t value_handle, const uint8_t *value, gatt_db_attribute_write(chrc->attr, 0, value, length, 0, NULL, notify_characteristic_cb, chrc); - gatt_characteristic_value_changed(value, length, chrc); + gatt_characteristic_value_changed(client, value, length, chrc); #else gatt_db_attribute_write(chrc->attr, 0, value, length, 0, NULL, write_characteristic_cb, chrc); @@ -1454,9 +1425,6 @@ static DBusMessage *characteristic_stop_notify(DBusConnection *conn, const char *sender = dbus_message_get_sender(msg); struct notify_client *client; - if (!chrc->notifying) - return btd_error_failed(msg, "Not notifying"); - client = queue_remove_if(chrc->notify_clients, match_notify_sender, (void *) sender); if (!client) @@ -2118,13 +2086,8 @@ static void register_notify(void *data, void *user_data) DBG("Failed to re-register notification client"); -#ifdef __TIZEN_PATCH__ queue_remove(notify_client->chrc->notify_clients, notify_client); queue_remove(client->all_notify_clients, notify_client); -#else - queue_remove(notify_client->chrc->notify_clients, client); - queue_remove(client->all_notify_clients, client); -#endif notify_client_free(notify_client); } @@ -2183,26 +2146,17 @@ static gboolean check_all_chrcs_ready(gpointer user_data) void btd_gatt_client_ready(struct btd_gatt_client *client) { - struct bt_gatt_client *gatt; - if (!client) return; - gatt = btd_device_get_gatt_client(client->device); - if (!gatt) { + if (!client->gatt) { error("GATT client not initialized"); return; } - bt_gatt_client_unref(client->gatt); - client->gatt = bt_gatt_client_ref(gatt); client->ready = true; DBG("GATT client ready"); -#ifdef __TIZEN_PATCH__ - if (queue_isempty(client->services)) { - DBG("Exporting services"); -#endif create_services(client); #ifdef __TIZEN_PATCH__ @@ -2218,17 +2172,7 @@ void btd_gatt_client_ready(struct btd_gatt_client *client) client->wait_charcs_id = g_timeout_add(100, check_all_chrcs_ready, client); - return; - } - - /* - * Services have already been created before. Re-enable notifications - * for any pre-registered notification sessions. - */ - queue_foreach(client->all_notify_clients, register_notify, client); - device_set_gatt_connected(client->device, TRUE); #endif - } void btd_gatt_client_connected(struct btd_gatt_client *client) @@ -2251,10 +2195,6 @@ void btd_gatt_client_connected(struct btd_gatt_client *client) * for any pre-registered notification sessions. */ queue_foreach(client->all_notify_clients, register_notify, client); - -#ifdef __TIZEN_PATCH__ - device_set_gatt_connected(client->device, TRUE); -#endif } void btd_gatt_client_service_added(struct btd_gatt_client *client, diff --git a/src/gatt-database.c b/src/gatt-database.c index 989f286..8b7b83e 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -89,6 +89,7 @@ struct gatt_app { GDBusClient *client; bool failed; struct queue *services; + struct queue *proxies; }; struct external_service { @@ -293,6 +294,12 @@ static struct device_state *device_state_create(bdaddr_t *bdaddr, uint8_t bdaddr_type) { struct device_state *dev_state; +#ifdef __TIZEN_PATCH__ + char addr[18] = { 0 }; + + ba2str(bdaddr, addr); + DBG("create device_state for %s [%d]", addr, bdaddr_type); +#endif dev_state = new0(struct device_state, 1); dev_state->ccc_states = queue_new(); @@ -330,6 +337,9 @@ static struct ccc_state *get_ccc_state(struct btd_gatt_database *database, { struct device_state *dev_state; struct ccc_state *ccc; +#ifdef __TIZEN_PATCH__ + char addr[18] = { 0 }; +#endif dev_state = get_device_state(database, bdaddr, bdaddr_type); @@ -337,6 +347,12 @@ static struct ccc_state *get_ccc_state(struct btd_gatt_database *database, if (ccc) return ccc; +#ifdef __TIZEN_PATCH__ + ba2str(bdaddr, addr); + DBG("create ccc_state of handle: 0x%04x for %s [%d]", + handle, addr, bdaddr_type); +#endif + ccc = new0(struct ccc_state, 1); ccc->handle = handle; queue_push_tail(dev_state->ccc_states, ccc); @@ -423,6 +439,7 @@ static void app_free(void *data) struct gatt_app *app = data; queue_destroy(app->services, service_free); + queue_destroy(app->proxies, NULL); if (app->client) { g_dbus_client_set_disconnect_watch(app->client, NULL, NULL); @@ -594,7 +611,9 @@ static void gap_device_name_read_cb(struct gatt_db_attribute *attrib, device_name = btd_adapter_get_name(database->adapter); #ifdef __TIZEN_PATCH__ - if (get_dst_info(att, &dst, &dst_type) && dst_type != BDADDR_BREDR) { + if (get_dst_info(att, &dst, &dst_type) && dst_type != BDADDR_BREDR && + bacmp(btd_adapter_get_address(database->adapter), + btd_adapter_get_le_address(database->adapter))) { char *ptr = NULL; g_strlcpy(le_name, device_name, @@ -752,14 +771,20 @@ static uint32_t database_add_record(struct btd_gatt_database *database, return 0; if (name != NULL) +#ifdef __TIZEN_PATCH__ + sdp_set_info_attr(record, name, "Samsung", NULL); +#else sdp_set_info_attr(record, name, "BlueZ", NULL); +#endif sdp_uuid16_create(&gap_uuid, UUID_GAP); +#ifndef __TIZEN_PATCH__ if (sdp_uuid_cmp(&svc, &gap_uuid) == 0) { sdp_set_url_attr(record, "http://www.bluez.org/", "http://www.bluez.org/", "http://www.bluez.org/"); } +#endif if (adapter_service_add(database->adapter, record) == 0) return record->handle; @@ -775,13 +800,7 @@ static void populate_gap_service(struct btd_gatt_database *database) /* Add the GAP service */ bt_uuid16_create(&uuid, UUID_GAP); - -#ifndef __TIZEN_PATCH__ service = gatt_db_add_service(database->db, &uuid, true, 5); -#else - service = gatt_db_add_service(database->db, &uuid, true, 7); -#endif - database->gap_handle = database_add_record(database, UUID_GAP, service, "Generic Access Profile"); @@ -819,14 +838,25 @@ static bool get_dst_info(struct bt_att *att, bdaddr_t *dst, uint8_t *dst_type) { GIOChannel *io = NULL; GError *gerr = NULL; +#ifdef __TIZEN_PATCH__ + struct btd_adapter *adapter; + bdaddr_t src; +#endif io = g_io_channel_unix_new(bt_att_get_fd(att)); if (!io) return false; +#ifdef __TIZEN_PATCH__ + bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, + BT_IO_OPT_DEST_BDADDR, dst, + BT_IO_OPT_DEST_TYPE, dst_type, + BT_IO_OPT_INVALID); +#else bt_io_get(io, &gerr, BT_IO_OPT_DEST_BDADDR, dst, BT_IO_OPT_DEST_TYPE, dst_type, BT_IO_OPT_INVALID); +#endif if (gerr) { error("gatt: bt_io_get: %s", gerr->message); g_error_free(gerr); @@ -835,6 +865,42 @@ static bool get_dst_info(struct bt_att *att, bdaddr_t *dst, uint8_t *dst_type) } g_io_channel_unref(io); + +#ifdef __TIZEN_PATCH__ + adapter = adapter_find(&src); + if (adapter == NULL) { + DBG("Cannot get adapter"); + return true; + } + + if (*dst_type == BDADDR_LE_PUBLIC) { + struct btd_device *device; + char addr[18] = { 0 }; + char addr_rpa[18] = { 0 }; + const bdaddr_t *rpa; + + device = btd_adapter_find_device(adapter, dst, *dst_type); + if (device == NULL) { + DBG("Cannot find device"); + return true; + } + + if (device_get_rpa_exist(device) == false) + return true; + + rpa = device_get_rpa(device); + if (rpa == NULL) + return true; + + ba2str(dst, addr); + ba2str(rpa, addr_rpa); + DBG("Convert IDA [%s] to RPA [%s]", addr, addr_rpa); + + bacpy(dst, rpa); + *dst_type = BDADDR_LE_RANDOM; + } +#endif + return true; } @@ -1072,7 +1138,11 @@ static void indicate_confirm_setup_cb(DBusMessageIter *iter, void *user_data) char *addr_value = NULL; gboolean complete = FALSE; - ba2str(device_get_address(device), dstaddr); + if (device_get_rpa_exist(device) == true) { + ba2str(device_get_rpa(device), dstaddr); + } else { + ba2str(device_get_address(device), dstaddr); + } addr_value = g_strdup(dstaddr); dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, @@ -1171,7 +1241,9 @@ static void send_notification_indication_to_devices(GDBusProxy *proxy, bool indicate) { struct notify_indicate notify_indicate; - DBG(""); + + DBG("notify for handle: 0x%04x", handle); + memset(¬ify_indicate, 0, sizeof(notify_indicate)); notify_indicate.database = database; @@ -1194,7 +1266,8 @@ static void send_unicast_notification_indication_to_device(GDBusProxy *proxy, { struct device_state *dev_state; struct notify_indicate notify_indicate; - DBG(""); + + DBG("notify for handle: 0x%04x", handle); memset(¬ify_indicate, 0, sizeof(notify_indicate)); @@ -1746,39 +1819,12 @@ static void proxy_added_cb(GDBusProxy *proxy, void *user_data) if (app->failed) return; + queue_push_tail(app->proxies, proxy); + iface = g_dbus_proxy_get_interface(proxy); path = g_dbus_proxy_get_path(proxy); - if (g_strcmp0(iface, GATT_SERVICE_IFACE) == 0) { - struct external_service *service; - - service = create_service(app, proxy, path); - if (!service) { - app->failed = true; - return; - } - } else if (g_strcmp0(iface, GATT_CHRC_IFACE) == 0) { - struct external_chrc *chrc; - - chrc = chrc_create(app, proxy, path); - if (!chrc) { - app->failed = true; - return; - } - } else if (g_strcmp0(iface, GATT_DESC_IFACE) == 0) { - struct external_desc *desc; - - desc = desc_create(app, proxy); - if (!desc) { - app->failed = true; - return; - } - } else { - DBG("Ignoring unrelated interface: %s", iface); - return; - } - - DBG("Object added: path: %s, iface: %s", path, iface); + DBG("Object received: %s, iface: %s", path, iface); } static void proxy_removed_cb(GDBusProxy *proxy, void *user_data) @@ -1953,12 +1999,9 @@ static struct pending_op *pending_read_new(struct queue *owner_queue, #endif op = new0(struct pending_op, 1); - if (!op) - return NULL; #ifdef __TIZEN_PATCH__ if (!get_dst_info(att, &bdaddr, &bdaddr_type)) { - free(op); return NULL; } #endif @@ -2016,11 +2059,6 @@ static void send_read(struct gatt_db_attribute *attrib, GDBusProxy *proxy, #else op = pending_read_new(owner_queue, attrib, id); #endif - if (!op) { - error("Failed to allocate memory for pending read call"); - ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES; - goto error; - } #ifdef __TIZEN_PATCH__ if (g_dbus_proxy_method_call(proxy, "ReadValue", read_setup_cb, read_reply_cb, @@ -2033,7 +2071,6 @@ static void send_read(struct gatt_db_attribute *attrib, GDBusProxy *proxy, pending_op_free(op); -error: gatt_db_attribute_read_result(attrib, id, ecode, NULL, 0); } @@ -2124,11 +2161,8 @@ static struct pending_op *pending_write_new(struct queue *owner_queue, #endif op = new0(struct pending_op, 1); - if (!op) - return NULL; #ifdef __TIZEN_PATCH__ if (!get_dst_info(att, &bdaddr, &bdaddr_type)) { - free(op); return NULL; } #endif @@ -2167,11 +2201,6 @@ static void send_write(struct gatt_db_attribute *attrib, GDBusProxy *proxy, #else op = pending_write_new(owner_queue, attrib, id, value, len); #endif - if (!op) { - error("Failed to allocate memory for pending read call"); - ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES; - goto error; - } if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb, write_reply_cb, op, @@ -2180,7 +2209,6 @@ static void send_write(struct gatt_db_attribute *attrib, GDBusProxy *proxy, pending_op_free(op); -error: gatt_db_attribute_write_result(attrib, id, ecode); } @@ -2768,12 +2796,92 @@ static bool database_add_app(struct gatt_app *app) return true; } +static void register_service(void *data, void *user_data) +{ + struct gatt_app *app = user_data; + GDBusProxy *proxy = data; + const char *iface = g_dbus_proxy_get_interface(proxy); + const char *path = g_dbus_proxy_get_path(proxy); + + if (app->failed) + return; + + if (g_strcmp0(iface, GATT_SERVICE_IFACE) == 0) { + struct external_service *service; + + service = create_service(app, proxy, path); + if (!service) { + app->failed = true; + return; + } + } +} + +static void register_characteristic(void *data, void *user_data) +{ + struct gatt_app *app = user_data; + GDBusProxy *proxy = data; + const char *iface = g_dbus_proxy_get_interface(proxy); + const char *path = g_dbus_proxy_get_path(proxy); + + if (app->failed) + return; + + iface = g_dbus_proxy_get_interface(proxy); + path = g_dbus_proxy_get_path(proxy); + + if (g_strcmp0(iface, GATT_CHRC_IFACE) == 0) { + struct external_chrc *chrc; + + chrc = chrc_create(app, proxy, path); + if (!chrc) { + app->failed = true; + return; + } + } +} + +static void register_descriptor(void *data, void *user_data) +{ + struct gatt_app *app = user_data; + GDBusProxy *proxy = data; + const char *iface = g_dbus_proxy_get_interface(proxy); + + if (app->failed) + return; + + if (g_strcmp0(iface, GATT_DESC_IFACE) == 0) { + struct external_desc *desc; + + desc = desc_create(app, proxy); + if (!desc) { + app->failed = true; + return; + } + } +} + static void client_ready_cb(GDBusClient *client, void *user_data) { struct gatt_app *app = user_data; DBusMessage *reply; bool fail = false; + /* + * Process received objects + */ + if (queue_isempty(app->proxies)) { + error("No object received"); + fail = true; + reply = btd_error_failed(app->reg, + "No object received"); + goto reply; + } + + queue_foreach(app->proxies, register_service, app); + queue_foreach(app->proxies, register_characteristic, app); + queue_foreach(app->proxies, register_descriptor, app); + if (!app->services || app->failed) { error("No valid external GATT objects found"); fail = true; @@ -2827,6 +2935,7 @@ static struct gatt_app *create_app(DBusConnection *conn, DBusMessage *msg, goto fail; app->services = queue_new(); + app->proxies = queue_new(); app->reg = dbus_message_ref(msg); g_dbus_client_set_disconnect_watch(app->client, client_disconnect_cb, diff --git a/src/main.conf b/src/main.conf new file mode 100644 index 0000000..372fd8c --- /dev/null +++ b/src/main.conf @@ -0,0 +1,89 @@ +[General] + +# Default adaper name +# Defaults to 'BlueZ X.YZ' +#Name = BlueZ + +# Default device class. Only the major and minor device class bits are +# considered. Defaults to '0x000000'. +#Class = 0x000100 + +# How long to stay in discoverable mode before going back to non-discoverable +# The value is in seconds. Default is 180, i.e. 3 minutes. +# 0 = disable timer, i.e. stay discoverable forever +#DiscoverableTimeout = 0 + +# How long to stay in pairable mode before going back to non-discoverable +# The value is in seconds. Default is 0. +# 0 = disable timer, i.e. stay pairable forever +#PairableTimeout = 0 + +# Automatic connection for bonded devices driven by platform/user events. +# If a platform plugin uses this mechanism, automatic connections will be +# enabled during the interval defined below. Initially, this feature +# intends to be used to establish connections to ATT channels. Default is 60. +#AutoConnectTimeout = 60 + +# Use vendor id source (assigner), vendor, product and version information for +# DID profile support. The values are separated by ":" and assigner, VID, PID +# and version. +# Possible vendor id source values: bluetooth, usb (defaults to usb) +#DeviceID = bluetooth:1234:5678:abcd + +# Do reverse service discovery for previously unknown devices that connect to +# us. This option is really only needed for qualification since the BITE tester +# doesn't like us doing reverse SDP for some test cases (though there could in +# theory be other useful purposes for this too). Defaults to 'true'. +#ReverseServiceDiscovery = true + +# Enable name resolving after inquiry. Set it to 'false' if you don't need +# remote devices name and want shorter discovery cycle. Defaults to 'true'. +#NameResolving = true + +# Enable runtime persistency of debug link keys. Default is false which +# makes debug link keys valid only for the duration of the connection +# that they were created for. +#DebugKeys = false + +# Restricts all controllers to the specified transport. Default value +# is "dual", i.e. both BR/EDR and LE enabled (when supported by the HW). +# Possible values: "dual", "bredr", "le" +#ControllerMode = dual + +# Enables Multi Profile Specification support. This allows to specify if +# system supports only Multiple Profiles Single Device (MPSD) configuration +# or both Multiple Profiles Single Device (MPSD) and Multiple Profiles Multiple +# Devices (MPMD) configurations. +# Possible values: "off", "single", "multiple" +#MultiProfile = off + +# Permanently enables the Fast Connectable setting for adapters that +# support it. When enabled other devices can connect faster to us, +# however the tradeoff is increased power consumptions. This feature +# will fully work only on kernel version 4.1 and newer. Defaults to +# 'false'. +#FastConnectable = false + +#[Policy] +# +# The ReconnectUUIDs defines the set of remote services that should try +# to be reconnected to in case of a link loss (link supervision +# timeout). The policy plugin should contain a sane set of values by +# default, but this list can be overridden here. By setting the list to +# empty the reconnection feature gets disabled. +#ReconnectUUIDs=00001112-0000-1000-8000-00805f9b34fb, 0000111f-0000-1000-8000-00805f9b34fb, 0000110a-0000-1000-8000-00805f9b34fb + +# ReconnectAttempts define the number of attempts to reconnect after a link +# lost. Setting the value to 0 disables reconnecting feature. +#ReconnectAttempts=7 + +# ReconnectIntervals define the set of intervals in seconds to use in between +# attempts. +# If the number of attempts defined in ReconnectAttempts is bigger than the +# set of intervals the last interval is repeated until the last attempt. +#ReconnectIntervals=1, 2, 4, 8, 16, 32, 64 + +# AutoEnable defines option to enable all controllers when they are found. +# This includes adapters present on start as well as adapters that are plugged +# in later on. Defaults to 'false'. +#AutoEnable=false diff --git a/src/main_hive.conf b/src/main_hive.conf new file mode 100644 index 0000000..4d5066d --- /dev/null +++ b/src/main_hive.conf @@ -0,0 +1,87 @@ +[General] + +# Default adaper name +# %h - substituted for hostname +# %d - substituted for adapter id +# Defaults to 'BlueZ' +#Name = %h-%d + +# Default device class. Only the major and minor device class bits are +# considered. Defaults to '0x000000'. +#ifdef __TIZEN_PATCH__ +Class = 0x40414 # HIVE +#else +#Class = 0x000100 +#endif + +# How long to stay in discoverable mode before going back to non-discoverable +# The value is in seconds. Default is 180, i.e. 3 minutes. +# 0 = disable timer, i.e. stay discoverable forever +#DiscoverableTimeout = 0 + +# How long to stay in pairable mode before going back to non-discoverable +# The value is in seconds. Default is 0. +# 0 = disable timer, i.e. stay pairable forever +#PairableTimeout = 0 + +# Automatic connection for bonded devices driven by platform/user events. +# If a platform plugin uses this mechanism, automatic connections will be +# enabled during the interval defined below. Initially, this feature +# intends to be used to establish connections to ATT channels. Default is 60. +#AutoConnectTimeout = 60 + +# Use vendor id source (assigner), vendor, product and version information for +# DID profile support. The values are separated by ":" and assigner, VID, PID +# and version. +# Possible vendor id source values: bluetooth, usb (defaults to usb) +#DeviceID = bluetooth:1234:5678:abcd + +# Do reverse service discovery for previously unknown devices that connect to +# us. This option is really only needed for qualification since the BITE tester +# doesn't like us doing reverse SDP for some test cases (though there could in +# theory be other useful purposes for this too). Defaults to 'true'. +#ReverseServiceDiscovery = true + +# Enable name resolving after inquiry. Set it to 'false' if you don't need +# remote devices name and want shorter discovery cycle. Defaults to 'true'. +#NameResolving = true + +# Enable runtime persistency of debug link keys. Default is false which +# makes debug link keys valid only for the duration of the connection +# that they were created for. +#DebugKeys = false + +# Restricts all controllers to the specified transport. Default value +# is "dual", i.e. both BR/EDR and LE enabled (when supported by the HW). +# Possible values: "dual", "bredr", "le" +#ControllerMode = dual + +# Enables Multi Profile Specification support. This allows to specify if +# system supports only Multiple Profiles Single Device (MPSD) configuration +# or both Multiple Profiles Single Device (MPSD) and Multiple Profiles Multiple +# Devices (MPMD) configurations. +# Possible values: "off", "single", "multiple" +#MultiProfile = off + +# Permanently enables the Fast Connectable setting for adapters that +# support it. When enabled other devices can connect faster to us, +# however the tradeoff is increased power consumptions. This feature +# will fully work only on kernel version 4.1 and newer. Defaults to +# 'false'. +#FastConnectable = false + +#ifdef __TIZEN_PATCH__ +# Enable the LE Privacy feature. If value is true, i.e. LE Privacy is enabled +# otherwise the feature is disabled by default for the local device. +EnableLEPrivacy = true +#endif + +#[Policy] +# +# The ReconnectUUIDs defines the set of remote services that should try +# to be reconnected to in case of a link loss (link supervision +# timeout). The policy plugin should contain a sane set of values by +# default, but this list can be overridden here. By setting the list to +# empty the reconnection feature gets disabled. +#ReconnectUUIDs= + diff --git a/src/profile.c b/src/profile.c index c12b57b..26a9e19 100644 --- a/src/profile.c +++ b/src/profile.c @@ -547,9 +547,6 @@ \ \ \ - \ - \ - \ " #else #define PSE_RECORD \ @@ -602,6 +599,12 @@ " #endif +#ifdef __TIZEN_PATCH__ +#define SUPPORTED_MESSAGE_TYPES "0x03" /* EMAIL and SMS_GSM */ +#else +#define SUPPORTED_MESSAGE_TYPES "0x0F" /* EMAIL, SMS_GSM, SMS_CDMA and MMS */ +#endif + #define MAS_RECORD \ " \ \ @@ -644,7 +647,7 @@ \ \ \ - \ + \ \ \ \ @@ -854,7 +857,7 @@ \ \ \ - \ + \ \ \ \ @@ -921,9 +924,6 @@ struct ext_profile { char *destination; char *app_path; #endif -#ifdef TIZEN_BT_HID_DEVICE_ENABLE - bool local_connect; -#endif }; struct ext_io { @@ -1259,7 +1259,6 @@ static bool send_new_connection(struct ext_profile *ext, struct ext_io *conn) dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path); fd = g_io_channel_unix_get_fd(conn->io); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict); @@ -1290,16 +1289,6 @@ static bool send_new_connection(struct ext_profile *ext, struct ext_io *conn) return true; } -#ifdef TIZEN_BT_HID_DEVICE_ENABLE -static int check_connection_psm(gconstpointer a, gconstpointer b) -{ - const struct ext_io *conn = a; - const int *psm = b; - DBG("conn->psm %d, psm %d", conn->psm, *psm); - return (conn->psm == *psm ? 0 : -1); -} -#endif - static void ext_connect(GIOChannel *io, GError *err, gpointer user_data) { struct ext_io *conn = user_data; @@ -1335,32 +1324,6 @@ static void ext_connect(GIOChannel *io, GError *err, gpointer user_data) conn); } -#ifdef TIZEN_BT_HID_DEVICE_ENABLE - if (g_strcmp0(ext->uuid, HID_UUID) == 0 && ext->local_connect == TRUE) { - GSList *l = NULL; - int psm = HID_DEVICE_CTRL_PSM; - ext->local_connect = FALSE; - l = g_slist_find_custom(ext->conns, &psm, check_connection_psm); - if (l == NULL) { - struct ext_io *conn1 = g_new0(struct ext_io, 1); - int error = 0; - ext->remote_psm = psm; - conn1->ext = ext; - conn1->psm = ext->remote_psm; - conn1->chan = ext->remote_chan; - error = connect_io(conn1, btd_adapter_get_address(conn->adapter), - device_get_address(conn->device)); - DBG("error from connect_io %d", error); - conn1->adapter = btd_adapter_ref(conn->adapter); - conn1->device = btd_device_ref(conn->device); - conn1->service = btd_service_ref(conn->service); - ext->conns = g_slist_append(ext->conns, conn1); - } else { - DBG("Connection Already there"); - } - } -#endif - if (conn->service && service_accept(conn->service) == 0) { if (send_new_connection(ext, conn)) return; @@ -1571,17 +1534,11 @@ static uint32_t ext_start_servers(struct ext_profile *ext, struct btd_adapter *adapter) { struct ext_io *l2cap = NULL; -#ifdef TIZEN_BT_HID_DEVICE_ENABLE - struct ext_io *l2cap1 = NULL; -#endif struct ext_io *rfcomm = NULL; BtIOConfirm confirm; BtIOConnect connect; GError *err = NULL; GIOChannel *io; -#ifdef TIZEN_BT_HID_DEVICE_ENABLE - GIOChannel *io1; -#endif if (ext->authorize) { confirm = ext_confirm; @@ -1627,26 +1584,6 @@ static uint32_t ext_start_servers(struct ext_profile *ext, ext->servers = g_slist_append(ext->servers, l2cap); DBG("%s listening on PSM %u", ext->name, psm); } -#ifdef TIZEN_BT_HID_DEVICE_ENABLE - if (g_strcmp0(ext->uuid , HID_UUID) == 0) { - psm = HID_DEVICE_CTRL_PSM; - l2cap1 = g_new0(struct ext_io, 1); - l2cap1->ext = ext; - io1 = bt_io_listen(connect, confirm, l2cap, NULL, &err, - BT_IO_OPT_SOURCE_BDADDR, - btd_adapter_get_address(adapter), - BT_IO_OPT_MODE, ext->mode, - BT_IO_OPT_PSM, psm, - BT_IO_OPT_SEC_LEVEL, ext->sec_level, - BT_IO_OPT_INVALID); - l2cap1->io = io1; - l2cap1->proto = BTPROTO_L2CAP; - l2cap1->psm = psm; - l2cap1->adapter = btd_adapter_ref(adapter); - ext->servers = g_slist_append(ext->servers, l2cap1); - DBG("%s listening on PSM %u", ext->name, psm); - } -#endif } if (ext->local_chan) { @@ -2047,7 +1984,7 @@ static int ext_connect_dev(struct btd_service *service) conn = g_new0(struct ext_io, 1); conn->ext = ext; -#ifndef TIZEN_BT_HID_DEVICE_ENABLE + if (ext->remote_psm || ext->remote_chan) { conn->psm = ext->remote_psm; conn->chan = ext->remote_chan; @@ -2060,28 +1997,7 @@ static int ext_connect_dev(struct btd_service *service) if (err < 0) goto failed; -#else - if (g_strcmp0(ext->uuid, HID_UUID) == 0) { - ext->local_connect = TRUE; - ext->remote_psm = HID_DEVICE_INTR_PSM; - conn->psm = ext->remote_psm; - conn->chan = ext->remote_chan; - err = connect_io(conn, btd_adapter_get_address(adapter), - device_get_address(dev)); - } else { - if (ext->remote_psm || ext->remote_chan) { - conn->psm = ext->remote_psm; - conn->chan = ext->remote_chan; - err = connect_io(conn, btd_adapter_get_address(adapter), - device_get_address(dev)); - } else { - err = resolve_service(conn, btd_adapter_get_address(adapter), - device_get_address(dev)); - } - } - if (err < 0) - goto failed; -#endif + conn->adapter = btd_adapter_ref(adapter); conn->device = btd_device_ref(dev); conn->service = btd_service_ref(service); @@ -2139,7 +2055,6 @@ static int ext_disconnect_dev(struct btd_service *service) if (!ext) return -ENOENT; -#ifndef TIZEN_BT_HID_DEVICE_ENABLE conn = find_connection(ext, dev); if (!conn || !conn->connected) return -ENOTCONN; @@ -2150,30 +2065,7 @@ static int ext_disconnect_dev(struct btd_service *service) err = send_disconn_req(ext, conn); if (err < 0) return err; -#else - if (g_strcmp0(ext->uuid, HID_UUID) != 0) { - conn = find_connection(ext, dev); - if (!conn || !conn->connected) - return -ENOTCONN; - - if (conn->pending) - return -EBUSY; - err = send_disconn_req(ext, conn); - if (err < 0) - return err; - } else { - GSList *l; - /* As HID will be using two psm we need to send disconnect - * request for both the psms */ - for (l = ext->conns; l != NULL; l = g_slist_next(l)) { - struct ext_io *conn1 = l->data; - if (conn1->device == dev) { - err = send_disconn_req(ext, conn1); - } - } - } -#endif return 0; } @@ -2252,7 +2144,11 @@ static char *get_pse_record(struct ext_profile *ext, struct ext_io *l2cap, if (rfcomm) chan = rfcomm->chan; +#ifdef __TIZEN_PATCH__ + return g_strdup_printf(PSE_RECORD, chan, ext->version, ext->name); +#else return g_strdup_printf(PSE_RECORD, chan, ext->version, ext->name, psm); +#endif } static char *get_mas_record(struct ext_profile *ext, struct ext_io *l2cap, @@ -2460,11 +2356,7 @@ static struct default_settings { .psm = BTD_PROFILE_PSM_AUTO, .mode = BT_IO_MODE_ERTM, .sec_level = BT_IO_SEC_LOW, -#ifdef __TIZEN_PATCH__ - .authorize = true, -#else .authorize = false, -#endif .get_record = get_opp_record, #ifdef __TIZEN_PATCH__ .version = 0x0100, @@ -2523,7 +2415,7 @@ static struct default_settings { .version = 0x0102 #ifdef TIZEN_BT_HID_DEVICE_ENABLE }, { - .uuid = HID_UUID, + .uuid = HID_DEVICE_UUID, .name = "HID Device", .psm = HID_DEVICE_INTR_PSM, .authorize = TRUE, @@ -2892,7 +2784,10 @@ static struct ext_profile *create_ext(const char *owner, const char *path, } DBG("Created \"%s\"", ext->name); - +#ifdef TIZEN_BT_HID_DEVICE_ENABLE + if (g_strcmp0(ext->uuid , HID_DEVICE_UUID) == 0) + ext->local_psm = 0; +#endif ext_profiles = g_slist_append(ext_profiles, ext); adapter_foreach(adapter_add_profile, &ext->p); diff --git a/src/shared/att.c b/src/shared/att.c index 187e685..a139660 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -596,13 +596,19 @@ static bool change_security(struct bt_att *att, uint8_t ecode) { int security; - security = bt_att_get_security(att); - if (security != BT_ATT_SECURITY_AUTO) + if (att->io_sec_level != BT_ATT_SECURITY_AUTO) return false; + security = bt_att_get_security(att); + if (ecode == BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION && security < BT_ATT_SECURITY_MEDIUM) security = BT_ATT_SECURITY_MEDIUM; +#ifdef __TIZEN_PATCH__ + else if (ecode == BT_ATT_ERROR_AUTHENTICATION && + security < BT_ATT_SECURITY_MEDIUM) + security = BT_ATT_SECURITY_MEDIUM; +#endif else if (ecode == BT_ATT_ERROR_AUTHENTICATION && security < BT_ATT_SECURITY_HIGH) security = BT_ATT_SECURITY_HIGH; @@ -1009,7 +1015,7 @@ struct bt_att *bt_att_new(int fd, bool ext_signed) att->io_on_l2cap = is_io_l2cap_based(att->fd); if (!att->io_on_l2cap) - att->io_sec_level = BT_SECURITY_LOW; + att->io_sec_level = BT_ATT_SECURITY_LOW; return bt_att_ref(att); diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index f8e8298..208f26c 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -320,25 +320,6 @@ struct handle_range { uint16_t end; }; -static bool match_notify_data_handle_range(const void *a, const void *b) -{ - const struct notify_data *notify_data = a; - struct notify_chrc *chrc = notify_data->chrc; - const struct handle_range *range = b; - - return chrc->value_handle >= range->start && - chrc->value_handle <= range->end; -} - -static bool match_notify_chrc_handle_range(const void *a, const void *b) -{ - const struct notify_chrc *chrc = a; - const struct handle_range *range = b; - - return chrc->value_handle >= range->start && - chrc->value_handle <= range->end; -} - static void notify_data_cleanup(void *data) { struct notify_data *notify_data = data; @@ -349,32 +330,6 @@ static void notify_data_cleanup(void *data) notify_data_unref(notify_data); } -static void gatt_client_remove_all_notify_in_range( - struct bt_gatt_client *client, - uint16_t start_handle, uint16_t end_handle) -{ - struct handle_range range; - - range.start = start_handle; - range.end = end_handle; - - queue_remove_all(client->notify_list, match_notify_data_handle_range, - &range, notify_data_cleanup); -} - -static void gatt_client_remove_notify_chrcs_in_range( - struct bt_gatt_client *client, - uint16_t start_handle, uint16_t end_handle) -{ - struct handle_range range; - - range.start = start_handle; - range.end = end_handle; - - queue_remove_all(client->notify_chrcs, match_notify_chrc_handle_range, - &range, notify_chrc_free); -} - struct discovery_op; typedef void (*discovery_op_complete_func_t)(struct discovery_op *op, @@ -386,11 +341,12 @@ struct discovery_op { struct bt_gatt_client *client; struct queue *pending_svcs; struct queue *pending_chrcs; - struct queue *tmp_queue; + struct queue *svcs; struct gatt_db_attribute *cur_svc; bool success; uint16_t start; uint16_t end; + uint16_t last; int ref_count; discovery_op_complete_func_t complete_func; discovery_op_fail_func_t failure_func; @@ -400,10 +356,45 @@ static void discovery_op_free(struct discovery_op *op) { queue_destroy(op->pending_svcs, NULL); queue_destroy(op->pending_chrcs, free); - queue_destroy(op->tmp_queue, NULL); + queue_destroy(op->svcs, NULL); free(op); } +static void discovery_op_complete(struct discovery_op *op, bool success, + uint8_t err) +{ + /* Reset remaining range */ + if (success) { +#ifdef __TIZEN_PATCH__ + util_debug(op->client->debug_callback, op->client->debug_data, + "op->start : %u, op->end : %u, op->last : %u", + op->start, op->end, op->last); + + if (op->last != UINT16_MAX) { + if (op->start != op->last) + op->last++; + + if (op->last <= op->end) + gatt_db_clear_range(op->client->db, + op->last, op->end); + } +#else + if (op->last != UINT16_MAX) + gatt_db_clear_range(op->client->db, op->last + 1, + UINT16_MAX); +#endif + } else { +#ifdef __TIZEN_PATCH__ + util_debug(op->client->debug_callback, op->client->debug_data, + "Fail to discover service. Clear DB [%d]", err); +#endif + gatt_db_clear(op->client->db); + } + + op->success = success; + op->complete_func(op, success, err); +} + static struct discovery_op *discovery_op_create(struct bt_gatt_client *client, uint16_t start, uint16_t end, discovery_op_complete_func_t complete_func, @@ -414,12 +405,15 @@ static struct discovery_op *discovery_op_create(struct bt_gatt_client *client, op = new0(struct discovery_op, 1); op->pending_svcs = queue_new(); op->pending_chrcs = queue_new(); - op->tmp_queue = queue_new(); + op->svcs = queue_new(); op->client = client; op->complete_func = complete_func; op->failure_func = failure_func; op->start = start; op->end = end; +#ifdef __TIZEN_PATCH__ + op->last = start; +#endif return op; } @@ -530,17 +524,11 @@ next: /* Move on to the next service */ attr = queue_pop_head(op->pending_svcs); if (!attr) { - struct queue *tmp_queue; - - tmp_queue = op->pending_svcs; - op->pending_svcs = op->tmp_queue; - op->tmp_queue = tmp_queue; - /* * We have processed all include definitions. Move on to * characteristics. */ - attr = queue_pop_head(op->pending_svcs); + attr = queue_pop_head(op->svcs); if (!attr) goto failed; @@ -564,7 +552,7 @@ next: goto failed; } - queue_push_tail(op->tmp_queue, attr); + queue_push_tail(op->svcs, attr); op->cur_svc = attr; if (!gatt_db_attribute_get_service_handles(attr, &start, &end)) goto failed; @@ -585,8 +573,7 @@ next: discovery_op_unref(op); failed: - op->success = false; - op->complete_func(op, false, att_ecode); + discovery_op_complete(op, false, att_ecode); } struct chrc { @@ -617,8 +604,12 @@ static bool discover_descs(struct discovery_op *op, bool *discovering) chrc_data->properties, NULL, NULL, NULL); - if (!attr) + if (!attr) { + util_debug(client->debug_callback, client->debug_data, + "Failed to insert characteristic at 0x%04x", + chrc_data->value_handle); goto failed; + } if (gatt_db_attribute_get_handle(attr) != chrc_data->value_handle) @@ -727,7 +718,7 @@ next: /* Done with the current service */ gatt_db_service_set_active(op->cur_svc, true); - attr = queue_pop_head(op->pending_svcs); + attr = queue_pop_head(op->svcs); if (!attr) goto done; @@ -756,8 +747,7 @@ failed: success = false; done: - op->success = success; - op->complete_func(op, success, att_ecode); + discovery_op_complete(op, success, att_ecode); } #ifdef __TIZEN_PATCH__ @@ -894,7 +884,7 @@ next: /* Done with the current service */ gatt_db_service_set_active(op->cur_svc, true); - attr = queue_pop_head(op->pending_svcs); + attr = queue_pop_head(op->svcs); if (!attr) goto done; @@ -923,8 +913,7 @@ failed: success = false; done: - op->success = success; - op->complete_func(op, success, att_ecode); + discovery_op_complete(op, success, att_ecode); } static void discover_secondary_cb(bool success, uint8_t att_ecode, @@ -974,6 +963,13 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode, start, end, uuid_str); /* Store the service */ +#ifdef __TIZEN_PATCH__ + if (client->in_svc_chngd) { + util_debug(client->debug_callback, client->debug_data, + "In service changed, delete service first."); + gatt_db_clear_range(client->db, start, end); + } +#endif attr = gatt_db_insert_service(client->db, start, &uuid, false, end - start + 1); if (!attr) { @@ -992,6 +988,10 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode, /* Skip if service already active */ if (!gatt_db_service_get_active(attr)) queue_push_tail(op->pending_svcs, attr); + + /* Update last handle */ + if (end > op->last) + op->last = end; } next: @@ -1005,10 +1005,10 @@ next: } /* - * Store the service in the tmp queue to be reused during + * Store the service in the svcs queue to be reused during * characteristics discovery later. */ - queue_push_tail(op->tmp_queue, attr); + queue_push_tail(op->svcs, attr); op->cur_svc = attr; if (!gatt_db_attribute_get_service_handles(attr, &start, &end)) { @@ -1029,8 +1029,7 @@ next: discovery_op_unref(op); done: - op->success = success; - op->complete_func(op, success, att_ecode); + discovery_op_complete(op, success, att_ecode); } static void discover_primary_cb(bool success, uint8_t att_ecode, @@ -1053,7 +1052,11 @@ static void discover_primary_cb(bool success, uint8_t att_ecode, "Primary service discovery failed." " ATT ECODE: 0x%02x", att_ecode); /* Reset error in case of not found */ +#ifdef __TIZEN_PATCH__ + if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) { +#else if (BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) { +#endif success = true; att_ecode = 0; } @@ -1078,6 +1081,13 @@ static void discover_primary_cb(bool success, uint8_t att_ecode, "start: 0x%04x, end: 0x%04x, uuid: %s", start, end, uuid_str); +#ifdef __TIZEN_PATCH__ + if (client->in_svc_chngd) { + util_debug(client->debug_callback, client->debug_data, + "In service changed, delete service first."); + gatt_db_clear_range(client->db, start, end); + } +#endif attr = gatt_db_insert_service(client->db, start, &uuid, true, end - start + 1); if (!attr) { @@ -1096,6 +1106,10 @@ static void discover_primary_cb(bool success, uint8_t att_ecode, /* Skip if service already active */ if (!gatt_db_service_get_active(attr)) queue_push_tail(op->pending_svcs, attr); + + /* Update last handle */ + if (end > op->last) + op->last = end; } secondary: @@ -1123,8 +1137,7 @@ secondary: success = false; done: - op->success = success; - op->complete_func(op, success, att_ecode); + discovery_op_complete(op, success, att_ecode); } static void notify_client_ready(struct bt_gatt_client *client, bool success, @@ -1549,22 +1562,6 @@ static void process_service_changed(struct bt_gatt_client *client, { struct discovery_op *op; - /* On full database reset just re-run attribute discovery */ - if (start_handle == 0x0001 && end_handle == 0xffff) - goto discover; - - /* Invalidate and remove all effected notify callbacks */ - gatt_client_remove_all_notify_in_range(client, start_handle, - end_handle); - gatt_client_remove_notify_chrcs_in_range(client, start_handle, - end_handle); - - /* Remove all services that overlap the modified range since we'll - * rediscover them - */ - gatt_db_clear_range(client->db, start_handle, end_handle); - -discover: op = discovery_op_create(client, start_handle, end_handle, service_changed_complete, service_changed_failure); @@ -1618,12 +1615,10 @@ static void service_changed_cb(uint16_t value_handle, const uint8_t *value, "Service Changed received - start: 0x%04x end: 0x%04x", start, end); -#ifndef __TIZEN_PATCH__ if (!client->in_svc_chngd) { process_service_changed(client, start, end); return; } -#endif op = new0(struct service_changed_op, 1); @@ -1753,6 +1748,11 @@ static void complete_unregister_notify(void *data) */ if (notify_data->att_id) { bt_att_cancel(notify_data->client->att, notify_data->att_id); + notify_data->att_id = 0; +#ifdef __TIZEN_PATCH__ + notify_data->chrc->ccc_write_id = 0; + __sync_sub_and_fetch(¬ify_data->chrc->notify_count, 1); +#endif goto done; } @@ -1795,9 +1795,8 @@ static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length, { struct bt_gatt_client *client = user_data; struct pdu_data pdu_data; -#ifdef __TIZEN_PATCH__ - struct service_changed_op *sc_op; +#ifdef __TIZEN_PATCH__ if (client->ready == false) { struct noti *noti; @@ -1834,15 +1833,6 @@ static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length, queue_foreach(client->notify_list, notify_handler, &pdu_data); -#ifdef __TIZEN_PATCH__ - if (client->in_svc_chngd == false && - (sc_op = queue_pop_head(client->svc_chngd_queue))) { - process_service_changed(client, sc_op->start_handle, - sc_op->end_handle); - free(sc_op); - } -#endif - if (opcode == BT_ATT_OP_HANDLE_VAL_IND) bt_att_send(client->att, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, NULL, NULL, NULL); @@ -2387,7 +2377,9 @@ static void read_long_cb(uint8_t opcode, const void *pdu, goto done; } - if (opcode != BT_ATT_OP_READ_BLOB_RSP || (!pdu && length)) { + if ((!op->offset && opcode != BT_ATT_OP_READ_RSP) + || (op->offset && opcode != BT_ATT_OP_READ_BLOB_RSP) + || (!pdu && length)) { success = false; goto done; } @@ -2440,7 +2432,9 @@ unsigned int bt_gatt_client_read_long_value(struct bt_gatt_client *client, { struct request *req; struct read_long_op *op; + uint8_t att_op; uint8_t pdu[4]; + uint16_t pdu_len; if (!client) return 0; @@ -2464,12 +2458,32 @@ unsigned int bt_gatt_client_read_long_value(struct bt_gatt_client *client, req->destroy = destroy_read_long_op; put_le16(value_handle, pdu); - put_le16(offset, pdu + 2); + pdu_len = sizeof(value_handle); + + /* + * Core v4.2, part F, section 1.3.4.4.5: + * If the attribute value has a fixed length that is less than or equal + * to (ATT_MTU - 3) octets in length, then an Error Response can be sent + * with the error code «Attribute Not Long». + * + * To remove need for caller to handle "Attribute Not Long" error when + * reading characteristics with short values, use Read Request for + * reading first part of characteristics value instead of Read Blob + * Request. Both are allowed in this case. + */ + + if (op->offset) { + att_op = BT_ATT_OP_READ_BLOB_REQ; + pdu_len += sizeof(op->offset); + + put_le16(op->offset, pdu + 2); + } else { + att_op = BT_ATT_OP_READ_REQ; + } + + req->att_id = bt_att_send(client->att, att_op, pdu, pdu_len, + read_long_cb, req, request_unref); - req->att_id = bt_att_send(client->att, BT_ATT_OP_READ_BLOB_REQ, - pdu, sizeof(pdu), - read_long_cb, req, - request_unref); if (!req->att_id) { op->destroy = NULL; request_unref(req); @@ -3257,8 +3271,14 @@ unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client, if (!client || !client->db || !chrc_value_handle || !callback) return 0; +#ifdef __TIZEN_PATCH__ + if (client->in_svc_chngd) + util_debug(client->debug_callback, client->debug_data, + "register_notify in service changed handling"); +#else if (client->in_svc_chngd) return 0; +#endif return register_notify(client, chrc_value_handle, callback, notify, user_data, destroy); diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c index d741abc..a3f1a48 100644 --- a/src/shared/gatt-db.c +++ b/src/shared/gatt-db.c @@ -1745,14 +1745,14 @@ bool get_ccc_notify_indicate(const struct gatt_db_attribute *ccc) return false; } -void set_ccc_unicast_address(const struct gatt_db_attribute *ccc, +void set_ccc_unicast_address(struct gatt_db_attribute *ccc, const char *address) { if (ccc) - str2ba(address, (bdaddr_t *)&ccc->unicast_addr); + str2ba(address, &ccc->unicast_addr); } -bdaddr_t *get_ccc_unicast_address(const struct gatt_db_attribute *ccc) +const bdaddr_t *get_ccc_unicast_address(const struct gatt_db_attribute *ccc) { if (ccc) return &ccc->unicast_addr; diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h index 581b7d5..8e9e554 100644 --- a/src/shared/gatt-db.h +++ b/src/shared/gatt-db.h @@ -241,8 +241,8 @@ void set_ccc_notify_indicate(struct gatt_db_attribute *ccc, bool get_ccc_notify_indicate(const struct gatt_db_attribute *ccc); -void set_ccc_unicast_address(const struct gatt_db_attribute *ccc, +void set_ccc_unicast_address(struct gatt_db_attribute *ccc, const char *address); -bdaddr_t *get_ccc_unicast_address(const struct gatt_db_attribute *ccc); +const bdaddr_t *get_ccc_unicast_address(const struct gatt_db_attribute *ccc); #endif diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c index 127e45b..64c400b 100644 --- a/src/shared/gatt-server.c +++ b/src/shared/gatt-server.c @@ -180,7 +180,11 @@ static bool encode_read_by_grp_type_rsp(struct gatt_db *db, struct queue *q, int iter = 0; uint16_t start_handle, end_handle; struct iovec value; +#ifdef __TIZEN_PATCH__ + uint8_t data_val_len = 0; +#else uint8_t data_val_len; +#endif *len = 0; @@ -519,7 +523,11 @@ static bool encode_find_info_rsp(struct gatt_db *db, struct queue *q, uint16_t handle; struct gatt_db_attribute *attr; const bt_uuid_t *type; +#ifdef __TIZEN_PATCH__ + int uuid_len = 0, cur_uuid_len; +#else int uuid_len, cur_uuid_len; +#endif int iter = 0; *len = 0; @@ -926,6 +934,12 @@ static void handle_read_req(struct bt_gatt_server *server, uint8_t opcode, ecode = BT_ATT_ERROR_UNLIKELY; error: +#ifdef __TIZEN_PATCH__ + util_debug(server->debug_callback, server->debug_data, + "Handling \"Read %sReq\" is failed : %d", + (opcode == BT_ATT_OP_READ_BLOB_REQ) ? "Blob" : "", + ecode); +#endif if (op) async_read_op_destroy(op); @@ -1223,6 +1237,9 @@ static void exec_next_prep_write(struct bt_gatt_server *server, err = BT_ATT_ERROR_UNLIKELY; error: + queue_remove_all(server->prep_queue, NULL, NULL, + prep_write_data_destroy); + bt_att_send_error_rsp(server->att, BT_ATT_OP_EXEC_WRITE_REQ, ehandle, err); } @@ -1267,6 +1284,8 @@ static void exec_write_cb(uint8_t opcode, const void *pdu, return; error: + queue_remove_all(server->prep_queue, NULL, NULL, + prep_write_data_destroy); bt_att_send_error_rsp(server->att, opcode, 0, ecode); } -- 2.7.4