l2c_utils.cc revision b8a477e9ac51898b05cb328eda897d95f1ef3d02
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Copyright (C) 1999-2012 Broadcom Corporation 45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * you may not use this file except in compliance with the License. 75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * You may obtain a copy of the License at: 85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * See the License for the specific language governing permissions and 155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * limitations under the License. 165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/ 185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * This file contains L2CAP utility functions 225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/ 245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <stdio.h> 265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h> 275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h> 285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 29258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h" 305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h" 31911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_utils.h" 325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h" 335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h" 34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btu.h" 35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "device/include/controller.h" 365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcidefs.h" 37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "hcimsgs.h" 38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2c_int.h" 39911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2cdefs.h" 40a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#include "osi/include/allocator.h" 415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 42911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonextern fixed_queue_t* btu_general_alarm_queue; 4378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov 445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 45ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 468451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Function l2cu_can_allocate_lcb 478451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * 488451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Description Look for an unused LCB 498451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * 508451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Returns true if there is space for one more lcb 518451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * 528451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren ******************************************************************************/ 538451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngrenbool l2cu_can_allocate_lcb(void) { 548451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren for (int i = 0; i < MAX_L2CAP_LINKS; i++) { 558451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren if (!l2cb.lcb_pool[i].in_use) return true; 568451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren } 578451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren return false; 588451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren} 598451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren 608451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren/******************************************************************************* 618451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * 62ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_allocate_lcb 63ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 64ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look for an unused LCB 65ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 66ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns LCB address or NULL if none found 67ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 68ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 69c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskitL2C_LCB* l2cu_allocate_lcb(const bt_bdaddr_t& p_bd_addr, bool is_bonding, 70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBT_TRANSPORT transport) { 71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { 75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_lcb->in_use) { 76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_lcb->l2c_lcb_timer); 77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_lcb->info_resp_timer); 78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(p_lcb, 0, sizeof(tL2C_LCB)); 79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 80c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski p_lcb->remote_bd_addr = p_bd_addr; 81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->in_use = true; 83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_DISCONNECTED; 84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->handle = HCI_INVALID_HANDLE; 85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_flush_tout = 0xFFFF; 86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->l2c_lcb_timer = alarm_new("l2c_lcb.l2c_lcb_timer"); 87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->info_resp_timer = alarm_new("l2c_lcb.info_resp_timer"); 88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->idle_timeout = l2cb.idle_timeout; 89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id = 1; /* spec does not allow '0' */ 90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->is_bonding = is_bonding; 91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->transport = transport; 92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->tx_data_len = 93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson controller_get_interface()->get_ble_default_data_packet_length(); 94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX); 95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (transport == BT_TRANSPORT_LE) { 97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.num_ble_links_active++; 98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ble_link_adjust_allocation(); 99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.num_links_active++; 101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_adjust_allocation(); 102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1031a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#if (L2CAP_UCD_INCLUDED == TRUE) 104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->ucd_out_sec_pending_q = fixed_queue_new(SIZE_MAX); 105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->ucd_in_sec_pending_q = fixed_queue_new(SIZE_MAX); 1061a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#endif 107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_xmit_data_q = list_new(NULL); 108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_lcb); 1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no free LCB found */ 113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_update_lcb_4_bonding 119ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 120ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Mark the lcb for bonding. Used when bonding takes place on 121ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * an existing ACL connection. (Pre-Lisbon devices) 122ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 123ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Nothing 124ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 125ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 126c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskivoid l2cu_update_lcb_4_bonding(const bt_bdaddr_t& p_bd_addr, bool is_bonding) { 127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR); 1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb) { 130c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski VLOG(1) << __func__ << " BDA: " << p_bd_addr 131c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski << " is_bonding: " << is_bonding; 132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->is_bonding = is_bonding; 133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_release_lcb 139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Release an LCB. All timers will be stopped and freed, 141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * channels dropped, buffers returned etc. 142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_lcb(tL2C_LCB* p_lcb) { 147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->in_use = false; 150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->is_bonding = false; 1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Stop and free timers */ 153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_lcb->l2c_lcb_timer); 154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->l2c_lcb_timer = NULL; 155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_lcb->info_resp_timer); 156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->info_resp_timer = NULL; 1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Release any unfinished L2CAP packet on this link */ 159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free_and_reset((void**)&p_lcb->p_hcit_rcv_acl); 1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 161d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE) 162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */ 163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_remove_sco_links(p_lcb->remote_bd_addr); 1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->sent_not_acked > 0) { 167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) { 168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.controller_le_xmit_window += p_lcb->sent_not_acked; 169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) { 170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs; 171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.controller_xmit_window += p_lcb->sent_not_acked; 174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) { 175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs; 176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17798657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach } 178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17998657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach 180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // Reset BLE connecting flag only if the address matches 181c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski if (l2cb.ble_connecting_bda == p_lcb->remote_bd_addr) 182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.is_ble_connecting = false; 1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_process_fixed_disc_cback(p_lcb); 1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Ensure no CCBs left on this LCB */ 189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; 190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = p_lcb->ccb_queue.p_first_ccb) { 191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_release_ccb(p_ccb); 192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Tell BTM Acl management the link was removed */ 195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->link_state == LST_CONNECTED) || 196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->link_state == LST_DISCONNECTING)) 197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport); 198ef92b534112a5df57de11ef45f5174f75d44b355Andre Eisenbach 199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Release any held buffers */ 200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->link_xmit_data_q) { 201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (!list_is_empty(p_lcb->link_xmit_data_q)) { 202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q)); 203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_remove(p_lcb->link_xmit_data_q, p_buf); 204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 2056c303aeca25783453333172d0b29e5472f1b1c93Chris Manton } 206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_free(p_lcb->link_xmit_data_q); 207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_xmit_data_q = NULL; 208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* clean up any security pending UCD */ 212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ucd_delete_sec_pending_q(p_lcb); 2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Re-adjust flow control windows make sure it does not go negative */ 216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) { 217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--; 2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ble_link_adjust_allocation(); 220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.num_links_active >= 1) l2cb.num_links_active--; 22292ac2d8919f8e38a091903270eb5500073d67d4bMudumba Ananth 223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_adjust_allocation(); 224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check for ping outstanding */ 227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->p_echo_rsp_cb) { 228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2CA_ECHO_RSP_CB* p_cb = p_lcb->p_echo_rsp_cb; 2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Zero out the callback in case app immediately calls us again */ 231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->p_echo_rsp_cb = NULL; 2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_cb)(L2CAP_PING_RESULT_NO_LINK); 234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2355e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar 236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check and release all the LE COC connections waiting for security */ 237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->le_sec_pending_q) { 238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) { 239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2CAP_SEC_DATA* p_buf = 240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (tL2CAP_SEC_DATA*)fixed_queue_try_dequeue(p_lcb->le_sec_pending_q); 241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->p_callback) 242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, 243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->p_ref_data, BTM_DEV_RESET); 244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 2455e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar } 246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_lcb->le_sec_pending_q, NULL); 247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->le_sec_pending_q = NULL; 248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_lcb_by_bd_addr 254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through all active LCBs for a match based on the 256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * remote BD address. 257ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 258ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to matched LCB, or NULL if no match 259ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 260ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 261c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskitL2C_LCB* l2cu_find_lcb_by_bd_addr(const bt_bdaddr_t& p_bd_addr, 262c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski tBT_TRANSPORT transport) { 263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { 267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->in_use) && p_lcb->transport == transport && 268c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski (p_lcb->remote_bd_addr == p_bd_addr)) { 269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_lcb); 2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 278ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_get_conn_role 280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 281ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Determine the desired role (master or slave) of a link. 282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If already got a slave link, this one must be a master. If 2839ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * already got at least 1 link where we are the master, make 2849ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * this also a master. 285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE 287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_conn_role(tL2C_LCB* p_this_lcb) { return l2cb.desire_role; } 2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_is_cmd_rejected 294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 295ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Checks if cmd_code is command or response 296ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If a command it will be rejected per spec. 2979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * This function is used when a illegal packet length is 2989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * detected. 299ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 300ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns bool - true if cmd_code is a command and it is rejected, 301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * false if response code. (command not rejected) 302ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 303ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t id, tL2C_LCB* p_lcb) { 305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson switch (cmd_code) { 3068fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_CONN_REQ: 3078fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_CONFIG_REQ: 3088fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_DISC_REQ: 3098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_ECHO_REQ: 3108fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_INFO_REQ: 3118fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_AMP_CONN_REQ: 3128fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_AMP_MOVE_REQ: 3138fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta case L2CAP_CMD_BLE_UPDATE_REQ: 314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, 315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_MTU, 0); 316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Dumping first Command (%d)", cmd_code); 317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return true; 3188fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson default: /* Otherwise a response */ 320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return false; 321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3228fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta} 3238fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 3248fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/******************************************************************************* 325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_build_header 327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Builds the L2CAP command packet header 329ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 330ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Pointer to allocated packet or NULL if no resources 331ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 332ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 333911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd, 334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t id) { 335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE); 336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset = L2CAP_SEND_CMD_OFFSET; 339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len = 340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET; 3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in HCI header - handle + pkt boundary */ 344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) { 345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE 346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson << L2CAP_PKT_TYPE_SHIFT))); 347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_lcb->handle | l2cb.non_flushable_pbf); 3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM( 352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT))); 3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD); 357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, len + L2CAP_CMD_OVERHEAD); 358cccf02fadb2dd4dceb22f2d58ed5840b0ef1860eChris Manton 359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) { 360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_BLE_SIGNALLING_CID); 361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID); 363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in L2CAP command header */ 366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, cmd); 367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, id); 368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, len); 3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf); 3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_adj_id 376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Checks for valid ID based on specified mask 378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * and adjusts the id if invalid. 379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adj_id(tL2C_LCB* p_lcb, uint8_t adj_mask) { 384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) { 385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id++; 386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_cmd_reject 392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "command reject" message 394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 397ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 398ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason, uint8_t rem_id, 400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t p1, uint16_t p2) { 401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t param_len; 402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in L2CAP packet header */ 406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED) 407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson param_len = 2; 408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (reason == L2CAP_CMD_REJ_INVALID_CID) 409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson param_len = 4; 410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson param_len = 0; 4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_CMD_REJECT_LEN + param_len), 414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_REJECT, rem_id); 415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer cmd_rej"); 417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, reason); 4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (param_len >= 2) UINT16_TO_STREAM(p, p1); 4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (param_len >= 4) UINT16_TO_STREAM(p, p2); 4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 433ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 434ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_connect_req 435ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 436ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "connection request" message 437ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 439ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 440ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 441ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_req(tL2C_CCB* p_ccb) { 443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_REQ_LEN, 453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_CONN_REQ, p_ccb->local_id); 454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req"); 456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm); 463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_connect_rsp 471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "connection response" message 473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result, 479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t status) { 480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (result == L2CAP_CONN_PENDING) { 484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if we already sent pending response */ 485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->flags & CCB_FLAG_SENT_PENDING) 486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->flags |= CCB_FLAG_SENT_PENDING; 489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN, 492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_CONN_RSP, p_ccb->remote_id); 493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_rsp"); 495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, result); 504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, status); 5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_reject_connection 512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "connection response neg" message 514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. This function is called when there is no peer 515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * CCB (non-existant PSM or no resources). 516ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 518ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 519ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid, 521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t rem_id, uint16_t result) { 522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = 526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id); 527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req"); 529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* Local CID of 0 */ 536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, remote_cid); 537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, result); 538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* Status of 0 */ 5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_config_req 546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "configuration request" message 548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 549ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 550ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 551ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 552ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t cfg_len = 0; 556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu_present) 565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) 567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) 569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) 571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcs_present) 573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->ext_flow_spec_present) 575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_ccb->p_lcb, 578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (uint16_t)(L2CAP_CONFIG_REQ_LEN + cfg_len), 579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_CONFIG_REQ, p_ccb->local_id); 580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req"); 582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->flags); /* Flags (continuation) */ 590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now, put the options */ 592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu_present) { 593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU); 594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN); 595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->mtu); 596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) { 598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT); 599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN); 600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->flush_to); 601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) { 603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS); 604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN); 605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->qos.qos_flags); 606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->qos.service_type); 607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.token_rate); 608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size); 609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth); 610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.latency); 611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.delay_variation); 612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) { 614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR); 615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN); 616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.mode); 617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz); 618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit); 619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->fcr.rtrans_tout); 620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->fcr.mon_tout); 621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->fcr.mps); 622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcs_present) { 625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCS); 626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_FCS_OPTION_LEN); 627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcs); 628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->ext_flow_spec_present) { 631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW); 632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN); 633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id); 634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype); 635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size); 636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time); 637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency); 638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout); 639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 6435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 645ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 646ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_config_rsp 647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "configuration response" message 649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t cfg_len = 0; 657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu_present) 661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) 663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) 665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) 667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->ext_flow_spec_present) 669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD; 670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_ccb->p_lcb, 672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (uint16_t)(L2CAP_CONFIG_RSP_LEN + cfg_len), 673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id); 674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req"); 676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flags); /* Flags (continuation) Must match request */ 685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->result); 686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now, put the options */ 688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu_present) { 689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU); 690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN); 691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->mtu); 692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) { 694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT); 695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN); 696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->flush_to); 697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) { 699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS); 700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN); 701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->qos.qos_flags); 702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->qos.service_type); 703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.token_rate); 704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size); 705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth); 706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.latency); 707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->qos.delay_variation); 708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) { 710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR); 711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN); 712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.mode); 713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz); 714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit); 715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.rtrans_tout); 716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.mon_tout); 717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->fcr.mps); 718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->ext_flow_spec_present) { 721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW); 722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN); 723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id); 724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype); 725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size); 726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time); 727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency); 728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout); 729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_config_rej 737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "configuration reject" message 739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data, 745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t data_len, uint16_t rej_len) { 746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t len, cfg_len, buf_space, len1; 747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t *p, *p_hci_len, *p_data_end; 748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t cfg_code; 7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", 751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson data_len, rej_len); 7528fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + 754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN; 755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len1 = 0xFFFF - len; 756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (rej_len > len1) { 757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - cfg_rej pkt size exceeds buffer design max limit."); 759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 7618fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + rej_len); 763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset = L2CAP_SEND_CMD_OFFSET; 764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET; 7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Put in HCI header - handle + pkt boundary */ 7675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) { 769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE 770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson << L2CAP_PKT_TYPE_SHIFT))); 771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 7725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM( 775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT))); 776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Remember the HCI header length position, and save space for it */ 779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_hci_len = p; 780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p += 2; 781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in L2CAP packet header */ 783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len); 784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID); 785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in L2CAP command header */ 787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, L2CAP_CMD_CONFIG_RSP); 788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(p, p_ccb->remote_id); 789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_CONFIG_RSP_LEN + rej_len); 791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* Flags = 0 (no continuation) */ 794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_CFG_UNKNOWN_OPTIONS); 795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson buf_space = rej_len; 797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now, put the rejected options */ 799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data_end = p_data + data_len; 800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (p_data < p_data_end) { 801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_code = *p_data; 802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cfg_len = *(p_data + 1); 803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson switch (cfg_code & 0x7F) { 805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* skip known options */ 806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case L2CAP_CFG_TYPE_MTU: 807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case L2CAP_CFG_TYPE_FLUSH_TOUT: 808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case L2CAP_CFG_TYPE_QOS: 809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD; 810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* unknown options; copy into rsp if not hints */ 813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson default: 814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* sanity check option length */ 815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) { 816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((cfg_code & 0x80) == 0) { 817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) { 818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD); 819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD; 820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD); 821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer"); 823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data = p_data_end; /* force loop exit */ 824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD; 828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* bad length; force loop exit */ 830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data = p_data_end; 8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 8345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len = (uint16_t)(p - p_hci_len - 2); 838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p_hci_len, len); 8395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len = len + 4; 8415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d", len, 843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len)); 8448fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 8475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 8485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 849ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 850ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_disc_req 851ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 852ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "disconnect request" message 853ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 854ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 855ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 856ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 857ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_req(tL2C_CCB* p_ccb) { 859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR *p_buf, *p_buf2; 860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 8615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb) || (p_ccb->p_lcb == NULL)) { 863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("%s L2CAP - ccb or lcb invalid", __func__); 864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 866bf955cb7e50e1047452e741effa504c8aefc8a4fvenkata Jagadeesh 867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 8725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN, 874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_DISC_REQ, p_ccb->local_id); 875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_req"); 877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 8825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Move all queued data packets to the LCB. In FCR mode, assume the higher 887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson layer checks that all buffers are sent before disconnecting. 888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) { 890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while ((p_buf2 = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) != 891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson NULL) { 892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_set_acl_hci_header(p_buf2, p_ccb); 893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, p_ccb, p_buf2); 8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 8985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 901ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 902ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_disc_rsp 903ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "disconnect response" message 905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 906ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * This function is passed the parameters for the disconnect 908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * response instead of the CCB address, as it may be called 909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to send a disconnect response when there is no CCB. 910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 912ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id, 915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t local_cid, uint16_t remote_cid) { 916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP, 920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson remote_id); 921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_rsp"); 923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, local_cid); 930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, remote_cid); 9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_echo_req 938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "echo request" message 940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. Note that we do not currently allow 941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * data in the echo request. 942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_req(tL2C_LCB* p_lcb, uint8_t* p_data, 947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t data_len) { 948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id++; 952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */ 9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_REQ_LEN + data_len), 955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_ECHO_REQ, p_lcb->id); 956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_req"); 958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 9635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (data_len) { 965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ARRAY_TO_STREAM(p, p_data, data_len); 966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 972ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 973ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_echo_rsp 974ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "echo response" message 976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 979ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 980ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data, 982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t data_len) { 983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t maxlen; 986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Filter out duplicate IDs or if available buffers are low (intruder 987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * checking) */ 988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!id || id == p_lcb->cur_echo_id) { 989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Dump this request since it is illegal */ 990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP ignoring duplicate echo request (%d)", id); 991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->cur_echo_id = id; 994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t acl_data_size = 996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson controller_get_interface()->get_acl_data_size_classic(); 997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t acl_packet_size = 998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson controller_get_interface()->get_acl_packet_size_classic(); 999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Don't return data if it does not fit in ACL and L2CAP MTU */ 1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size) 1001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ? acl_data_size 1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson : (uint16_t)L2CAP_CMD_BUF_SIZE; 1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson maxlen -= 1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (uint16_t)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + 1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN); 1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (data_len > maxlen) data_len = 0; 1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len), 1010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_ECHO_RSP, id); 1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_rsp"); 1013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 1018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (data_len) { 1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ARRAY_TO_STREAM(p, p_data, data_len); 1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 10245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 10255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1028ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_info_req 1029ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "info request" message 1031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 1032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) { 1036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 1037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* check for wrap and/or BRCM ID */ 1040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id++; 1041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_lcb, L2CAP_ADJ_ID); 10425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id); 1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 1045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for info_req"); 1046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT("l2cu_send_peer_info_req: type 0x%04x", info_type); 10505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1051911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 1052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, info_type); 10555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->w4_info_rsp = true; 1057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS, 1058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_info_resp_timer_timeout, p_lcb, 1059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btu_general_alarm_queue); 10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 10625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_info_rsp 1067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send an L2CAP "info response" message 1069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 1070ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1071ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1072ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t remote_id, 1075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t info_type) { 1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 1077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t len = L2CAP_INFO_RSP_LEN; 10795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE) 1081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) && 1082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2cb.test_info_resp & 1083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | 1084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC | 1085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW | 1086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_UCD_RECEPTION))) 10875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) && 1089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_SUPPORTED_MASK & 1090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | 1091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS | 1092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_UCD_RECEPTION)) != 0) 10935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE; 1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) { 1097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len += L2CAP_FIXED_CHNL_ARRAY_SIZE; 1098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) { 1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len += L2CAP_CONNLESS_MTU_INFO_SIZE; 1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id); 1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no buffer for info_rsp"); 1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 1109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, info_type); 11125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE) 1114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) && 1115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2cb.test_info_resp & 1116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | 1117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_UCD_RECEPTION))) 11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) && 1120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_SUPPORTED_MASK & 1121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | 1122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_UCD_RECEPTION)) != 0) 11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS); 1126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) { 1127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* optional data are not added for now */ 1128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, L2CAP_BLE_EXTFEA_MASK); 1129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1130d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE) 1131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, l2cb.test_info_resp); 11325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 11335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 1134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, 1135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS); 11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 1137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, L2CAP_EXTFEA_SUPPORTED_MASK); 11385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 11395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 11405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) { 1142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS); 1143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE); 11445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p[0] = L2CAP_FIXED_CHNL_SIG_BIT; 11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION) 1148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT; 11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 11515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 1153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Skip fixed channels not used on BR/EDR-ACL link */ 1156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((xx >= L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL) && 1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (xx <= L2CAP_SMP_CID - L2CAP_FIRST_FIXED_CHNL)) 1158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) 1161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |= 1162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8); 1163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif 1166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) { 1167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS); 1168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_UCD_MTU); 1169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM( 1171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */ 1172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 11755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 11765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 1178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_enqueue_ccb 1180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description queue CCB by priority. The first CCB is highest priority and 1182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * is served at first. The CCB is queued to an LLCB or an LCB. 1183ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1184ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 1185ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1186ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_enqueue_ccb(tL2C_CCB* p_ccb) { 1188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb1; 1189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB_Q* p_q = NULL; 11905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find out which queue the channel is on 1192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue; 11945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->in_use) || (p_q == NULL)) { 1196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: 0x%08x", 1198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb); 1199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_enqueue_ccb CID: 0x%04x priority: %d", 1203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->ccb_priority); 12045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the queue is empty, we go at the front */ 1206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_q->p_first_ccb) { 1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_first_ccb = p_q->p_last_ccb = p_ccb; 1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL; 1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb1 = p_q->p_first_ccb; 1211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (p_ccb1 != NULL) { 1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Insert new ccb at the end of the same priority. Lower number, higher 1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * priority */ 1215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->ccb_priority < p_ccb1->ccb_priority) { 1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Are we at the head of the queue ? */ 1217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb1 == p_q->p_first_ccb) 1218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_first_ccb = p_ccb; 1219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb1->p_prev_ccb->p_next_ccb = p_ccb; 12215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = p_ccb1; 1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb; 1224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb1->p_prev_ccb = p_ccb; 1225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 1226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb1 = p_ccb1->p_next_ccb; 1229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we are lower then anyone in the list, we go at the end */ 1232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb1) { 1233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* add new ccb at the end of the list */ 1234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_last_ccb->p_next_ccb = p_ccb; 12355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = NULL; 1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_prev_ccb = p_q->p_last_ccb; 1238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_last_ccb = p_ccb; 12395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 1243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Adding CCB into round robin service table of its LCB */ 1244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb != NULL) { 1245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if this is the first channel in this priority group */ 1246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) { 1247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the first channel to this CCB */ 1248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb; 1249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the next serving channel in this group to this CCB */ 1250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb; 1251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Initialize quota of this priority group based on its priority */ 1252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = 1253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority); 1254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* increase number of channels in this group */ 1256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++; 1257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 12595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 12605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 1262ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1263ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_dequeue_ccb 1264ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1265ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description dequeue CCB from a queue 1266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1268ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1269ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_dequeue_ccb(tL2C_CCB* p_ccb) { 1271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB_Q* p_q = NULL; 12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_dequeue_ccb CID: 0x%04x", p_ccb->local_cid); 12745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find out which queue the channel is on 1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue; 12785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL)) { 1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_dequeue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: 0x%08x p_q: " 1282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "0x%08x p_q->p_first_ccb: 0x%08x", 1283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q, 1284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q ? p_q->p_first_ccb : 0); 1285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 1289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Removing CCB from round robin service table of its LCB */ 1290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb != NULL) { 1291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* decrease number of channels in this priority group */ 1292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--; 1293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if it was the last channel in the priority group */ 1295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) { 1296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL; 1297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL; 1298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if it is the first channel of this group */ 1300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb) { 1301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = 1302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb; 1303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if it is the next serving channel of this group */ 1305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb) { 1306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* simply, start serving from the first channel */ 1307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = 1308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb; 1309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 13135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == p_q->p_first_ccb) { 1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We are removing the first in a queue */ 1316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_first_ccb = p_ccb->p_next_ccb; 13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_q->p_first_ccb) 1319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_first_ccb->p_prev_ccb = NULL; 13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 1321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_last_ccb = NULL; 1322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_ccb == p_q->p_last_ccb) { 1323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We are removing the last in a queue */ 1324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_last_ccb = p_ccb->p_prev_ccb; 1325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_q->p_last_ccb->p_next_ccb = NULL; 1326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* In the middle of a chain. */ 1328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb; 1329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb; 1330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL; 13335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 13345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 1336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_change_pri_ccb 1338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description 1340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1342ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1343ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority) { 1345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->ccb_priority != priority) { 1346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If CCB is not the only guy on the queue */ 1347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL)) { 1348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("Update CCB list in logical link"); 13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Remove CCB from queue and re-queue it at new priority */ 1351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_dequeue_ccb(p_ccb); 13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ccb_priority = priority; 1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_enqueue_ccb(p_ccb); 1355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 1357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If CCB is the only guy on the queue, no need to re-enqueue */ 1359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* update only round robin service data */ 1360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0; 1361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL; 1362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL; 1363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ccb_priority = priority; 1365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb; 1367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb; 1368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = 1369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority); 1370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1; 13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif 1373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 13755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_allocate_ccb 1379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function allocates a Channel Control Block and 1381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * attaches it to a link control block. The local CID 1382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * is also assigned. 1383ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1384ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to CCB, or NULL if none 1385ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1387911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid) { 1388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 1389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_prev; 13905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x", cid); 13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!l2cb.p_free_ccb_first) return (NULL); 13945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If a CID was passed in, use that, else take the first free one */ 1396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (cid == 0) { 1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cb.p_free_ccb_first; 1398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_first = p_ccb->p_next_ccb; 1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_prev = NULL; 14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID]; 14035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == l2cb.p_free_ccb_first) 1405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_first = p_ccb->p_next_ccb; 1406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 1407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL; 1408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_prev = p_prev->p_next_ccb) { 1409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_prev->p_next_ccb == p_ccb) { 1410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_prev->p_next_ccb = p_ccb->p_next_ccb; 14115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == l2cb.p_free_ccb_last) l2cb.p_free_ccb_last = p_prev; 14135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 1415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_prev == NULL) { 1418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free " 1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "list", 1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson cid); 1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL; 1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->in_use = true; 1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get a CID for the connection */ 1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid = L2CAP_BASE_APPL_CID + (uint16_t)(p_ccb - l2cb.ccb_pool); 1433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb = p_lcb; 1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb = NULL; 1436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->should_free_rcb = false; 1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set priority then insert ccb into LCB queue (if we have an LCB) */ 1439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW; 1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb) l2cu_enqueue_ccb(p_ccb); 1442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* clear what peer wants to configure */ 1444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_bits = 0; 1445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in default values for configuration */ 1447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 1448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 1449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in default values for local/peer configurations */ 1451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO; 1452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU; 1453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type = 1454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_SERV_TYPE; 1455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate = 1456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_TOKEN_RATE; 1457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size = 1458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_BUCKET_SIZE; 1459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth = 1460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_PEAK_BANDWIDTH; 1461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency = 1462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_LATENCY; 1463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation = 1464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_DEFAULT_DELAY; 1465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->bypass_fcs = 0; 1467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO)); 1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_already_rejected = false; 1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES; 1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_ccb->fcrb.ack_timer); 1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_timer = alarm_new("l2c_fcrb.ack_timer"); 1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* CSP408639 Fix: When L2CAP send amp move channel request or receive 1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move 1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * request -> Stop retrans/monitor timer -> Change channel state to 1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * CST_AMP_MOVING. */ 1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_ccb->fcrb.mon_retrans_timer); 1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.mon_retrans_timer = alarm_new("l2c_fcrb.mon_retrans_timer"); 1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.preferred_mode = 1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */ 1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.allowed_modes = 1484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */ 1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE; 1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE; 1487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE; 1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE; 1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->max_rx_mtu = L2CAP_MTU_SIZE; 1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32; 1491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX); 1493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX); 1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX); 1495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX); 1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cong_sent = false; 1498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->buff_quota = 2; /* This gets set after config */ 1499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If CCB was reserved Config_Done can already have some value */ 1501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (cid == 0) 1502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->config_done = 0; 1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 1504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid, 1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->config_done); 1506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->chnl_state = CST_CLOSED; 1509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->flags = 0; 1510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW; 1511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW; 15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 1514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_flushable = false; 15155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 15165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_ccb->l2c_ccb_timer); 1518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer"); 15195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_adjust_chnl_allocation(); 15215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb); 15235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 15245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_start_post_bond_timer 1528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function starts the ACL Link inactivity timer after 1530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * dedicated bonding 1531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * This timer can be longer than the normal link inactivity 1532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * timer for some platforms. 1533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 15349ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns bool - true if idle timer started or disconnect initiated 15359ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * false if there's one or more pending CCB's exist 1536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_start_post_bond_timer(uint16_t handle) { 1539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle); 15405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_lcb) return (true); 15425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->is_bonding = false; 15445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Only start timer if no control blocks allocated */ 1546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->ccb_queue.p_first_ccb != NULL) return (false); 15475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If no channels on the connection, start idle timeout */ 1549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->link_state == LST_CONNECTED) || 1550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->link_state == LST_CONNECTING) || 1551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->link_state == LST_DISCONNECTING)) { 1552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson period_ms_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000; 155378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov 1554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->idle_timeout == 0) { 1555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER); 1556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_DISCONNECTING; 1557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS; 15585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout, 1560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb, btu_general_alarm_queue); 1561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 1562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 15635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 15655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 15665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1568ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1569ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_release_ccb 1570ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1571ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function releases a Channel Control Block. The timer 15729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * is stopped, any attached buffers freed, and the CCB is 15739ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * removed from the link control block. 1574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1575ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1576ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1577ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_ccb(tL2C_CCB* p_ccb) { 1579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = p_ccb->p_lcb; 1580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_RCB* p_rcb = p_ccb->p_rcb; 15815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_release_ccb: cid 0x%04x in_use: %u", 1583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->in_use); 15845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If already released, could be race condition */ 1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->in_use) return; 15875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) { 1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_sec_clr_service_by_psm(p_rcb->psm); 1590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1591ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta 1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->should_free_rcb) { 1593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_rcb); 1594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb = NULL; 1595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->should_free_rcb = false; 1596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1597a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati 1598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_sec_clr_temp_auth_service(p_lcb->remote_bd_addr); 1599ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta 1600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Free the timer */ 1601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_ccb->l2c_ccb_timer); 1602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->l2c_ccb_timer = NULL; 16035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_ccb->xmit_hold_q, osi_free); 1605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->xmit_hold_q = NULL; 16065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_cleanup(p_ccb); 16085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Channel may not be assigned to any LCB if it was just pre-reserved */ 1610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID) 16115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) 16135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson )) { 1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_dequeue_ccb(p_ccb); 1616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Delink the CCB from the LCB */ 1618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb = NULL; 1619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put the CCB back on the free pool */ 1622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!l2cb.p_free_ccb_first) { 1623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_first = p_ccb; 1624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_last = p_ccb; 1625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = NULL; 1626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_prev_ccb = NULL; 1627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_next_ccb = NULL; 1629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_prev_ccb = l2cb.p_free_ccb_last; 1630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_last->p_next_ccb = p_ccb; 1631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.p_free_ccb_last = p_ccb; 1632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Flag as not in use */ 1635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->in_use = false; 1636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If no channels on the connection, start idle timeout */ 1638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) { 1639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_lcb->ccb_queue.p_first_ccb) { 16407c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski // Closing a security channel on LE device should not start connection 16417c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski // timeout 16427c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski if (p_lcb->transport == BT_TRANSPORT_LE && 16437c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski p_ccb->local_cid == L2CAP_SMP_CID) 16447c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski return; 16457c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski 1646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_no_dynamic_ccbs(p_lcb); 1647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Link is still active, adjust channel quotas. */ 1649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_adjust_chnl_allocation(); 16505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 16535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_ccb_by_remote_cid 1657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through all active CCBs on a link for a match based 1659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * on the remote CID. 1660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1661ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to matched CCB, or NULL if no match 1662ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1663ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1664911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb, uint16_t remote_cid) { 1665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 16665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If LCB is NULL, look through all active links */ 1668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_lcb) { 1669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 1670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) 1672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) return (p_ccb); 1673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 1676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 16775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 16785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1680ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1681ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_allocate_rcb 1682ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1683ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through the Registration Control Blocks for a free 1684ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * one. 1685ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1686ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Pointer to the RCB or NULL if not found 1687ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1688ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1689911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_rcb(uint16_t psm) { 1690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_RCB* p_rcb = &l2cb.rcb_pool[0]; 1691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) { 1694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_rcb->in_use) { 1695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->in_use = true; 1696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->psm = psm; 16975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 1698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->ucd.state = L2C_UCD_STATE_UNUSED; 16995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_rcb); 17015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no free RCB found */ 1705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 17065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 17075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17086721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 1709ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_allocate_ble_rcb 1711ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through the BLE Registration Control Blocks for a free 1713ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * one. 1714ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1715ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Pointer to the BLE RCB or NULL if not found 1716ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1717ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1718911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm) { 1719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0]; 1720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 17216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) { 1723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_rcb->in_use) { 1724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->in_use = true; 1725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->psm = psm; 17266721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#if (L2CAP_UCD_INCLUDED == TRUE) 1727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->ucd.state = L2C_UCD_STATE_UNUSED; 17286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#endif 1729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_rcb); 17306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 1731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17326721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no free RCB found */ 1734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 17356721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 17365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_release_rcb 1740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Mark an RCB as no longet in use 1742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1744ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1745ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_rcb(tL2C_RCB* p_rcb) { 1747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->in_use = false; 1748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rcb->psm = 0; 17495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 17505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1753ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_disconnect_chnl 1754ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1755ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Disconnect a channel. Typically, this is due to either 17569ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * receiving a bad configuration, bad packet or max_retries 17579ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * expiring. 1758ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1759ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_disconnect_chnl(tL2C_CCB* p_ccb) { 1761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t local_cid = p_ccb->local_cid; 17625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (local_cid >= L2CAP_BASE_APPL_CID) { 1764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2CA_DISCONNECT_IND_CB* p_disc_cb = 1765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 17665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - disconnect_chnl CID: 0x%04x", local_cid); 17685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_send_peer_disc_req(p_ccb); 17705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_release_ccb(p_ccb); 17725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_disc_cb)(local_cid, false); 1774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* failure on the AMP channel, probably need to disconnect ACL */ 1776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid); 1777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 17795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1781ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1782ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_rcb_by_psm 1783ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1784ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through the Registration Control Blocks to see if 1785ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * anyone registered to handle the PSM in question 1786ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1787ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Pointer to the RCB or NULL if not found 1788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1790911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm) { 1791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_RCB* p_rcb = &l2cb.rcb_pool[0]; 1792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 17935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) { 1795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb); 1796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 1799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 18005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 18015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 1803ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_ble_rcb_by_psm 1805ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1806ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through the BLE Registration Control Blocks to see if 1807ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * anyone registered to handle the PSM in question 1808ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1809ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Pointer to the BLE RCB or NULL if not found 1810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1811ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1812911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) { 1813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0]; 1814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 18156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) { 1817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb); 1818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 18196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 1821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 18226721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 18235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1825ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1826ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_peer_cfg_req 1827ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 18289ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function is called when the peer sends us a "config 18299ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * request" message. It extracts the configuration of interest 18309ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * and saves it in the CCB. 1831ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 18329ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Note: Negotiation of the FCR channel type is handled 18339ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * internally, all others are passed to the upper layer. 1834ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1835ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns uint8_t - L2CAP_PEER_CFG_OK if passed to upper layer, 18369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * L2CAP_PEER_CFG_UNACCEPTABLE if automatically 18379ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * responded to because parameters are 18389ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * unnacceptable from a specification point 18399ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * of view. 18409ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * L2CAP_PEER_CFG_DISCONNECT if no compatible channel 18419ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * modes between the two devices, and shall 18429ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * be closed. 1843ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1844ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool mtu_ok = true; 1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool qos_type_ok = true; 1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool flush_to_ok = true; 1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool fcr_ok = true; 1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t fcr_status; 1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Ignore FCR parameters for basic mode */ 1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_cfg->fcr_present) p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; 1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the MTU that our peer can receive */ 1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu_present) { 1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Make sure MTU is at least the minimum */ 1858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->mtu >= L2CAP_MIN_MTU) { 1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* In basic mode, limit the MTU to our buffer size */ 1860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->fcr_present == false) && (p_cfg->mtu > L2CAP_MTU_SIZE)) 1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu = L2CAP_MTU_SIZE; 1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the accepted value in case of renegotiation */ 1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.mtu = p_cfg->mtu; 1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.mtu_present = true; 1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU; 1867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Illegal MTU value */ 1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu = L2CAP_MIN_MTU; 1870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mtu_ok = false; 1871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Reload mtu from a previously accepted config request */ 1874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->peer_cfg.mtu_present) { 1875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu_present = true; 1876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu = p_ccb->peer_cfg.mtu; 1877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Verify that the flush timeout is a valid value (0 is illegal) */ 1880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) { 1881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_cfg->flush_to) { 1882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */ 1883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson flush_to_ok = false; 1884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Save the accepted value in case of renegotiation */ 1885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.flush_to_present = true; 1887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.flush_to = p_cfg->flush_to; 1888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO; 1889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Reload flush_to from a previously accepted config request */ 1892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->peer_cfg.flush_to_present) { 1893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flush_to_present = true; 1894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flush_to = p_ccb->peer_cfg.flush_to; 1895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the QOS settings the the peer is using */ 1898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) { 1899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Make sure service type is not a reserved value; otherwise let upper 1900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson layer decide if acceptable 1901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos.service_type <= GUARANTEED) { 1903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.qos = p_cfg->qos; 1904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.qos_present = true; 1905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS; 1906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Illegal service type value */ 19075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->qos.service_type = BEST_EFFORT; 1909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson qos_type_ok = false; 19105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Reload QOS from a previously accepted config request */ 1913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->peer_cfg.qos_present) { 1914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->qos_present = true; 1915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->qos = p_ccb->peer_cfg.qos; 1916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_status = l2c_fcr_process_peer_cfg_req(p_ccb, p_cfg); 1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fcr_status == L2CAP_PEER_CFG_DISCONNECT) { 1920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Notify caller to disconnect the channel (incompatible modes) */ 1921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->result = L2CAP_CFG_FAILED_NO_REASON; 1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0; 19235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (L2CAP_PEER_CFG_DISCONNECT); 1925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK); 19285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Return any unacceptable parameters */ 1930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) { 1931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adjust_out_mps(p_ccb); 1932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (L2CAP_PEER_CFG_OK); 1933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 19355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (mtu_ok) p_cfg->mtu_present = false; 1937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (flush_to_ok) p_cfg->flush_to_present = false; 1938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (qos_type_ok) p_cfg->qos_present = false; 1939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fcr_ok) p_cfg->fcr_present = false; 19405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (L2CAP_PEER_CFG_UNACCEPTABLE); 1942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 19445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_peer_cfg_rsp 1948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 19499ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function is called when the peer sends us a "config 19509ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * response" message. It extracts the configuration of interest 19519ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * and saves it in the CCB. 1952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1953ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1954ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1955ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we wanted QoS and the peer sends us a positive response with QoS, use 1958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * his values */ 1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->qos_present) && (p_ccb->our_cfg.qos_present)) 1960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos = p_cfg->qos; 19615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) { 1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the retransmission and monitor timeout values */ 1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) { 1965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout; 1966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout; 1967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Calculate the max number of packets for which we can delay sending an ack 1970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) 1972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3; 1973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3; 19755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 1977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, " 1978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "max_held_acks: %d", 1979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, 1980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks); 1981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 19835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1985ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_our_cfg_req 1987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1988ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called when we send a "config request" 1989ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * message. It extracts the configuration of interest and saves 1990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * it in the CCB. 1991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1992ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 1993ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1994ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 1996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb; 1997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t hci_flush_to; 1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the QOS settings we are using for transmit */ 2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->qos_present) { 2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos_present = true; 2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.qos = p_cfg->qos; 2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) { 2006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Override FCR options if attempting streaming or basic */ 2007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) 2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS)); 2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* On BR/EDR, timer values are zero in config request */ 2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* On class 2 AMP, timer value in config request shall be non-0 processing 2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * time */ 2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* timer value in config response shall be greater than 2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * received processing time */ 2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0; 2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) 2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0; 2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the threshold to send acks (may be updated in the cfg response) */ 2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3; 2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Include FCS option only if peer can handle it */ 2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) { 2026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* FCS check can be bypassed if peer also desires to bypass */ 2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) 2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR; 2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 2030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcs_present = false; 2031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; 2033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode; 2036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr_present = p_cfg->fcr_present; 2037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check the flush timeout. If it is lower than the current one used */ 2039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* then we need to adjust the flush timeout sent to the controller */ 2040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to_present) { 2041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->flush_to == 0) || 2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) { 2043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* don't send invalid flush timeout */ 2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* SPEC: The sender of the Request shall specify its flush timeout value 2045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if it differs from the default value of 0xFFFF */ 2047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flush_to_present = false; 2048911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.flush_to = p_cfg->flush_to; 2050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = p_ccb->p_lcb; 20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to < p_lcb->link_flush_tout) { 2053911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_flush_tout = p_cfg->flush_to; 20545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the timeout is within range of HCI, set the flush timeout */ 2056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) { 2057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Convert flush timeout to 0.625 ms units, with round */ 2058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5; 2059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to); 20605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 20655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_our_cfg_rsp 2069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 20709ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function is called when we send the peer a "config 20719ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * response" message. It extracts the configuration of interest 20729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * and saves it in the CCB. 2073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2074ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2075ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2076ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 2078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If peer wants QoS, we are allowed to change the values in a positive 2079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * response */ 2080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present)) 2081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.qos = p_cfg->qos; 2082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 2083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->qos_present = false; 20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_adj_our_rsp_options(p_ccb, p_cfg); 20865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 20875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_device_reset 2091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2092ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called when reset of the device is 2093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * completed. For all active connection simulate HCI_DISC 2094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2095ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_device_reset(void) { 2099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 2100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 21015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { 2103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) { 2104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_hci_disc_comp(p_lcb->handle, (uint8_t)-1); 21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.is_ble_connecting = false; 21085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 21095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_create_conn 2113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function initiates an acl connection via HCI 2115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if successful, false if get buffer fails. 2117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport) { 212096fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski uint8_t phy = controller_get_interface()->get_le_all_initiating_phys(); 212196fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski return l2cu_create_conn(p_lcb, transport, phy); 212296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski} 212396fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski 212496fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowskibool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport, 212596fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski uint8_t initiating_phys) { 2126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 2127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0]; 2128d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE) 2129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool is_sco_active; 21305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 21315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBT_DEVICE_TYPE dev_type; 2133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBLE_ADDR_TYPE addr_type; 21340fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach 2135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type); 21360fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach 2137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (transport == BT_TRANSPORT_LE) { 2138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!controller_get_interface()->supports_ble()) return false; 21390fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach 2140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->ble_addr_type = addr_type; 2141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->transport = BT_TRANSPORT_LE; 214296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski p_lcb->initiating_phys = initiating_phys; 21435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (l2cble_create_conn(p_lcb)); 2145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If there is a connection where we perform as a slave, try to switch roles 2148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for this connection */ 2149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; 2150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx++, p_lcb_cur++) { 2151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb_cur == p_lcb) continue; 21525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) { 2154d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE) 2155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The LMP_switch_req shall be sent only if the ACL logical transport 2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson is in active mode, when encryption is disabled, and all synchronous 2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson logical transports on the same physical link are disabled." */ 21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if there is any SCO Active on this BD Address */ 2160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr); 21615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_API( 2163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", 2164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (is_sco_active == true) ? "true" : "false"); 21655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (is_sco_active == true) 2167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; /* No Master Slave switch not allowed when SCO Active */ 21685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 2169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */ 2170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) { 2171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* mark this lcb waiting for switch to be completed and 2172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson start switch on the other one */ 2173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH; 2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_role = HCI_ROLE_MASTER; 2175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (BTM_SwitchRole(p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == 2177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BTM_CMD_STARTED) { 2178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue( 2179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->l2c_lcb_timer, L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS, 2180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); 2181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 21825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_CONNECTING; 21885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (l2cu_create_conn_after_switch(p_lcb)); 21905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 21915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_get_num_hi_priority 2195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Gets the number of high priority channels. 2197ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns 2199ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_num_hi_priority(void) { 2202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t no_hi = 0; 2203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 2204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 22055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { 2207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) { 2208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson no_hi++; 22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return no_hi; 22125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 22135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2216ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_create_conn_after_switch 2217ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2218ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function initiates an acl connection via HCI 2219ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If switch required to create connection it is already done. 2220ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2221ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if successful, false if get buffer fails. 2222ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 22245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) { 2226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t allow_switch = HCI_CR_CONN_ALLOW_SWITCH; 2227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBTM_INQ_INFO* p_inq_info; 2228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t page_scan_rep_mode; 2229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t page_scan_mode; 2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t clock_offset; 2231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p_features; 2232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t num_acl = BTM_GetNumAclLinks(); 2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_lcb->remote_bd_addr); 2234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t no_hi_prio_chs = l2cu_get_num_hi_priority(); 22355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_features = BTM_ReadLocalFeatures(); 22375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d", 2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding); 2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* FW team says that we can participant in 4 piconets 2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * typically 3 piconet + 1 for scanning. 2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * We can enhance the code to count the number of piconets later. */ 2244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (((!l2cb.disallow_switch && (num_acl < 3)) || 2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->is_bonding && (no_hi_prio_chs == 0))) && 2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson HCI_SWITCH_SUPPORTED(p_features)) 2247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson allow_switch = HCI_CR_CONN_ALLOW_SWITCH; 2248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 2249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH; 22505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_CONNECTING; 22525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check with the BT manager if details about remote device are known */ 2254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr); 2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_inq_info != NULL) { 2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode; 2257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson page_scan_mode = p_inq_info->results.page_scan_mode; 2258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson clock_offset = (uint16_t)(p_inq_info->results.clock_offset); 2259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* No info known. Use default settings */ 2261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1; 2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE; 22635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0; 2265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 22665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2267b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski btsnd_hcic_create_conn( 2268b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 | 2269b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 | 2270b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5), 2271b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch); 22725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_acl_update_busy_level(BTM_BLI_PAGE_EVT); 22745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS, 2276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue); 2277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 2279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 22805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_lcb_by_state 2284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through all active LCBs for a match based on the 2286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * LCB state. 2287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to first matched LCB, or NULL if no match 2289ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2291911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) { 2292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t i; 2293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 22945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) { 2296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->in_use) && (p_lcb->link_state == state)) { 2297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_lcb); 22985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 23005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 2302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 23035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 23045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2306ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2307ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_lcb_disconnecting 2308ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2309ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description On each active lcb, check if the lcb is in disconnecting 2310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * state, or if there are no ccb's on the lcb (implying 23115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project idle timeout is running), or if last ccb on the link 23125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project is in disconnecting state. 2313ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2314ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if any of above conditions met, false otherwise 2315ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2316ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_lcb_disconnecting(void) { 2318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb; 2319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 2320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t i; 2321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool status = false; 23225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = &l2cb.lcb_pool[0]; 23245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) { 2326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->in_use) { 2327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* no ccbs on lcb, or lcb is in disconnecting state */ 2328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_lcb->ccb_queue.p_first_ccb) || 2329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->link_state == LST_DISCONNECTING)) { 2330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = true; 2331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 2332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* only one ccb left on lcb */ 2334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) { 2335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = p_lcb->ccb_queue.p_first_ccb; 2336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->in_use) && 2338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) || 2339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) { 2340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = true; 2341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 23425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return status; 23475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 23485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_set_acl_priority 2352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Sets the transmission priority for a channel. 2354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * (For initial implementation only two values are valid. 2355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH). 2356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if a valid channel, else false 2358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 23605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2361c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskibool l2cu_set_acl_priority(const bt_bdaddr_t& bd_addr, uint8_t priority, 2362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool reset_after_rs) { 2363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb; 2364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* pp; 2365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE]; 2366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t vs_param; 23675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority); 23695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find the link control block for the acl channel */ 2371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR); 2372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb == NULL) { 2373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority"); 2374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 2375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 23765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (BTM_IS_BRCM_CONTROLLER()) { 2378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Called from above L2CAP through API; send VSC if changed */ 2379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!reset_after_rs && (priority != p_lcb->acl_priority)) || 2380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Called because of a master/slave role switch; if high resend VSC */ 2381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) { 2382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson pp = command; 23835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH 2385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson : HCI_BRCM_ACL_PRIORITY_LOW; 23865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(pp, p_lcb->handle); 2388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT8_TO_STREAM(pp, vs_param); 23895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY, 2391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, 2392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson NULL); 23935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Adjust lmp buffer allocation for this channel if priority changed */ 2395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->acl_priority != priority) { 2396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->acl_priority = priority; 2397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_adjust_allocation(); 2398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 23995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 24025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 24035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 24055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 2406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_set_non_flushable_pbf 2408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts 2410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2412ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_non_flushable_pbf(bool is_supported) { 2415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (is_supported) 2416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.non_flushable_pbf = 2417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT); 2418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 2419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT); 24205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 24215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 24225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2425ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_resubmit_pending_sec_req 2426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2427ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called when required security procedures 2428ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * are completed and any pending requests can be re-submitted. 2429ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2430ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2431ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2432ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2433c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskivoid l2cu_resubmit_pending_sec_req(const bt_bdaddr_t* p_bda) { 2434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb; 2435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 2436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_next_ccb; 2437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 24385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req p_bda: 0x%08x", p_bda); 24405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we are called with a BDA, only resubmit for that BDA */ 2442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_bda) { 2443c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski p_lcb = l2cu_find_lcb_by_bd_addr(*p_bda, BT_TRANSPORT_BR_EDR); 2444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we don't have one, this is an error */ 2446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb) { 2447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For all channels, send the event through their FSMs */ 2448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) { 2449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_next_ccb = p_ccb->p_next_ccb; 2450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL); 2451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR"); 24545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* No BDA pasesed in, so check all links */ 2457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; 2458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx++, p_lcb++) { 2459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->in_use) { 2460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For all channels, send the event through their FSMs */ 2461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) { 2462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_next_ccb = p_ccb->p_next_ccb; 2463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL); 24645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 24665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 24685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 24695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2470d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE) 24715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_set_info_rsp_mask 2474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function allows the script wrapper to change the 2476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * info resp mask for conformance testing. 2477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2478ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to CCB, or NULL if none 2479ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2480ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; } 2482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif /* L2CAP_CONFORMANCE_TESTING */ 24835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2485ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2486ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_adjust_out_mps 2487ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2488ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Sets our MPS based on current controller capabilities 2489ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2490ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2491ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2492ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adjust_out_mps(tL2C_CCB* p_ccb) { 2494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t packet_size; 2495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* on the tx side MTU is selected based on packet size of the controller */ 2497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_size = btm_get_max_packet_size(p_ccb->p_lcb->remote_bd_addr); 2498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + 2500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) { 2501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* something is very wrong */ 2502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 2503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", 2504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_size, p_ccb->peer_cfg.fcr.mps); 2505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps; 2506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + 2508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN); 2509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We try to negotiate MTU that each packet can be split into whole 2511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson number of max packets. For example if link is 1.2 max packet size is 339 2512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bytes. 2513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 2514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson overhead. 2515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is 2516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691. 2517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 2519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet 2520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */ 2521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mps >= packet_size) 2522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size; 25235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 2524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps; 25255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u " 2528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "packet_size: %u", 2529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size); 2530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 25315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 25325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_initialize_fixed_ccb 2536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Initialize a fixed channel's CCB 2538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true or false 2540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid, 2543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2CAP_FCR_OPTS* p_fcr) { 25445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 2545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 2546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we already have a CCB, then simply return */ 2548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]; 2549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb != NULL) && p_ccb->in_use) { 2550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 2551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * NOTE: The "in_use" check is needed to ignore leftover entries 2552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * that have been already released by l2cu_release_ccb(). 2553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 2555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 25565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cu_allocate_ccb(NULL, 0); 2558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (false); 25595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_lcb->l2c_lcb_timer); 2561ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta 2562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set CID for the connection */ 2563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid = fixed_cid; 2564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->remote_cid = fixed_cid; 25655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_flushable = false; 25675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr) { 2569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the FCR parameters. For now, we will use default pools */ 2570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr; 25715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE; 2573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE; 2574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE; 2575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE; 25765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3; 2578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 25795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Link ccb to lcb and lcb to ccb */ 2581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb; 2582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb = p_lcb; 25835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* There is no configuration, so if the link is up, the channel is up */ 2585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN; 25865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the default idle timeout value to use */ 2588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fixed_chnl_idle_tout = 2589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout; 25905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 2591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 25925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 25935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2595ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2596ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_no_dynamic_ccbs 2597ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 25989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Handles the case when there are no more dynamic CCBs. If 25999ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * there are any fixed CCBs, start the longest of the fixed CCB 26009ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * timeouts, otherwise start the default link idle timeout or 26019ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * disconnect. 2602ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2603ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2604ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2605ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) { 2607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBTM_STATUS rc; 2608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson period_ms_t timeout_ms = p_lcb->idle_timeout * 1000; 2609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool start_timeout = true; 26105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 26115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 2612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 26135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 2615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->p_fixed_ccbs[xx] != NULL) && 2616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) { 2617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000; 26185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 26205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 26215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the link is pairing, do not mess with the timeouts */ 2623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->is_bonding) return; 2624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (timeout_ms == 0) { 2626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link"); 2628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER); 2630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (rc == BTM_CMD_STARTED) { 2631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_process_fixed_disc_cback(p_lcb); 2632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_DISCONNECTING; 2633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS; 2634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (rc == BTM_SUCCESS) { 2635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_process_fixed_disc_cback(p_lcb); 2636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* BTM SEC will make sure that link is release (probably after pairing is 2637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * done) */ 2638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_DISCONNECTING; 2639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson start_timeout = false; 2640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_lcb->is_bonding) { 2641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER); 2642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_process_fixed_disc_cback(p_lcb); 2643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->link_state = LST_DISCONNECTING; 2644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS; 264578bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov } else { 2646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* probably no buffer to send disconnect */ 2647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timeout_ms = BT_1SEC_TIMEOUT_MS; 26485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (start_timeout) { 2652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__, timeout_ms); 2653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout, 2654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb, btu_general_alarm_queue); 2655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_lcb->l2c_lcb_timer); 2657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 26585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 26595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 26605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 26615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2662ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2663ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_fixed_chnl_resp 2664ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2665ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description handle a fixed channel response (or lack thereof) 2666ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * if the link failed, or a fixed channel response was 2667ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * not received, the bitfield is all zeros. 2668ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2669ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) { 2671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_BR_EDR) { 2672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* ignore all not assigned BR/EDR channels */ 2673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->peer_chnl_mask[0] &= 2674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT | 2675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FIXED_CHNL_SMP_BR_BIT); 2676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 2677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask; 2678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Tell all registered fixed channels about the connection */ 2680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 2681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* skip sending LE fix channel callbacks on BR/EDR links */ 2682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_BR_EDR && 2683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID && 2684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) 2685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 2686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) { 2687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] & 2688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) { 2689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->p_fixed_ccbs[xx]) 2690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN; 2691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL, 2692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->remote_bd_addr, true, 0, 2693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->transport); 2694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)( 2696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false, 2697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->disc_reason, p_lcb->transport); 2698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->p_fixed_ccbs[xx]) { 2700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]); 2701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->p_fixed_ccbs[xx] = NULL; 27025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 27045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 27065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 27075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 27085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 27098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/******************************************************************************* 2710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2711ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_process_fixed_disc_cback 2712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 27139ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description send l2cap fixed channel disconnection callback to the 27149ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * application 2715ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2716ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2717ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2718ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) { 27208fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#if (L2CAP_NUM_FIXED_CHNLS > 0) 27218fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 2722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Select peer channels mask to use depending on transport */ 2723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0]; 2724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // For LE, reset the stored peer channel mask 2726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0; 2727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 2729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->p_fixed_ccbs[xx]) { 2730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) { 2731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_l2c_chnl_ctrl_block; 2732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx]; 2733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->p_fixed_ccbs[xx] = NULL; 2734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_release_ccb(p_l2c_chnl_ctrl_block); 2735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)( 2736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false, 2737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->disc_reason, p_lcb->transport); 2738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) && 2740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)) 2741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)( 2742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false, 2743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->disc_reason, p_lcb->transport); 2744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 27458fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#endif 27468fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta} 27478fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta 27485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2749ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2750ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_par_req 2751ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send a BLE parameter update request message 2753ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 2754ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2755ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2756ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2757ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int, 2759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_int, uint16_t latency, 2760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t timeout) { 2761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 27635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 2765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id++; 2766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_lcb, L2CAP_ADJ_ID); 27675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN, 2769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id); 2770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer"); 2772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 27745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 27775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, min_int); 2779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, max_int); 2780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, latency); 2781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, timeout); 27825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 27845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 27855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 27865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2787ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_par_rsp 2789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2790ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send a BLE parameter update response message 2791ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to the peer. 2792ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2793ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2794ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2795ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason, 2797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t rem_id) { 2798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 28005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN, 2802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_UPDATE_RSP, rem_id); 2803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer"); 2805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 28075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 28105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, reason); 28125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 28145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 28155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 28166721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 2817ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2818ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_credit_based_conn_req 2819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 28209ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Build and send a BLE packet to establish LE connection 28219ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * oriented L2CAP channel. 2822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2823ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2824ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2825ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) { 2827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 2829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = NULL; 2830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t mtu; 2831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t mps; 2832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t initial_credit; 28336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return; 2835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = p_ccb->p_lcb; 28366721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 2838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 2839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 28406721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 28426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN, 2844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id); 2845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer"); 2847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 28496721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 28526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mtu = p_ccb->local_conn_cfg.mtu; 2854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mps = p_ccb->local_conn_cfg.mps; 2855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson initial_credit = p_ccb->local_conn_cfg.credits; 28566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\ 2859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mtu:%d mps:%d initial_credit:%d", 2860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit); 28616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm); 2863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 2864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, mtu); 2865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, mps); 2866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, initial_credit); 28676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 28696721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 28706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 28716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 2872ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2873ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_reject_ble_connection 2874ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 28759ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Build and send an L2CAP "Credit based connection res" 28769ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * message to the peer. This function is called for non-success 28779ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * cases. 2878ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2879ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2880ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2881ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id, 2883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t result) { 2884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 28866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN, 2888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id); 2889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_reject_ble_connection - no buffer"); 2891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 28936721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 28966721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* Local CID of 0 */ 2898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* MTU */ 2899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* MPS */ 2900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, 0); /* initial credit */ 2901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, result); 29026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 29046721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 29056721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 29066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 2907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_credit_based_conn_res 2909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 29109ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Build and send an L2CAP "Credit based connection res" 29119ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * message to the peer. This function is called in case of 29129ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * success. 2913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2914ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2915ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2916ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb, 2918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t result) { 2919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 29216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res"); 2923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = 2924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN, 2925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id); 2926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer"); 2928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 29306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 29336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); /* Local CID */ 2935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu); /* MTU */ 2936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps); /* MPS */ 2937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */ 2938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, result); 29396721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 29416721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 29426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 29436721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 2944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_flow_control_credit 2946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Build and send a BLE packet to give credits to peer device 2948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * for LE connection oriented L2CAP channel. 2949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb, 2954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t credit_value) { 2955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 2957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = NULL; 29586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return; 2960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = p_ccb->p_lcb; 29616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 2963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 2964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 29656721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 29676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN, 2969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id); 2970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 2971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer"); 2972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 2973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 29746721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 2976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 29776721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 2979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, credit_value); 29806721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 2981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 29826721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 29836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 29846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 2985ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_send_peer_ble_credit_based_conn_req 2987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 29889ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Build and send a BLE packet to disconnect LE connection 29899ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * oriented L2CAP channel. 2990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2992ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2993ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) { 2995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 2997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = NULL; 2998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s", __func__); 29996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return; 3001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb = p_ccb->p_lcb; 30026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create an identifier for this packet */ 3004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->id++; 3005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID); 30066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_id = p_ccb->p_lcb->id; 3008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ, 3009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->id); 3010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) { 3011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 3012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2cu_send_peer_ble_credit_based_disconn_req - no buffer"); 3013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 3014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 30156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + 3017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD; 30186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 3020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->local_cid); 30216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_lcb, NULL, p_buf); 30236721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 30245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 30255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 3026ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Functions used by both Full and Light Stack 3027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 30285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 30295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 3030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_lcb_by_handle 3032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through all active LCBs for a match based on the 3034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * HCI handle. 3035ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3036ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to matched LCB, or NULL if no match 3037ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3038ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3039911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) { 3040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 3041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; 30425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { 3044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->in_use) && (p_lcb->handle == handle)) { 3045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_lcb); 30465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 30485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no match found */ 3050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 30515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 30525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 30535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 3054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_find_ccb_by_cid 3056ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3057ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Look through all active CCBs on a link for a match based 3058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * on the local CID. If passed the link pointer is NULL, all 3059ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * active links are searched. 3060ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3061ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to matched CCB, or NULL if no match 3062ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3063ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3064911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) { 3065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb = NULL; 30665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 3067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t xx; 30685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 30695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (local_cid >= L2CAP_BASE_APPL_CID) { 3071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* find the associated CCB by "index" */ 3072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson local_cid -= L2CAP_BASE_APPL_CID; 30735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (local_cid >= MAX_L2CAP_CHANNELS) return NULL; 30755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cb.ccb_pool + local_cid; 30775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* make sure the CCB is in use */ 3079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->in_use) { 3080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = NULL; 30815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* make sure it's for the same LCB */ 3083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_lcb && p_lcb != p_ccb->p_lcb) { 3084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = NULL; 30855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (L2CAP_UCD_INCLUDED == TRUE) 3088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 3089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* searching fixed channel */ 3090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cb.ccb_pool; 3091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) { 3092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->local_cid == local_cid) && (p_ccb->in_use) && 3093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_lcb == p_ccb->p_lcb)) 3094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 3095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 3096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb++; 3097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (xx >= MAX_L2CAP_CHANNELS) return NULL; 3099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 31005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 31015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb); 31035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 31045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 31055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 31065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 31075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 3108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_get_next_channel_in_rr 3110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description get the next channel to send on a link. It also adjusts the 3112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * CCB queue to do a basic priority and round-robin scheduling. 3113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to CCB or NULL 3115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) { 3118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_serve_ccb = NULL; 3119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 31205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int i, j; 31225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* scan all of priority until finding a channel to serve */ 3124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++) { 3125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* scan all channel within serving priority group until finding a channel to 3126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * serve */ 3127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); 3128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson j++) { 3129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* scaning from next serving channel */ 3130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb; 31315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) { 3133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri); 3134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 3135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d", 3138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ccb_priority, p_ccb->local_cid, 3139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->xmit_hold_q)); 3140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* store the next serving channel */ 3142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* this channel is the last channel of its priority group */ 3143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->p_next_ccb == NULL) || 3144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) { 3145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* next serving channel is set to the first channel in the group */ 3146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = 3147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb; 3148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* next serving channel is set to the next channel in the group */ 3150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb; 3151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->chnl_state != CST_OPEN) continue; 3154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 3156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s : Connection oriented channel", __func__); 3157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue; 3158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* eL2CAP option in use */ 3161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { 3162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue; 31635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) { 3165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue; 31665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If in eRTM mode, check for window closure */ 3168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && 3169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2c_fcr_is_flow_controlled(p_ccb))) 3170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 3171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue; 31745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 31765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* found a channel to serve */ 3178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_serve_ccb = p_ccb; 3179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* decrease quota of its priority group */ 3180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_lcb->rr_pri].quota--; 31815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 31825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if there is no more quota of the priority group or no channel to have 3184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * data to send */ 3185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) { 3186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* serve next priority group */ 3187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY; 3188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* initialize its quota */ 3189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_lcb->rr_pri].quota = 3190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri); 31915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_serve_ccb) { 3195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x", 3196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_serve_ccb->ccb_priority, 3197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota, 3198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_serve_ccb->local_cid); 3199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 32005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return p_serve_ccb; 32025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 32035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */ 32055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 32065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 3207ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_get_next_channel 3209ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3210ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description get the next channel to send on a link bassed on priority 3211ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * scheduling. 3212ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3213ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to CCB or NULL 3214ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) { 3217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 32185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the first CCB with data to send. 3220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 3221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) { 3222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->chnl_state != CST_OPEN) continue; 32235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue; 32255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) return p_ccb; 32275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue; 32295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If in eRTM mode, check for window closure */ 3231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && 3232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2c_fcr_is_flow_controlled(p_ccb))) 3233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 32345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, we found someone */ 3236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return p_ccb; 3237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 32385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 32405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 32415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */ 32425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 324335e95c989923880e838741d52035c065c043921dYamei Duvoid l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) { 3244c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski if (p_cbi->cb != NULL) p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu); 324535e95c989923880e838741d52035c065c043921dYamei Du} 324635e95c989923880e838741d52035c065c043921dYamei Du 32475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 3248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_get_next_buffer_to_send 3250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description get the next buffer to send on a link. It also adjusts the 3252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * CCB queue to do a basic priority and round-robin scheduling. 3253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to buffer or NULL 3255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3257c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskiBT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb, 3258c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski tL2C_TX_COMPLETE_CB_INFO* p_cbi) { 3259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_CCB* p_ccb; 3260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 32615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Highest priority are fixed channels */ 32635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 3264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int xx; 32655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 326635e95c989923880e838741d52035c065c043921dYamei Du p_cbi->cb = NULL; 326735e95c989923880e838741d52035c065c043921dYamei Du 3268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 3269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = p_lcb->p_fixed_ccbs[xx]; 3270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) continue; 32715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* eL2CAP option in use */ 3273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { 3274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue; 32755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* No more checks needed if sending from the reatransmit queue */ 3277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) { 3278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue; 3279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If in eRTM mode, check for window closure */ 3281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && 3282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2c_fcr_is_flow_controlled(p_ccb))) 3283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 3284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0); 3287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf != NULL) { 3288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_check_channel_congestion(p_ccb); 3289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_set_acl_hci_header(p_buf, p_ccb); 3290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf); 3291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) { 3294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 3295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (NULL == p_buf) { 329635e95c989923880e838741d52035c065c043921dYamei Du L2CAP_TRACE_ERROR("%s: No data to be sent", __func__); 3297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 3298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 329935e95c989923880e838741d52035c065c043921dYamei Du 330035e95c989923880e838741d52035c065c043921dYamei Du /* Prepare callback info for TX completion */ 330135e95c989923880e838741d52035c065c043921dYamei Du p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb; 330235e95c989923880e838741d52035c065c043921dYamei Du p_cbi->local_cid = p_ccb->local_cid; 330335e95c989923880e838741d52035c065c043921dYamei Du p_cbi->num_sdu = 1; 3304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_check_channel_congestion(p_ccb); 3306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_set_acl_hci_header(p_buf, p_ccb); 3307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf); 3308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 33115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 33125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 33135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 3314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* get next serving channel in round-robin */ 3315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cu_get_next_channel_in_rr(p_lcb); 33165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else 3317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = l2cu_get_next_channel(p_lcb); 33185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 33195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Return if no buffer */ 3321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (NULL); 33226721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 3323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 3324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check credits */ 3325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_conn_cfg.credits == 0) { 3326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__); 3327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 33285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0); 3330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) return (NULL); 33315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_conn_cfg.credits--; 3333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { 3335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0); 3336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) return (NULL); 3337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 3339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (NULL == p_buf) { 3340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent"); 3341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 3342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 33455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && 3347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE)) 3348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1); 33495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_check_channel_congestion(p_ccb); 33515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_set_acl_hci_header(p_buf, p_ccb); 33535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf); 33555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 33565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 33575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 3358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_set_acl_hci_header 3360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Set HCI handle for ACL packet 3362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3363ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 3364ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3365ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) { 3367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 33685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the pointer to the beginning of the data minus 4 bytes for the packet 3370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * header */ 3371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE; 33725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 3374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE 3375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson << L2CAP_PKT_TYPE_SHIFT)); 3376eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh 3377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t acl_data_size = 3378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson controller_get_interface()->get_acl_data_size_ble(); 3379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The HCI transport will segment the buffers. */ 3380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len > acl_data_size) { 3381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, acl_data_size); 3382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_buf->len); 338484baa7f16e830394408278dbb8c508dd9fa02887Myles Watson } 3385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3386eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 3387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == 3388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FLUSHABLE_CH_BASED) && 3389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->is_flushable)) || 3390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == 3391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FLUSHABLE_PKT)) { 3392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM( 3393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)); 3394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf); 3396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3397eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#else 3398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM( 3399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)); 3400eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#endif 34015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t acl_data_size = 3403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson controller_get_interface()->get_acl_data_size_classic(); 3404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The HCI transport will segment the buffers. */ 3405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len > acl_data_size) { 3406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, acl_data_size); 3407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_buf->len); 34095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset -= HCI_DATA_PREAMBLE_SIZE; 3412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len += HCI_DATA_PREAMBLE_SIZE; 34135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 34145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 34155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 3416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_check_channel_congestion 3418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3419ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description check if any change in congestion status 3420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 3422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_check_channel_congestion(tL2C_CCB* p_ccb) { 3425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q); 34265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 34275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 3428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) { 3429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q); 3430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 34315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 3432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the CCB queue limit is subject to a quota, check for congestion */ 3433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if this channel has outgoing traffic */ 3434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->buff_quota != 0) { 3435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If this channel was congested */ 3436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->cong_sent) { 3437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the channel is not congested now, tell the app */ 3438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (q_count <= (p_ccb->buff_quota / 2)) { 3439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cong_sent = false; 3440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) { 3441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 3442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - Calling CongestionStatus_Cb (false), CID: 0x%04x " 3443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "xmit_hold_q.count: %u buff_quota: %u", 3444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, q_count, p_ccb->buff_quota); 3445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Prevent recursive calling */ 3447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.is_cong_cback_context = true; 3448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, 3449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson false); 3450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cb.is_cong_cback_context = false; 3451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 34525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 3453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) { 3454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) { 3455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 3456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - Calling UCD CongestionStatus_Cb (false), " 3457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SecPendingQ:%u,XmitQ:%u,Quota:%u", 3458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q), 3459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota); 3460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( 3461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->remote_bd_addr, false); 3462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 34645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 3465493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0) 3466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 3467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t xx; 3468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 3469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) { 3470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) 3471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)( 3472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->remote_bd_addr, false); 3473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 34745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif 3478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 3480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If this channel was not congested but it is congested now, tell the app 3481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 3482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (q_count > p_ccb->buff_quota) { 3483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cong_sent = true; 3484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) { 3485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 3486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - Calling CongestionStatus_Cb " 3487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "(true),CID:0x%04x,XmitQ:%u,Quota:%u", 3488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, q_count, p_ccb->buff_quota); 3489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, 3491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson true); 34925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 34935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE) 3494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) { 3495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) { 3496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 3497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - Calling UCD CongestionStatus_Cb (true), " 3498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SecPendingQ:%u,XmitQ:%u,Quota:%u", 3499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q), 3500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota); 3501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( 3502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->remote_bd_addr, true); 3503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 35055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 3506493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0) 3507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 3508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t xx; 3509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { 3510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) { 3511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) 3512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)( 3513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->remote_bd_addr, true); 3514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 35155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 35175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif 3519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 35205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 35225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 35235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3524494b510b9bdf5bf9bb8b74181a8f640e54e6cd40Gurpreet Ghai/******************************************************************************* 3525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2cu_is_ccb_active 3527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Check if Channel Control Block is in use or released 3529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns bool - true if Channel Control Block is in use 3531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * false if p_ccb is null or is released. 3532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); } 3535