• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
init(void)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 
clean_up(void)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 
classic_peer_by_address(bt_bdaddr_t * address)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 
classic_peer_get_address(classic_peer_t * peer)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
bdaddr_equality_fn(const void * x,const void * y)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