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