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