Home | History | Annotate | Download | only in classic
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014 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_classic_peer"
     20 
     21 #include "device/include/classic/peer.h"
     22 
     23 #include <assert.h>
     24 #include <cutils/log.h>
     25 #include <pthread.h>
     26 #include <stdbool.h>
     27 
     28 #include "btcore/include/module.h"
     29 #include "osi/include/allocator.h"
     30 #include "osi/include/future.h"
     31 #include "osi/include/hash_map.h"
     32 #include "osi/include/osi.h"
     33 
     34 struct classic_peer_t {
     35   bt_bdaddr_t address;
     36 };
     37 
     38 static const size_t number_of_address_buckets = 42;
     39 
     40 static bool initialized;
     41 static pthread_mutex_t bag_of_peers_lock;
     42 static hash_map_t *peers_by_address;
     43 
     44 static bool bdaddr_equality_fn(const void *x, const void *y);
     45 
     46 // Module lifecycle functions
     47 
     48 static future_t *init(void) {
     49   peers_by_address = hash_map_new(
     50     number_of_address_buckets,
     51     hash_function_bdaddr,
     52     NULL,
     53     osi_free,
     54     bdaddr_equality_fn);
     55 
     56   pthread_mutex_init(&bag_of_peers_lock, NULL);
     57 
     58   initialized = true;
     59   return NULL;
     60 }
     61 
     62 static future_t *clean_up(void) {
     63   initialized = false;
     64 
     65   hash_map_free(peers_by_address);
     66   peers_by_address = NULL;
     67 
     68   pthread_mutex_destroy(&bag_of_peers_lock);
     69   return NULL;
     70 }
     71 
     72 EXPORT_SYMBOL const module_t classic_peer_module = {
     73   .name = CLASSIC_PEER_MODULE,
     74   .init = init,
     75   .start_up = NULL,
     76   .shut_down = NULL,
     77   .clean_up = clean_up,
     78   .dependencies = {
     79     NULL
     80   }
     81 };
     82 
     83 // Interface functions
     84 
     85 classic_peer_t *classic_peer_by_address(bt_bdaddr_t *address) {
     86   assert(initialized);
     87   assert(address != NULL);
     88 
     89   classic_peer_t *peer = hash_map_get(peers_by_address, address);
     90 
     91   if (!peer) {
     92     pthread_mutex_lock(&bag_of_peers_lock);
     93 
     94     // Make sure it didn't get added in the meantime
     95     peer = hash_map_get(peers_by_address, address);
     96     if (peer)
     97       goto done;
     98 
     99     // Splice in a new peer struct on behalf of the caller.
    100     peer = osi_calloc(sizeof(classic_peer_t));
    101     peer->address = *address;
    102     hash_map_set(peers_by_address, &peer->address, peer);
    103 
    104     pthread_mutex_unlock(&bag_of_peers_lock);
    105   }
    106 
    107 done:
    108   return peer;
    109 }
    110 
    111 const bt_bdaddr_t *classic_peer_get_address(classic_peer_t *peer) {
    112   assert(peer != NULL);
    113   return &peer->address;
    114 }
    115 
    116 // Internal functions
    117 
    118 // Wrapper for bdaddr_equals used in the hash map of peers by address
    119 static bool bdaddr_equality_fn(const void *x, const void *y) {
    120   return bdaddr_equals((bt_bdaddr_t *)x, (bt_bdaddr_t *)y);
    121 }
    122