summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeungyoun Ju <sy39.ju@samsung.com>2016-11-30 15:34:59 +0900
committerInjun Yang <injun.yang@samsung.com>2016-11-30 15:34:59 +0900
commit6c6326b6951ca35b91f358f49526bf825654fd6a (patch)
tree80c4cd4deb72a503a9f3cdc8a4ee8bca36cc94b6
parent47c0a178d9aa83873c2e438fd695423010a9e76f (diff)
downloadbluez-6c6326b6951ca35b91f358f49526bf825654fd6a.tar.gz
bluez-6c6326b6951ca35b91f358f49526bf825654fd6a.tar.bz2
bluez-6c6326b6951ca35b91f358f49526bf825654fd6a.zip
Set IRK always
[Problem] Android 6.x devices which don't support privacy 1.2 couldn't make LE connection to the device which doesn't distribute IRK when pairing. [Cause & Measure] Android 6.x devices which don't support privacy 1.2 use wrong address type when it tries to connect if remote device doesn't distributes IRK. This is Android 6.x device's bug but for compatibility Tizen need to distribute IRK even though Privacy feature is disabled. [Checking Method] Pair BLE with A3 / A5 phones of Android version 6.x -> Disconnect -> Try connect BLE again Change-Id: I63d60721d6c2b7472110d09ceda51ca04e898029 Signed-off-by: Injun Yang <injun.yang@samsung.com>
-rw-r--r--lib/mgmt.h7
-rw-r--r--src/adapter.c95
2 files changed, 82 insertions, 20 deletions
diff --git a/lib/mgmt.h b/lib/mgmt.h
index bc1c6969..e92aa3a3 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -1050,7 +1050,12 @@ struct mgmt_cp_le_set_data_length {
} __packed;
#define MGMT_LE_SET_DATA_LENGTH_SIZE 10
-#define MGMT_OP_SET_DEV_RPA_RES_SUPPORT (TIZEN_OP_CODE_BASE + 0x19)
+#define MGMT_OP_SET_IRK (TIZEN_OP_CODE_BASE + 0x19)
+struct mgmt_cp_set_irk {
+ uint8_t irk[16];
+} __packed;
+
+#define MGMT_OP_SET_DEV_RPA_RES_SUPPORT (TIZEN_OP_CODE_BASE + 0x1a)
struct mgmt_cp_set_dev_rpa_res_support {
struct mgmt_addr_info addr;
uint8_t res_support;
diff --git a/src/adapter.c b/src/adapter.c
index 828f54fe..762a00d4 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -574,6 +574,7 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode,
uint8_t mode);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
static bool set_privacy(struct btd_adapter *adapter, bool privacy);
+static bool set_irk(struct btd_adapter *adapter, bool set);
#endif
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
@@ -12507,8 +12508,16 @@ static int adapter_register(struct btd_adapter *adapter)
if (adapter->le_privacy_enabled &&
(adapter->supported_settings & MGMT_SETTING_PRIVACY))
set_privacy(adapter, true);
- else
+ else {
+ /*
+ * Some Android devices don't consider the device as LE one,
+ * if the device doesn't distribute IRK when pairing.
+ * Because of this compatibility issue, set IRK
+ * even though privacy feature is disabled.
+ */
DBG("LE privacy feature not configured or supported");
+ set_irk(adapter, true);
+ }
#endif
/* retrieve the active connections: address the scenario where
@@ -12816,6 +12825,29 @@ static void unpaired_callback(uint16_t index, uint16_t length,
}
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+static uint8_t *generate_irk(void)
+{
+ int fd;
+ uint8_t *irk;
+
+ DBG("Generate IRK");
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ irk = g_malloc0(MGMT_IRK_SIZE);
+ if (read(fd, irk, MGMT_IRK_SIZE) != MGMT_IRK_SIZE) {
+ error("Cannot read random bytes");
+ g_free(irk);
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+
+ return irk;
+}
+
static void set_privacy_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -12835,28 +12867,15 @@ static bool set_privacy(struct btd_adapter *adapter, bool privacy)
memset(&cp, 0, sizeof(cp));
- 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;
+ if (privacy) {
+ if (adapter->local_irk == NULL) {
+ adapter->local_irk = generate_irk();
+ if (adapter->local_irk == NULL)
+ goto fail;
}
- close(fd);
store_adapter_info(adapter);
- }
- if (privacy) {
cp.privacy = 0x01;
memcpy(cp.irk, adapter->local_irk, MGMT_IRK_SIZE);
}
@@ -12872,6 +12891,44 @@ fail:
return false;
}
+static void set_irk_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct btd_adapter *adapter = user_data;
+
+ if (status != MGMT_STATUS_SUCCESS)
+ error("Setting IRK is failed for hci%u: %s (0x%02x)",
+ adapter->dev_id, mgmt_errstr(status), status);
+ else
+ DBG("Setting IRK is succeed for hci%u", adapter->dev_id);
+}
+
+static bool set_irk(struct btd_adapter *adapter, bool set)
+{
+ struct mgmt_cp_set_irk cp;
+
+ memset(&cp, 0, sizeof(cp));
+
+ if (set) {
+ if (adapter->local_irk == NULL) {
+ adapter->local_irk = generate_irk();
+ if (adapter->local_irk == NULL)
+ goto fail;
+ }
+
+ store_adapter_info(adapter);
+ memcpy(cp.irk, adapter->local_irk, MGMT_IRK_SIZE);
+ }
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_SET_IRK,
+ adapter->dev_id, sizeof(cp), &cp,
+ set_irk_complete, adapter, NULL) > 0)
+ return true;
+
+fail:
+ error("Failed to set irk %u", adapter->dev_id);
+ return false;
+}
int btd_adapter_connect_ipsp(struct btd_adapter *adapter,
const bdaddr_t *bdaddr,