The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * Copyright (C) 1999-2012 Broadcom Corporation |
| 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 | /****************************************************************************** |
| 20 | * |
| 21 | * this file contains the functions relating to link management. A "link" |
| 22 | * is a connection between this device and another device. Only ACL links |
| 23 | * are managed. |
| 24 | * |
| 25 | ******************************************************************************/ |
| 26 | |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 27 | #include <base/logging.h> |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 28 | #include <stdio.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 29 | #include <stdlib.h> |
| 30 | #include <string.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 31 | |
Pavlin Radoslavov | 258c253 | 2015-09-27 20:59:05 -0700 | [diff] [blame] | 32 | #include "bt_common.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 33 | #include "bt_types.h" |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 34 | #include "bt_utils.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 35 | #include "btm_api.h" |
| 36 | #include "btm_int.h" |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 37 | #include "btu.h" |
| 38 | #include "device/include/controller.h" |
| 39 | #include "hcimsgs.h" |
| 40 | #include "l2c_api.h" |
| 41 | #include "l2c_int.h" |
| 42 | #include "l2cdefs.h" |
Myles Watson | d7ffd64 | 2016-10-27 10:27:36 -0700 | [diff] [blame] | 43 | #include "osi/include/osi.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 44 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 45 | extern fixed_queue_t* btu_general_alarm_queue; |
Pavlin Radoslavov | 78bcff7 | 2015-12-04 17:36:34 -0800 | [diff] [blame] | 46 | |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 47 | static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, |
| 48 | tL2C_TX_COMPLETE_CB_INFO* p_cbi); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 49 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 50 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 51 | * |
| 52 | * Function l2c_link_hci_conn_req |
| 53 | * |
| 54 | * Description This function is called when an HCI Connection Request |
| 55 | * event is received. |
| 56 | * |
| 57 | * Returns true, if accept conn |
| 58 | * |
| 59 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 60 | bool l2c_link_hci_conn_req(const RawAddress& bd_addr) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 61 | tL2C_LCB* p_lcb; |
| 62 | tL2C_LCB* p_lcb_cur; |
| 63 | int xx; |
| 64 | bool no_links; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 65 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 66 | /* See if we have a link control block for the remote device */ |
| 67 | p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 68 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 69 | /* If we don't have one, create one and accept the connection. */ |
| 70 | if (!p_lcb) { |
| 71 | p_lcb = l2cu_allocate_lcb(bd_addr, false, BT_TRANSPORT_BR_EDR); |
| 72 | if (!p_lcb) { |
| 73 | btsnd_hcic_reject_conn(bd_addr, HCI_ERR_HOST_REJECT_RESOURCES); |
| 74 | L2CAP_TRACE_ERROR("L2CAP failed to allocate LCB"); |
| 75 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 76 | } |
| 77 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 78 | no_links = true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 79 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 80 | /* If we already have connection, accept as a master */ |
| 81 | for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; |
| 82 | xx++, p_lcb_cur++) { |
| 83 | if (p_lcb_cur == p_lcb) continue; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 84 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 85 | if (p_lcb_cur->in_use) { |
| 86 | no_links = false; |
| 87 | p_lcb->link_role = HCI_ROLE_MASTER; |
| 88 | break; |
| 89 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 90 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 91 | |
| 92 | if (no_links) { |
| 93 | if (!btm_dev_support_switch(bd_addr)) |
| 94 | p_lcb->link_role = HCI_ROLE_SLAVE; |
| 95 | else |
| 96 | p_lcb->link_role = l2cu_get_conn_role(p_lcb); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 97 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 98 | |
| 99 | /* Tell the other side we accept the connection */ |
Jakub Pawlowski | b8a477e | 2017-06-16 15:16:15 -0700 | [diff] [blame] | 100 | btsnd_hcic_accept_conn(bd_addr, p_lcb->link_role); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 101 | |
| 102 | p_lcb->link_state = LST_CONNECTING; |
| 103 | |
| 104 | /* Start a timer waiting for connect complete */ |
| 105 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS, |
| 106 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 107 | return (true); |
| 108 | } |
| 109 | |
| 110 | /* We already had a link control block to the guy. Check what state it is in |
| 111 | */ |
| 112 | if ((p_lcb->link_state == LST_CONNECTING) || |
| 113 | (p_lcb->link_state == LST_CONNECT_HOLDING)) { |
| 114 | /* Connection collision. Accept the connection anyways. */ |
| 115 | |
| 116 | if (!btm_dev_support_switch(bd_addr)) |
| 117 | p_lcb->link_role = HCI_ROLE_SLAVE; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 118 | else |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 119 | p_lcb->link_role = l2cu_get_conn_role(p_lcb); |
| 120 | |
Jakub Pawlowski | b8a477e | 2017-06-16 15:16:15 -0700 | [diff] [blame] | 121 | btsnd_hcic_accept_conn(bd_addr, p_lcb->link_role); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 122 | |
| 123 | p_lcb->link_state = LST_CONNECTING; |
| 124 | return (true); |
| 125 | } else if (p_lcb->link_state == LST_DISCONNECTING) { |
| 126 | /* In disconnecting state, reject the connection. */ |
| 127 | btsnd_hcic_reject_conn(bd_addr, HCI_ERR_HOST_REJECT_DEVICE); |
| 128 | } else { |
| 129 | L2CAP_TRACE_ERROR( |
| 130 | "L2CAP got conn_req while connected (state:%d). Reject it", |
| 131 | p_lcb->link_state); |
| 132 | /* Reject the connection with ACL Connection Already exist reason */ |
| 133 | btsnd_hcic_reject_conn(bd_addr, HCI_ERR_CONNECTION_EXISTS); |
| 134 | } |
| 135 | return (false); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 139 | * |
| 140 | * Function l2c_link_hci_conn_comp |
| 141 | * |
| 142 | * Description This function is called when an HCI Connection Complete |
| 143 | * event is received. |
| 144 | * |
| 145 | * Returns void |
| 146 | * |
| 147 | ******************************************************************************/ |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 148 | bool l2c_link_hci_conn_comp(uint8_t status, uint16_t handle, |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 149 | const RawAddress& p_bda) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 150 | tL2C_CONN_INFO ci; |
| 151 | tL2C_LCB* p_lcb; |
| 152 | tL2C_CCB* p_ccb; |
| 153 | tBTM_SEC_DEV_REC* p_dev_info = NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 154 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 155 | btm_acl_update_busy_level(BTM_BLI_PAGE_DONE_EVT); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 156 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 157 | /* Save the parameters */ |
| 158 | ci.status = status; |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 159 | ci.bd_addr = p_bda; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 160 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 161 | /* See if we have a link control block for the remote device */ |
| 162 | p_lcb = l2cu_find_lcb_by_bd_addr(ci.bd_addr, BT_TRANSPORT_BR_EDR); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 163 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 164 | /* If we don't have one, this is an error */ |
| 165 | if (!p_lcb) { |
| 166 | L2CAP_TRACE_WARNING("L2CAP got conn_comp for unknown BD_ADDR"); |
| 167 | return (false); |
| 168 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 169 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 170 | if (p_lcb->link_state != LST_CONNECTING) { |
| 171 | L2CAP_TRACE_ERROR("L2CAP got conn_comp in bad state: %d status: 0x%d", |
| 172 | p_lcb->link_state, status); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 173 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 174 | if (status != HCI_SUCCESS) l2c_link_hci_disc_comp(p_lcb->handle, status); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 175 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 176 | return (false); |
| 177 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 178 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 179 | /* Save the handle */ |
| 180 | p_lcb->handle = handle; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 181 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 182 | if (ci.status == HCI_SUCCESS) { |
| 183 | /* Connected OK. Change state to connected */ |
| 184 | p_lcb->link_state = LST_CONNECTED; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 185 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 186 | /* Get the peer information if the l2cap flow-control/rtrans is supported */ |
| 187 | l2cu_send_peer_info_req(p_lcb, L2CAP_EXTENDED_FEATURES_INFO_TYPE); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 188 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 189 | /* Tell BTM Acl management about the link */ |
| 190 | p_dev_info = btm_find_dev(p_bda); |
| 191 | if (p_dev_info != NULL) |
| 192 | btm_acl_created(ci.bd_addr, p_dev_info->dev_class, |
| 193 | p_dev_info->sec_bd_name, handle, p_lcb->link_role, |
| 194 | BT_TRANSPORT_BR_EDR); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 195 | else |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 196 | btm_acl_created(ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, |
| 197 | BT_TRANSPORT_BR_EDR); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 198 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 199 | BTM_SetLinkSuperTout(ci.bd_addr, btm_cb.btm_def_link_super_tout); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 200 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 201 | /* If dedicated bonding do not process any further */ |
| 202 | if (p_lcb->is_bonding) { |
| 203 | if (l2cu_start_post_bond_timer(handle)) return (true); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 204 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 205 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 206 | /* Update the timeouts in the hold queue */ |
| 207 | l2c_process_held_packets(false); |
| 208 | |
| 209 | alarm_cancel(p_lcb->l2c_lcb_timer); |
| 210 | |
| 211 | /* For all channels, send the event through their FSMs */ |
| 212 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; |
| 213 | p_ccb = p_ccb->p_next_ccb) { |
| 214 | l2c_csm_execute(p_ccb, L2CEVT_LP_CONNECT_CFM, &ci); |
| 215 | } |
| 216 | |
| 217 | if (p_lcb->p_echo_rsp_cb) { |
| 218 | l2cu_send_peer_echo_req(p_lcb, NULL, 0); |
| 219 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_ECHO_RSP_TIMEOUT_MS, |
| 220 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 221 | } else if (!p_lcb->ccb_queue.p_first_ccb) { |
| 222 | period_ms_t timeout_ms = L2CAP_LINK_STARTUP_TOUT * 1000; |
| 223 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, |
| 224 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 225 | } |
| 226 | } |
| 227 | /* Max number of acl connections. */ |
| 228 | /* If there's an lcb disconnecting set this one to holding */ |
| 229 | else if ((ci.status == HCI_ERR_MAX_NUM_OF_CONNECTIONS) && |
| 230 | l2cu_lcb_disconnecting()) { |
| 231 | p_lcb->link_state = LST_CONNECT_HOLDING; |
| 232 | p_lcb->handle = HCI_INVALID_HANDLE; |
| 233 | } else { |
| 234 | /* Just in case app decides to try again in the callback context */ |
| 235 | p_lcb->link_state = LST_DISCONNECTING; |
| 236 | |
| 237 | /* Connection failed. For all channels, send the event through */ |
| 238 | /* their FSMs. The CCBs should remove themselves from the LCB */ |
| 239 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) { |
| 240 | tL2C_CCB* pn = p_ccb->p_next_ccb; |
| 241 | |
| 242 | l2c_csm_execute(p_ccb, L2CEVT_LP_CONNECT_CFM_NEG, &ci); |
| 243 | |
| 244 | p_ccb = pn; |
| 245 | } |
| 246 | |
| 247 | p_lcb->disc_reason = status; |
| 248 | /* Release the LCB */ |
| 249 | if (p_lcb->ccb_queue.p_first_ccb == NULL) |
| 250 | l2cu_release_lcb(p_lcb); |
| 251 | else /* there are any CCBs remaining */ |
| 252 | { |
| 253 | if (ci.status == HCI_ERR_CONNECTION_EXISTS) { |
| 254 | /* we are in collision situation, wait for connecttion request from |
| 255 | * controller */ |
| 256 | p_lcb->link_state = LST_CONNECTING; |
| 257 | } else { |
| 258 | l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR); |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | return (true); |
| 263 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 264 | |
| 265 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 266 | * |
| 267 | * Function l2c_link_sec_comp |
| 268 | * |
| 269 | * Description This function is called when required security procedures |
| 270 | * are completed. |
| 271 | * |
| 272 | * Returns void |
| 273 | * |
| 274 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 275 | void l2c_link_sec_comp(const RawAddress* p_bda, |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 276 | UNUSED_ATTR tBT_TRANSPORT transport, void* p_ref_data, |
| 277 | uint8_t status) { |
| 278 | l2c_link_sec_comp2(*p_bda, transport, p_ref_data, status); |
| 279 | } |
| 280 | |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 281 | void l2c_link_sec_comp2(const RawAddress& p_bda, |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 282 | UNUSED_ATTR tBT_TRANSPORT transport, void* p_ref_data, |
| 283 | uint8_t status) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 284 | tL2C_CONN_INFO ci; |
| 285 | tL2C_LCB* p_lcb; |
| 286 | tL2C_CCB* p_ccb; |
| 287 | tL2C_CCB* p_next_ccb; |
| 288 | uint8_t event; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 289 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 290 | L2CAP_TRACE_DEBUG("l2c_link_sec_comp: %d, 0x%x", status, p_ref_data); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 291 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 292 | if (status == BTM_SUCCESS_NO_SECURITY) status = BTM_SUCCESS; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 293 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 294 | /* Save the parameters */ |
| 295 | ci.status = status; |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 296 | ci.bd_addr = p_bda; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 297 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 298 | p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, transport); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 299 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 300 | /* If we don't have one, this is an error */ |
| 301 | if (!p_lcb) { |
| 302 | L2CAP_TRACE_WARNING("L2CAP got sec_comp for unknown BD_ADDR"); |
| 303 | return; |
| 304 | } |
| 305 | |
| 306 | /* Match p_ccb with p_ref_data returned by sec manager */ |
| 307 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) { |
| 308 | p_next_ccb = p_ccb->p_next_ccb; |
| 309 | |
| 310 | if (p_ccb == p_ref_data) { |
| 311 | switch (status) { |
| 312 | case BTM_SUCCESS: |
| 313 | event = L2CEVT_SEC_COMP; |
| 314 | break; |
| 315 | |
| 316 | case BTM_DELAY_CHECK: |
| 317 | /* start a timer - encryption change not received before L2CAP connect |
| 318 | * req */ |
| 319 | alarm_set_on_queue( |
| 320 | p_ccb->l2c_ccb_timer, L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS, |
| 321 | l2c_ccb_timer_timeout, p_ccb, btu_general_alarm_queue); |
| 322 | return; |
| 323 | |
| 324 | default: |
| 325 | event = L2CEVT_SEC_COMP_NEG; |
| 326 | } |
| 327 | l2c_csm_execute(p_ccb, event, &ci); |
| 328 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 329 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 330 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 331 | } |
| 332 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 333 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 334 | * |
| 335 | * Function l2c_link_hci_disc_comp |
| 336 | * |
| 337 | * Description This function is called when an HCI Disconnect Complete |
| 338 | * event is received. |
| 339 | * |
| 340 | * Returns true if the link is known about, else false |
| 341 | * |
| 342 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 343 | bool l2c_link_hci_disc_comp(uint16_t handle, uint8_t reason) { |
| 344 | tL2C_LCB* p_lcb; |
| 345 | tL2C_CCB* p_ccb; |
| 346 | bool status = true; |
| 347 | bool lcb_is_free = true; |
| 348 | tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 349 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 350 | /* See if we have a link control block for the connection */ |
| 351 | p_lcb = l2cu_find_lcb_by_handle(handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 352 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 353 | /* If we don't have one, maybe an SCO link. Send to MM */ |
| 354 | if (!p_lcb) { |
| 355 | status = false; |
| 356 | } else { |
| 357 | /* There can be a case when we rejected PIN code authentication */ |
| 358 | /* otherwise save a new reason */ |
| 359 | if (btm_cb.acl_disc_reason != HCI_ERR_HOST_REJECT_SECURITY) |
| 360 | btm_cb.acl_disc_reason = reason; |
| 361 | |
| 362 | p_lcb->disc_reason = btm_cb.acl_disc_reason; |
| 363 | |
| 364 | /* Just in case app decides to try again in the callback context */ |
| 365 | p_lcb->link_state = LST_DISCONNECTING; |
| 366 | |
| 367 | /* Check for BLE and handle that differently */ |
| 368 | if (p_lcb->transport == BT_TRANSPORT_LE) |
| 369 | btm_ble_update_link_topology_mask(p_lcb->link_role, false); |
| 370 | /* Link is disconnected. For all channels, send the event through */ |
| 371 | /* their FSMs. The CCBs should remove themselves from the LCB */ |
| 372 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) { |
| 373 | tL2C_CCB* pn = p_ccb->p_next_ccb; |
| 374 | |
| 375 | /* Keep connect pending control block (if exists) |
| 376 | * Possible Race condition when a reconnect occurs |
| 377 | * on the channel during a disconnect of link. This |
| 378 | * ccb will be automatically retried after link disconnect |
| 379 | * arrives |
| 380 | */ |
| 381 | if (p_ccb != p_lcb->p_pending_ccb) { |
| 382 | l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, &reason); |
| 383 | } |
| 384 | p_ccb = pn; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 385 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 386 | |
Ganesh Ganapathi Batta | 8fe5887 | 2014-04-16 16:50:09 -0700 | [diff] [blame] | 387 | #if (BTM_SCO_INCLUDED == TRUE) |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 388 | if (p_lcb->transport == BT_TRANSPORT_BR_EDR) |
| 389 | /* Tell SCO management to drop any SCOs on this ACL */ |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 390 | btm_sco_acl_removed(&p_lcb->remote_bd_addr); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 391 | #endif |
| 392 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 393 | /* If waiting for disconnect and reconnect is pending start the reconnect |
| 394 | now |
| 395 | race condition where layer above issued connect request on link that was |
| 396 | disconnecting |
| 397 | */ |
| 398 | if (p_lcb->ccb_queue.p_first_ccb != NULL || p_lcb->p_pending_ccb) { |
| 399 | L2CAP_TRACE_DEBUG( |
| 400 | "l2c_link_hci_disc_comp: Restarting pending ACL request"); |
| 401 | transport = p_lcb->transport; |
| 402 | /* for LE link, always drop and re-open to ensure to get LE remote feature |
| 403 | */ |
| 404 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 405 | l2cb.is_ble_connecting = false; |
| 406 | btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport); |
| 407 | /* Release any held buffers */ |
| 408 | BT_HDR* p_buf; |
| 409 | while (!list_is_empty(p_lcb->link_xmit_data_q)) { |
| 410 | p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q)); |
| 411 | list_remove(p_lcb->link_xmit_data_q, p_buf); |
| 412 | osi_free(p_buf); |
| 413 | } |
| 414 | } else { |
Pavlin Radoslavov | e34b0eb | 2016-05-16 17:14:03 -0700 | [diff] [blame] | 415 | #if (L2CAP_NUM_FIXED_CHNLS > 0) |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 416 | /* If we are going to re-use the LCB without dropping it, release all |
| 417 | fixed channels |
| 418 | here */ |
| 419 | int xx; |
| 420 | for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { |
| 421 | if (p_lcb->p_fixed_ccbs[xx] && |
| 422 | p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) { |
| 423 | (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)( |
| 424 | xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false, |
| 425 | p_lcb->disc_reason, p_lcb->transport); |
| 426 | if (p_lcb->p_fixed_ccbs[xx] == NULL) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 427 | L2CAP_TRACE_ERROR( |
| 428 | "%s: unexpected p_fixed_ccbs[%d] is NULL remote_bd_addr = %s " |
| 429 | "p_lcb = %p in_use = %d link_state = %d handle = %d " |
| 430 | "link_role = %d is_bonding = %d disc_reason = %d transport = " |
| 431 | "%d", |
Jakub Pawlowski | b707f44 | 2017-07-03 15:39:36 -0700 | [diff] [blame^] | 432 | __func__, xx, p_lcb->remote_bd_addr.ToString().c_str(), p_lcb, |
| 433 | p_lcb->in_use, p_lcb->link_state, p_lcb->handle, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 434 | p_lcb->link_role, p_lcb->is_bonding, p_lcb->disc_reason, |
| 435 | p_lcb->transport); |
| 436 | } |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 437 | CHECK(p_lcb->p_fixed_ccbs[xx] != NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 438 | l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 439 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 440 | p_lcb->p_fixed_ccbs[xx] = NULL; |
Prerepa Viswanadham | 7ae2515 | 2014-09-10 17:08:11 -0700 | [diff] [blame] | 441 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 442 | } |
Ganesh Ganapathi Batta | 8fe5887 | 2014-04-16 16:50:09 -0700 | [diff] [blame] | 443 | #endif |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 444 | } |
| 445 | if (l2cu_create_conn(p_lcb, transport)) |
| 446 | lcb_is_free = false; /* still using this lcb */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 447 | } |
| 448 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 449 | p_lcb->p_pending_ccb = NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 450 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 451 | /* Release the LCB */ |
| 452 | if (lcb_is_free) l2cu_release_lcb(p_lcb); |
| 453 | } |
| 454 | |
| 455 | /* Now that we have a free acl connection, see if any lcbs are pending */ |
| 456 | if (lcb_is_free && |
| 457 | ((p_lcb = l2cu_find_lcb_by_state(LST_CONNECT_HOLDING)) != NULL)) { |
| 458 | /* we found one-- create a connection */ |
| 459 | l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR); |
| 460 | } |
| 461 | |
| 462 | return status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 463 | } |
| 464 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 465 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 466 | * |
| 467 | * Function l2c_link_hci_qos_violation |
| 468 | * |
| 469 | * Description This function is called when an HCI QOS Violation |
| 470 | * event is received. |
| 471 | * |
| 472 | * Returns true if the link is known about, else false |
| 473 | * |
| 474 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 475 | bool l2c_link_hci_qos_violation(uint16_t handle) { |
| 476 | tL2C_LCB* p_lcb; |
| 477 | tL2C_CCB* p_ccb; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 478 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 479 | /* See if we have a link control block for the connection */ |
| 480 | p_lcb = l2cu_find_lcb_by_handle(handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 481 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 482 | /* If we don't have one, maybe an SCO link. */ |
| 483 | if (!p_lcb) return (false); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 484 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 485 | /* For all channels, tell the upper layer about it */ |
| 486 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) { |
| 487 | if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb) |
| 488 | l2c_csm_execute(p_ccb, L2CEVT_LP_QOS_VIOLATION_IND, NULL); |
| 489 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 490 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 491 | return (true); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 492 | } |
| 493 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 494 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 495 | * |
| 496 | * Function l2c_link_timeout |
| 497 | * |
| 498 | * Description This function is called when a link timer expires |
| 499 | * |
| 500 | * Returns void |
| 501 | * |
| 502 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 503 | void l2c_link_timeout(tL2C_LCB* p_lcb) { |
| 504 | tL2C_CCB* p_ccb; |
| 505 | tBTM_STATUS rc; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 506 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 507 | L2CAP_TRACE_EVENT( |
| 508 | "L2CAP - l2c_link_timeout() link state %d first CCB %p is_bonding:%d", |
| 509 | p_lcb->link_state, p_lcb->ccb_queue.p_first_ccb, p_lcb->is_bonding); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 510 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 511 | /* If link was connecting or disconnecting, clear all channels and drop the |
| 512 | * LCB */ |
| 513 | if ((p_lcb->link_state == LST_CONNECTING_WAIT_SWITCH) || |
| 514 | (p_lcb->link_state == LST_CONNECTING) || |
| 515 | (p_lcb->link_state == LST_CONNECT_HOLDING) || |
| 516 | (p_lcb->link_state == LST_DISCONNECTING)) { |
| 517 | p_lcb->p_pending_ccb = NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 518 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 519 | /* For all channels, send a disconnect indication event through */ |
| 520 | /* their FSMs. The CCBs should remove themselves from the LCB */ |
| 521 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) { |
| 522 | tL2C_CCB* pn = p_ccb->p_next_ccb; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 523 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 524 | l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, NULL); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 525 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 526 | p_ccb = pn; |
| 527 | } |
| 528 | if (p_lcb->link_state == LST_CONNECTING && l2cb.is_ble_connecting == true) { |
| 529 | L2CA_CancelBleConnectReq(l2cb.ble_connecting_bda); |
| 530 | } |
| 531 | /* Release the LCB */ |
| 532 | l2cu_release_lcb(p_lcb); |
| 533 | } |
| 534 | |
| 535 | /* If link is connected, check for inactivity timeout */ |
| 536 | if (p_lcb->link_state == LST_CONNECTED) { |
| 537 | /* Check for ping outstanding */ |
| 538 | if (p_lcb->p_echo_rsp_cb) { |
| 539 | tL2CA_ECHO_RSP_CB* p_cb = p_lcb->p_echo_rsp_cb; |
| 540 | |
| 541 | /* Zero out the callback in case app immediately calls us again */ |
| 542 | p_lcb->p_echo_rsp_cb = NULL; |
| 543 | |
| 544 | (*p_cb)(L2CAP_PING_RESULT_NO_RESP); |
| 545 | |
| 546 | L2CAP_TRACE_WARNING("L2CAP - ping timeout"); |
| 547 | |
| 548 | /* For all channels, send a disconnect indication event through */ |
| 549 | /* their FSMs. The CCBs should remove themselves from the LCB */ |
| 550 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) { |
| 551 | tL2C_CCB* pn = p_ccb->p_next_ccb; |
| 552 | |
| 553 | l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, NULL); |
| 554 | |
| 555 | p_ccb = pn; |
| 556 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 557 | } |
| 558 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 559 | /* If no channels in use, drop the link. */ |
| 560 | if (!p_lcb->ccb_queue.p_first_ccb) { |
| 561 | period_ms_t timeout_ms; |
| 562 | bool start_timeout = true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 563 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 564 | rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 565 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 566 | if (rc == BTM_CMD_STORED) { |
| 567 | /* Security Manager will take care of disconnecting, state will be |
| 568 | * updated at that time */ |
| 569 | start_timeout = false; |
| 570 | } else if (rc == BTM_CMD_STARTED) { |
| 571 | p_lcb->link_state = LST_DISCONNECTING; |
| 572 | timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS; |
| 573 | } else if (rc == BTM_SUCCESS) { |
| 574 | l2cu_process_fixed_disc_cback(p_lcb); |
| 575 | /* BTM SEC will make sure that link is release (probably after pairing |
| 576 | * is done) */ |
| 577 | p_lcb->link_state = LST_DISCONNECTING; |
| 578 | start_timeout = false; |
| 579 | } else if (rc == BTM_BUSY) { |
| 580 | /* BTM is still executing security process. Let lcb stay as connected */ |
| 581 | start_timeout = false; |
| 582 | } else if (p_lcb->is_bonding) { |
| 583 | btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER); |
| 584 | l2cu_process_fixed_disc_cback(p_lcb); |
| 585 | p_lcb->link_state = LST_DISCONNECTING; |
| 586 | timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS; |
| 587 | } else { |
| 588 | /* probably no buffer to send disconnect */ |
| 589 | timeout_ms = BT_1SEC_TIMEOUT_MS; |
| 590 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 591 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 592 | if (start_timeout) { |
| 593 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, |
| 594 | l2c_lcb_timer_timeout, p_lcb, |
| 595 | btu_general_alarm_queue); |
| 596 | } |
| 597 | } else { |
| 598 | /* Check in case we were flow controlled */ |
| 599 | l2c_link_check_send_pkts(p_lcb, NULL, NULL); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 600 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 601 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 602 | } |
| 603 | |
| 604 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 605 | * |
| 606 | * Function l2c_info_resp_timer_timeout |
| 607 | * |
| 608 | * Description This function is called when an info request times out |
| 609 | * |
| 610 | * Returns void |
| 611 | * |
| 612 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 613 | void l2c_info_resp_timer_timeout(void* data) { |
| 614 | tL2C_LCB* p_lcb = (tL2C_LCB*)data; |
| 615 | tL2C_CCB* p_ccb; |
| 616 | tL2C_CONN_INFO ci; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 617 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 618 | /* If we timed out waiting for info response, just continue using basic if |
| 619 | * allowed */ |
| 620 | if (p_lcb->w4_info_rsp) { |
| 621 | /* If waiting for security complete, restart the info response timer */ |
| 622 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; |
| 623 | p_ccb = p_ccb->p_next_ccb) { |
| 624 | if ((p_ccb->chnl_state == CST_ORIG_W4_SEC_COMP) || |
| 625 | (p_ccb->chnl_state == CST_TERM_W4_SEC_COMP)) { |
| 626 | alarm_set_on_queue( |
| 627 | p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS, |
| 628 | l2c_info_resp_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 629 | return; |
| 630 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 631 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 632 | |
| 633 | p_lcb->w4_info_rsp = false; |
| 634 | |
| 635 | /* If link is in process of being brought up */ |
| 636 | if ((p_lcb->link_state != LST_DISCONNECTED) && |
| 637 | (p_lcb->link_state != LST_DISCONNECTING)) { |
| 638 | /* Notify active channels that peer info is finished */ |
| 639 | if (p_lcb->ccb_queue.p_first_ccb) { |
| 640 | ci.status = HCI_SUCCESS; |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 641 | ci.bd_addr = p_lcb->remote_bd_addr; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 642 | |
| 643 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; |
| 644 | p_ccb = p_ccb->p_next_ccb) { |
| 645 | l2c_csm_execute(p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci); |
| 646 | } |
| 647 | } |
| 648 | } |
| 649 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 650 | } |
| 651 | |
| 652 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 653 | * |
| 654 | * Function l2c_link_adjust_allocation |
| 655 | * |
| 656 | * Description This function is called when a link is created or removed |
| 657 | * to calculate the amount of packets each link may send to |
| 658 | * the HCI without an ack coming back. |
| 659 | * |
| 660 | * Currently, this is a simple allocation, dividing the |
| 661 | * number of Controller Packets by the number of links. In |
| 662 | * the future, QOS configuration should be examined. |
| 663 | * |
| 664 | * Returns void |
| 665 | * |
| 666 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 667 | void l2c_link_adjust_allocation(void) { |
| 668 | uint16_t qq, yy, qq_remainder; |
| 669 | tL2C_LCB* p_lcb; |
| 670 | uint16_t hi_quota, low_quota; |
| 671 | uint16_t num_lowpri_links = 0; |
| 672 | uint16_t num_hipri_links = 0; |
| 673 | uint16_t controller_xmit_quota = l2cb.num_lm_acl_bufs; |
| 674 | uint16_t high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 675 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 676 | /* If no links active, reset buffer quotas and controller buffers */ |
| 677 | if (l2cb.num_links_active == 0) { |
| 678 | l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs; |
| 679 | l2cb.round_robin_quota = l2cb.round_robin_unacked = 0; |
| 680 | return; |
| 681 | } |
| 682 | |
| 683 | /* First, count the links */ |
| 684 | for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { |
| 685 | if (p_lcb->in_use) { |
| 686 | if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) |
| 687 | num_hipri_links++; |
| 688 | else |
| 689 | num_lowpri_links++; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 690 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 691 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 692 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 693 | /* now adjust high priority link quota */ |
| 694 | low_quota = num_lowpri_links ? 1 : 0; |
| 695 | while ((num_hipri_links * high_pri_link_quota + low_quota) > |
| 696 | controller_xmit_quota) |
| 697 | high_pri_link_quota--; |
| 698 | |
| 699 | /* Work out the xmit quota and buffer quota high and low priorities */ |
| 700 | hi_quota = num_hipri_links * high_pri_link_quota; |
| 701 | low_quota = |
| 702 | (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1; |
| 703 | |
| 704 | /* Work out and save the HCI xmit quota for each low priority link */ |
| 705 | |
| 706 | /* If each low priority link cannot have at least one buffer */ |
| 707 | if (num_lowpri_links > low_quota) { |
| 708 | l2cb.round_robin_quota = low_quota; |
| 709 | qq = qq_remainder = 1; |
| 710 | } |
| 711 | /* If each low priority link can have at least one buffer */ |
| 712 | else if (num_lowpri_links > 0) { |
| 713 | l2cb.round_robin_quota = 0; |
| 714 | l2cb.round_robin_unacked = 0; |
| 715 | qq = low_quota / num_lowpri_links; |
| 716 | qq_remainder = low_quota % num_lowpri_links; |
| 717 | } |
| 718 | /* If no low priority link */ |
| 719 | else { |
| 720 | l2cb.round_robin_quota = 0; |
| 721 | l2cb.round_robin_unacked = 0; |
| 722 | qq = qq_remainder = 1; |
| 723 | } |
| 724 | |
| 725 | L2CAP_TRACE_EVENT( |
| 726 | "l2c_link_adjust_allocation num_hipri: %u num_lowpri: %u low_quota: " |
| 727 | "%u round_robin_quota: %u qq: %u", |
| 728 | num_hipri_links, num_lowpri_links, low_quota, l2cb.round_robin_quota, qq); |
| 729 | |
| 730 | /* Now, assign the quotas to each link */ |
| 731 | for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { |
| 732 | if (p_lcb->in_use) { |
| 733 | if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) { |
| 734 | p_lcb->link_xmit_quota = high_pri_link_quota; |
| 735 | } else { |
| 736 | /* Safety check in case we switched to round-robin with something |
| 737 | * outstanding */ |
| 738 | /* if sent_not_acked is added into round_robin_unacked then don't add it |
| 739 | * again */ |
| 740 | /* l2cap keeps updating sent_not_acked for exiting from round robin */ |
| 741 | if ((p_lcb->link_xmit_quota > 0) && (qq == 0)) |
| 742 | l2cb.round_robin_unacked += p_lcb->sent_not_acked; |
| 743 | |
| 744 | p_lcb->link_xmit_quota = qq; |
| 745 | if (qq_remainder > 0) { |
| 746 | p_lcb->link_xmit_quota++; |
| 747 | qq_remainder--; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 748 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 749 | } |
| 750 | |
| 751 | L2CAP_TRACE_EVENT( |
| 752 | "l2c_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d", yy, |
| 753 | p_lcb->acl_priority, p_lcb->link_xmit_quota); |
| 754 | |
| 755 | L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d", |
| 756 | p_lcb->sent_not_acked, l2cb.round_robin_unacked); |
| 757 | |
| 758 | /* There is a special case where we have readjusted the link quotas and */ |
| 759 | /* this link may have sent anything but some other link sent packets so */ |
| 760 | /* so we may need a timer to kick off this link's transmissions. */ |
| 761 | if ((p_lcb->link_state == LST_CONNECTED) && |
| 762 | (!list_is_empty(p_lcb->link_xmit_data_q)) && |
| 763 | (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) { |
| 764 | alarm_set_on_queue( |
| 765 | p_lcb->l2c_lcb_timer, L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS, |
| 766 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 767 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 768 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 769 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 770 | } |
| 771 | |
| 772 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 773 | * |
| 774 | * Function l2c_link_adjust_chnl_allocation |
| 775 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 776 | * Description This function is called to calculate the amount of packets |
| 777 | * each non-F&EC channel may have outstanding. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 778 | * |
| 779 | * Currently, this is a simple allocation, dividing the number |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 780 | * of packets allocated to the link by the number of channels. |
| 781 | * In the future, QOS configuration should be examined. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 782 | * |
| 783 | * Returns void |
| 784 | * |
| 785 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 786 | void l2c_link_adjust_chnl_allocation(void) { |
| 787 | uint8_t xx; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 788 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 789 | L2CAP_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 790 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 791 | /* assign buffer quota to each channel based on its data rate requirement */ |
| 792 | for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) { |
| 793 | tL2C_CCB* p_ccb = l2cb.ccb_pool + xx; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 794 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 795 | if (!p_ccb->in_use) continue; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 796 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 797 | tL2CAP_CHNL_DATA_RATE data_rate = p_ccb->tx_data_rate + p_ccb->rx_data_rate; |
| 798 | p_ccb->buff_quota = L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA * data_rate; |
| 799 | L2CAP_TRACE_EVENT( |
| 800 | "CID:0x%04x FCR Mode:%u Priority:%u TxDataRate:%u RxDataRate:%u " |
| 801 | "Quota:%u", |
| 802 | p_ccb->local_cid, p_ccb->peer_cfg.fcr.mode, p_ccb->ccb_priority, |
| 803 | p_ccb->tx_data_rate, p_ccb->rx_data_rate, p_ccb->buff_quota); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 804 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 805 | /* quota may be change so check congestion */ |
| 806 | l2cu_check_channel_congestion(p_ccb); |
| 807 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 808 | } |
| 809 | |
| 810 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 811 | * |
| 812 | * Function l2c_link_processs_num_bufs |
| 813 | * |
| 814 | * Description This function is called when a "controller buffer size" |
| 815 | * event is first received from the controller. It updates |
| 816 | * the L2CAP values. |
| 817 | * |
| 818 | * Returns void |
| 819 | * |
| 820 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 821 | void l2c_link_processs_num_bufs(uint16_t num_lm_acl_bufs) { |
| 822 | l2cb.num_lm_acl_bufs = l2cb.controller_xmit_window = num_lm_acl_bufs; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 823 | } |
| 824 | |
| 825 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 826 | * |
| 827 | * Function l2c_link_pkts_rcvd |
| 828 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 829 | * Description This function is called from the HCI transport when it is |
| 830 | * time to send a "Host ready for packets" command. This is |
| 831 | * only when host to controller flow control is used. It fills |
| 832 | * in the arrays of numbers of packets and handles. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 833 | * |
| 834 | * Returns count of number of entries filled in |
| 835 | * |
| 836 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 837 | uint8_t l2c_link_pkts_rcvd(UNUSED_ATTR uint16_t* num_pkts, |
| 838 | UNUSED_ATTR uint16_t* handles) { |
| 839 | uint8_t num_found = 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 840 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 841 | return (num_found); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 842 | } |
| 843 | |
| 844 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 845 | * |
| 846 | * Function l2c_link_role_changed |
| 847 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 848 | * Description This function is called whan a link's master/slave role |
| 849 | * change event is received. It simply updates the link control |
| 850 | * block. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 851 | * |
| 852 | * Returns void |
| 853 | * |
| 854 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 855 | void l2c_link_role_changed(const RawAddress* bd_addr, uint8_t new_role, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 856 | uint8_t hci_status) { |
| 857 | tL2C_LCB* p_lcb; |
| 858 | int xx; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 859 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 860 | /* Make sure not called from HCI Command Status (bd_addr and new_role are |
| 861 | * invalid) */ |
| 862 | if (bd_addr) { |
| 863 | /* If here came form hci role change event */ |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 864 | p_lcb = l2cu_find_lcb_by_bd_addr(*bd_addr, BT_TRANSPORT_BR_EDR); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 865 | if (p_lcb) { |
| 866 | p_lcb->link_role = new_role; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 867 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 868 | /* Reset high priority link if needed */ |
| 869 | if (hci_status == HCI_SUCCESS) |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 870 | l2cu_set_acl_priority(*bd_addr, p_lcb->acl_priority, true); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 871 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 872 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 873 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 874 | /* Check if any LCB was waiting for switch to be completed */ |
| 875 | for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { |
| 876 | if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTING_WAIT_SWITCH)) { |
| 877 | l2cu_create_conn_after_switch(p_lcb); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 878 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 879 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 880 | } |
| 881 | |
| 882 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 883 | * |
| 884 | * Function l2c_pin_code_request |
| 885 | * |
| 886 | * Description This function is called whan a pin-code request is received |
| 887 | * on a connection. If there are no channels active yet on the |
| 888 | * link, it extends the link first connection timer. Make sure |
| 889 | * that inactivity timer is not extended if PIN code happens |
| 890 | * to be after last ccb released. |
| 891 | * |
| 892 | * Returns void |
| 893 | * |
| 894 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 895 | void l2c_pin_code_request(const RawAddress& bd_addr) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 896 | tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 897 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 898 | if ((p_lcb) && (!p_lcb->ccb_queue.p_first_ccb)) { |
| 899 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_EXT_TIMEOUT_MS, |
| 900 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 901 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 902 | } |
| 903 | |
Marie Janssen | d19e078 | 2016-07-15 12:48:27 -0700 | [diff] [blame] | 904 | #if (L2CAP_WAKE_PARKED_LINK == TRUE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 905 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 906 | * |
| 907 | * Function l2c_link_check_power_mode |
| 908 | * |
| 909 | * Description This function is called to check power mode. |
| 910 | * |
| 911 | * Returns true if link is going to be active from park |
| 912 | * false if nothing to send or not in park mode |
| 913 | * |
| 914 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 915 | bool l2c_link_check_power_mode(tL2C_LCB* p_lcb) { |
| 916 | tBTM_PM_MODE mode; |
| 917 | tL2C_CCB* p_ccb; |
| 918 | bool need_to_active = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 919 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 920 | /* |
| 921 | * We only switch park to active only if we have unsent packets |
| 922 | */ |
| 923 | if (list_is_empty(p_lcb->link_xmit_data_q)) { |
| 924 | for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; |
| 925 | p_ccb = p_ccb->p_next_ccb) { |
| 926 | if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) { |
Marie Janssen | d19e078 | 2016-07-15 12:48:27 -0700 | [diff] [blame] | 927 | need_to_active = true; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 928 | break; |
| 929 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 930 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 931 | } else |
| 932 | need_to_active = true; |
| 933 | |
| 934 | /* if we have packets to send */ |
| 935 | if (need_to_active) { |
| 936 | /* check power mode */ |
| 937 | if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode) == BTM_SUCCESS) { |
| 938 | if (mode == BTM_PM_STS_PENDING) { |
| 939 | L2CAP_TRACE_DEBUG("LCB(0x%x) is in PM pending state", p_lcb->handle); |
| 940 | |
| 941 | return true; |
| 942 | } |
| 943 | } |
| 944 | } |
| 945 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 946 | } |
Chris Manton | e7ef465 | 2014-10-15 16:31:49 -0700 | [diff] [blame] | 947 | #endif /* L2CAP_WAKE_PARKED_LINK == TRUE) */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 948 | |
| 949 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 950 | * |
| 951 | * Function l2c_link_check_send_pkts |
| 952 | * |
| 953 | * Description This function is called to check if it can send packets |
| 954 | * to the Host Controller. It may be passed the address of |
| 955 | * a packet to send. |
| 956 | * |
| 957 | * Returns void |
| 958 | * |
| 959 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 960 | void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) { |
| 961 | int xx; |
| 962 | bool single_write = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 963 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 964 | /* Save the channel ID for faster counting */ |
| 965 | if (p_buf) { |
| 966 | if (p_ccb != NULL) { |
| 967 | p_buf->event = p_ccb->local_cid; |
| 968 | single_write = true; |
| 969 | } else |
| 970 | p_buf->event = 0; |
| 971 | |
| 972 | p_buf->layer_specific = 0; |
| 973 | list_append(p_lcb->link_xmit_data_q, p_buf); |
| 974 | |
| 975 | if (p_lcb->link_xmit_quota == 0) { |
| 976 | if (p_lcb->transport == BT_TRANSPORT_LE) |
| 977 | l2cb.ble_check_round_robin = true; |
| 978 | else |
| 979 | l2cb.check_round_robin = true; |
| 980 | } |
| 981 | } |
| 982 | |
| 983 | /* If this is called from uncongested callback context break recursive |
| 984 | *calling. |
| 985 | ** This LCB will be served when receiving number of completed packet event. |
| 986 | */ |
| 987 | if (l2cb.is_cong_cback_context) return; |
| 988 | |
| 989 | /* If we are in a scenario where there are not enough buffers for each link to |
| 990 | ** have at least 1, then do a round-robin for all the LCBs |
| 991 | */ |
| 992 | if ((p_lcb == NULL) || (p_lcb->link_xmit_quota == 0)) { |
| 993 | if (p_lcb == NULL) |
| 994 | p_lcb = l2cb.lcb_pool; |
| 995 | else if (!single_write) |
| 996 | p_lcb++; |
| 997 | |
| 998 | /* Loop through, starting at the next */ |
| 999 | for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1000 | /* Check for wraparound */ |
| 1001 | if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS]) p_lcb = &l2cb.lcb_pool[0]; |
| 1002 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1003 | /* If controller window is full, nothing to do */ |
| 1004 | if (((l2cb.controller_xmit_window == 0 || |
| 1005 | (l2cb.round_robin_unacked >= l2cb.round_robin_quota)) && |
| 1006 | (p_lcb->transport == BT_TRANSPORT_BR_EDR)) || |
| 1007 | (p_lcb->transport == BT_TRANSPORT_LE && |
| 1008 | (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota || |
| 1009 | l2cb.controller_le_xmit_window == 0))) |
Ruina Liu | bd6b122 | 2015-09-24 10:04:16 +0800 | [diff] [blame] | 1010 | continue; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1011 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1012 | if ((!p_lcb->in_use) || (p_lcb->partial_segment_being_sent) || |
| 1013 | (p_lcb->link_state != LST_CONNECTED) || |
| 1014 | (p_lcb->link_xmit_quota != 0) || (L2C_LINK_CHECK_POWER_MODE(p_lcb))) |
| 1015 | continue; |
| 1016 | |
| 1017 | /* See if we can send anything from the Link Queue */ |
| 1018 | if (!list_is_empty(p_lcb->link_xmit_data_q)) { |
| 1019 | p_buf = (BT_HDR*)list_front(p_lcb->link_xmit_data_q); |
| 1020 | list_remove(p_lcb->link_xmit_data_q, p_buf); |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1021 | l2c_link_send_to_lower(p_lcb, p_buf, NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1022 | } else if (single_write) { |
| 1023 | /* If only doing one write, break out */ |
| 1024 | break; |
| 1025 | } |
| 1026 | /* If nothing on the link queue, check the channel queue */ |
| 1027 | else { |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1028 | tL2C_TX_COMPLETE_CB_INFO cbi; |
| 1029 | p_buf = l2cu_get_next_buffer_to_send(p_lcb, &cbi); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1030 | if (p_buf != NULL) { |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1031 | l2c_link_send_to_lower(p_lcb, p_buf, &cbi); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1032 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1033 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1034 | } |
| 1035 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1036 | /* If we finished without using up our quota, no need for a safety check */ |
| 1037 | if ((l2cb.controller_xmit_window > 0) && |
| 1038 | (l2cb.round_robin_unacked < l2cb.round_robin_quota) && |
| 1039 | (p_lcb->transport == BT_TRANSPORT_BR_EDR)) |
| 1040 | l2cb.check_round_robin = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1041 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1042 | if ((l2cb.controller_le_xmit_window > 0) && |
| 1043 | (l2cb.ble_round_robin_unacked < l2cb.ble_round_robin_quota) && |
| 1044 | (p_lcb->transport == BT_TRANSPORT_LE)) |
| 1045 | l2cb.ble_check_round_robin = false; |
| 1046 | } else /* if this is not round-robin service */ |
| 1047 | { |
| 1048 | /* If a partial segment is being sent, can't send anything else */ |
| 1049 | if ((p_lcb->partial_segment_being_sent) || |
| 1050 | (p_lcb->link_state != LST_CONNECTED) || |
| 1051 | (L2C_LINK_CHECK_POWER_MODE(p_lcb))) |
| 1052 | return; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1053 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1054 | /* See if we can send anything from the link queue */ |
| 1055 | while (((l2cb.controller_xmit_window != 0 && |
| 1056 | (p_lcb->transport == BT_TRANSPORT_BR_EDR)) || |
| 1057 | (l2cb.controller_le_xmit_window != 0 && |
| 1058 | (p_lcb->transport == BT_TRANSPORT_LE))) && |
| 1059 | (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) { |
| 1060 | if (list_is_empty(p_lcb->link_xmit_data_q)) break; |
Satya Calloji | 444a8da | 2015-03-06 10:38:22 -0800 | [diff] [blame] | 1061 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1062 | p_buf = (BT_HDR*)list_front(p_lcb->link_xmit_data_q); |
| 1063 | list_remove(p_lcb->link_xmit_data_q, p_buf); |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1064 | if (!l2c_link_send_to_lower(p_lcb, p_buf, NULL)) break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1065 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1066 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1067 | if (!single_write) { |
| 1068 | /* See if we can send anything for any channel */ |
| 1069 | while (((l2cb.controller_xmit_window != 0 && |
| 1070 | (p_lcb->transport == BT_TRANSPORT_BR_EDR)) || |
| 1071 | (l2cb.controller_le_xmit_window != 0 && |
| 1072 | (p_lcb->transport == BT_TRANSPORT_LE))) && |
| 1073 | (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) { |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1074 | tL2C_TX_COMPLETE_CB_INFO cbi; |
| 1075 | p_buf = l2cu_get_next_buffer_to_send(p_lcb, &cbi); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1076 | if (p_buf == NULL) break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1077 | |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1078 | if (!l2c_link_send_to_lower(p_lcb, p_buf, &cbi)) break; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1079 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1080 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1081 | |
| 1082 | /* There is a special case where we have readjusted the link quotas and */ |
| 1083 | /* this link may have sent anything but some other link sent packets so */ |
| 1084 | /* so we may need a timer to kick off this link's transmissions. */ |
| 1085 | if ((!list_is_empty(p_lcb->link_xmit_data_q)) && |
| 1086 | (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) { |
| 1087 | alarm_set_on_queue(p_lcb->l2c_lcb_timer, |
| 1088 | L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS, |
| 1089 | l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); |
| 1090 | } |
| 1091 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1092 | } |
| 1093 | |
| 1094 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1095 | * |
| 1096 | * Function l2c_link_send_to_lower |
| 1097 | * |
| 1098 | * Description This function queues the buffer for HCI transmission |
| 1099 | * |
| 1100 | * Returns true for success, false for fail |
| 1101 | * |
| 1102 | ******************************************************************************/ |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 1103 | static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, |
| 1104 | tL2C_TX_COMPLETE_CB_INFO* p_cbi) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1105 | uint16_t num_segs; |
| 1106 | uint16_t xmit_window, acl_data_size; |
| 1107 | const controller_t* controller = controller_get_interface(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1108 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1109 | if ((p_buf->len <= controller->get_acl_packet_size_classic() && |
| 1110 | (p_lcb->transport == BT_TRANSPORT_BR_EDR)) || |
| 1111 | ((p_lcb->transport == BT_TRANSPORT_LE) && |
| 1112 | (p_buf->len <= controller->get_acl_packet_size_ble()))) { |
| 1113 | if (p_lcb->link_xmit_quota == 0) { |
| 1114 | if (p_lcb->transport == BT_TRANSPORT_LE) |
| 1115 | l2cb.ble_round_robin_unacked++; |
| 1116 | else |
| 1117 | l2cb.round_robin_unacked++; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1118 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1119 | p_lcb->sent_not_acked++; |
| 1120 | p_buf->layer_specific = 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1121 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1122 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1123 | l2cb.controller_le_xmit_window--; |
| 1124 | bte_main_hci_send( |
| 1125 | p_buf, (uint16_t)(BT_EVT_TO_LM_HCI_ACL | LOCAL_BLE_CONTROLLER_ID)); |
| 1126 | } else { |
| 1127 | l2cb.controller_xmit_window--; |
| 1128 | bte_main_hci_send(p_buf, BT_EVT_TO_LM_HCI_ACL); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1129 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1130 | } else { |
| 1131 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1132 | acl_data_size = controller->get_acl_data_size_ble(); |
| 1133 | xmit_window = l2cb.controller_le_xmit_window; |
| 1134 | |
| 1135 | } else { |
| 1136 | acl_data_size = controller->get_acl_data_size_classic(); |
| 1137 | xmit_window = l2cb.controller_xmit_window; |
| 1138 | } |
| 1139 | num_segs = (p_buf->len - HCI_DATA_PREAMBLE_SIZE + acl_data_size - 1) / |
| 1140 | acl_data_size; |
| 1141 | |
| 1142 | /* If doing round-robin, then only 1 segment each time */ |
| 1143 | if (p_lcb->link_xmit_quota == 0) { |
| 1144 | num_segs = 1; |
| 1145 | p_lcb->partial_segment_being_sent = true; |
| 1146 | } else { |
| 1147 | /* Multi-segment packet. Make sure it can fit */ |
| 1148 | if (num_segs > xmit_window) { |
| 1149 | num_segs = xmit_window; |
| 1150 | p_lcb->partial_segment_being_sent = true; |
| 1151 | } |
| 1152 | |
| 1153 | if (num_segs > (p_lcb->link_xmit_quota - p_lcb->sent_not_acked)) { |
| 1154 | num_segs = (p_lcb->link_xmit_quota - p_lcb->sent_not_acked); |
| 1155 | p_lcb->partial_segment_being_sent = true; |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | p_buf->layer_specific = num_segs; |
| 1160 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1161 | l2cb.controller_le_xmit_window -= num_segs; |
| 1162 | if (p_lcb->link_xmit_quota == 0) l2cb.ble_round_robin_unacked += num_segs; |
| 1163 | } else { |
| 1164 | l2cb.controller_xmit_window -= num_segs; |
| 1165 | |
| 1166 | if (p_lcb->link_xmit_quota == 0) l2cb.round_robin_unacked += num_segs; |
| 1167 | } |
| 1168 | |
| 1169 | p_lcb->sent_not_acked += num_segs; |
| 1170 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1171 | bte_main_hci_send( |
| 1172 | p_buf, (uint16_t)(BT_EVT_TO_LM_HCI_ACL | LOCAL_BLE_CONTROLLER_ID)); |
| 1173 | } else { |
| 1174 | bte_main_hci_send(p_buf, BT_EVT_TO_LM_HCI_ACL); |
| 1175 | } |
| 1176 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1177 | |
| 1178 | #if (L2CAP_HCI_FLOW_CONTROL_DEBUG == TRUE) |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1179 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1180 | L2CAP_TRACE_DEBUG( |
| 1181 | "TotalWin=%d,Hndl=0x%x,Quota=%d,Unack=%d,RRQuota=%d,RRUnack=%d", |
| 1182 | l2cb.controller_le_xmit_window, p_lcb->handle, p_lcb->link_xmit_quota, |
| 1183 | p_lcb->sent_not_acked, l2cb.ble_round_robin_quota, |
| 1184 | l2cb.ble_round_robin_unacked); |
| 1185 | } else { |
| 1186 | L2CAP_TRACE_DEBUG( |
| 1187 | "TotalWin=%d,Hndl=0x%x,Quota=%d,Unack=%d,RRQuota=%d,RRUnack=%d", |
| 1188 | l2cb.controller_xmit_window, p_lcb->handle, p_lcb->link_xmit_quota, |
| 1189 | p_lcb->sent_not_acked, l2cb.round_robin_quota, |
| 1190 | l2cb.round_robin_unacked); |
| 1191 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1192 | #endif |
| 1193 | |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 1194 | if (p_cbi) l2cu_tx_complete(p_cbi); |
Yamei Du | 35e95c9 | 2015-11-18 17:28:07 +0800 | [diff] [blame] | 1195 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1196 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1197 | } |
| 1198 | |
| 1199 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1200 | * |
| 1201 | * Function l2c_link_process_num_completed_pkts |
| 1202 | * |
| 1203 | * Description This function is called when a "number-of-completed-packets" |
| 1204 | * event is received from the controller. It updates all the |
| 1205 | * LCB transmit counts. |
| 1206 | * |
| 1207 | * Returns void |
| 1208 | * |
| 1209 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1210 | void l2c_link_process_num_completed_pkts(uint8_t* p) { |
| 1211 | uint8_t num_handles, xx; |
| 1212 | uint16_t handle; |
| 1213 | uint16_t num_sent; |
| 1214 | tL2C_LCB* p_lcb; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1215 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1216 | STREAM_TO_UINT8(num_handles, p); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1217 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1218 | for (xx = 0; xx < num_handles; xx++) { |
| 1219 | STREAM_TO_UINT16(handle, p); |
| 1220 | STREAM_TO_UINT16(num_sent, p); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1221 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1222 | p_lcb = l2cu_find_lcb_by_handle(handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1223 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1224 | /* Callback for number of completed packet event */ |
| 1225 | /* Originally designed for [3DSG] */ |
| 1226 | if ((p_lcb != NULL) && (p_lcb->p_nocp_cb)) { |
| 1227 | L2CAP_TRACE_DEBUG("L2CAP - calling NoCP callback"); |
| 1228 | (*p_lcb->p_nocp_cb)(p_lcb->remote_bd_addr); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1229 | } |
| 1230 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1231 | if (p_lcb) { |
| 1232 | if (p_lcb && (p_lcb->transport == BT_TRANSPORT_LE)) |
| 1233 | l2cb.controller_le_xmit_window += num_sent; |
| 1234 | else { |
| 1235 | /* Maintain the total window to the controller */ |
| 1236 | l2cb.controller_xmit_window += num_sent; |
| 1237 | } |
| 1238 | /* If doing round-robin, adjust communal counts */ |
| 1239 | if (p_lcb->link_xmit_quota == 0) { |
| 1240 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1241 | /* Don't go negative */ |
| 1242 | if (l2cb.ble_round_robin_unacked > num_sent) |
| 1243 | l2cb.ble_round_robin_unacked -= num_sent; |
| 1244 | else |
| 1245 | l2cb.ble_round_robin_unacked = 0; |
| 1246 | } else { |
| 1247 | /* Don't go negative */ |
| 1248 | if (l2cb.round_robin_unacked > num_sent) |
| 1249 | l2cb.round_robin_unacked -= num_sent; |
| 1250 | else |
| 1251 | l2cb.round_robin_unacked = 0; |
| 1252 | } |
| 1253 | } |
| 1254 | |
| 1255 | /* Don't go negative */ |
| 1256 | if (p_lcb->sent_not_acked > num_sent) |
| 1257 | p_lcb->sent_not_acked -= num_sent; |
| 1258 | else |
| 1259 | p_lcb->sent_not_acked = 0; |
| 1260 | |
| 1261 | l2c_link_check_send_pkts(p_lcb, NULL, NULL); |
| 1262 | |
| 1263 | /* If we were doing round-robin for low priority links, check 'em */ |
| 1264 | if ((p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) && |
| 1265 | (l2cb.check_round_robin) && |
| 1266 | (l2cb.round_robin_unacked < l2cb.round_robin_quota)) { |
| 1267 | l2c_link_check_send_pkts(NULL, NULL, NULL); |
| 1268 | } |
| 1269 | if ((p_lcb->transport == BT_TRANSPORT_LE) && |
| 1270 | (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) && |
| 1271 | ((l2cb.ble_check_round_robin) && |
| 1272 | (l2cb.ble_round_robin_unacked < l2cb.ble_round_robin_quota))) { |
| 1273 | l2c_link_check_send_pkts(NULL, NULL, NULL); |
| 1274 | } |
| 1275 | } |
| 1276 | |
| 1277 | #if (L2CAP_HCI_FLOW_CONTROL_DEBUG == TRUE) |
| 1278 | if (p_lcb) { |
| 1279 | if (p_lcb->transport == BT_TRANSPORT_LE) { |
| 1280 | L2CAP_TRACE_DEBUG( |
| 1281 | "TotalWin=%d,LinkUnack(0x%x)=%d,RRCheck=%d,RRUnack=%d", |
| 1282 | l2cb.controller_le_xmit_window, p_lcb->handle, |
| 1283 | p_lcb->sent_not_acked, l2cb.ble_check_round_robin, |
| 1284 | l2cb.ble_round_robin_unacked); |
| 1285 | } else { |
| 1286 | L2CAP_TRACE_DEBUG( |
| 1287 | "TotalWin=%d,LinkUnack(0x%x)=%d,RRCheck=%d,RRUnack=%d", |
| 1288 | l2cb.controller_xmit_window, p_lcb->handle, p_lcb->sent_not_acked, |
| 1289 | l2cb.check_round_robin, l2cb.round_robin_unacked); |
| 1290 | } |
| 1291 | } else { |
| 1292 | L2CAP_TRACE_DEBUG( |
| 1293 | "TotalWin=%d LE_Win: %d, Handle=0x%x, RRCheck=%d, RRUnack=%d", |
| 1294 | l2cb.controller_xmit_window, l2cb.controller_le_xmit_window, handle, |
| 1295 | l2cb.ble_check_round_robin, l2cb.ble_round_robin_unacked); |
| 1296 | } |
| 1297 | #endif |
| 1298 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1299 | } |
| 1300 | |
| 1301 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1302 | * |
| 1303 | * Function l2c_link_segments_xmitted |
| 1304 | * |
| 1305 | * Description This function is called from the HCI Interface when an ACL |
| 1306 | * data packet segment is transmitted. |
| 1307 | * |
| 1308 | * Returns void |
| 1309 | * |
| 1310 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1311 | void l2c_link_segments_xmitted(BT_HDR* p_msg) { |
| 1312 | uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset; |
| 1313 | uint16_t handle; |
| 1314 | tL2C_LCB* p_lcb; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1315 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1316 | /* Extract the handle */ |
| 1317 | STREAM_TO_UINT16(handle, p); |
| 1318 | handle = HCID_GET_HANDLE(handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1319 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1320 | /* Find the LCB based on the handle */ |
| 1321 | p_lcb = l2cu_find_lcb_by_handle(handle); |
| 1322 | if (p_lcb == NULL) { |
| 1323 | L2CAP_TRACE_WARNING("L2CAP - rcvd segment complete, unknown handle: %d", |
| 1324 | handle); |
| 1325 | osi_free(p_msg); |
| 1326 | return; |
| 1327 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1328 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1329 | if (p_lcb->link_state == LST_CONNECTED) { |
| 1330 | /* Enqueue the buffer to the head of the transmit queue, and see */ |
| 1331 | /* if we can transmit anything more. */ |
| 1332 | list_prepend(p_lcb->link_xmit_data_q, p_msg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1333 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1334 | p_lcb->partial_segment_being_sent = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1335 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1336 | l2c_link_check_send_pkts(p_lcb, NULL, NULL); |
| 1337 | } else |
| 1338 | osi_free(p_msg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1339 | } |