Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a9c4389 authored by Andre Eisenbach's avatar Andre Eisenbach
Browse files

DO NOT MERGE Add ability to add interop entries dynamically (2/2)

Add ability and interface for adding dynamic entries to the interop
workaround database.

Bug: 26548845
Change-Id: Id886e4233fc1548727e79f1581cdc0c6f0738d59
parent 6790325e
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -50,9 +50,10 @@
#include "btsnoop.h"
#include "btsnoop.h"
#include "btsnoop_mem.h"
#include "btsnoop_mem.h"
#include "bt_utils.h"
#include "bt_utils.h"
#include "osi/include/osi.h"
#include "device/include/interop.h"
#include "osi/include/allocation_tracker.h"
#include "osi/include/allocation_tracker.h"
#include "osi/include/log.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "stack_manager.h"
#include "stack_manager.h"
#include "btif_config.h"
#include "btif_config.h"


@@ -456,7 +457,9 @@ static const bt_interface_t bluetoothInterface = {
    set_os_callouts,
    set_os_callouts,
    read_energy_info,
    read_energy_info,
    dump,
    dump,
    config_clear
    config_clear,
    interop_database_clear,
    interop_database_add,
};
};


const bt_interface_t* bluetooth__get_bluetooth_interface ()
const bt_interface_t* bluetooth__get_bluetooth_interface ()
+12 −2
Original line number Original line Diff line number Diff line
@@ -22,11 +22,13 @@


#include "btcore/include/bdaddr.h"
#include "btcore/include/bdaddr.h"


static const char INTEROP_MODULE[] = "interop_module";

typedef enum {
typedef enum {
  // Disable secure connections
  // Disable secure connections
  // This is for pre BT 4.1/2 devices that do not handle secure mode
  // This is for pre BT 4.1/2 devices that do not handle secure mode
  // very well.
  // very well.
  INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
  INTEROP_DISABLE_LE_SECURE_CONNECTIONS = 0,


  // Some devices have proven problematic during the pairing process, often
  // Some devices have proven problematic during the pairing process, often
  // requiring multiple retries to complete pairing. To avoid degrading the user
  // requiring multiple retries to complete pairing. To avoid degrading the user
@@ -38,5 +40,13 @@ typedef enum {
// Check if a given |addr| matches a known interoperability workaround as identified
// Check if a given |addr| matches a known interoperability workaround as identified
// by the |interop_feature_t| enum. This API is used for simple address based lookups
// by the |interop_feature_t| enum. This API is used for simple address based lookups
// where more information is not available. No look-ups or random address resolution
// where more information is not available. No look-ups or random address resolution
// is performed on |addr|.
// are performed on |addr|.
bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr);
bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr);

// Add a dynamic interop database entry for a device matching the first |length| bytes
// of |addr|, implementing the workaround identified by |feature|. |addr| may not be
// null and |length| must be greater than 0 and less than sizeof(bt_bdaddr_t).
void interop_database_add(const interop_feature_t feature, const bt_bdaddr_t *addr, size_t length);

// Clear the dynamic portion of the interoperability workaround database.
void interop_database_clear(void);
+1 −1
Original line number Original line Diff line number Diff line
@@ -22,7 +22,7 @@


typedef struct {
typedef struct {
  bt_bdaddr_t addr;
  bt_bdaddr_t addr;
  uint8_t len;
  size_t length;
  interop_feature_t feature;
  interop_feature_t feature;
} interop_entry_t;
} interop_entry_t;


+96 −6
Original line number Original line Diff line number Diff line
@@ -21,13 +21,78 @@
#include <assert.h>
#include <assert.h>
#include <string.h> // For memcmp
#include <string.h> // For memcmp


#include "btcore/include/module.h"
#include "device/include/interop.h"
#include "device/include/interop.h"
#include "device/include/interop_database.h"
#include "device/include/interop_database.h"
#include "osi/include/allocator.h"
#include "osi/include/list.h"
#include "osi/include/log.h"
#include "osi/include/log.h"


#define CASE_RETURN_STR(const) case const: return #const;
#define CASE_RETURN_STR(const) case const: return #const;


static const char* interop_feature_string(const interop_feature_t feature) {
static list_t *interop_list = NULL;

static const char* interop_feature_string_(const interop_feature_t feature);
static void interop_free_entry_(void *data);
static void interop_lazy_init_(void);
static bool interop_match_fixed_(const interop_feature_t feature, const bt_bdaddr_t *addr);
static bool interop_match_dynamic_(const interop_feature_t feature, const bt_bdaddr_t *addr);

// Interface functions

bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  assert(addr);

  if (interop_match_fixed_(feature, addr) || interop_match_dynamic_(feature, addr)) {
    char bdstr[20] = {0};
    LOG_WARN("%s() Device %s is a match for interop workaround %s.",
          __func__, bdaddr_to_string(addr, bdstr, sizeof(bdstr)),
                        interop_feature_string_(feature));
    return true;
  }

  return false;
}

void interop_database_add(const interop_feature_t feature, const bt_bdaddr_t *addr, size_t length) {
  assert(addr);
  assert(length > 0);
  assert(length < sizeof(bt_bdaddr_t));

  interop_entry_t *entry = osi_calloc(sizeof(interop_entry_t));
  memcpy(&entry->addr, addr, length);
  entry->feature = feature;
  entry->length = length;

  interop_lazy_init_();
  list_append(interop_list, entry);
}

void interop_database_clear() {
  if (interop_list)
    list_clear(interop_list);
}

// Module life-cycle functions

static future_t *interop_clean_up(void) {
  list_free(interop_list);
  interop_list = NULL;
  return future_new_immediate(FUTURE_SUCCESS);
}

const module_t interop_module = {
  .name = INTEROP_MODULE,
  .init = NULL,
  .start_up = NULL,
  .shut_down = NULL,
  .clean_up = interop_clean_up,
  .dependencies = {NULL},
};

// Local functions

static const char* interop_feature_string_(const interop_feature_t feature) {
  switch (feature) {
  switch (feature) {
    CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS)
    CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS)
    CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING)
    CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING)
@@ -36,19 +101,44 @@ static const char* interop_feature_string(const interop_feature_t feature) {
  return "UNKNOWN";
  return "UNKNOWN";
}
}


// Interface functions
static void interop_free_entry_(void *data) {
  interop_entry_t *entry = (interop_entry_t *)data;
  osi_free(entry);
}


bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) {
static void interop_lazy_init_(void) {
  if (interop_list == NULL) {
    interop_list = list_new(interop_free_entry_);
  }
}

static bool interop_match_dynamic_(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  if (interop_list == NULL || list_length(interop_list) == 0)
    return false;

  const list_node_t *node = list_begin(interop_list);
  while (node != list_end(interop_list)) {
    interop_entry_t *entry = list_node(node);
    assert(entry);

    if (feature == entry->feature && memcmp(addr, &entry->addr, entry->length) == 0)
      return true;

    node = list_next(node);
  }
  return false;
}

static bool interop_match_fixed_(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  assert(addr);
  assert(addr);


  const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t);
  const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t);

  for (size_t i = 0; i != db_size; ++i) {
  for (size_t i = 0; i != db_size; ++i) {
    if (feature == interop_database[i].feature &&
    if (feature == interop_database[i].feature &&
        memcmp(addr, &interop_database[i].addr, interop_database[i].len) == 0) {
        memcmp(addr, &interop_database[i].addr, interop_database[i].length) == 0) {
      char bdstr[20] = {0};
      char bdstr[20] = {0};
      LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__,
      LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__,
          bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string(feature));
          bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string_(feature));
      return true;
      return true;
    }
    }
  }
  }
+20 −0
Original line number Original line Diff line number Diff line
@@ -42,3 +42,23 @@ TEST(InteropTest, test_lookup_miss) {
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
}
}


TEST(InteropTest, test_dynamic) {
  bt_bdaddr_t test_address;

  string_to_bdaddr("11:22:33:44:55:66", &test_address);
  EXPECT_FALSE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));

  interop_database_add(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address, 3);
  EXPECT_TRUE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));

  string_to_bdaddr("66:55:44:33:22:11", &test_address);
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));

  interop_database_add(INTEROP_AUTO_RETRY_PAIRING, &test_address, 3);
  EXPECT_TRUE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
  EXPECT_FALSE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));

  interop_database_clear();
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
}
Loading