Set IRK always 73/101173/1
authorSeungyoun Ju <sy39.ju@samsung.com>
Wed, 30 Nov 2016 06:34:59 +0000 (15:34 +0900)
committerSudha Bheemanna <b.sudha@samsung.com>
Wed, 30 Nov 2016 10:34:38 +0000 (16:04 +0530)
[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>
Signed-off-by: Sudha Bheemanna <b.sudha@samsung.com>
lib/mgmt.h
src/adapter.c

index bc1c696..e92aa3a 100644 (file)
@@ -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;
index 9d76e64..d930feb 100644 (file)
@@ -585,6 +585,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
@@ -12527,8 +12528,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
@@ -12836,6 +12845,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)
 {
@@ -12855,28 +12887,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);
        }
@@ -12892,6 +12911,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,