Home | History | Annotate | Download | only in src
      1 /******************************************************************************
      2  *
      3  *  Copyright 2015 Google, Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #define LOG_TAG "bt_device_interop"
     20 
     21 #include <base/logging.h>
     22 #include <string.h>  // For memcmp
     23 
     24 #include "btcore/include/module.h"
     25 #include "device/include/interop.h"
     26 #include "device/include/interop_database.h"
     27 #include "osi/include/allocator.h"
     28 #include "osi/include/list.h"
     29 #include "osi/include/log.h"
     30 
     31 #define CASE_RETURN_STR(const) \
     32   case const:                  \
     33     return #const;
     34 
     35 static list_t* interop_list = NULL;
     36 
     37 static const char* interop_feature_string_(const interop_feature_t feature);
     38 static void interop_free_entry_(void* data);
     39 static void interop_lazy_init_(void);
     40 static bool interop_match_fixed_(const interop_feature_t feature,
     41                                  const RawAddress* addr);
     42 static bool interop_match_dynamic_(const interop_feature_t feature,
     43                                    const RawAddress* addr);
     44 
     45 // Interface functions
     46 
     47 bool interop_match_addr(const interop_feature_t feature,
     48                         const RawAddress* addr) {
     49   CHECK(addr);
     50 
     51   if (interop_match_fixed_(feature, addr) ||
     52       interop_match_dynamic_(feature, addr)) {
     53     LOG_WARN(LOG_TAG, "%s() Device %s is a match for interop workaround %s.",
     54              __func__, addr->ToString().c_str(),
     55              interop_feature_string_(feature));
     56     return true;
     57   }
     58 
     59   return false;
     60 }
     61 
     62 bool interop_match_name(const interop_feature_t feature, const char* name) {
     63   CHECK(name);
     64 
     65   const size_t db_size =
     66       sizeof(interop_name_database) / sizeof(interop_name_entry_t);
     67   for (size_t i = 0; i != db_size; ++i) {
     68     if (feature == interop_name_database[i].feature &&
     69         strlen(name) >= interop_name_database[i].length &&
     70         strncmp(name, interop_name_database[i].name,
     71                 interop_name_database[i].length) == 0) {
     72       return true;
     73     }
     74   }
     75 
     76   return false;
     77 }
     78 
     79 void interop_database_add(uint16_t feature, const RawAddress* addr,
     80                           size_t length) {
     81   CHECK(addr);
     82   CHECK(length > 0);
     83   CHECK(length < RawAddress::kLength);
     84 
     85   interop_addr_entry_t* entry = static_cast<interop_addr_entry_t*>(
     86       osi_calloc(sizeof(interop_addr_entry_t)));
     87   memcpy(&entry->addr, addr, length);
     88   entry->feature = static_cast<interop_feature_t>(feature);
     89   entry->length = length;
     90 
     91   interop_lazy_init_();
     92   list_append(interop_list, entry);
     93 }
     94 
     95 void interop_database_clear() {
     96   if (interop_list) list_clear(interop_list);
     97 }
     98 
     99 // Module life-cycle functions
    100 
    101 static future_t* interop_clean_up(void) {
    102   list_free(interop_list);
    103   interop_list = NULL;
    104   return future_new_immediate(FUTURE_SUCCESS);
    105 }
    106 
    107 EXPORT_SYMBOL module_t interop_module = {
    108     .name = INTEROP_MODULE,
    109     .init = NULL,
    110     .start_up = NULL,
    111     .shut_down = NULL,
    112     .clean_up = interop_clean_up,
    113     .dependencies = {NULL},
    114 };
    115 
    116 // Local functions
    117 
    118 static const char* interop_feature_string_(const interop_feature_t feature) {
    119   switch (feature) {
    120     CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS)
    121     CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING)
    122     CASE_RETURN_STR(INTEROP_DISABLE_ABSOLUTE_VOLUME)
    123     CASE_RETURN_STR(INTEROP_DISABLE_AUTO_PAIRING)
    124     CASE_RETURN_STR(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN)
    125     CASE_RETURN_STR(INTEROP_2MBPS_LINK_ONLY)
    126     CASE_RETURN_STR(INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S)
    127     CASE_RETURN_STR(INTEROP_GATTC_NO_SERVICE_CHANGED_IND)
    128     CASE_RETURN_STR(INTEROP_DISABLE_AVDTP_RECONFIGURE)
    129     CASE_RETURN_STR(INTEROP_DYNAMIC_ROLE_SWITCH)
    130     CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH)
    131   }
    132 
    133   return "UNKNOWN";
    134 }
    135 
    136 static void interop_free_entry_(void* data) {
    137   interop_addr_entry_t* entry = (interop_addr_entry_t*)data;
    138   osi_free(entry);
    139 }
    140 
    141 static void interop_lazy_init_(void) {
    142   if (interop_list == NULL) {
    143     interop_list = list_new(interop_free_entry_);
    144   }
    145 }
    146 
    147 static bool interop_match_dynamic_(const interop_feature_t feature,
    148                                    const RawAddress* addr) {
    149   if (interop_list == NULL || list_length(interop_list) == 0) return false;
    150 
    151   const list_node_t* node = list_begin(interop_list);
    152   while (node != list_end(interop_list)) {
    153     interop_addr_entry_t* entry =
    154         static_cast<interop_addr_entry_t*>(list_node(node));
    155     CHECK(entry);
    156 
    157     if (feature == entry->feature &&
    158         memcmp(addr, &entry->addr, entry->length) == 0)
    159       return true;
    160 
    161     node = list_next(node);
    162   }
    163   return false;
    164 }
    165 
    166 static bool interop_match_fixed_(const interop_feature_t feature,
    167                                  const RawAddress* addr) {
    168   CHECK(addr);
    169 
    170   const size_t db_size =
    171       sizeof(interop_addr_database) / sizeof(interop_addr_entry_t);
    172   for (size_t i = 0; i != db_size; ++i) {
    173     if (feature == interop_addr_database[i].feature &&
    174         memcmp(addr, &interop_addr_database[i].addr,
    175                interop_addr_database[i].length) == 0) {
    176       return true;
    177     }
    178   }
    179 
    180   return false;
    181 }
    182