1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdint>
#include "osi/include/log.h"
#include "stack/btm/btm_ble_int.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_sec.h"
#include "stack/gatt/connection_manager.h"
#include "stack/include/acl_api.h"
#include "stack/include/bt_types.h"
#include "stack/include/l2cap_hci_link_interface.h"
#include "types/raw_address.h"
extern tBTM_CB btm_cb;
void btm_ble_advertiser_notify_terminated_legacy(uint8_t status,
uint16_t connection_handle);
void btm_ble_increment_link_topology_mask(uint8_t link_role);
bool maybe_resolve_address(RawAddress* bda, tBLE_ADDR_TYPE* bda_type);
static bool acl_ble_common_connection(const tBLE_BD_ADDR& address_with_type,
uint16_t handle, tHCI_ROLE role,
bool is_in_security_db,
uint16_t conn_interval,
uint16_t conn_latency,
uint16_t conn_timeout) {
if (role == HCI_ROLE_CENTRAL) {
btm_cb.ble_ctr_cb.set_connection_state_idle();
btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
}
// Inform any applications that a connection has completed.
connection_manager::on_connection_complete(address_with_type.bda);
// Allocate or update the security device record for this device
btm_ble_connected(address_with_type.bda, handle, HCI_ENCRYPT_MODE_DISABLED,
role, address_with_type.type, is_in_security_db);
// Update the link topology information for our device
btm_ble_increment_link_topology_mask(role);
// Inform l2cap of a potential connection.
if (!l2cble_conn_comp(handle, role, address_with_type.bda,
address_with_type.type, conn_interval, conn_latency,
conn_timeout)) {
btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION,
"stack::acl::ble_acl fail");
LOG_WARN("Unable to complete l2cap connection");
return false;
}
/* Tell BTM Acl management about the link */
btm_acl_created(address_with_type.bda, handle, role, BT_TRANSPORT_LE);
return true;
}
void acl_ble_connection_complete(const tBLE_BD_ADDR& address_with_type,
uint16_t handle, tHCI_ROLE role, bool match,
uint16_t conn_interval, uint16_t conn_latency,
uint16_t conn_timeout) {
if (!acl_ble_common_connection(address_with_type, handle, role, match,
conn_interval, conn_latency, conn_timeout)) {
LOG_WARN("Unable to create non enhanced ble acl connection");
return;
}
btm_ble_update_mode_operation(role, &address_with_type.bda, HCI_SUCCESS);
if (role == HCI_ROLE_PERIPHERAL)
btm_ble_advertiser_notify_terminated_legacy(HCI_SUCCESS, handle);
}
void acl_ble_enhanced_connection_complete(
const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
bool match, uint16_t conn_interval, uint16_t conn_latency,
uint16_t conn_timeout, const RawAddress& local_rpa,
const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type) {
if (!acl_ble_common_connection(address_with_type, handle, role, match,
conn_interval, conn_latency, conn_timeout)) {
LOG_WARN("Unable to create enhanced ble acl connection");
return;
}
btm_ble_refresh_local_resolvable_private_addr(address_with_type.bda,
local_rpa);
if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
btm_ble_refresh_peer_resolvable_private_addr(
address_with_type.bda, peer_rpa, tBTM_SEC_BLE::BTM_BLE_ADDR_RRA);
btm_ble_update_mode_operation(role, &address_with_type.bda, HCI_SUCCESS);
if (role == HCI_ROLE_PERIPHERAL)
btm_ble_advertiser_notify_terminated_legacy(HCI_SUCCESS, handle);
}
static bool maybe_resolve_received_address(
const tBLE_BD_ADDR& address_with_type,
tBLE_BD_ADDR* resolved_address_with_type) {
ASSERT(resolved_address_with_type != nullptr);
*resolved_address_with_type = address_with_type;
return maybe_resolve_address(&resolved_address_with_type->bda,
&resolved_address_with_type->type);
}
void acl_ble_enhanced_connection_complete_from_shim(
const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout,
const RawAddress& local_rpa, const RawAddress& peer_rpa,
tBLE_ADDR_TYPE peer_addr_type) {
if (!connection_manager::remove_unconditional_from_shim(
address_with_type.bda)) {
LOG_WARN(
"Unable to remove from legacy connection manager accept list addr:%s",
PRIVATE_ADDRESS(address_with_type.bda));
}
tBLE_BD_ADDR resolved_address_with_type;
const bool is_in_security_db = maybe_resolve_received_address(
address_with_type, &resolved_address_with_type);
acl_ble_enhanced_connection_complete(resolved_address_with_type, handle, role,
is_in_security_db, conn_interval,
conn_latency, conn_timeout, local_rpa,
peer_rpa, peer_addr_type);
// The legacy stack continues the LE connection after the read remote version
// complete has been received.
// maybe_chain_more_commands_after_read_remote_version_complete
}
void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type,
uint16_t handle, bool enhanced,
tHCI_STATUS status) {
if (status != HCI_ERR_ADVERTISING_TIMEOUT) {
btm_cb.ble_ctr_cb.set_connection_state_idle();
btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
connection_manager::on_connection_timed_out_from_shim(
address_with_type.bda);
} else {
btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
}
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, &address_with_type.bda,
status);
}
void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval,
uint16_t latency, uint16_t timeout,
tHCI_STATUS status);
void acl_ble_update_event_received(tHCI_STATUS status, uint16_t handle,
uint16_t interval, uint16_t latency,
uint16_t timeout) {
l2cble_process_conn_update_evt(handle, status, interval, latency, timeout);
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);
if (!p_dev_rec) return;
gatt_notify_conn_update(p_dev_rec->ble.pseudo_addr, interval, latency,
timeout, status);
}
void acl_ble_data_length_change_event(uint16_t handle, uint16_t max_tx_octets,
uint16_t max_tx_time,
uint16_t max_rx_octets,
uint16_t max_rx_time) {
LOG_DEBUG(
"Data length change event received handle:0x%04x max_tx_octets:%hu "
"max_tx_time:%hu max_rx_octets:%hu max_rx_time:%hu",
handle, max_tx_octets, max_tx_time, max_rx_octets, max_rx_time);
l2cble_process_data_length_change_event(handle, max_tx_octets, max_rx_octets);
}
|